diff --git a/docs/docs.json b/docs/docs.json index c40ff5a1..f4031e62 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -102,7 +102,6 @@ "features/global-observability", "features/host-console", "features/multi-node", - "features/node-compatibility", "features/fleet-view", "features/remote-updates", "features/stack-labels", @@ -124,10 +123,9 @@ { "group": "Reference", "pages": [ + "features/node-compatibility", "reference/settings", - "reference/security-advisories", - "reference/architecture", - "reference/development" + "reference/security-advisories" ] }, { diff --git a/docs/features/alerts-notifications.mdx b/docs/features/alerts-notifications.mdx index a3d5f25c..8d988e4a 100644 --- a/docs/features/alerts-notifications.mdx +++ b/docs/features/alerts-notifications.mdx @@ -3,38 +3,37 @@ title: Alerts & Notifications description: Set threshold-based alerts on container metrics and route them to Discord, Slack, or any webhook. --- -Sencho can watch your containers for resource anomalies and notify you when thresholds are breached. Alerts are defined per stack, and notifications are delivered through external agents you configure. +Sencho can watch your containers for resource anomalies and notify you when thresholds are breached. Alerts are defined per stack, and notifications are delivered through external channels you configure. + +## Setting up notification channels + +At least one channel must be enabled before alerts can be delivered externally. Go to **Settings > Notifications**. Notifications & Alerts settings showing Discord, Slack, and Webhook tabs -## How alerts work - -Sencho's monitoring service samples container metrics every minute and evaluates all defined alert rules. When a rule's condition holds true for the configured duration, a notification is dispatched. A cooldown period prevents the same alert from firing repeatedly. - -## Setting up a notification agent - -At least one agent must be enabled before alerts can be delivered. Go to **Settings → Notifications**. +Three channel types are available, each configured with a webhook URL and an enable/disable toggle: ### Discord -1. In Discord, go to your server's **Settings → Integrations → Webhooks** +1. In Discord, go to your server's **Settings > Integrations > Webhooks** 2. Click **New Webhook**, choose a channel, and copy the webhook URL -3. In Sencho, open **Settings → Notifications → Discord**, paste the URL, enable the toggle, and click **Save** -4. Click **Test** to send a test message +3. In Sencho, open **Settings > Notifications > Discord**, paste the URL, enable the toggle, and click **Save** +4. Click **Test** to send a test message and verify the connection ### Slack 1. In Slack, go to **api.slack.com/apps**, create an app, and add the **Incoming Webhooks** feature 2. Activate it and copy the generated webhook URL for your chosen channel -3. In Sencho, open **Settings → Notifications → Slack**, paste the URL, enable the toggle, and click **Save** +3. In Sencho, open **Settings > Notifications > Slack**, paste the URL, enable the toggle, and click **Save** ### Generic Webhook -Any HTTP endpoint that accepts a POST with a JSON body can receive Sencho alerts. Go to **Settings → Notifications → Webhook**, enter the URL, and click **Save**. +Any HTTP endpoint that accepts a POST with a JSON body can receive Sencho alerts. Go to **Settings > Notifications > Webhook**, enter the URL, enable the toggle, and click **Save**. The payload format is: + ```json { "level": "warning", @@ -45,76 +44,94 @@ The payload format is: ## Creating stack alerts -Stack alerts are configured per-stack. Right-click a stack in the sidebar (or click the **⋮** button) and select **Alerts**. +Stack alerts are configured per stack. Right-click a stack in the sidebar (or click the three-dot menu) and select **Alerts**. A panel slides open showing existing rules and a form to create new ones. - Stack context menu showing the Alerts option + Stack Alerts panel showing the notification status banner and alert rule form -The alerts panel slides open, showing existing rules for the stack and a form to create new ones. +The panel includes: - - Alert panel showing alert rules and creation form - +- **Notification status banner** at the top, showing whether channels are configured. If no channels are enabled, a warning explains that rules will be evaluated but no external notifications will be sent. +- **Existing Rules** section listing all active rules for this stack, each showing the metric, condition, duration, and cooldown. Hover over a rule to reveal the delete button. +- **Add New Rule** form with the fields described below. ### Alert fields | Field | Description | |-------|-------------| -| **Metric** | The container metric to watch | -| **Operator** | Comparison operator: `>`, `>=`, `<`, `<=`, `==` | -| **Threshold** | The value to compare against | -| **Duration (minutes)** | How long the condition must hold before firing | -| **Cooldown (minutes)** | Minimum time between repeated notifications for this rule | +| **Metric** | The container metric to watch (see table below) | +| **Operator** | Comparison: Greater than, Greater or equal, Less than, Less or equal, Equals | +| **Threshold** | The numerical value to compare against | +| **Duration (mins)** | How long the condition must hold before firing (default: 5) | +| **Cooldown (mins)** | Minimum time between repeated notifications for this rule (default: 60) | ### Available metrics -| Metric | Unit | Description | -|--------|------|-------------| -| `cpu_percent` | % | CPU usage relative to total host cores | -| `memory_mb` | MB | RSS memory used by the container | -| `memory_percent` | % | Memory used as a fraction of the host total | -| `net_rx` | bytes/s | Inbound network rate | -| `net_tx` | bytes/s | Outbound network rate | -| `restart_count` | count | Number of times the container has restarted | +| Metric | Description | +|--------|-------------| +| CPU Usage (%) | CPU usage relative to total host cores | +| Memory Usage (%) | Memory used as a fraction of the host total | +| Memory Usage (MB) | RSS memory used by the container | +| Network In (MB) | Inbound network throughput | +| Network Out (MB) | Outbound network throughput | +| Restart Count | Number of times the container has restarted | ### Example: alert on high CPU -To alert when any container in a stack uses more than 80% CPU for over 5 consecutive minutes, with a 30-minute cooldown: +To alert when any container in a stack uses more than 80% CPU for over 5 consecutive minutes, with a 60-minute cooldown: | Field | Value | |-------|-------| -| Metric | `cpu_percent` | -| Operator | `>` | -| Threshold | `80` | -| Duration | `5` | -| Cooldown | `30` | +| Metric | CPU Usage (%) | +| Operator | Greater than | +| Threshold | 80 | +| Duration | 5 | +| Cooldown | 60 | ## Notification history -All dispatched notifications appear in the **notification bell** (top-right of the nav bar). Click it to see recent alerts with their level, message, and timestamp. Mark all as read or clear individual entries from there. +All dispatched notifications appear in the **notification bell** in the top-right corner of the navigation bar. A red dot pulses on the bell when unread notifications exist. + + + Notification popover showing recent alert entries with level badges and timestamps + + +Click the bell to open the notification popover, which shows: + +- **Level badge** for each entry (ERROR in red, WARNING in amber, INFO in default) +- **Node name** badge for notifications from remote nodes +- **Timestamp** of when the alert was triggered +- **Alert message** describing what was breached + +The popover header includes: + +| Action | What it does | +|--------|--------------| +| **Mark all as read** | Marks all notifications as read (removes the red dot) | +| **Clear all** | Deletes all notifications from the list | + +You can also dismiss individual notifications by hovering over them and clicking the dismiss button. - Notifications only reach external agents (Discord, Slack, Webhook) if at least one agent is enabled. Dashboard notifications appear regardless. + Notifications only reach external channels (Discord, Slack, Webhook) if at least one channel is enabled. Dashboard notifications appear regardless. ## Alerts on remote nodes -Alerts work the same way on remote nodes as they do locally. When you switch to a remote node and right-click a stack, the alerts panel shows and manages rules for that remote instance. +Alerts work the same way on remote nodes as they do locally. When you switch to a remote node and open a stack's alerts panel, you are managing rules on that remote instance. - - Alert panel on a remote node - +Key details: -### How it works +- **Alert rules are stored on each node independently.** Rules created while a remote node is selected are saved on that remote instance, not your primary instance. +- **Monitoring runs locally on each node.** Each Sencho instance evaluates its own alert rules against its own container metrics. +- **Notifications are sent by the node that detects the breach.** Make sure notification channels are configured on each remote node where you want to receive alerts, since channel settings are per-instance. -1. **Alert rules are stored on each node independently.** When you create an alert while a remote node is selected, the rule is saved on that remote Sencho instance's database - not your primary instance. -2. **Monitoring runs locally on each node.** The remote Sencho instance evaluates its own alert rules against its own container metrics every minute. -3. **Notifications are sent by the node that detects the breach.** Make sure notification agents (Discord, Slack, Webhook) are configured on each remote node where you want to receive alerts - notification settings are per-instance. +The alert panel shows a blue info banner when you are configuring alerts on a remote node, including which channels are active on that node. ### Setup checklist for remote alerts -1. On the **remote** Sencho instance, go to **Settings → Notifications** and configure at least one agent +1. On the **remote** Sencho instance, go to **Settings > Notifications** and configure at least one channel 2. From your **primary** instance, switch to the remote node 3. Right-click a stack and select **Alerts** to create rules 4. The remote instance handles monitoring and notification delivery independently diff --git a/docs/features/api-tokens.mdx b/docs/features/api-tokens.mdx index 59171287..fd9bb60f 100644 --- a/docs/features/api-tokens.mdx +++ b/docs/features/api-tokens.mdx @@ -7,7 +7,7 @@ description: Generate scoped API tokens for CI/CD pipelines, scripts, and automa API Tokens require a Sencho **Admiral** license. Skipper and Community Edition do not include this feature. -API tokens let you authenticate external tools - CI/CD pipelines, deployment scripts, monitoring integrations - without sharing user credentials. Each token is scoped to a specific permission level so you can follow the principle of least privilege. +API tokens let you authenticate external tools (CI/CD pipelines, deployment scripts, monitoring integrations) without sharing user credentials. Each token is scoped to a specific permission level so you can follow the principle of least privilege. ## Permission scopes @@ -15,9 +15,9 @@ Every token is created with one of three permission levels: | Scope | Allowed actions | |-------|----------------| -| **Read Only** | `GET` requests only - view stacks, containers, metrics, and settings | -| **Deploy Only** | Everything in Read Only, plus stack operations: deploy, down, restart, stop, start, update | -| **Full Admin** | Full stack and container management - all read and write operations on stacks, containers, images, and system metrics | +| **Read Only** | `GET` requests only: view stacks, containers, metrics, and settings | +| **Deploy Only** | Everything in Read Only, plus stack lifecycle operations: deploy, down, restart, stop, start, update | +| **Full Admin** | All read and write operations except the universal restrictions listed below | Choose the narrowest scope that fits your use case. A CI pipeline that only deploys stacks should use **Deploy Only**, not Full Admin. @@ -41,17 +41,29 @@ These restrictions ensure that API tokens cannot escalate privileges or modify t 1. Open **Settings Hub** and navigate to the **API Tokens** tab (visible to Admiral admins only). 2. Click **Create Token**. -3. Enter a descriptive name (e.g., "GitHub Actions deploy"), select a permission scope, and optionally choose an expiration period (30, 60, 90 days, or 1 year). Tokens without an expiration must be revoked manually. -4. Click **Create**. The raw token is displayed **once** - copy it immediately. +3. Fill in the creation form: + - **Name**: A descriptive label (e.g., "GitHub Actions deploy") + - **Permission Scope**: Select Read Only, Deploy Only, or Full Admin + - **Expiration**: Choose 30 days, 60 days, 90 days, 1 year, or no expiration. Tokens without an expiration must be revoked manually. +4. Click **Create**. A green banner appears with the raw token value. Copy it immediately using the copy button. - API Tokens management view in Settings Hub + API Tokens management view in Settings Hub showing the token list and create form The token value is shown only at creation time. Sencho stores a SHA-256 hash of the token, not the token itself. If you lose it, revoke and create a new one. +## Managing tokens + +The token list displays each active token as a card showing: + +- **Name** and **scope badge** (color-coded: teal for Read Only, gray for Deploy Only, red for Full Admin) +- **Created date** +- **Last used** timestamp (relative, e.g., "3h ago"), or "Never" if unused +- **Expiration date**, if one was set. Expired tokens are marked in red. + ## Using a token Pass the token as a Bearer token in the `Authorization` header: @@ -84,11 +96,12 @@ If a token attempts an action outside its scope, Sencho returns a `403` response ## Revoking a token -Click the trash icon next to any token in the API Tokens settings tab. Revocation is immediate - any in-flight or future requests using the revoked token will receive a `401` response. +Click the trash icon next to any token in the API Tokens settings tab. A confirmation dialog warns that revoking the token will immediately invalidate it and break any pipelines or scripts using it. After confirmation, revocation is instant: any in-flight or future requests using the revoked token will receive a `401` response. ## Security model -- **Hashed storage** - Only a SHA-256 hash of the token is stored in the database. The raw token is never persisted. -- **Audit trail** - All actions performed via API tokens are recorded in the [Audit Log](/features/audit-log) under the creating user's username. -- **Optional expiry** - Tokens can be created with an expiration period (30 days, 60 days, 90 days, or 1 year). Tokens without an expiry must be revoked manually when no longer needed. -- **Scope enforcement** - Permission checks happen at the middleware level before any route handler executes, ensuring consistent enforcement across all endpoints. +- **Hashed storage**: Only a SHA-256 hash of the token is stored in the database. The raw token is never persisted. +- **Audit trail**: All actions performed via API tokens are recorded in the [Audit Log](/features/audit-log) under the creating user's username. +- **Optional expiry**: Tokens can be created with an expiration period (30 days, 60 days, 90 days, or 1 year). Tokens without an expiry must be revoked manually when no longer needed. +- **Usage tracking**: Each token tracks when it was last used, visible in the token list. +- **Scope enforcement**: Permission checks happen at the middleware level before any route handler executes, ensuring consistent enforcement across all endpoints. diff --git a/docs/features/app-store.mdx b/docs/features/app-store.mdx index cd6dd22f..6fcdbbfa 100644 --- a/docs/features/app-store.mdx +++ b/docs/features/app-store.mdx @@ -3,7 +3,7 @@ title: App Store description: Browse and deploy pre-configured application templates in one click. --- -The **App Store** tab lets you browse a curated catalogue of Docker Compose templates and deploy any of them as a new stack with environment-specific configuration - no YAML required. +The **App Store** tab lets you browse a curated catalogue of Docker Compose templates and deploy any of them as a new stack with environment-specific configuration, no YAML required. App Store showing a grid of application templates with category filters @@ -11,44 +11,58 @@ The **App Store** tab lets you browse a curated catalogue of Docker Compose temp ## Browsing templates -Templates are loaded from a remote registry (configurable in **Settings → App Store**). The default registry provides 190+ self-hosted application templates. +Templates are loaded from a remote registry (configurable in **Settings > App Store**). The default registry is LinuxServer.io. A live count of available apps is shown next to the category pills. -**Search:** Type in the search bar to filter templates by name or description in real-time. +**Search:** Type in the search bar to filter templates by name, description, or category in real-time. **Categories:** Click any category pill to narrow the list: -`Automation` · `Books` · `Development` · `Documentation` · `Downloaders` · `Media` · `Monitoring` · `Networking` · `Other` · `Product` +`All` · `Automation` · `Books` · `Development` · `Documentation` · `Downloaders` · `Media` · `Monitoring` · `Networking` · `Other` · `Productivity` · `Security` · `Utilities` Each template card shows: -- Application logo +- Application logo (or a placeholder icon if unavailable) - Name and short description -- Category tags -- Links to the GitHub repo and documentation (where available) +- Up to three category badges (click a badge to filter by that category) ## Deploying a template -Click any template card to open the **deployment sheet** on the right side of the screen. Fill in the fields and click **Deploy**. +Click any template card to open the **deployment sheet** on the right side of the screen. + + + Deployment sheet for heimdall showing stack name, ports, volumes, and environment variables + + +The sheet header displays the app logo, title, and a truncated description with a **Read more** / **Read less** toggle. Below the description you may see: + +- **Architecture badges** (e.g. `amd64`, `arm64`) when the template declares supported platforms +- **GitHub stars** count +- **Source** link to the GitHub repository +- **Docs** link to the official documentation + +When deploying to a remote node, a badge at the top of the sheet shows the target node name. ### Stack name -Pre-filled with the template name in lowercase. You can change it - the same [naming rules](/features/stack-management#creating-a-stack) apply (lowercase, hyphens, no spaces). +Pre-filled with the template name in lowercase. You can change it; the same [naming rules](/features/stack-management#creating-a-stack) apply (lowercase, hyphens, no spaces). -### Environment variables +### Ports -Each template declares the variables it needs. Sencho pre-fills sensible defaults where available (e.g. `PUID=1000`, `PGID=1000`, `TZ` from your browser locale). - -Edit any value before deploying. You can also click **Custom Env** to add arbitrary key-value pairs not defined by the template. +For each exposed port, the sheet shows an editable **host port** field (left side) and the fixed **container port** (right side). Edit the host port to avoid conflicts with other services on the same machine. ### Volumes -For each container mount point, enter the **host path** where that data should be stored. Suggested defaults (e.g. `./config`, `./data`) are shown as placeholders. +For each container mount point, enter the **host path** where that data should be stored. Suggested defaults (e.g. `./config`, `./data`) are pre-filled. Relative paths like `./config` are resolved relative to the stack directory inside your `COMPOSE_DIR`. Absolute paths map directly to the host filesystem. -### Ports +### Environment variables -For each exposed port, edit the **host port** (left side). The container port (right side) is fixed by the template and cannot be changed here - edit the compose file after deployment if needed. +Each template declares the variables it needs. Sencho pre-fills sensible defaults where available (e.g. `PUID=1000`, `PGID=1000`, `TZ` from your browser locale). Edit any value before deploying. + +### Custom variables + +Below the template variables, an **Add Custom Variable** section lets you define arbitrary key-value pairs not declared by the template. Type a key and value, then click **+** to add it. ### What happens on Deploy @@ -58,14 +72,18 @@ For each exposed port, edit the **host port** (left side). The container port (r 4. On success: switches you to the Editor view for that stack 5. On failure: rolls back by running `docker compose down` and deleting the stack directory -A toast notification confirms success or shows the error message. +A toast notification confirms success or shows the error message. Large images may take a few minutes to pull. + + + Deploying a template requires the `stack:create` permission. Users without this permission will see the Deploy button disabled. + ## Custom template registry By default Sencho uses the LinuxServer.io template registry. To use your own: -1. Open **Settings → App Store** +1. Open **Settings > App Store** 2. Enter your registry URL (must serve a JSON array of template objects in Portainer v2 format) -3. Click **Save** +3. Click **Save & Refresh** -To force a refresh of the cached templates, click **Refresh Cache** in the same settings panel. +Sencho saves the new URL and automatically refreshes the template cache from the new source. To revert to the default registry, click **Reset to Default**. diff --git a/docs/features/atomic-deployments.mdx b/docs/features/atomic-deployments.mdx index 41995286..d0c7e008 100644 --- a/docs/features/atomic-deployments.mdx +++ b/docs/features/atomic-deployments.mdx @@ -4,30 +4,36 @@ description: Zero-downtime deployments with automatic rollback for Sencho Pro us --- - Atomic Deployments require a Sencho Pro license. Community Edition uses standard deployments without backup or rollback. + Atomic Deployments require a **Sencho Skipper** or **Admiral** license. Community Edition uses standard deployments without backup or rollback. Sencho Pro wraps every deployment in a safety net. Before applying changes, it backs up your current configuration. If the deployment fails, it automatically rolls back to the previous working state. ## How it works -1. **Backup** - Before a deploy or update, Sencho copies `compose.yaml` and `.env` files to a `.sencho-backup/` directory inside the stack folder +1. **Backup** - Before a deploy or update, Sencho copies your `compose.yaml` and `.env` files to a backup directory inside the stack folder 2. **Deploy** - Sencho runs the requested compose operation (up, pull + recreate, etc.) -3. **Health probe** - After deployment, Sencho checks whether any containers exited with a non-zero exit code +3. **Health probe** - After deployment, Sencho waits briefly, then checks whether any containers exited with a non-zero exit code 4. **Auto-rollback** - If a crash is detected, Sencho restores the backed-up files and re-deploys automatically -This entire sequence happens transparently. You see a single deploy action - Sencho handles the safety logic behind the scenes. +This entire sequence happens transparently. You see a single deploy action; Sencho handles the safety logic behind the scenes. + +## Which operations are protected + +Atomic deployments apply to: + +- **Deploy** from the stack editor (compose down + up) +- **Update** from the stack editor (pull latest images + recreate) +- **Webhook triggers** for deploy and pull actions +- **Scheduled tasks** that perform deploys or updates +- **App Store installs** when deploying a new stack ## Manual rollback -Pro admins can manually roll back to the previous deployment at any time by clicking the **Rollback** button in the stack action bar. The button appears whenever a backup exists, and its tooltip shows the timestamp of the last backup. +You can manually roll back to the previous deployment at any time by clicking the **Rollback** button in the stack editor's action bar. The button only appears when a backup exists from a prior deployment. -Clicking Rollback restores the backed-up `compose.yaml` and `.env` files, then re-deploys the stack with the restored configuration. - -## Webhook support - -Deployments triggered via webhooks also use atomic rollback. Whether you deploy manually through the UI or automatically from a CI/CD pipeline, the same backup-and-recover flow applies. +Hover over the Rollback button to see a tooltip with the timestamp of the last backup. Clicking it restores the backed-up `compose.yaml` and `.env` files, then re-deploys the stack with the restored configuration. ## Community Edition behavior -Community users continue to use the standard deploy flow - no backup is created and no rollback is available. Upgrading to Pro enables atomic deployments immediately with no configuration required. +Community users continue to use the standard deploy flow: no backup is created and no rollback is available. Upgrading to Skipper or Admiral enables atomic deployments immediately with no configuration required. diff --git a/docs/features/audit-log.mdx b/docs/features/audit-log.mdx index 381068c5..c98d5960 100644 --- a/docs/features/audit-log.mdx +++ b/docs/features/audit-log.mdx @@ -17,12 +17,19 @@ Every `POST`, `PUT`, `DELETE`, and `PATCH` request to the Sencho API is automati |-------|-------------| | **Timestamp** | When the action occurred | | **User** | The authenticated username that performed the action | -| **Method** | HTTP method (`POST`, `PUT`, `DELETE`, `PATCH`) | +| **Method** | HTTP method (`POST`, `PUT`, `DELETE`, `PATCH`), shown as a color-coded badge | | **Action** | Human-readable summary (e.g., "Deployed stack: nginx-proxy") | -| **Status** | HTTP response status code | -| **Node** | Which node the action targeted | -| **Request Path** | Full API path (visible in expanded detail view) | -| **IP Address** | Client IP address (visible in expanded detail view) | +| **Status** | HTTP response status code, color-coded by result (green for success, yellow for client errors, red for server errors) | +| **Node** | Which node the action targeted, or `-` for local-only actions | + +Expanding a row reveals additional detail: + +| Field | Description | +|-------|-------------| +| **Request Path** | Full API path of the request | +| **IP Address** | Client IP address | +| **Node ID** | Numeric node ID, or "Local" for local actions | +| **Entry ID** | Unique identifier for the audit entry | ### Example actions tracked @@ -43,24 +50,32 @@ Every `POST`, `PUT`, `DELETE`, and `PATCH` request to the Sencho API is automati Navigate to the **Audit** tab in the sidebar. This tab is visible to users with the **Admin** or **Auditor** role on an Admiral license. - Audit Log view showing a timeline of actions with search, filters, and export + Audit Log view showing the action table with search filters, color-coded method badges, and export controls -Click any row to expand it and see full request details including the API path, IP address, node ID, and entry ID. +Click any row to expand it and see the full request details inline. -## Filtering & search + + Audit Log with an expanded row showing request path, IP address, node ID, and entry ID + + +The header displays the total number of matching entries and provides **Refresh** and **Export** controls. + +Results are paginated at 50 entries per page. Navigation controls appear at the bottom of the table when there are multiple pages. + +## Filtering and search The audit log provides several ways to find specific entries: -- **Full-text search** — Search across action summaries, API paths, and usernames -- **Method filter** — Filter by HTTP method (POST, PUT, DELETE, PATCH) -- **Date range** — Set a start and/or end date to narrow results to a specific time window +- **Full-text search** - Search across action summaries, API paths, and usernames +- **Method filter** - Filter by HTTP method (POST, PUT, DELETE, PATCH) using the dropdown +- **Date range** - Set a start and/or end date to narrow results to a specific time window All filters work together and are applied server-side with pagination. ## Export -Export the currently filtered audit log dataset as **CSV** or **JSON** using the **Export** dropdown in the header. The export respects all active filters — so you can narrow down to a date range or specific user before exporting. +Export the currently filtered audit log dataset as **CSV** or **JSON** using the **Export** dropdown in the header. The export respects all active filters, so you can narrow down to a date range or specific user before exporting. Exports are capped at 10,000 entries per download. @@ -75,7 +90,7 @@ The **Auditor** role provides read-only access to the audit log without granting Auditors **cannot** modify settings, manage users, deploy stacks, or perform any other administrative actions. This role is ideal for compliance officers, security reviewers, or team leads who need visibility into system activity without operational access. -To create an Auditor user, go to **Settings → Users** and select the **Auditor** role when creating a new user. +To create an Auditor user, go to **Settings > Users** and select the **Auditor** role when creating a new user. ## Configurable data retention @@ -83,10 +98,14 @@ Audit log entries are automatically cleaned up based on your configured retentio To change the retention period: -1. Go to **Settings → Developer → Data Retention** -2. Set the **Audit Log Retention** value (1–365 days) +1. Go to **Settings > Developer > Data Retention** +2. Set the **Audit Log Retention** value (1-365 days) 3. Click **Save Developer Settings** + + Data Retention settings showing Audit Log Retention set to 90 days + + Cleanup runs automatically as part of Sencho's periodic maintenance cycle. ## Security at rest diff --git a/docs/features/auto-update-policies.mdx b/docs/features/auto-update-policies.mdx index 6d9c9e82..ff9df405 100644 --- a/docs/features/auto-update-policies.mdx +++ b/docs/features/auto-update-policies.mdx @@ -9,9 +9,9 @@ description: "Automatically check for and apply container image updates on a sch ## Overview -Auto-Update Policies let you define schedules for Sencho to automatically check your container images for updates and apply them when new versions are available. Think of it as a built-in Watchtower — but integrated directly into your Sencho dashboard with full visibility into what was updated and when. +Auto-Update Policies let you define schedules for Sencho to automatically check your container images for updates and apply them when new versions are available. Think of it as a built-in Watchtower, integrated directly into your Sencho dashboard with full visibility into what was updated and when. -Each policy targets a specific stack and runs on a cron schedule. When triggered, Sencho: +Each policy targets a specific stack (or all stacks on a node) and runs on a cron schedule. When triggered, Sencho: 1. Inspects every container in the target stack 2. Compares local image digests against the remote registry @@ -22,7 +22,7 @@ Each policy targets a specific stack and runs on a cron schedule. When triggered Auto-Update Policies view showing the policies list -## Creating a Policy +## Creating a policy Navigate to **Auto-Update** in the sidebar and click **New Policy**. @@ -36,10 +36,13 @@ Fill in the following fields: |-------|-------------| | **Name** | A descriptive name for the policy (e.g., "Nightly media stack update") | | **Node** | The node where the target stack runs | -| **Stack** | The stack to monitor and update | -| **Schedule** | A cron expression or preset defining how often to check | +| **Stack** | The stack to monitor and update, or **All Stacks** to update every stack on the selected node | +| **Check Frequency** | A cron preset or custom cron expression defining how often to check | +| **Enabled** | Toggle to enable or disable the policy on creation | -### Schedule Presets +The Stack selector becomes available after choosing a node. Selecting **All Stacks** will check and update every stack on that node during each run. + +### Schedule presets For convenience, Sencho offers common schedule presets: @@ -52,68 +55,83 @@ For convenience, Sencho offers common schedule presets: | Weekly (Sunday 3 AM) | `0 3 * * 0` | Minimal disruption for stable stacks | | Custom | User-defined | Any valid cron expression | -## Filtering by Node +When using a preset, a human-readable description of the schedule is shown below the selector. Custom cron expressions are validated and described in real time. -In a multi-node environment, you can filter the policy list to show only policies targeting a specific node. Click the **calendar icon** on any node row in **Settings → Nodes** to jump directly to a filtered view. A filter bar at the top shows the active node, with a **Clear filter** button to return to the full list. +## Filtering by node -## Managing Policies +In a multi-node environment, you can filter the policy list to show only policies targeting a specific node. Click the **calendar icon** on any node row in **Settings > Nodes** to jump directly to a filtered view. A filter badge at the top shows the active node, with a **Clear filter** button to return to the full list. -Each policy in the list shows: +## Managing policies -- **Name** and target stack -- **Schedule** in human-readable form (e.g., "Every 6 hours") -- **Status** — enabled or disabled -- **Last run** — when it last executed and whether it succeeded -- **Next run** — when it will execute next +The policy list is displayed as a table with the following columns: -### Available Actions +| Column | Description | +|--------|-------------| +| **Name** | The policy name | +| **Stack** | Target stack name, or "All Stacks" for wildcard policies | +| **Schedule** | Human-readable description with the raw cron expression below | +| **Status** | Last run result: **Success** (green), **Failed** (red), or "Never run" | +| **Last Run** | Timestamp of the most recent execution | +| **Next Run** | When the policy will next execute | +| **Enabled** | Toggle switch to enable or disable the policy | +| **Actions** | Action buttons (see below) | -- **Toggle** — Enable or disable a policy without deleting it -- **Run Now** — Trigger an immediate check-and-update cycle -- **Edit** — Modify the policy name, target, or schedule -- **Delete** — Permanently remove the policy +### Available actions -## Run History +Each policy row has four action buttons: -Click the clock icon on any policy to view its run history. Each entry shows: +- **Run Now** (play icon) - Trigger an immediate check-and-update cycle without waiting for the next scheduled run +- **Execution History** (clock icon) - Open the run history panel for this policy +- **Edit** (pencil icon) - Modify the policy name, target, or schedule +- **Delete** (trash icon) - Permanently remove the policy and all its execution history after confirmation -- **Timestamp** — When the run started -- **Status** — Success or failure -- **Output** — Detailed log of what was checked and whether updates were applied +## Run history -This gives you full auditability over what changed and when. +Click the clock icon on any policy to open the run history panel. The history is displayed as a table with the following columns: -## How It Works +| Column | Description | +|--------|-------------| +| **Time** | When the run started | +| **Source** | Whether the run was triggered by the **Scheduler** or **Manual** (via Run Now) | +| **Status** | Success, Failed, or Running | +| **Duration** | How long the run took (in seconds) | +| **Details** | Output summary or error message | + +Run history is paginated at 20 entries per page. You can export the full history as CSV using the download button in the panel header. + +## How it works Under the hood, Auto-Update Policies are built on the same scheduling engine as [Scheduled Operations](/features/scheduled-operations). The key difference is that auto-update policies: - Are available to **Skipper** tier (Scheduled Operations requires Admiral) -- Always target a **stack** (not individual containers) +- Can target a single **stack** or **all stacks** on a node - Perform a **check-then-update** flow rather than a blind restart -### The Check-Then-Update Flow +### The check-then-update flow -1. **Enumerate images** — Sencho lists all unique images used by containers in the target stack -2. **Check digests** — For each image, Sencho compares the local `RepoDigests` against the remote registry manifest digest -3. **Conditional update** — Only if at least one image has a newer version does Sencho run `docker compose up -d` to pull and recreate -4. **Clear indicators** — After a successful update, the blue update indicator dot is automatically cleared +1. **Enumerate images** - Sencho lists all unique pullable images used by containers in the target stack +2. **Check digests** - For each image, Sencho compares the local digest against the remote registry manifest +3. **Conditional update** - Only if at least one image has a newer version does Sencho run `docker compose up -d` to pull and recreate +4. **Clear indicators** - After a successful update, the blue update indicator dot is automatically cleared +5. **Notify** - A notification is dispatched informing you which stack was updated and which images changed -If no updates are found, the run completes with a "No updates available" message and no containers are restarted. +If no updates are found, the run completes with an "all images up to date" message and no containers are restarted. -## Relationship to Image Update Detection +## Relationship to image update detection Sencho has two complementary features for keeping your images current: | Feature | Purpose | Tier | |---------|---------|------| -| **Image Update Detection** | Passive — shows a blue dot on stacks with available updates | All tiers | -| **Auto-Update Policies** | Active — automatically applies updates on a schedule | Skipper+ | +| **Image Update Detection** | Passive: shows a blue dot on stacks with available updates | All tiers | +| **Auto-Update Policies** | Active: automatically applies updates on a schedule | Skipper+ | Image Update Detection runs in the background every 6 hours and highlights stacks that have newer images available. Auto-Update Policies take this a step further by automatically applying those updates based on your defined schedule. -## Best Practices +## Best practices -- **Start with longer intervals** — Use "Daily at 3 AM" or "Weekly" for production stacks. Reserve shorter intervals for dev/staging environments. -- **Pin critical images** — If a stack uses `image: postgres:16.2` (pinned tag), auto-update will only detect updates to that exact tag. Use floating tags like `postgres:16` if you want minor version updates. -- **Monitor run history** — Check run history periodically to ensure updates are applying cleanly. Failed runs may indicate registry authentication issues or compose file problems. -- **Combine with notifications** — Sencho sends alert notifications when auto-updates are applied, so you stay informed even when updates happen automatically. +- **Start with longer intervals** - Use "Daily at 3 AM" or "Weekly" for production stacks. Reserve shorter intervals for dev/staging environments. +- **Pin critical images** - If a stack uses `image: postgres:16.2` (pinned tag), auto-update will only detect updates to that exact tag. Use floating tags like `postgres:16` if you want minor version updates. +- **Monitor run history** - Check run history periodically to ensure updates are applying cleanly. Failed runs may indicate registry authentication issues or compose file problems. +- **Use "All Stacks" carefully** - Wildcard policies update every stack on the node. This is convenient for dev environments but may be too aggressive for production. +- **Combine with notifications** - Sencho sends alert notifications when auto-updates are applied, so you stay informed even when updates happen automatically. diff --git a/docs/features/dashboard.mdx b/docs/features/dashboard.mdx index d26f64ce..49e2047f 100644 --- a/docs/features/dashboard.mdx +++ b/docs/features/dashboard.mdx @@ -1,60 +1,70 @@ --- title: Dashboard -description: Real-time system stats, historical metrics, and a quick-start converter for your host machine. +description: Real-time system stats, stack health, historical metrics, and recent alerts for your host machine. --- -The **Home** tab is the first thing you see after logging in. It shows a live snapshot of your host's health alongside container activity across all stacks. +The **Home** tab is the first thing you see after logging in. It provides a live overview of your node's health, resource usage, stack status, and recent alert activity. - Sencho dashboard showing container stats, system stats, and historical charts + Sencho dashboard showing health status, resource gauges, stack health table, and historical charts -## Container stats +## Health status bar -The top row summarises container state at a glance: +The top bar provides an at-a-glance health assessment for the active node. Sencho evaluates CPU, RAM, disk usage, exited containers, and unread error alerts to derive one of three states: + +| Status | Meaning | +|--------|---------| +| **Healthy** | All systems nominal. No resources above warning thresholds, no unread errors. | +| **Degraded** | At least one resource is above 80%, or there are unread error alerts. | +| **Critical** | At least one resource is above 90%, or there are exited containers with unread errors. | + +The bar also shows the active node name, the number of running containers, the current alert count, and a relative timestamp for the last data refresh. + +## Resource gauges + +Five compact cards display real-time host and container metrics: | Card | What it shows | |------|---------------| -| **Active Containers** | Running containers - broken down as `N managed · N external` | -| **Exited Containers** | Stopped or crashed containers | -| **Docker Network** | Current inbound/outbound network throughput across all containers | +| **CPU** | Current CPU usage percentage, core count, and a color-coded gauge bar | +| **Memory** | RAM usage percentage, used/total in GB, and a gauge bar | +| **Disk** | Disk usage percentage, used/total for the primary mount, and a gauge bar | +| **Containers** | Active container count (hover to see managed vs. external breakdown) and exited count | +| **Network** | Current RX (receive) and TX (transmit) throughput in bytes/second | -**Managed** means the container belongs to a stack in your `COMPOSE_DIR`. **External** means it exists on the Docker host but was started outside Sencho (e.g. by another Compose project or `docker run`). +Gauge bars turn yellow at 80% usage and red at 90%. -## System stats +## Stack health table -The second row shows host-level resource usage, polled every few seconds: +A table listing every stack in your `COMPOSE_DIR` with live status and resource usage: -| Card | What it shows | -|------|---------------| -| **Host CPU** | Current CPU usage percentage and core count | -| **Host RAM** | Used / total memory in GB and percentage | -| **Host Disk** | Used / total disk space for the primary mount point | +| Column | Description | +|--------|-------------| +| **Stack** | Stack name (derived from the directory name) | +| **Status** | `UP` (running) or `DN` (exited) | +| **CPU** | Aggregate CPU usage across all containers in the stack, normalized over host cores | +| **Memory** | Total memory allocated by the stack's containers | -When any value exceeds configured thresholds (set in **Settings → System Limits**), the card changes colour as a visual warning. +Click any row to navigate directly to that stack's editor. Stacks are sorted with running stacks first, then alphabetically. If you have more than 8 stacks, the table paginates automatically. ## Historical metrics charts -Two area charts display time-series data sampled at one-minute intervals, retained for up to 24 hours (configurable in **Settings → Developer**): +Two area charts display time-series data sampled at one-minute intervals, retained for up to 24 hours: -- **Normalized CPU Usage** - total CPU percentage across all managed containers, normalised over all host cores -- **Normalized RAM Usage** - total memory allocated by managed containers, in GB +- **CPU Usage** - normalized total CPU percentage across all managed containers over host cores +- **RAM Usage** - total memory allocated by managed containers, in GB -The x-axis shows time labels. Hover over a data point to see the exact value at that moment. +Hover over a data point to see the exact value at that moment. - Charts only show data from the moment Sencho started. If you just installed Sencho, they will be mostly empty until metrics accumulate. + Charts only show data from the moment Sencho started collecting. If you just installed Sencho, they will be mostly empty until metrics accumulate. -## Convert `docker run` to Compose +## Recent alerts -The bottom panel provides a quick converter: paste any `docker run` command and Sencho transforms it into a valid `docker-compose.yaml` snippet. +The bottom section displays triggered alert notifications sorted by recency. Each entry shows the severity level (info, warning, or error), the alert message, and a relative timestamp. -```bash -# Example input -docker run -d --name myapp -p 8080:80 -e TZ=UTC -v /data:/app/data nginx:latest -``` +Use the **Clear All Notifications** button to dismiss all alerts. If you have more than 8 alerts, the list paginates. -Click **Convert** and the output YAML appears ready to copy. You can then create a new stack and paste it into the editor. - -This is useful when migrating existing containers to managed Compose stacks without having to write YAML by hand. +Alert thresholds are configured per stack in **Settings > Notifications**. See [Alerts & Notifications](/features/alerts-notifications) for setup details. diff --git a/docs/features/editor.mdx b/docs/features/editor.mdx index 141e8dc6..2797fc7e 100644 --- a/docs/features/editor.mdx +++ b/docs/features/editor.mdx @@ -3,10 +3,10 @@ title: Editor description: Edit compose files and environment variables, and manage containers directly from the dashboard. --- -Selecting a stack opens the editor view - a split-pane layout with container management on the left and a full Monaco code editor on the right. +Selecting a stack opens the editor view, a two-column layout. The left column shows the command center (stack controls, containers, and an embedded terminal). The right column holds the Monaco code editor. - Editor view showing container panel and Monaco editor + Editor view showing command center on the left and Monaco editor on the right ## Compose file editor @@ -17,11 +17,13 @@ Click **Edit** to enter edit mode. Your changes are unsaved until you explicitly ### Save options -| Button | What it does | +The primary action button is **Save & Deploy**, which writes the file to disk and immediately runs `docker compose up -d`. A dropdown arrow next to it reveals additional options: + +| Action | What it does | |--------|--------------| -| **Save** | Writes the file to disk. Does not restart any containers. | -| **Save & Deploy** | Writes the file, then immediately runs `docker compose up -d`. Use this to apply compose changes in one step. | -| **Discard** | Reverts the editor to the last saved version. Unsaved changes are lost. | +| **Save & Deploy** | Writes the file, then runs `docker compose up -d` to apply changes immediately. | +| **Save Only** | Writes the file to disk without restarting any containers. | +| **Discard Changes** | Reverts the editor to the last saved version. Unsaved changes are lost. | ## Environment file editor @@ -35,34 +37,39 @@ The `.env` editor has the same save/discard controls as the compose editor. Chan ## Container panel -The left panel lists all containers that belong to the selected stack. Each container shows: +The left column lists all containers that belong to the selected stack under the **CONTAINERS** heading. Each container shows: -- **Status badge** - `running`, `exited`, `starting`, or `unhealthy` -- **Live stats** - CPU %, RAM usage, and network I/O updated every 1–2 seconds -- **Port mappings** - host:container port pairs (if any) +- **Status badge** - `running`, `exited`, `starting`, or `unhealthy` (hover for detailed status text) +- **Live stats** - CPU %, RAM usage, and network I/O displayed inline, updated every few seconds ### Container actions -Each container row has action buttons that appear on hover: +Each container row has action buttons on the right side: -| Button | Icon | What it does | -|--------|------|--------------| -| **Open App** | External link | Opens the container's web UI in a new tab (uses the first mapped port) | -| **View Live Logs** | Scroll text | Opens a live log stream modal for that container (available when running) | -| **Open Bash Terminal** | Terminal | Opens an interactive bash session inside the container (admin only, available when running) | +| Button | What it does | +|--------|--------------| +| **Open App** | Opens the container's web UI in a new tab (uses the detected web port). Only shown when a port is mapped. | +| **View Live Logs** | Opens a live log stream modal for that container. Only available when the container is running. | +| **Open Bash Terminal** | Opens an interactive bash session inside the container. Admin only, only available when running. | - Container action buttons on a running container + Container row showing status badge, live stats, and action buttons -### Log viewer +## Embedded terminal -The log viewer streams output from a single container in real-time using Server-Sent Events. Logs auto-scroll to the bottom as new lines arrive. Close the modal to stop the stream. +Below the container list, an embedded terminal streams the combined output from the stack's containers. This provides a persistent view of container logs without opening a separate modal. + +The terminal supports search (find text within the log output) and export (download the current log buffer). ### Container terminal (exec) -The terminal modal gives you an interactive bash shell inside the running container - equivalent to `docker exec -it bash`. It uses a full xterm.js emulator with color support and tab completion. +The terminal modal from the container action buttons gives you an interactive bash shell inside a running container, equivalent to `docker exec -it bash`. It uses a full xterm.js emulator with color support and tab completion. The container terminal requires the container to have `bash` (or `sh`) installed. Minimal images (e.g. Alpine-based) may need `sh` instead. + +## Log viewer + +The log viewer (opened from the container action buttons) streams output from a single container in real-time using Server-Sent Events. Logs auto-scroll to the bottom as new lines arrive. Close the modal to stop the stream. diff --git a/docs/features/fleet-backups.mdx b/docs/features/fleet-backups.mdx index 331087b9..a3176b7d 100644 --- a/docs/features/fleet-backups.mdx +++ b/docs/features/fleet-backups.mdx @@ -7,67 +7,72 @@ description: Snapshot compose files across all nodes for disaster recovery and a Fleet-Wide Backups require a Sencho Pro license. The feature is available to Pro admins in the Fleet View. -Create point-in-time snapshots of every `compose.yaml` and `.env` file across your entire fleet - local and remote nodes alike. Snapshots are stored centrally in Sencho's database and can be browsed, previewed, and restored at any time. +Create point-in-time snapshots of every `compose.yaml` and `.env` file across your entire fleet, local and remote nodes alike. Snapshots are stored centrally in Sencho's database and can be browsed, previewed, and restored at any time. ## Creating a snapshot 1. Navigate to **Fleet View** and select the **Snapshots** tab -2. Click **Create Snapshot** -3. Optionally enter a description (e.g. "Before v2 migration") -4. Click **Create** - Sencho captures files from every reachable node +2. Click **Create Snapshot** in the top-right corner +3. An inline form appears with an optional description field (e.g. "Before v2 migration") +4. Click **Create** to capture files from every reachable node - Create Snapshot dialog + Inline form for creating a fleet snapshot with an optional description field During creation, Sencho connects to each node in parallel: -- **Local nodes** - reads files directly from the compose directory -- **Remote nodes** - fetches files via the Distributed API proxy using the node's API token +- **Local nodes** are read directly from the compose directory +- **Remote nodes** are fetched via the Distributed API proxy using the node's API token -If a remote node is offline or unreachable, it is **skipped gracefully**. The snapshot is still created with data from all reachable nodes, and skipped nodes are recorded with the reason for the failure. +If a remote node is offline or unreachable, it is **skipped gracefully**. The snapshot still captures data from all reachable nodes, and skipped nodes are recorded with the reason for the failure. + +### Scheduled snapshots + +Fleet snapshots can also be created automatically on a recurring schedule. Navigate to the **Schedules** view, create a new scheduled operation, and select **Fleet Snapshot** as the action type. Scheduled snapshots appear in the snapshot list with a "Scheduled snapshot" prefix in their description. ## Browsing snapshots +The snapshot list shows each snapshot in a table with the following columns: + +- **Date** - when the snapshot was taken +- **Description** - your optional label, or a prefix like "Scheduled snapshot" for automated ones +- **Scope** - how many nodes and stacks were captured (e.g. "2 nodes, 22 stacks") +- **Warnings** - a warning icon with a count if any nodes were skipped, or "None" +- **Actions** - **View** to open the detail view, and a delete button for admins + - Snapshot list showing date, description, scope, and warnings + Snapshot list showing date, description, scope, warnings, and action buttons -The snapshot list shows: -- **Date** - when the snapshot was taken -- **Description** - your optional label -- **Scope** - how many nodes and stacks were captured -- **Warnings** - an indicator if any nodes were skipped +## Snapshot detail view -Click **View** to open the detail view, which presents a collapsible tree: +Click **View** on any snapshot to open the detail view. The header card displays the snapshot's title (or "Untitled Snapshot"), who created it, when, and badge counts for nodes and stacks captured. -``` -Node A (local) - ├── traefik/ - │ ├── compose.yaml - │ └── .env - └── postgres/ - └── compose.yaml -Node B (remote) - └── grafana/ - ├── compose.yaml - └── .env -``` +Below the header, each node appears as a collapsible card. Expand a node to see its stacks, then expand a stack to see individual files. Each file has a **Preview** button that renders the file contents inline. -Expand any file to preview its contents inline. + + Snapshot detail view showing a collapsible tree of nodes, stacks, and files with preview buttons + + +If any nodes were unreachable during snapshot creation, a warning banner appears at the top of the detail view listing each skipped node and the reason it was skipped. ## Restoring from a snapshot Admins can restore individual stacks from any snapshot: 1. Open a snapshot's detail view -2. Find the stack you want to restore -3. Click **Restore** -4. Optionally check **Redeploy stack after restore** to immediately apply the restored configuration -5. Confirm the action +2. Expand the node and stack you want to restore +3. Click **Restore** below the file list +4. A confirmation dialog appears. Optionally check **Redeploy stack after restore** to immediately apply the restored configuration. +5. Click **Restore** to confirm + + + Restore confirmation dialog with a redeploy checkbox + Sencho writes the snapshot's files back to the target node: -- **Local nodes** - files are written directly, and the current files are backed up first (creating a rollback point via the atomic deployment system) -- **Remote nodes** - files are pushed via the Distributed API proxy +- **Local nodes** have files written directly, with the current files backed up first (creating a rollback point via the atomic deployment system) +- **Remote nodes** receive files via the Distributed API proxy Restoring overwrites the current compose and environment files on the target node. If atomic deployments are enabled, the current files are backed up before restoration. @@ -75,17 +80,17 @@ Sencho writes the snapshot's files back to the target node: ## Deleting snapshots -Admins can delete snapshots from the list view. Deleting a snapshot permanently removes all captured file data from the database. This action cannot be undone. +Admins can delete snapshots from the list view by clicking the trash icon on the right side of each row. A confirmation dialog asks you to confirm before the snapshot is permanently removed. Deleting a snapshot removes all captured file data from the database. This action cannot be undone. ## Access control -| Action | Admin | Viewer | -|--------|-------|--------| -| View snapshot list | Yes | Yes | -| Browse snapshot contents | Yes | Yes | -| Create snapshot | Yes | No | -| Restore from snapshot | Yes | No | -| Delete snapshot | Yes | No | +| Action | Admin | Node Admin | Deployer | Auditor | Viewer | +|--------|-------|------------|----------|---------|--------| +| View snapshot list | Yes | Yes | Yes | Yes | Yes | +| Browse snapshot contents | Yes | Yes | Yes | Yes | Yes | +| Create snapshot | Yes | No | No | No | No | +| Restore from snapshot | Yes | No | No | No | No | +| Delete snapshot | Yes | No | No | No | No | ## Storage diff --git a/docs/features/fleet-view.mdx b/docs/features/fleet-view.mdx index f1af2130..489ef6e7 100644 --- a/docs/features/fleet-view.mdx +++ b/docs/features/fleet-view.mdx @@ -3,12 +3,26 @@ title: Fleet View description: Monitor all your nodes from a single dashboard with real-time health metrics, search, filtering, and container drill-down. --- -The **Fleet** tab gives you a bird's-eye view of every node in your Sencho deployment - local and remote - on one screen. It is available to all tiers, with advanced features unlocked by Sencho Pro. +The **Fleet** tab gives you a bird's-eye view of every node in your Sencho deployment, local and remote, on one screen. It is available to all tiers, with advanced features unlocked by Sencho Pro. - Fleet View showing health summary cards, toolbar, and node grid + Fleet Overview showing health summary cards, toolbar, node cards, and tabs +## Page layout + +The Fleet page is divided into two tabs: + +- **Overview** - the main monitoring view described on this page +- **Snapshots** - fleet-wide backup snapshots (covered in [Fleet Backups](/features/fleet-backups)) + +The header shows **Fleet Overview** with a subtitle summarising the current state (e.g. "2 of 2 nodes online, 31 containers, 21 stacks"). Two buttons sit in the top-right corner: + +| Button | What it does | +|--------|--------------| +| **Check Updates** | Opens the Node Updates modal to view and apply Sencho version updates across your fleet (Pro) | +| **Refresh** | Re-fetches data from all nodes. Shows a spinner while loading | + ## Community features Every Sencho installation gets the full fleet monitoring grid at no cost. @@ -21,13 +35,18 @@ Each node appears as a card showing: |------|-------------| | **Status badge** | Online (green) or Offline (grayed out) | | **Type badge** | `local` or `remote` | +| **Version badge** | The node's Sencho version (e.g. `v0.38.0`). Remote nodes running older versions that cannot report their version show no version badge | +| **Update available badge** | Orange pill shown when a newer Sencho version is available for this node | +| **Critical badge** | Red pill shown when CPU or disk usage exceeds 90% | | **Running containers** | Count of containers in `running` state | | **Stopped containers** | Count of containers in `exited` state | | **Stacks** | Total number of Compose stacks on the node | -| **CPU usage** | Current percentage with colour-coded bar (green → amber → red) | +| **CPU usage** | Current percentage with colour-coded bar (green to amber to red) | | **RAM usage** | Used / total with percentage bar | | **Disk usage** | Used / total with percentage bar | +Nodes with an available Sencho update also show an **Update to vX.Y.Z** button at the bottom of the card. + Offline nodes are visually dimmed and show a "Node unreachable" placeholder instead of stats. ### Manual refresh @@ -55,7 +74,7 @@ Four cards appear above the node grid, aggregating data across all online nodes: ### Auto-refresh -Fleet data automatically refreshes every 30 seconds. A subtle indicator at the bottom of the page confirms this is active. +Fleet data automatically refreshes every 30 seconds. A subtle indicator at the bottom of the page confirms this is active. When a node update is in progress, the refresh rate increases to every 5 seconds so you can watch status changes in near real-time. ### Search @@ -82,36 +101,57 @@ Filter pills let you narrow the grid: | Filter | Options | |--------|---------| -| **Status** | All · Online · Offline | -| **Type** | All Types · Local · Remote | +| **Status** | All, Online, Offline | +| **Type** | All Types, Local, Remote | | **Critical Only** | Show only nodes with CPU or disk above 90% | +| **Tags** | Filter by stack labels assigned to nodes | A "Clear filters" button appears when filters hide all nodes. ### Stack drill-down -Click **Stack details** on any online node card to expand the stack list. Each stack shows a count of its containers. +Click **Stack details** on any online node card to expand the stack list. The button shows the total stack count (e.g. "18 stacks"). Each stack in the list shows a container count badge. Click a stack name to expand it further and see individual containers with: - Container name - State badge (running, exited, restarting) -- Uptime (e.g. "Up 43 hours") +- Image name (e.g. `linuxserver/plex:latest`) +- Uptime (e.g. "Up 4 days") -Hover over any container row to reveal an **Open in editor** button that navigates you directly to that node's stack editor. +Hover over any container row to reveal an **Open in editor** button that navigates you directly to that stack's editor on the corresponding node. - Fleet View with stack expanded showing container details + Fleet View with Stack details expanded showing the stack list and a container drill-down ### Critical node detection Nodes with CPU or disk usage above 90% automatically receive a red **Critical** badge. Combined with the **Critical Only** filter, this lets you quickly triage overloaded servers. +### Node Updates + +Click **Check Updates** in the header to open the Node Updates modal. This lets you manage Sencho version updates across your entire fleet from one place. + + + Node Updates modal showing update status for all fleet nodes + + +The modal shows: + +- **Summary cards** at the top: counts of nodes that are Up to date, have updates Available, are currently Updating, or have Failed +- **Gateway version** label showing your primary instance's version +- **Filter** search box to find specific nodes +- **Node table** with columns: Node name, Type, Current version, Latest version, and Status (either an "Up to date" badge or an "Update" button) +- **Recheck** button to re-scan for available updates +- **Update All** button to trigger updates on all remote nodes that have a pending update + +When you click **Update** on a remote node, Sencho sends the update command and the node restarts with the new version. If you update the local node, a reconnection overlay appears while your primary instance restarts. + --- ## How fleet data is fetched -Fleet View queries all registered nodes in parallel. Each node responds independently - one slow or offline node does not block the others. Local node data comes from the Docker socket and system stats directly. Remote node data is fetched over the Distributed API proxy using each node's Bearer token. +Fleet View queries all registered nodes in parallel. Each node responds independently; one slow or offline node does not block the others. Local node data comes from the Docker socket and system stats directly. Remote node data is fetched over the Distributed API proxy using each node's Bearer token. Fleet View always runs on your primary (local) Sencho instance. It is never proxied through a remote node. diff --git a/docs/features/global-observability.mdx b/docs/features/global-observability.mdx index 2ad6c06f..088f9473 100644 --- a/docs/features/global-observability.mdx +++ b/docs/features/global-observability.mdx @@ -3,7 +3,7 @@ title: Global Observability description: A unified, searchable log stream from every container across all your stacks. --- -The **Logs** tab aggregates output from all running containers into a single scrollable view. Instead of tailing logs one container at a time, you see everything in one place - with filtering to focus on what matters. +The **Logs** tab aggregates output from all running containers into a single scrollable view. Instead of tailing logs one container at a time, you see everything in one place, with filtering to focus on what matters. Global Observability view showing real-time log lines from multiple containers @@ -11,48 +11,60 @@ The **Logs** tab aggregates output from all running containers into a single scr ## Log format -Each line shows: +Each line displays: -- **Timestamp** - when the log line was emitted -- **Stack name** - the Compose stack the container belongs to (colour-coded) -- **Container name** - the specific container -- **Level** - `INFO`, `WARN`, or `ERROR` (where detectable) -- **Message** - the raw log output +- **Timestamp** - when the log line was emitted (local time, 12-hour format) +- **Container name** - the specific container that produced the line, shown in brackets +- **Level** - `INFO`, `WARN`, or `ERROR` (where detectable), colour-coded for quick scanning +- **Message** - the raw log output, tinted red for `STDERR` lines + +`WARN` lines appear in amber, `ERROR` lines in red, and `INFO` lines in green so you can spot problems at a glance. ## Streaming modes -Sencho supports two modes for fetching logs, switchable via the **Developer mode** toggle: +Sencho supports two modes for fetching logs, controlled by the **Developer Mode** toggle in **Settings → Developer**: | Mode | How it works | Best for | |------|-------------|----------| -| **Standard** (default) | Polls all containers every N seconds (configurable in Settings → Developer) | General use; lower overhead | -| **Developer mode** | Server-Sent Events stream; logs arrive as they are emitted | Debugging; watching a specific event in real-time | +| **Standard** (default) | Polls all containers on a configurable interval | General use; lower overhead | +| **Developer mode** | Server-Sent Events (SSE) stream; logs arrive as they are emitted | Debugging; watching events in real time | -The default polling interval is 5 seconds. You can change it to 1, 3, 5, or 10 seconds in **Settings → Developer → Global Logs Refresh Rate**. +When Developer Mode is active, a pulsing green **● LIVE** indicator appears in the toolbar to confirm the SSE stream is connected. + +The default polling interval is 5 seconds. You can change it to 1, 3, 5, or 10 seconds in **Settings → Developer → Standard Log Polling Rate**. This setting is disabled while Developer Mode is active because SSE streaming replaces polling entirely. ## Filtering logs -Use the controls above the log panel to narrow what you see: +Use the controls in the toolbar above the log panel to narrow what you see: | Control | What it does | |---------|-------------| -| **Stack filter** | Multi-select dropdown - show only logs from chosen stacks | -| **Stream** | `ALL` / `STDOUT` / `STDERR` - filter by output stream | -| **Search** | Full-text filter on the message field (case-insensitive) | +| **Search** | Full-text filter across the message, container name, and stack name (case-insensitive) | +| **Stacks** | Checkbox dropdown; select one or more stacks to show only their containers' logs. Displays "All" when nothing is selected. | +| **All Streams** | Filter by output stream: `All Streams`, `STDOUT`, or `STDERR` | -Filters combine - you can show only `STDERR` from a specific stack while searching for a keyword. +Filters combine. For example, you can show only `STDERR` from a specific stack while searching for a keyword. ## Controls | Button | What it does | |--------|-------------| -| **Clear** | Clears the current log buffer in the UI (does not delete logs from Docker) | -| **Auto-scroll** toggle | When enabled, the view scrolls to the bottom as new lines arrive | +| **Clear** (trash icon) | Clears the current log buffer in the UI. Does not delete logs from Docker. | +| **Download** (download icon) | Exports the currently filtered logs as a `.txt` file. The filename includes a timestamp for easy identification. | -## Capacity limits +## Auto-scroll -To avoid browser memory issues, the log view keeps a maximum of **2,000 entries** in memory at a time. Older entries are dropped as new ones arrive. For deeper investigation, use the [per-container log viewer](/features/editor#log-viewer) in the Editor tab, or `docker compose logs` directly from the [Host Console](/features/host-console). +The log view automatically scrolls to the bottom as new lines arrive. If you scroll up to inspect older entries, auto-scroll pauses so you are not pulled away. Scrolling back to the bottom re-enables it. + +## Display limits + +To keep the browser responsive, the log viewer enforces two capacity limits: + +- **Memory buffer** - a maximum of 2,000 log entries are held in memory at a time. Older entries are dropped as new ones arrive. +- **Rendered rows** - only the most recent 300 entries from the filtered set are rendered as DOM nodes. If more entries match, a notice appears at the top of the log area showing how many entries exist versus how many are displayed. + +For deeper investigation, use the [per-container log viewer](/features/editor#log-viewer) in the Editor tab, or `docker compose logs` directly from the [Host Console](/features/host-console). - Log retention on the backend is controlled by **Settings → Developer → Log Retention Days** (default: 30 days). This affects historical logs stored in Sencho's database, not the live stream. + Log data retention on the backend is controlled by **Settings → Developer → Notification Log Retention** (default: 30 days). This affects historical notification and alert logs stored in Sencho's database, not the live container stream shown here. diff --git a/docs/features/host-console.mdx b/docs/features/host-console.mdx index c888e824..129aa9fc 100644 --- a/docs/features/host-console.mdx +++ b/docs/features/host-console.mdx @@ -6,62 +6,60 @@ description: An interactive terminal on your host OS, directly in the browser - The **Console** tab opens a full interactive terminal session on the machine running Sencho. It behaves exactly like an SSH session, but without needing an SSH server, client, or key management. - The Host Console requires a **Sencho Admiral** license. Community and Skipper users see an upgrade prompt instead. [Learn more about licensing](/features/licensing). + The Host Console requires a **Sencho Admiral** license. Community and Skipper users will not see the Console tab in the navigation bar. [Learn more about licensing](/features/licensing). - Host Console showing a PowerShell prompt inside the Sencho container working directory + Host Console showing a PowerShell prompt in the COMPOSE_DIR working directory ## What it is -The host console spawns a real PTY (pseudo-terminal) process on the Sencho host using `node-pty`. Your keystrokes are sent over a WebSocket and the terminal output is streamed back in real-time. The terminal emulator is [xterm.js](https://xtermjs.org/), the same engine used by VS Code's built-in terminal. +The Host Console gives you a real terminal session on the Sencho host, streamed to your browser over a WebSocket. It supports: -Features: - Full colour and cursor support -- Tab completion (via the host shell) -- Scrollback buffer (10,000 lines) +- Tab completion (provided by the host shell) - Automatic terminal resizing when you resize the browser window - Copy and paste +- Cursor blinking ## Opening the console -Click **Console** in the top navigation bar. The session starts immediately in the stack's working directory if a stack is selected, otherwise in the `COMPOSE_DIR` root. +Click **Console** in the top navigation bar. The session starts immediately in the `COMPOSE_DIR` root. If a stack is selected in the sidebar, the terminal opens directly inside that stack's directory instead. -The header shows the connection status (**Connected** in green) and which node the console is attached to. +The header bar shows: -Click **Close Console** to end the session and terminate the shell process on the host. +- **Host Console** label with a terminal icon +- The active **node name** (e.g. "Local" or a remote node) +- The **stack name** in parentheses, if one is selected +- A green **Connected** badge while the WebSocket session is active +- A **Close Console** button on the right to end the session + +Clicking **Close Console** terminates the shell process on the host and disconnects the WebSocket. ## Shell type -The shell depends on the host OS: -- **Linux/macOS hosts:** `bash` or `sh` -- **Windows hosts (Docker Desktop):** PowerShell (as shown in the screenshot - the console opens inside the Sencho container's Windows environment) +The shell depends on the host operating system: + +- **Linux / macOS hosts:** `bash` (falls back to `sh` if bash is not available) +- **Windows hosts:** PowerShell + +In a typical Docker deployment, the Sencho container runs Linux, so the console opens a `bash` shell regardless of the Docker host's OS. The PowerShell prompt shown in the screenshot above reflects a native Windows development environment. ## Availability -The Host Console is available to **admin** users on the **Admiral** tier. Access is enforced at every layer: +The Host Console is available to **admin** users on the **Admiral** tier. If your instance is on the Community or Skipper tier, the Console tab does not appear in the navigation bar at all. Attempting to access the console endpoint directly without the correct license is rejected. -- **UI:** The Console tab only appears in the navigation bar for Admiral-licensed admin users. -- **API:** The `POST /api/system/console-token` endpoint returns `403 Forbidden` without an Admiral license. -- **WebSocket:** The `/api/system/host-console` upgrade handler rejects connections without an Admiral license. +## Security considerations -### What Community and Skipper users see +The Host Console has stricter access requirements than other features: -If you are on the Community or Skipper tier, navigating to the Console view shows an upgrade prompt with a link to the [pricing page](https://sencho.io/pricing). The Console tab is hidden from the navigation bar entirely. - -## Security model - -The host console has a stricter authentication requirement than other features: - -- Requires a valid **browser session** (httpOnly cookie). Node-proxy tokens used for multi-node communication are explicitly blocked. -- Each session is issued a short-lived **console token** (60-second TTL) before the WebSocket is established. -- Access is restricted to the **Admiral** license tier, ensuring only teams with appropriate licensing can use interactive shell access. -- Sensitive environment variables (names containing SECRET, PASSWORD, TOKEN, KEY, or CREDENTIAL, plus `DATABASE_URL`) are automatically stripped from the console environment so they cannot be read via `env` or `printenv`. -- Because the console gives full shell access to the host, you should secure your Sencho instance with HTTPS and a strong password if it is exposed to a network. +- **Browser sessions only.** API tokens used for multi-node communication cannot open a console session. +- **Admiral license required.** The license check is enforced at every layer, not just in the UI. +- **Sensitive environment variables are stripped.** Environment variables whose names suggest secrets (passwords, tokens, keys, credentials) and certain well-known database connection strings are automatically removed from the console environment. Running `env` or `printenv` inside the console will not reveal them. - The host console provides unrestricted shell access to the machine running Sencho. Do not expose Sencho on a public network without HTTPS and strong authentication. + The Host Console provides unrestricted shell access to the machine running Sencho. Do not expose Sencho on a public network without HTTPS and strong authentication. ## Common uses diff --git a/docs/features/licensing.mdx b/docs/features/licensing.mdx index 7162bd21..90e8278d 100644 --- a/docs/features/licensing.mdx +++ b/docs/features/licensing.mdx @@ -1,12 +1,12 @@ --- title: Licensing & Billing -description: How Sencho Pro licensing works - trials, activation, and subscription management. +description: How Sencho licensing works, including trials, activation, and subscription management. --- -Sencho uses an open-core model. The **Community** tier is free forever with unlimited nodes. **Pro** unlocks advanced features like fleet management, RBAC, webhooks, atomic deployments, and fleet-wide backups. +Sencho uses an open-core model. The **Community** tier is free forever with unlimited nodes. Paid tiers unlock advanced features: **Skipper** for solo operators and **Admiral** for teams. - *Our tier names are inspired by the meaning of Sencho (船長) — because you're the captain of your container fleet.* + *Our tier names are inspired by the meaning of Sencho (船長), because you're the captain of your container fleet.* ## Plans @@ -19,9 +19,25 @@ Sencho uses an open-core model. The **Community** tier is free forever with unli Lifetime pricing is an early-adopter offer available for a limited time only. +### Feature breakdown + +**Skipper** includes everything in Community, plus: +- Fleet View with drill-down +- Webhooks and stack labels +- Atomic deployments and fleet-wide backups +- Auto-update policies + +**Admiral** includes everything in Skipper, plus: +- Unlimited admin and viewer accounts +- Scoped RBAC (deployer, node-admin, auditor roles) +- SSO, audit log, and host console +- API tokens and private registries +- Notification routing +- Scheduled operations + ## Free trial -Every new Sencho installation starts with a **14-day Skipper trial** - no license key or credit card required. Skipper features like fleet management, RBAC viewer accounts, webhooks, and atomic deployments are unlocked during the trial so you can evaluate them with your real infrastructure. Admiral features (SSO, audit log, host console, unlimited accounts) require an Admiral license. +Every new Sencho installation starts with a **14-day Skipper trial**. No license key or credit card is required. Skipper features like fleet management, webhooks, atomic deployments, and auto-update policies are unlocked during the trial so you can evaluate them with your real infrastructure. Admiral-exclusive features (SSO, audit log, host console, scoped RBAC, unlimited accounts) require an Admiral license. When the trial expires, Sencho automatically reverts to the Community tier. No data is lost. @@ -30,13 +46,13 @@ When the trial expires, Sencho automatically reverts to the Community tier. No d You can upgrade directly from **Settings > License** in your Sencho dashboard. The upgrade cards shown depend on your current tier: - **Community users** see both **Skipper** and **Admiral** options with feature highlights and direct checkout links. -- **Skipper users** see an **Admiral** upgrade card for when you need unlimited accounts. -- **Admiral users** are on the highest tier - no upgrade cards are shown. +- **Skipper users** see an **Admiral** upgrade card for when you need unlimited accounts and team features. +- **Admiral users** are on the highest tier, so no upgrade cards are shown. -Clicking an upgrade button opens the Lemon Squeezy checkout in a new tab. After completing the purchase, you'll receive a license key by email. +Clicking an upgrade button opens the Lemon Squeezy checkout in a new tab. After completing the purchase, you will receive a license key by email. - License settings showing upgrade cards for Skipper and Admiral + License settings showing Skipper and Admiral upgrade cards for Community users ## Activating your license @@ -45,7 +61,7 @@ Clicking an upgrade button opens the Lemon Squeezy checkout in a new tab. After 2. Paste your key into the **License Key** field at the bottom of the page. 3. Click **Activate**. -Sencho validates the key against Lemon Squeezy and activates Pro features immediately. +Sencho validates the key against Lemon Squeezy and unlocks your tier's features immediately. ## License validation @@ -53,11 +69,18 @@ Active licenses are re-validated every **72 hours** against the Lemon Squeezy AP ## Managing your subscription -To manage your subscription (update payment method, view invoices, cancel, or switch plans), visit the [Lemon Squeezy customer portal](https://app.lemonsqueezy.com/my-orders) or use the link in your purchase confirmation email. +Once your license is active, you can manage your subscription in two ways: + +- **From the License page:** Go to **Settings > License** and click **Manage Subscription**. This opens the Lemon Squeezy billing portal where you can update your payment method, view invoices, cancel, or switch plans. +- **From the profile menu:** Click your profile icon in the top bar and select **Billing** for quick access to the same portal. + + + License settings showing an active Admiral subscription with Manage Subscription button + ## Multi-node license enforcement -If you manage multiple servers through Sencho's [multi-node feature](/features/multi-node), you only need a license on your **primary instance**. All remote nodes automatically inherit the primary's license tier for proxied requests — no per-node activation required. +If you manage multiple servers through Sencho's [multi-node feature](/features/multi-node), you only need a license on your **primary instance**. All remote nodes automatically inherit the primary's license tier for proxied requests. No per-node activation is required. For details on how this works, see [License enforcement across nodes](/features/multi-node#license-enforcement-across-nodes). diff --git a/docs/features/multi-node.mdx b/docs/features/multi-node.mdx index b85141ff..55f54474 100644 --- a/docs/features/multi-node.mdx +++ b/docs/features/multi-node.mdx @@ -3,7 +3,7 @@ title: Multi-Node Management description: Connect multiple Sencho instances and manage all your servers from a single dashboard. --- -Sencho's multi-node feature lets you manage Docker Compose stacks on multiple servers - all from the same browser tab. Each server runs its own Sencho instance, and your primary instance acts as a transparent proxy to the others. +Sencho's multi-node feature lets you manage Docker Compose stacks on multiple servers, all from the same browser tab. Each server runs its own Sencho instance, and your primary instance acts as a transparent proxy to the others. Node Manager showing a local and a remote node, both Online @@ -15,16 +15,16 @@ There is no central server. Each Sencho instance manages its own host independen ## The local node -Your primary Sencho installation is always listed as **Local**. It is the default node, marked with a star, and cannot be deleted. All operations on the local node run directly against the host's Docker socket. +Your primary Sencho installation is always listed as **Local**. It is the default node, marked with a star icon, and cannot be deleted. All operations on the local node run directly against the host's Docker socket. ## Adding a remote node ### Step 1: Generate a token on the remote machine -On the **remote** Sencho instance (the server you want to add), open **Settings → Nodes** and click **Generate Token**. Copy the generated token - you'll only see it once. +On the **remote** Sencho instance (the server you want to add), open **Settings → Nodes**. You will see a **Generate Node Token** section at the top of the page. Click **Generate Token**, then copy the token that appears. You will only see it once. - The token is a long-lived JWT scoped to `node_proxy`. Anyone with this token can fully control that Sencho instance, so treat it like a password. + The token is a long-lived credential that grants full control over that Sencho instance. Treat it like a password. ### Step 2: Add the node on your primary instance @@ -32,17 +32,18 @@ On the **remote** Sencho instance (the server you want to add), open **Settings On your **primary** Sencho instance, open **Settings → Nodes** and click **+ Add Node**. Fill in: - Add Node form with Name, Type, API URL, and Token fields + Add Node form with Name, Type, API URL, Token, and Compose Directory fields | Field | Description | |-------|-------------| -| **Name** | A display name (e.g. `prod-server`, `media-box`) | -| **Type** | Select **Remote** | -| **Sencho API URL** | The full HTTP/HTTPS URL of the remote instance (e.g. `http://192.168.1.20:3001`) | +| **Name** | A display name (e.g. `Production VPS`, `media-box`) | +| **Type** | Select **Remote** (or **Local** for an additional local Docker socket) | +| **Sencho API URL** | The full HTTP/HTTPS URL of the remote instance (e.g. `http://192.168.1.50:3000`) | | **API Token** | The token you generated in Step 1 | +| **Compose Directory** | The root directory where compose stack folders live on the remote node (defaults to `/app/compose`) | -Click **Create**. Sencho immediately tests the connection and shows the result. +Click **Add Node**. Sencho immediately tests the connection and shows the result. ### Step 3: Verify connectivity @@ -51,28 +52,16 @@ A successful connection shows the remote node as **Online** with a green badge. - The API URL is correct (include the port if non-standard) - The token was copied correctly without extra whitespace -Click the **wifi icon** (test connection) on any node row at any time to re-check status. - -## The 1:1 path rule for remote nodes - -The Compose directory path matters on remote nodes too. When you register a remote node, its `COMPOSE_DIR` is whatever that remote instance was configured with. Make sure the remote Sencho's `COMPOSE_DIR` follows the [1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule) on that remote host. +Click the **wifi icon** (Test Connection) on any node row at any time to re-check status. A successful test shows a **Connection Details** panel below the table with information about the remote instance, including its OS, architecture, container count, and Sencho version. ## Switching between nodes -The **node switcher** dropdown in the top-left of the sidebar shows the currently active node. Click it to switch to any registered node. All views - dashboard stats, stack list, editor, resources, logs - immediately reflect the selected node. +The **node switcher** dropdown in the top-left of the sidebar shows the currently active node and its Sencho version. Click it to switch to any registered node. All views (dashboard stats, stack list, editor, resources, logs) immediately reflect the selected node. Node switcher dropdown expanded showing available nodes -Node status indicators: - -| Indicator | Meaning | -|-----------|---------| -| Green dot | Node is reachable and responding | -| Red dot | Node is unreachable | -| Gray dot | Status not yet checked | - ## Per-node scheduling and update indicators The Nodes table surfaces scheduling and update status at a glance for each node: @@ -86,7 +75,7 @@ The Nodes table surfaces scheduling and update status at a glance for each node: | **Schedules** | Number of active scheduled tasks targeting this node, plus a relative countdown to the next run (e.g. "next 2h") | | **Updates** | Whether auto-update policies are enabled ("Auto" badge), and how many stacks have pending image updates (pulsing blue dot with count) | -Click the **calendar icon** on any node row to jump directly to the Schedules view filtered to that node. From there you can create, edit, or manage scheduled tasks scoped to the selected node. The filter bar shows which node you're viewing, with a **Clear filter** button to return to the full list. +Click the **calendar icon** on any node row to jump directly to the Schedules view filtered to that node. From there you can create, edit, or manage scheduled tasks scoped to the selected node. The filter bar shows which node you are viewing, with a **Clear filter** button to return to the full list. When a node is deleted, all scheduled tasks and update status data associated with it are automatically cleaned up. @@ -96,17 +85,17 @@ When you have a paid license (Skipper or Admiral) on your primary instance, all ### How it works -Your primary Sencho instance asserts its license tier to remote nodes on every proxied request. Remote nodes trust this assertion because it arrives alongside a valid node proxy token — the same token you configured when adding the node. No additional configuration is required. +Your primary Sencho instance asserts its license tier to remote nodes on every proxied request. Remote nodes trust this assertion because it arrives alongside the valid node token you configured when adding the node. No additional configuration is required. This means: -- **Paid primary → remote nodes**: Pro and Admiral features work on all remote nodes, governed by the primary instance's license. -- **Community primary → remote nodes**: Pro-gated features are blocked on remote nodes, even if a remote node has its own paid license. The primary's tier is authoritative for proxied requests. +- **Paid primary → remote nodes**: Skipper and Admiral features work on all remote nodes, governed by the primary instance's license. +- **Community primary → remote nodes**: Paid features are blocked on remote nodes, even if a remote node has its own paid license. The primary's tier is authoritative for proxied requests. - **Direct access to a node**: If you access a remote Sencho instance directly (not through the primary), it uses its own local license tier as usual. ### Why this matters -Without this trust chain, remote nodes would default to the Community tier and block Pro/Admiral features — even though the primary instance has a valid paid license. Distributed license enforcement eliminates this gap so your fleet behaves consistently regardless of which node you're operating on. +Without this trust chain, remote nodes would default to the Community tier and block paid features, even though the primary instance has a valid license. Distributed license enforcement eliminates this gap so your fleet behaves consistently regardless of which node you are operating on. Remote nodes do not need their own license keys. A single license on the primary instance covers all nodes managed through it. @@ -114,22 +103,21 @@ Without this trust chain, remote nodes would default to the Community tier and b ## Editing and deleting nodes -Click the **pencil icon** on any remote node row to edit its name, URL, or token. Click the **trash icon** to remove it. The local node cannot be edited or deleted. +Click the **pencil icon** on any node row to edit its name, URL, token, or compose directory. Click the **trash icon** to remove a remote node. The local (default) node cannot be deleted. ## Security ### Token security -Node tokens are JWTs with a configurable expiry that grant full control over the remote Sencho instance. Treat them like passwords: +Node tokens grant full control over the remote Sencho instance. Treat them like passwords: -- **Rotate immediately** if a token is compromised: Settings → Nodes → Generate Token on the remote instance. The old token is invalidated instantly. -- Tokens have a configurable expiry. Generate a new token on the remote instance to renew access. -- Tokens are **encrypted at rest** in Sencho's database. Even if the database file is extracted, the tokens cannot be read without the instance's encryption key. -- Tokens are scoped to `node_proxy` — they cannot access the host console or container exec terminals. Interactive shell access always requires a real browser session on that specific instance. +- **Rotate immediately** if a token is compromised: go to the remote instance's **Settings → Nodes** and click **Generate Token**. The old token is invalidated instantly. +- Tokens are **encrypted at rest** in Sencho's database. +- Tokens cannot be used to open interactive terminals (Host Console or container exec). Interactive shell access always requires a real browser session on that specific instance. ### Transport encryption -Sencho delegates transport encryption to your infrastructure rather than implementing TLS at the application layer. This is the same approach used by [Dockge](https://github.com/louislam/dockge) and other self-hosted tools — it avoids certificate management burden while letting you use the encryption layer that best fits your environment. +Sencho delegates transport encryption to your infrastructure rather than implementing TLS at the application layer. This is the same approach used by other self-hosted tools; it avoids certificate management burden while letting you use the encryption layer that best fits your environment. **Never send node tokens over plain HTTP across the public internet.** A token intercepted in transit grants full control of the remote instance. Always use one of the approaches below when nodes communicate over untrusted networks. @@ -145,7 +133,7 @@ There are three recommended approaches depending on your deployment: #### Private network (LAN or VPC) -If all your Sencho instances are on the same local network, VPC, or subnet — HTTP is perfectly fine. The token never leaves the private network, so there is no interception risk. +If all your Sencho instances are on the same local network, VPC, or subnet, HTTP is perfectly fine. The token never leaves the private network, so there is no interception risk. ``` http://192.168.1.50:3000 ← safe on a private LAN @@ -155,7 +143,7 @@ http://10.0.1.20:3000 ← safe inside a VPC #### VPN tunnel (WireGuard, Tailscale) - This is the simplest approach for connecting nodes across the internet. A VPN encrypts all traffic between your servers at the network layer — no certificate management required. + This is the simplest approach for connecting nodes across the internet. A VPN encrypts all traffic between your servers at the network layer, with no certificate management required. With a mesh VPN like [Tailscale](https://tailscale.com) or [WireGuard](https://www.wireguard.com/), each server gets a private IP on the VPN. Use those IPs as your Sencho API URLs: @@ -164,11 +152,11 @@ With a mesh VPN like [Tailscale](https://tailscale.com) or [WireGuard](https://w http://100.64.0.2:3000 ← Tailscale IP, encrypted by the VPN tunnel ``` -All traffic between nodes is encrypted by the VPN — Sencho does not need to do anything additional. +All traffic between nodes is encrypted by the VPN. Sencho does not need to do anything additional. #### Reverse proxy (Caddy, Nginx, Traefik) -If you prefer TLS termination at each node, place a reverse proxy in front of each Sencho instance. [Caddy](https://caddyserver.com/) is the simplest option — it auto-provisions HTTPS certificates from Let's Encrypt with zero configuration: +If you prefer TLS termination at each node, place a reverse proxy in front of each Sencho instance. [Caddy](https://caddyserver.com/) is the simplest option; it auto-provisions HTTPS certificates from Let's Encrypt with zero configuration: ```text Caddyfile @@ -205,6 +193,6 @@ https://sencho.example.com ← TLS terminated by Caddy/Nginx ### Why Sencho doesn't implement application-layer TLS -Some tools auto-generate self-signed TLS certificates between their server and agents (e.g. Portainer's standard agent). In practice, this provides minimal security benefit — the certificates are self-signed with no verification, meaning they don't protect against man-in-the-middle attacks. It is effectively security theater. +Some tools auto-generate self-signed TLS certificates between their server and agents. In practice, this provides minimal security benefit because the certificates are self-signed with no verification, meaning they do not protect against man-in-the-middle attacks. -Sencho takes a deliberate approach: infrastructure-level encryption (VPN, reverse proxy, or private networking) is more robust, easier to manage, and doesn't impose certificate rotation burden on the user. This is the same model used by Dockge, Yacht, and other self-hosted orchestrators. +Sencho takes a deliberate approach: infrastructure-level encryption (VPN, reverse proxy, or private networking) is more robust, easier to manage, and does not impose certificate rotation burden on the user. This is the same model used by other self-hosted orchestrators. diff --git a/docs/features/node-compatibility.mdx b/docs/features/node-compatibility.mdx index f6d9580e..ed99bb32 100644 --- a/docs/features/node-compatibility.mdx +++ b/docs/features/node-compatibility.mdx @@ -1,33 +1,33 @@ --- title: Node Compatibility -description: How Sencho handles version differences across nodes and gracefully degrades features that aren't available on older instances. +description: How Sencho handles version differences across nodes and gracefully degrades features that are not available on older instances. --- -When you manage multiple nodes, each running its own Sencho instance, those instances may be on different versions. A node running v0.28 won't have features that shipped in v0.31. Sencho detects this automatically and disables features that the active node doesn't support — no errors, no broken pages. +When you manage [multiple nodes](/features/multi-node), each running its own Sencho instance, those instances may be on different versions. A node running an older version will not have features that shipped in a newer release. Sencho detects this automatically and disables features that the active node does not support, with no errors or broken pages. ## How it works -Every Sencho instance exposes a `/api/meta` endpoint that returns its version and a list of **capabilities** — feature flags describing what that instance supports. When you switch to a node, your primary instance fetches this metadata and caches it for 5 minutes. +Every Sencho instance advertises a set of **capabilities**: feature flags describing what it supports. When you switch to a node, your primary instance fetches this metadata and caches it briefly. Features that require a capability the active node does not have are visually dimmed with an explanation overlay. -Features that require a capability the active node doesn't have are visually dimmed with an explanation overlay. Core features like stack management, containers, and resource monitoring are always available on every Sencho version. +Core features like stack management, containers, and resource monitoring are always available on every Sencho version. -## What you'll see +## What you will see ### Version in the node switcher -The sidebar node switcher shows each node's Sencho version next to its name. If a node is too old to report its version (pre-compatibility era), no version is shown. +The sidebar node switcher shows each node's Sencho version next to its name. If a node is too old to report its version, no version is shown. ### Disabled features -When you switch to a node that lacks a capability, the affected feature appears dimmed with a pill overlay explaining why: +When you switch to a node that lacks a capability, the affected feature appears dimmed and blurred with a pill overlay explaining why. For example: -> **Fleet Management** is not available — prod-server is running v0.28.0 +> "Fleet Management is not available - prod-server is running v0.28.0" -The feature content is still visible (blurred) so you can see what you're missing, but it's non-interactive. Switch to a node that supports the feature, or update the remote node to the latest Sencho version. +The feature content is still visible (blurred) so you can see what you are missing, but it is non-interactive. Switch to a node that supports the feature, or update the remote node to the latest Sencho version. ### Connection test details -When you test a remote node's connection in **Settings > Nodes**, the result now includes the remote Sencho version alongside Docker info, container counts, and system stats. +When you test a remote node's connection in **Settings → Nodes**, the result includes the remote Sencho version alongside Docker info, container counts, and system stats. ## Capability list @@ -55,19 +55,20 @@ Every Sencho release includes a static list of capabilities. Here are the capabi | `api-tokens` | API token management | | `users` | User management | | `registries` | Private registry management | +| `self-update` | Self-update from the dashboard | - Capabilities are flag-based, not version-based. Sencho never compares version numbers — it checks whether the remote node explicitly advertises support for a feature. This means the system stays forward-compatible as new features are added. + Capabilities are flag-based, not version-based. Sencho never compares version numbers; it checks whether the remote node explicitly advertises support for a feature. This means the system stays forward-compatible as new features are added. ## Handling older nodes -Nodes running a Sencho version from before the compatibility system was introduced (pre-v0.32) don't have the `/api/meta` endpoint. Sencho handles this gracefully: +Nodes running a Sencho version from before the compatibility system was introduced do not have the metadata endpoint. Sencho handles this gracefully: - The version shows as blank in the node switcher - All gated features appear as unavailable on that node - Core features (stacks, containers, resources, logs) work normally -- No errors are thrown — the UI degrades cleanly +- No errors are thrown; the UI degrades cleanly The fix is straightforward: update the remote node to the latest Sencho version. See the [upgrade guide](/operations/upgrade) for instructions. @@ -75,7 +76,7 @@ The fix is straightforward: update the remote node to the latest Sencho version. Some features require both a license tier (Skipper or Admiral) **and** node capability support. When both gates apply: -1. The license gate is checked first — if you're on the Community tier, you see the upgrade prompt -2. If your license covers the feature but the node doesn't support it, you see the compatibility overlay instead +1. The license gate is checked first. If you are on the Community tier, you see the upgrade prompt. +2. If your license covers the feature but the node does not support it, you see the compatibility overlay instead. -This means you won't see confusing "upgrade to unlock" messages for features that wouldn't work on the active node anyway. +This means you will not see confusing "upgrade to unlock" messages for features that would not work on the active node anyway. diff --git a/docs/features/notification-routing.mdx b/docs/features/notification-routing.mdx index 3d5badab..19023618 100644 --- a/docs/features/notification-routing.mdx +++ b/docs/features/notification-routing.mdx @@ -4,67 +4,69 @@ description: Route stack alerts to specific Discord, Slack, or webhook channels --- - Notification Routing requires a **Sencho Admiral** license. Community and Skipper users can configure global notification channels in **Settings → Notifications**. + Notification Routing requires a **Sencho Admiral** license. Community and Skipper users can configure global notification channels in **Settings > Notifications**. Notification Routing lets you direct alerts from specific stacks to dedicated channels. Instead of all alerts going to a single global endpoint, you can send production alerts to one Slack channel and staging alerts to another. - Notification Routing settings with a configured route + Notification Routing settings showing the empty state with Add Route button ## How routing works When Sencho dispatches an alert (container crash, threshold breach, scheduled task failure), the routing engine: -1. **Checks routing rules** — sorted by priority (lowest number first). If the alert's stack matches a rule's stack list, the notification is sent to that rule's channel. -2. **Falls back to global agents** — if no routing rule matches (or the alert has no stack context, such as host resource warnings), the notification goes to the global channels configured in **Settings → Notifications**. +1. **Checks routing rules** sorted by priority (lowest number first). If the alert's stack matches a rule's stack list, the notification is sent to that rule's channel. +2. **Falls back to global channels** if no routing rule matches (or the alert has no stack context, such as host resource warnings). Global channels are configured in **Settings > Notifications**. -Routing rules and global agents are independent — a matched route **replaces** the global dispatch for that alert, it does not send to both. +Routing rules and global channels are independent. A matched route **replaces** the global dispatch for that alert; it does not send to both. -## Setting up routing rules +## Creating a routing rule -1. Go to **Settings → Routing** (requires admin and Admiral tier) -2. Click **Add Route** -3. Fill in: +1. Go to **Settings > Routing** +2. Click **+ Add Route** +3. Fill in the form: + + + New Routing Rule dialog with Name, Stacks, Channel, Priority, and Enabled fields + | Field | Description | |-------|-------------| -| **Name** | A label for this rule (e.g., "Production to Discord") | -| **Stacks** | One or more stacks this rule applies to. Use the dropdown to search and select. | -| **Channel** | Choose Discord, Slack, or Webhook and provide the endpoint URL | +| **Name** | A label for this rule (e.g. "Production to Discord") | +| **Stacks** | One or more stacks this rule applies to. Use the searchable dropdown to find and add stacks. Selected stacks appear as removable pills below the dropdown. | +| **Channel** | Choose Discord, Slack, or Webhook using the tab bar, then enter the endpoint URL. The URL must use HTTPS. | | **Priority** | Lower values are evaluated first. Default is 0. | | **Enabled** | Toggle the rule on or off without deleting it | 4. Click **Create** to save the rule - - New Routing Rule dialog with stack selection - - ## Managing rules -From the routing rules list, you can: +Each routing rule appears as a card showing the rule name, channel type badge, assigned stack pills, the channel URL (truncated), and priority (when non-zero). + +From the rule card, you can: - **Toggle** a rule on/off with the switch -- **Test** a rule by clicking the lightning bolt icon — sends a test notification to the rule's channel +- **Test** a rule by clicking the lightning bolt icon, which sends a test notification to the rule's channel - **Edit** a rule by clicking the pencil icon -- **Delete** a rule via the trash icon (with confirmation) +- **Delete** a rule via the trash icon (with a confirmation dialog) ## Priority and matching -Rules are evaluated in ascending priority order. If multiple rules match the same stack, **all matching rules fire** — this allows you to send the same alert to multiple channels (e.g., both a Slack channel and a custom webhook). +Rules are evaluated in ascending priority order. If multiple rules match the same stack, **all matching rules fire**. This lets you send the same alert to multiple channels (e.g. both a Slack channel and a custom webhook). -If any rule matches, global agents are skipped for that alert. +If any rule matches, global channels are skipped for that alert. ## Fallback behavior -Alerts without a stack context always use global agents. These include: +Alerts without a stack context always use global channels. These include: - Host CPU, memory, and disk threshold warnings -- Docker data accumulation (janitor) notifications +- Docker data accumulation notifications -Stack-scoped alerts that don't match any routing rule also fall back to global agents. +Stack-scoped alerts that do not match any routing rule also fall back to global channels. ## Example setup @@ -72,24 +74,7 @@ Stack-scoped alerts that don't match any routing rule also fall back to global a | Rule | Stacks | Channel | Priority | |------|--------|---------|----------| -| Prod to Slack | `prod-api`, `prod-web` | Slack: `https://hooks.slack.com/...` | 0 | -| Staging to Discord | `staging-api`, `staging-web` | Discord: `https://discord.com/api/webhooks/...` | 10 | +| Prod to Slack | `prod-api`, `prod-web` | Slack | 0 | +| Staging to Discord | `staging-api`, `staging-web` | Discord | 10 | -Any other stack alerts (e.g., `dev-tools`) would fall back to your global notification settings. - -## Troubleshooting - - - - Verify the **stack name** in the route matches exactly. Stack names are case-sensitive and correspond to the Docker Compose project name (the directory name). Check that the route is **enabled**. - - - Real alerts are dispatched by the monitoring service, which evaluates every 30 seconds. Make sure you have at least one alert rule or crash detection enabled. Also verify the stack name in your routing rule matches the stack that triggers the alert. - - - Notification Routing is an Admiral-tier feature. Activate an Admiral license in **Settings → License** or visit [sencho.io/pricing](https://sencho.io/pricing) to upgrade. - - - Not currently. Host resource alerts don't have a stack context and always use global notification agents. Routing rules only apply to stack-scoped alerts. - - +Any other stack alerts (e.g. `dev-tools`) would fall back to your global notification channels. diff --git a/docs/features/overview.mdx b/docs/features/overview.mdx index e09d3853..c22c6072 100644 --- a/docs/features/overview.mdx +++ b/docs/features/overview.mdx @@ -5,12 +5,16 @@ description: A high-level tour of everything Sencho can do. ## Dashboard -The Home view shows real-time system stats at a glance - active containers, exited containers, Docker network activity, and host resource usage (CPU, RAM, disk). Historical CPU and RAM charts display trends over the last 24 hours. A Docker Run converter lets you paste any `docker run` command and convert it to a Compose stack. [Learn more →](/features/dashboard) +The Home view shows real-time system stats at a glance: active containers, exited containers, Docker network activity, and host resource usage (CPU, RAM, disk). Historical CPU and RAM charts display trends over the last 24 hours. A Docker Run converter lets you paste any `docker run` command and convert it to a Compose stack. [Learn more →](/features/dashboard) ## Stack management Deploy, start, stop, restart, update, and remove Docker Compose stacks through a point-and-click interface. Right-click any stack in the sidebar for a context menu with quick actions including alerts configuration, update checks, and deployment controls. [Learn more →](/features/stack-management) +## Stack labels + +Tag your stacks with custom colored labels like `production`, `staging`, or `media-server`. Filter the sidebar by label, identify stacks at a glance, and organize your infrastructure visually. Skipper or Admiral. [Learn more →](/features/stack-labels) + ## Editor Full in-browser Monaco editor for your `compose.yaml` and `.env` files with syntax highlighting. Toggle edit mode, save to disk, or save and deploy in one step. The container panel shows per-container live stats (CPU, RAM, network), with buttons to open the app, stream logs, or launch a bash terminal. [Learn more →](/features/editor) @@ -29,7 +33,7 @@ Run scoped prune operations to clean up Sencho-managed resources only, or target ## App Store -Browse 190+ pre-configured application templates. Filter by category (Media, Automation, Development, etc.), configure environment variables, volumes, and ports, and deploy with a single click. Customize the template source URL to use your own registry. [Learn more →](/features/app-store) +Browse pre-configured application templates. Filter by category (Media, Automation, Development, etc.), configure environment variables, volumes, and ports, and deploy with a single click. Customize the template source URL to use your own registry. [Learn more →](/features/app-store) ## Global observability @@ -37,27 +41,55 @@ The **Logs** view aggregates output from all containers across all stacks into a ## Host console -Open an interactive terminal on the host OS directly in the browser - full xterm.js emulation with color support. No SSH client required. Admin-only access. [Learn more →](/features/host-console) +Open an interactive terminal on the host OS directly in the browser with full xterm.js emulation and color support. No SSH client required. Admin-only access. [Learn more →](/features/host-console) ## Multi-node support -Add remote Sencho instances as nodes. All dashboard operations - stack management, logs, stats - work identically whether you're targeting your local machine or a server on the other side of the world. Uses a transparent HTTP proxy model; no SSH or shared Docker sockets required. [Learn more →](/features/multi-node) +Add remote Sencho instances as nodes. All dashboard operations (stack management, logs, stats) work identically whether you're targeting your local machine or a server on the other side of the world. Uses a transparent HTTP proxy model; no SSH or shared Docker sockets required. [Learn more →](/features/multi-node) + +## Node compatibility + +When you manage multiple nodes running different Sencho versions, the dashboard automatically detects each node's capabilities and disables features that aren't supported on older instances. No errors, no broken pages. [Learn more →](/features/node-compatibility) ## Fleet View Monitor your entire infrastructure from a single screen. The fleet dashboard shows all nodes with health metrics, container counts, and resource usage. Pro users unlock fleet health summary cards, container drill-down, search, sorting, filtering, and critical node detection. [Learn more →](/features/fleet-view) +## Remote updates + +Check for outdated nodes and trigger over-the-air updates from the Fleet View. When the gateway is running a newer version than a remote node, a one-click update pulls the latest image and recreates the container automatically. [Learn more →](/features/remote-updates) + ## Alerts & notifications Configure threshold-based alerts (CPU, memory, network, restart count) per stack. Route notifications to Discord, Slack, or any generic webhook endpoint. Alerts are evaluated every minute with configurable duration and cooldown. [Learn more →](/features/alerts-notifications) +## Notification routing + +Route alerts to specific channels with per-stack routing rules. Send production alerts to a critical Slack channel while routing dev stack alerts to a less urgent Discord channel. Admiral only. [Learn more →](/features/notification-routing) + ## Webhooks Trigger stack actions from external CI/CD pipelines via HTTP webhooks. Create a webhook targeting a specific stack and action, then call it from GitHub Actions, GitLab CI, or any system that can send an HTTP POST. Requests are authenticated with HMAC-SHA256 signatures. [Learn more →](/features/webhooks) +## API tokens + +Generate scoped API tokens for CI/CD pipelines, scripts, and automation workflows. Each token is assigned a permission level (Read Only, Deploy Only, or Full Admin) so you can follow the principle of least privilege. Admiral only. [Learn more →](/features/api-tokens) + +## Auto-update policies + +Define schedules for Sencho to automatically check your container images for updates and apply them when new versions are available. Each policy targets a specific stack and runs on a cron schedule, with full run history for auditability. Think of it as a built-in Watchtower integrated into your dashboard. Skipper or Admiral. [Learn more →](/features/auto-update-policies) + +## Scheduled operations + +Automate recurring maintenance tasks like stack restarts, fleet snapshots, and system prunes on a cron schedule. Every execution is logged with full history so you always know what ran and when. Admiral only. [Learn more →](/features/scheduled-operations) + ## RBAC & user management -Create viewer accounts with read-only access to dashboards, logs, and file contents - while keeping deploy and edit permissions locked to admins. Sencho Pro supports two roles: Admin (full access) and Viewer (read-only). [Learn more →](/features/rbac) +Create viewer accounts with read-only access to dashboards, logs, and file contents, while keeping deploy and edit permissions locked to admins. Sencho Pro supports two roles: Admin (full access) and Viewer (read-only). [Learn more →](/features/rbac) + +## SSO & LDAP authentication + +Authenticate with your existing identity provider. Sencho supports LDAP/Active Directory, Google, GitHub, and Okta. SSO works alongside password authentication and auto-provisions accounts on first login with configurable role mapping. Admiral only. [Learn more →](/features/sso) ## Atomic deployments @@ -65,15 +97,15 @@ Pro users get automatic backup and rollback on every deployment. Before applying ## Fleet-wide backups -Create point-in-time snapshots of every compose file and environment file across all nodes. Snapshots are stored centrally and can be browsed by node and stack. Restore individual stacks from any snapshot with optional one-click redeploy - even to remote nodes. [Learn more →](/features/fleet-backups) +Create point-in-time snapshots of every compose file and environment file across all nodes. Snapshots are stored centrally and can be browsed by node and stack. Restore individual stacks from any snapshot with optional one-click redeploy, even to remote nodes. [Learn more →](/features/fleet-backups) ## Private registries -Store credentials for private Docker registries - Docker Hub organizations, GHCR, AWS ECR, and self-hosted registries. Sencho injects them automatically during deploy and pull operations. ECR short-lived tokens are refreshed on every operation. Admiral only. [Learn more →](/features/private-registries) +Store credentials for private Docker registries: Docker Hub organizations, GHCR, AWS ECR, and self-hosted registries. Sencho injects them automatically during deploy and pull operations. ECR short-lived tokens are refreshed on every operation. Admiral only. [Learn more →](/features/private-registries) ## Audit log -Track every mutating action across your Sencho instance with a searchable audit trail. See who deployed, stopped, deleted, or changed settings - with timestamps, user attribution, and node context. Admiral only. [Learn more →](/features/audit-log) +Track every mutating action across your Sencho instance with a searchable audit trail. See who deployed, stopped, deleted, or changed settings, with timestamps, user attribution, and node context. Admiral only. [Learn more →](/features/audit-log) ## Licensing & billing diff --git a/docs/features/private-registries.mdx b/docs/features/private-registries.mdx index dc187249..7cdabb1e 100644 --- a/docs/features/private-registries.mdx +++ b/docs/features/private-registries.mdx @@ -22,7 +22,7 @@ Sencho can store credentials for your private Docker registries and inject them 1. Open **Settings Hub** and navigate to the **Registries** tab (visible to Admiral admins only). 2. Click **Add Registry**. -3. Select the registry type. The URL field auto-fills with the standard endpoint for Docker Hub and GHCR. +3. Select the registry type. When you switch types, the URL field auto-fills with the standard endpoint for Docker Hub and GHCR. 4. Enter a descriptive name, the registry URL, and your credentials. 5. For **ECR** registries, also provide the AWS region (e.g., `us-east-1`). 6. Click **Add**. @@ -35,9 +35,28 @@ Sencho can store credentials for your private Docker registries and inject them Add Registry form with type selector, credentials, and URL fields -## Testing connectivity +## Managing registries -After adding a registry, click the checkmark icon on the registry card to test the connection. Sencho will attempt to authenticate against the registry's `/v2/` endpoint and report success or failure. +Each configured registry appears as a card showing: + +- **Name** and **type badge** (e.g., Docker Hub, GHCR, AWS ECR, Custom) +- **Registry URL** (monospaced) +- **Username** +- **Secret status** (whether a secret is stored) +- **AWS Region**, if the registry is an ECR type +- **Created date** + +Each card has three action buttons: + +- **Test connection** (checkmark icon) to verify credentials +- **Edit** (pencil icon) to modify the registry name, URL, credentials, or type +- **Delete** (trash icon) to remove the registry after confirmation + +When editing a registry, you can leave the secret field blank to keep the existing stored secret. Only fill it in if you want to replace it. + +### Testing connectivity + +Click the checkmark icon on any registry card to test the connection. Sencho authenticates against the registry's `/v2/` endpoint and reports success or failure. For ECR registries, the test verifies that the AWS credentials can successfully obtain an authorization token. @@ -103,11 +122,11 @@ AWS ECR uses short-lived authentication tokens (valid for 12 hours) derived from ## Security -- **Encrypted storage** - Registry secrets are encrypted at rest using AES-256-GCM, the same encryption used for remote node tokens and SSO secrets. +- **Encrypted storage** - Registry secrets are encrypted at rest, using the same encryption layer as remote node tokens and SSO secrets. - **No persistent Docker login** - Credentials are written to a temporary file for the duration of each operation and immediately deleted afterward. - **Secrets never exposed** - The API never returns decrypted secrets. The UI shows only whether a secret is stored. - **Audit trail** - Registry create, update, and delete operations are recorded in the [Audit Log](/features/audit-log). -- **Admin-only access** - Only admin users with a Admiral license can manage registry credentials. +- **Admin-only access** - Only admin users with an Admiral license can manage registry credentials. ## Multi-node behavior diff --git a/docs/features/rbac.mdx b/docs/features/rbac.mdx index 0fe0d8bf..546967aa 100644 --- a/docs/features/rbac.mdx +++ b/docs/features/rbac.mdx @@ -1,50 +1,97 @@ --- title: RBAC & User Management -description: Role-based access control for Sencho - manage admin, viewer, deployer, and node admin accounts with scoped permissions. +description: Role-based access control for Sencho - manage admin, viewer, deployer, node admin, and auditor accounts with scoped permissions. --- - Multi-user support requires a Sencho Pro license. Community Edition supports a single admin account only. Intermediate roles (Deployer, Node Admin) and scoped permissions require **Admiral**. + Multi-user support requires a **Sencho Skipper** or **Admiral** license. Community Edition supports a single admin account only. Intermediate roles (Deployer, Node Admin, Auditor) and scoped permissions require **Admiral**. -Sencho supports role-based access control with four distinct roles. The classic **Admin** and **Viewer** roles are available on all Pro tiers, while **Deployer** and **Node Admin** are exclusive to Admiral and support scoped permissions per stack or node. +Sencho supports role-based access control with five distinct roles. **Admin** and **Viewer** are available on all Pro tiers, while **Deployer**, **Node Admin**, and **Auditor** are exclusive to Admiral. ## Roles | Role | Description | Tier | |------|-------------|------| -| **Admin** | Full access to all features — deploy, edit, manage users, configure nodes, and more | Pro | -| **Viewer** | Read-only access to dashboards, logs, stats, and file contents | Pro | -| **Deployer** | Can deploy, restart, stop, and start stacks — but cannot edit compose files, delete stacks, or access system settings | Admiral | -| **Node Admin** | Full stack and node management within their scope — cannot access system settings, users, or license management | Admiral | +| **Admin** | Full access to all features: deploy, edit, manage users, configure nodes, and system settings | Skipper+ | +| **Viewer** | Read-only access to dashboards, logs, stats, and file contents | Skipper+ | +| **Deployer** | Can deploy, restart, stop, and start stacks, but cannot edit compose files, delete stacks, or access system settings | Admiral | +| **Node Admin** | Full stack and node management within their scope, but no access to system settings, users, or license management | Admiral | +| **Auditor** | Read-only access like Viewer, plus access to the audit log | Admiral | ### Permission matrix -| Action | Admin | Node Admin | Deployer | Viewer | -|--------|-------|------------|----------|--------| -| View stacks, logs, stats | ✅ | ✅ | ✅ | ✅ | -| Deploy / restart / stop / start stacks | ✅ | ✅ | ✅ | ❌ | -| Edit compose and `.env` files | ✅ | ✅ | ❌ | ❌ | -| Create and delete stacks | ✅ | ✅ | ❌ | ❌ | -| View nodes | ✅ | ✅ | ✅ | ✅ | -| Add / edit / delete nodes | ✅ | ✅ | ❌ | ❌ | -| System settings | ✅ | ❌ | ❌ | ❌ | -| User management | ✅ | ❌ | ❌ | ❌ | -| License management | ✅ | ❌ | ❌ | ❌ | -| Webhooks | ✅ | ❌ | ❌ | ❌ | -| API tokens | ✅ | ❌ | ❌ | ❌ | -| Host console | ✅ | ❌ | ❌ | ❌ | -| Audit log | ✅ | ❌ | ❌ | ❌ | +| Action | Admin | Node Admin | Deployer | Auditor | Viewer | +|--------|-------|------------|----------|---------|--------| +| View stacks, logs, stats | Yes | Yes | Yes | Yes | Yes | +| Deploy / restart / stop / start stacks | Yes | Yes | Yes | No | No | +| Edit compose and `.env` files | Yes | Yes | No | No | No | +| Create and delete stacks | Yes | Yes | No | No | No | +| View nodes | Yes | Yes | Yes | Yes | Yes | +| Add / edit / delete nodes | Yes | Yes | No | No | No | +| Audit log | Yes | No | No | Yes | No | +| System settings | Yes | No | No | No | No | +| User management | Yes | No | No | No | No | +| License management | Yes | No | No | No | No | +| Webhooks | Yes | No | No | No | No | +| API tokens | Yes | No | No | No | No | +| Host console | Yes | No | No | No | No | + +## Managing users + +Go to **Settings > Users** to view the user list. The table shows each user's username, role badge, creation date, and action buttons. + + + User Management showing the users table with username, role, and creation date + + +From the user table you can: + +- **Edit** a user by clicking the pencil icon +- **Delete** a user by clicking the trash icon (with a confirmation dialog) + +You cannot delete your own account. The delete button is disabled for the currently logged-in user. + +### Creating a user + +Click **Add User** to open the creation form. + + + New User form with Username, Role, Password, and Confirm Password fields + + +| Field | Description | +|-------|-------------| +| **Username** | At least 3 characters. Letters, numbers, underscores, and hyphens only. | +| **Role** | Select from the available roles (see below) | +| **Password** | At least 8 characters | +| **Confirm Password** | Must match the password field | + +On Admiral, all five roles appear in the role selector. On Skipper, only Admin and Viewer are available. + + + Role selector dropdown showing all five roles on Admiral + + +### Editing a user + +Click the pencil icon on a user row to edit. You can change the username, role, and optionally set a new password. Leave the password fields blank to keep the existing password. ## Scoped permissions - Scoped permissions require a **Admiral** license. + Scoped permissions require an **Admiral** license. -Roles can be scoped to specific stacks or nodes. This means you can grant a user the **Deployer** role globally, but also give them **Node Admin** access on a specific node — or limit a viewer to deploy access on only certain stacks. +Roles can be scoped to specific stacks or nodes. This lets you grant a user elevated permissions on particular resources without giving them broad access. -Scoped permissions **add to** the user's global role. They never reduce it. A user with a global Viewer role plus a scoped Deployer assignment on "my-app" stack can deploy "my-app" but has read-only access to everything else. +Scoped permissions **add to** the user's global role. They never reduce it. A user with a global Viewer role plus a scoped Deployer assignment on the "my-app" stack can deploy "my-app" but has read-only access to everything else. + +When editing a user on Admiral, a **Scoped Permissions** section appears below the user form. From there you can: + +1. **View** the user's current scoped assignments, each showing the role badge, resource type, and resource name +2. **Add** a new scope by selecting a role (Deployer, Node Admin, or Admin), resource type (Stack or Node), and the specific resource +3. **Remove** an existing scope with the trash icon ### Example scenarios @@ -52,50 +99,22 @@ Scoped permissions **add to** the user's global role. They never reduce it. A us - A **Deployer** with a scoped **Node Admin** assignment on node "staging-server" can manage stacks and nodes on that server, plus deploy globally. - A **Node Admin** without any scoped assignments can manage all stacks and nodes but has no access to system settings. -## Managing users - - - User Management with role-based access control - - -Admins can manage accounts in **Settings → Users**. From there you can: - -- **Create** a new user with a username, password, and role -- **Edit** an existing user's password or role -- **Delete** a user account - -When creating or editing a user on Admiral, you'll see all four role options in the role selector. On Skipper, only Admin and Viewer are available. - - - Role selector showing all four roles on Admiral - - -## Managing scoped permissions - -When editing a user on Admiral, a **Scoped Permissions** section appears below the user form. Here you can: - -1. **View** the user's current scoped assignments -2. **Add** a new scope by selecting a role, resource type (stack or node), and specific resource -3. **Remove** an existing scope - -Each scoped assignment grants the specified role's permissions on the specified resource only. - ## SSO auto-provisioning -With a Admiral license, users can also be created automatically when they log in via SSO (LDAP, Google, GitHub, or Okta). SSO users appear in the Users list alongside local accounts. They are assigned a role based on identity provider group membership or claim mapping. +With an Admiral license, users can also be created automatically when they log in via SSO (LDAP, Google, GitHub, or Okta). SSO users appear in the Users list alongside local accounts and are assigned a role based on identity provider group membership or claim mapping. -SSO users cannot log in with a password — they must always authenticate through their identity provider. After SSO provisioning, an admin can add scoped permissions to SSO users just like local accounts. +SSO users cannot log in with a password; they must always authenticate through their identity provider. After SSO provisioning, an admin can add scoped permissions to SSO users just like local accounts. -To set up identity provider authentication, see [SSO Authentication →](/features/sso). +To set up identity provider authentication, see [SSO Authentication](/features/sso). ## Migration from single-admin setup -When you upgrade to Sencho Pro, your existing single-admin credentials are automatically migrated to the new users table. No manual action is required — your login continues to work as before, and your account is assigned the Admin role. +When you upgrade to a Skipper or Admiral license, your existing single-admin credentials are automatically migrated. No manual action is required; your login continues to work as before, and your account is assigned the Admin role. -## License tiers +## Account limits by tier | Tier | Admin accounts | Non-admin accounts | Intermediate roles | Scoped permissions | |------|---------------|-------------------|-------------------|-------------------| -| **Community** | 1 | 0 | ❌ | ❌ | -| **Skipper** | 1 | 3 | ❌ | ❌ | -| **Admiral** | Unlimited | Unlimited | ✅ | ✅ | +| **Community** | 1 | 0 | No | No | +| **Skipper** | 1 | 3 | No | No | +| **Admiral** | Unlimited | Unlimited | Yes | Yes | diff --git a/docs/features/remote-updates.mdx b/docs/features/remote-updates.mdx index afe442f8..debcbbc1 100644 --- a/docs/features/remote-updates.mdx +++ b/docs/features/remote-updates.mdx @@ -1,12 +1,12 @@ --- -title: Remote updates -description: Check for outdated nodes and trigger over-the-air updates from the Fleet View. +title: Remote Updates +description: Check for outdated nodes and trigger over-the-air Sencho updates from the Fleet View. --- -Sencho can update remote nodes directly from the dashboard. When the gateway is running a newer version than a remote node, a one-click update pulls the latest image and recreates the container automatically. +Sencho can update remote nodes directly from the dashboard. When your primary instance is running a newer version than a remote node, a one-click update pulls the latest image and recreates the container automatically. - Remote updates require **Sencho Pro** (Skipper or Admiral tier). + Remote updates require a **Sencho Pro** license (Skipper or Admiral tier). ## Prerequisites @@ -15,79 +15,70 @@ Remote updates work when each node meets these conditions: - Deployed via **Docker Compose** (the recommended method) - The Docker socket (`/var/run/docker.sock`) is mounted into the container -- Running **Sencho v0.32.0** or later (the version that introduced the `self-update` capability) +- Running a Sencho version that supports the `self-update` [capability](/features/node-compatibility) -Nodes deployed with `docker run` or orchestrators like Kubernetes do not support self-update. These nodes will show a "self-update unavailable" message. - -## How it works - -1. The gateway compares each node's version (from `/api/meta`) against its own version. -2. If a node is running an older version, the Fleet View shows an **Update available** badge. -3. Clicking **Update** sends a command to the remote node. -4. The remote node pulls the latest `saelix/sencho` image and recreates its own container. -5. The gateway polls the node until it comes back online with the new version. - -The remote node briefly goes offline during the update (typically 10–30 seconds depending on image pull speed). The Fleet View tracks the progress and shows **Updating**, **Updated**, or **Timed out** status badges. +Nodes deployed with `docker run` or orchestrators like Kubernetes do not support self-update. These nodes show an error message when you attempt to update them. ## Checking for updates Open the **Fleet** tab and click **Check Updates** in the header. This opens the **Node Updates** dialog, which lists every node with its current version and update status. - Node Updates dialog showing update status for each node + Node Updates dialog showing update status for each node -Each node row shows: +The dialog includes: -| Element | Meaning | -|---------|---------| -| Version label (e.g. `v0.31.0`) | The node's current Sencho version | -| **Up to date** badge | Node is running the latest version | -| **Update** button | A newer version is available — click to update | -| **Updating** badge | The node is pulling and restarting | +- **Summary cards** at the top showing counts of nodes that are Up to date, have updates Available, are currently Updating, or have Failed +- **Gateway version** label showing your primary instance's version +- **Filter** search box to find specific nodes by name or type +- **Node table** with columns for name, type, current version, latest version, and status + +Each node's status column shows one of: + +| Status | Meaning | +|--------|---------| +| **Up to date** badge | Node is running the same version as the gateway | +| **Update** button | A newer version is available; click to update | +| **Updating** badge | The node is pulling the new image and restarting | | **Updated** badge | The node came back online with the new version | | **Timed out** badge | The node did not come back within 5 minutes | +| **Failed** badge | The update command failed | -Nodes running a version too old to report their version will show `pre-X.Y.Z` as the current version. +Nodes that are too old to report their version show "unknown" in the current version column. These nodes are treated as outdated. ## Updating a single node -Click the **Update** button next to any outdated node in the Node Updates dialog, or click the **Update to vX.Y.Z** button directly on the node card in Fleet View. For remote nodes, the update happens in the background. For the local (gateway) node, a confirmation dialog appears warning about the brief dashboard disconnection. +You can trigger an update in two ways: + +- Click the **Update** button next to a node in the Node Updates dialog +- Click the **Update to vX.Y.Z** button directly on a node card in Fleet View + +For remote nodes, the update happens in the background. The Fleet View automatically polls at a faster rate (every 5 seconds) while an update is in progress, so you can watch the status change in near real-time. ## Updating all nodes -Click **Update All (N)** in the Node Updates dialog to trigger updates on all outdated remote nodes simultaneously. The local node is intentionally excluded from bulk updates — update it separately to avoid losing dashboard connectivity. +Click **Update All (N)** in the footer of the Node Updates dialog to trigger updates on all outdated remote nodes simultaneously. The local node is excluded from bulk updates to avoid losing dashboard connectivity. ## Local node updates -When updating the local (gateway) node: +When you update the local (gateway) node: -1. A confirmation dialog explains that the dashboard will briefly disconnect. -2. After confirming, the server pulls the new image and restarts. -3. A reconnecting overlay appears and polls the server every 3 seconds. +1. A confirmation dialog appears explaining that the dashboard will briefly disconnect. +2. After confirming, the server pulls the latest image and restarts. +3. A reconnecting overlay appears and polls the server every few seconds. 4. The page automatically reloads when the server comes back. If the server does not return within 5 minutes, a timeout message appears with a manual reload option. -## Troubleshooting +## What happens during an update -### Node shows "self-update unavailable" +When an update is triggered on a node, Sencho: -The node is not running inside a Docker Compose-managed container, or the Docker socket is not mounted. Check that your `docker-compose.yml` includes the socket volume mount: +1. Pulls the latest `saelix/sencho` image using Docker Compose +2. Recreates the container with the new image +3. The node goes briefly offline during the restart -```yaml -volumes: - - /var/run/docker.sock:/var/run/docker.sock -``` +The gateway monitors the remote node until it comes back online with the new version, then marks it as **Updated**. -### Update times out - -The image pull may be slow on the remote host, or the container failed to restart. SSH into the remote host and check `docker logs sencho` for errors. You can also manually update by running: - -```bash -docker compose pull && docker compose up -d -``` - -### Old node does not show update button - -Nodes running Sencho versions before v0.32.0 do not advertise the `self-update` capability. Update them manually first, then future updates can be triggered from the dashboard. +If you run into issues with remote updates, see the [Troubleshooting](/operations/troubleshooting#remote-update-button-does-not-appear) page. diff --git a/docs/features/resources.mdx b/docs/features/resources.mdx index 4766d484..d1e4ed9c 100644 --- a/docs/features/resources.mdx +++ b/docs/features/resources.mdx @@ -11,7 +11,7 @@ The **Resources** tab gives you a full view of everything Docker is storing on y ## Docker disk footprint -The stacked bar at the top visualises how your Docker disk usage is distributed: +The stacked bar at the top visualizes how your Docker disk usage is distributed: | Segment | Meaning | |---------|---------| @@ -23,16 +23,16 @@ Click any segment to automatically filter the tabs below to that category. ## Quick Clean panel -Four prune buttons let you reclaim disk space immediately. By default they operate on **Sencho-managed resources only** - they will not touch external Docker projects. +Four prune buttons let you reclaim disk space immediately. By default they operate on **Sencho-managed resources only**, so they will not touch external Docker projects. | Button | What it removes | |--------|----------------| | **Prune Unused Images** | Images with no running containers in Sencho stacks | | **Prune Unused Volumes** | Volumes not attached to any Sencho container | | **Prune Dead Networks** | Networks not connected to any Sencho container | -| **Purge Unmanaged Containers** | Containers Sencho doesn't recognise (started outside it) | +| **Purge Unmanaged Containers** | Containers Sencho doesn't recognize (started outside it) | -Each button has a **⋮ More options** menu that lets you target **all Docker resources** instead of Sencho-only. Use this carefully - it can affect other Compose projects running on the same host. +The first three buttons have a **More options** dropdown that lets you target **all Docker resources** instead of Sencho-only. Use this carefully, as it can affect other Compose projects running on the same host. The "Purge Unmanaged Containers" button always targets unmanaged containers only. A confirmation dialog appears before any destructive operation, showing a summary of what will be removed. @@ -42,10 +42,11 @@ A confirmation dialog appears before any destructive operation, showing a summar Lists all Docker images on the host with their ID, repository tag, size, and status. -**Filter buttons:** `All` · `Managed` · `External` +**Filter buttons:** `All` / `Managed` / `External` **Status badges:** -- `In Use` + stack name - image is actively used by a running container +- `In Use` + stack name - image is actively used by a running container in a Sencho-managed stack +- `In Use` + `External` - image is used by a container outside Sencho - `Unused` - image has no running containers; safe to delete Click the trash icon on any row to delete an individual image. Sencho will warn you if the image is in use. @@ -54,7 +55,7 @@ Click the trash icon on any row to delete an individual image. Sencho will warn Lists all Docker volumes. Columns: name, driver, mount point, size, and managed status. -**Filter buttons:** `All` · `Managed` · `External` +**Filter buttons:** `All` / `Managed` / `External` Deleting a volume is permanent. Any data stored in it will be lost. Always back up important volume data before pruning. @@ -64,7 +65,7 @@ Lists all Docker volumes. Columns: name, driver, mount point, size, and managed Lists all Docker networks. Columns: ID, name, driver, scope (`local`, `global`, `swarm`), and managed status. -**Filter buttons:** `All` · `Managed` · `External` +**Filter buttons:** `All` / `Managed` / `External` System networks (like `bridge`, `host`, `none`) are shown but cannot be deleted. @@ -93,10 +94,10 @@ Click **+ Create Network** (admin only) to open the creation dialog. Click the eye icon on any network row to open a detail panel showing: -- **Overview** — ID, driver, scope, creation date, internal/attachable flags -- **IPAM configuration** — Subnet, gateway, and IP range -- **Connected containers** — Container name, IPv4 address, and MAC address -- **Labels** — All Docker labels applied to the network +- **Overview** - ID, driver, scope, creation date, internal/attachable flags +- **IPAM configuration** - Subnet, gateway, and IP range +- **Connected containers** - Container name, IPv4 address, and MAC address +- **Labels** - All Docker labels applied to the network Network inspect panel showing IPAM config and connected containers @@ -110,9 +111,9 @@ Switch to the **Topology** view to see an interactive graph of your Docker netwo Network topology visualization showing containers connected to networks -- **Network nodes** — Dashed border cards showing network name and driver, color-coded by status (managed, external, system) -- **Container nodes** — Cards showing container name with IP addresses per network -- **Edges** — Animated connections between networks and their containers +- **Network nodes** - Dashed border cards showing network name and driver, color-coded by status (managed, external, system) +- **Container nodes** - Cards showing container name with IP addresses per network +- **Edges** - Animated connections between networks and their containers - Pan, zoom, and drag nodes to explore the topology - A mini map in the bottom-right provides an overview @@ -124,4 +125,4 @@ Switch to the **Topology** view to see an interactive graph of your Docker netwo Lists containers running on the host that are not part of any Sencho-managed stack. This includes containers started with `docker run`, or Compose projects outside your `COMPOSE_DIR`. -This view is useful for identifying orphaned containers after a failed deployment or after moving stacks in and out of `COMPOSE_DIR`. +This view is useful for identifying orphaned containers after a failed deployment or after moving stacks in and out of `COMPOSE_DIR`. A badge on the tab shows the count of unmanaged containers when any are detected. diff --git a/docs/features/scheduled-operations.mdx b/docs/features/scheduled-operations.mdx index dda380ec..aec992d9 100644 --- a/docs/features/scheduled-operations.mdx +++ b/docs/features/scheduled-operations.mdx @@ -10,7 +10,7 @@ description: Automate recurring Docker operations like stack restarts, fleet sna ## Overview -Scheduled Operations lets you automate recurring maintenance tasks across your infrastructure. Define a cron schedule, choose an action, and Sencho handles the rest - including a full execution history log so you always know what ran and when. +Scheduled Operations lets you automate recurring maintenance tasks across your infrastructure. Define a cron schedule, choose an action, and Sencho handles the rest, including a full execution history log so you always know what ran and when. Scheduled operations list view showing tasks with status, schedule, and actions @@ -20,29 +20,45 @@ Scheduled Operations lets you automate recurring maintenance tasks across your i | Action | Target | Description | |--------|--------|-------------| -| **Restart Stack** | A specific stack (or specific services within it) on a specific node | Restarts all or selected containers in the stack via the Docker Engine API | +| **Restart Stack** | A specific stack (or specific services within it) on a specific node | Restarts all or selected containers in the stack | | **Fleet Snapshot** | All nodes | Creates a fleet-wide backup of all compose files and `.env` files | -| **System Prune** | A specific node (or the default node) | Prunes selected resources, optionally filtered by Docker label | +| **System Prune** | The default node | Prunes selected resources, optionally filtered by Docker label | ## Creating a Scheduled Task 1. Navigate to the **Schedules** tab in the top navigation bar (visible to Admiral admins). 2. Click **New Schedule**. 3. Fill in the form: - - **Name** - a descriptive label (e.g. "Nightly staging restart"). - - **Action** - choose Restart Stack, Fleet Snapshot, or System Prune. - - **Stack / Node** - if you chose Restart Stack, select the target stack and the node it runs on. - - **Services** - optionally select specific services within the stack to restart. Leave empty to restart all services. - - **Prune Targets** - if you chose System Prune, select which resources to prune (containers, images, networks, volumes). All are selected by default. - - **Label Filter** - optionally filter prune operations to resources matching a specific Docker label (e.g. `com.docker.compose.project=mystack`). - - **Cron Expression** - standard 5-field cron format. A human-readable preview appears below the input. - - **Enabled** - toggle the task on or off. + - **Name**: A descriptive label (e.g. "Nightly staging restart"). + - **Action**: Choose Restart Stack, Fleet Snapshot, or System Prune. The form fields below change based on your selection. + - **Node**: (Restart Stack only) Select the node where the target stack runs. + - **Stack**: (Restart Stack only) Select the stack to restart. Becomes available after choosing a node. + - **Services**: (Restart Stack only) Optionally select specific services within the stack to restart. Leave empty to restart all services. + - **Prune Targets**: (System Prune only) Select which resources to prune: containers, images, networks, volumes. All are selected by default. + - **Label Filter**: (System Prune only) Optionally filter prune operations to resources matching a specific Docker label (e.g. `com.docker.compose.project=mystack`). + - **Cron Expression**: Standard 5-field cron format. A human-readable preview appears below the input. + - **Enabled**: Toggle the task on or off. 4. Click **Create**. Create scheduled task dialog with action, cron expression, and prune target options +## Task List + +The task list is displayed as a table with the following columns: + +| Column | Description | +|--------|-------------| +| **Name** | The task name | +| **Action** | Task type badge: Restart Stack, Fleet Snapshot, or System Prune | +| **Target** | Stack name (with selected services, if any), or the target type for non-stack actions | +| **Schedule** | Human-readable description with the raw cron expression below | +| **Status** | Last run result: **Success** (green), **Failed** (red), or "Never run" | +| **Next Run** | When the task will next execute | +| **Enabled** | Toggle switch to enable or disable the task | +| **Actions** | Action buttons (see [Managing Tasks](#managing-tasks)) | + ## Granular Targeting ### Per-Service Restart @@ -98,10 +114,14 @@ When creating a new task while a node filter is active, Sencho pre-selects that ## Managing Tasks -- **Enable/Disable** - Use the toggle switch in the task list to pause or resume a schedule without deleting it. -- **Run Now** - Click the play icon to immediately execute a task. This works even on disabled tasks, allowing you to test a schedule before enabling it. Manual runs are labeled "Manual" in the execution history. -- **Edit** - Click the pencil icon to update the task name, schedule, or target. -- **Delete** - Click the trash icon to permanently remove the task and all its execution history. +Each task row has four action buttons: + +- **Run Now** (play icon): Immediately execute the task without waiting for the next scheduled run. Manual runs are labeled "Manual" in the execution history. +- **Execution History** (clock icon): Open the run history panel for this task. +- **Edit** (pencil icon): Modify the task name, action, target, or schedule. +- **Delete** (trash icon): Permanently remove the task and all its execution history after confirmation. + +Use the **Enabled** toggle switch in the task list to pause or resume a schedule without deleting it. ## Failure Notifications @@ -117,20 +137,20 @@ To configure notification channels, go to **Settings > Notifications**. ## Execution History -Click the history icon on any task to view its execution log. Each entry shows: +Click the clock icon on any task to open the run history panel. The history is displayed as a table with the following columns: -- **Timestamp** - when the task ran. -- **Source** - whether the run was triggered by the scheduler or manually via Run Now. -- **Status** - success or failure. -- **Duration** - how long the execution took. -- **Details** - output message or error description. +| Column | Description | +|--------|-------------| +| **Time** | When the run started | +| **Source** | Whether the run was triggered by the **Scheduler** or **Manual** (via Run Now) | +| **Status** | Success, Failed, or Running | +| **Duration** | How long the run took (in seconds) | +| **Details** | Output summary or error message | + +Run history is paginated at 20 entries per page. You can export the full history as CSV using the download button in the panel header. Execution history is retained for 30 days. -### Exporting History - -Click the download icon in the top-right corner of the execution history panel to export the full history as a CSV file. The export includes all runs within the 30-day retention window — not just the current page. - Execution history showing run source, status, duration, and details with export button diff --git a/docs/features/sso.mdx b/docs/features/sso.mdx index 9772ad31..424d00fa 100644 --- a/docs/features/sso.mdx +++ b/docs/features/sso.mdx @@ -81,23 +81,45 @@ SSO can be configured two ways: ### Via Settings UI -Admins can manage SSO providers in **Settings → SSO**. Each provider has: +Admins can manage SSO providers in **Settings → SSO**. Each provider is displayed as a collapsible card with: -- An **enable/disable** toggle -- Provider-specific configuration fields +- An **enable/disable** toggle and an **Active** badge when enabled +- Provider-specific configuration fields (expand the card to configure) +- A **Save** button to persist changes - A **Test Connection** button to verify connectivity before saving +- A **Remove** button to delete an existing provider configuration SSO settings panel showing all four identity providers -Expand a provider card to configure it. Here's the LDAP configuration form: +Expand a provider card to configure it. The LDAP configuration form includes: + +| Field | Description | +|-------|-------------| +| **Server URL** | LDAP server URL (e.g., `ldap://ldap.example.com:389` or `ldaps://...` for TLS) | +| **Bind DN** | Service account DN used to search the directory | +| **Bind Password** | Service account password | +| **Search Base** | Base DN for user searches (e.g., `ou=users,dc=example,dc=com`) | +| **Search Filter** | LDAP filter template using `{{username}}` as placeholder | +| **Admin Group DN** | DN of the group whose members receive the Admin role | +| **Default Role** | Role assigned to users not in the admin group (Viewer or Admin) | +| **Verify TLS certificate** | Toggle to enable or disable TLS certificate verification | LDAP configuration form with server URL, bind DN, search base, and role mapping -And an OIDC provider (Google) configuration form: +OIDC providers (Google, GitHub, Okta) share a common configuration form: + +| Field | Description | +|-------|-------------| +| **Issuer URL** | (Okta only) Your Okta issuer URL | +| **Client ID** | OAuth client ID from your identity provider | +| **Client Secret** | OAuth client secret | +| **Admin Claim** | JWT claim name inspected for role mapping (e.g., `groups`) | +| **Admin Claim Value** | Value within the claim that grants Admin (e.g., `sencho-admins`) | +| **Default Role** | Role assigned when no claim mapping matches (Viewer or Admin) | Google OIDC configuration form with client ID, client secret, and role claim mapping @@ -114,6 +136,7 @@ Environment variables are useful for initial deployment or infrastructure-as-cod | Variable | Default | Description | |----------|---------|-------------| | `SSO_LDAP_ENABLED` | `false` | Enable LDAP authentication | +| `SSO_LDAP_DISPLAY_NAME` | `LDAP` | Label shown on the login button (e.g., "Corporate AD") | | `SSO_LDAP_URL` | - | LDAP server URL (e.g., `ldap://ldap.example.com:389` or `ldaps://ldap.example.com:636`) | | `SSO_LDAP_BIND_DN` | - | Service account DN for searching users | | `SSO_LDAP_BIND_PASSWORD` | - | Service account password (encrypted at rest in the database) | @@ -171,23 +194,8 @@ If not set, Sencho auto-detects the URL from the request's `Host` header and pro - **PKCE** - All OIDC flows use `code_challenge_method=S256` to prevent authorization code interception - **State parameter** - A cryptographic random value protects against CSRF attacks on the OAuth callback -- **Encrypted secrets** - LDAP bind passwords and OIDC client secrets are encrypted at rest with AES-256-GCM +- **Encrypted secrets** - LDAP bind passwords and OIDC client secrets are encrypted at rest - **No local password** - SSO users are created with an unusable password hash. They cannot bypass SSO by using the password login form - **Admin-only configuration** - Only Admiral administrators can enable or configure SSO providers -## Troubleshooting - -### LDAP connection refused -Verify the LDAP server is reachable from the Sencho container. If LDAP is on the host machine, use `host.docker.internal` (Docker Desktop) or the host's LAN IP address - not `localhost`. - -### TLS certificate errors -If your LDAP server uses a self-signed certificate, set `SSO_LDAP_TLS_REJECT_UNAUTHORIZED=false`. For production, install a trusted certificate instead. - -### OAuth callback URL mismatch -The redirect URI registered in your identity provider must exactly match what Sencho sends. Check: -1. `SSO_CALLBACK_URL` is set to your external URL (e.g., `https://sencho.example.com`) -2. The callback URL in your provider's settings is `https://sencho.example.com/api/auth/sso/oidc//callback` -3. Protocol matches - don't mix `http` and `https` - -### SSO buttons not appearing on login page -SSO providers only appear on the login page when they are both **configured** and **enabled**. Check Settings → SSO to verify the provider is active. +For common SSO issues (LDAP connection errors, OAuth callback mismatches, SSO buttons not appearing), see the [Troubleshooting](/operations/troubleshooting#ldap-connection-refused) page. diff --git a/docs/features/stack-labels.mdx b/docs/features/stack-labels.mdx index 1ab060eb..e91580fe 100644 --- a/docs/features/stack-labels.mdx +++ b/docs/features/stack-labels.mdx @@ -10,54 +10,69 @@ description: Organize your stacks with colored labels for quick filtering, group Stack Labels let you tag your Docker Compose stacks with custom colored labels like `production`, `staging`, or `media-server`. Once labeled, you can filter your stack list, identify stacks at a glance, and run bulk actions on entire groups. - Sidebar showing stacks with colored label dots + Sidebar showing stacks with colored label dots and a label filter pill ## Creating labels ### From Settings -1. Open **Settings → Labels** -2. Click **New Label** -3. Enter a name and pick a color +1. Open **Settings > Labels** +2. Click **+ New Label** +3. Enter a name and pick a color from the 10 available swatches 4. Click **Create** - Settings Labels section with label management + Settings Labels section showing existing labels with assignment counts + + +The label list shows each label's color, name, and how many stacks are currently assigned to it. Hover over a label row to reveal **Edit** and **Delete** buttons. + + + Create Label dialog with name input and color picker ### From the stack context menu -1. Right-click any stack in the sidebar (or click the three-dot menu) -2. Hover over **Labels** -3. Click **Manage labels...** at the bottom of the sub-menu -4. Create your label from the Settings panel that opens +You can also create labels without leaving the sidebar: + +1. Right-click any stack in the sidebar +2. Hover over **Labels** to open the submenu +3. Click **Manage labels...** at the bottom to open the Labels section in Settings + +### From the three-dot menu + +1. Click the three-dot menu on any stack row in the sidebar +2. Click **Labels** to open the label assignment popover +3. Click **Create new label** at the bottom of the popover to create and assign in one step ## Assigning labels to stacks -1. Right-click a stack in the sidebar (or click the three-dot menu) -2. Hover over **Labels** to open the sub-menu -3. Click a label to toggle it on or off +There are two ways to assign labels: + +**Right-click context menu:** Right-click a stack in the sidebar, hover over **Labels**, and click a label to toggle it on or off. A checkmark indicates the label is currently assigned. - Right-click context menu with Labels sub-menu + Right-click context menu with Labels submenu showing assigned label with checkmark +**Three-dot menu popover:** Click the three-dot menu on a stack row, then click **Labels**. The popover shows all labels with checkmarks for assigned ones. Click any label to toggle it. + A stack can have multiple labels. Changes save immediately. ## Filtering by label ### Sidebar -When you have labels, a pill bar appears between the search box and the stack list. Click a label pill to filter — only stacks with that label are shown. Click multiple pills to see stacks matching **any** of the selected labels. Click an active pill again to deselect it. +When at least one label exists, a pill bar appears between the search box and the stack list. Click a label pill to filter: only stacks with that label are shown. Click multiple pills to see stacks matching **any** of the selected labels. Click an active pill again to deselect it. - Sidebar filtered by label showing only matching stacks + Sidebar filtered by the prod label showing only matching stacks ### Fleet View -Label filter pills appear in the Fleet View toolbar alongside the existing Status and Type filters. Selecting a label filters to nodes that contain stacks with that label. +The **Tags** filter in the [Fleet View](/features/fleet-view) toolbar lets you filter nodes by stack labels. Selecting a label filters to nodes that contain stacks with that label. ## Bulk actions @@ -69,28 +84,17 @@ Right-click a label pill in the sidebar to access bulk actions: | **Stop all** | Stops every stack with that label | | **Restart all** | Restarts every stack with that label | + + Right-click context menu on a label pill showing Deploy all, Stop all, and Restart all options + + A confirmation dialog shows which stacks will be affected before executing. ## Managing labels -Open **Settings → Labels** to view, edit, and delete your labels. +Open **Settings > Labels** to view, edit, and delete your labels. -- **Edit**: Change a label's name or color -- **Delete**: Removes the label and unassigns it from all stacks +- **Edit**: Click the pencil icon on a label row to change its name or color +- **Delete**: Click the trash icon to remove the label. A confirmation dialog explains that the label will be removed from all stacks. This cannot be undone. -## Troubleshooting - - - - Labels require a **Skipper** or **Admiral** license. Verify your license tier in **Settings → License**. Labels also only appear when at least one label has been created. - - - If you downgrade from Skipper/Admiral to Community, the label UI is hidden but your data is preserved. Upgrading again will restore all labels and assignments. - - - If a stack was deleted from disk but still had a label assignment, it will be skipped during bulk actions. The results toast will indicate how many stacks failed. Remove orphaned assignments by re-opening **Settings → Labels**. - - - Label names must be unique per node. If you see a “label with that name already exists” error, choose a different name or edit the existing label. - - +Label names must be unique per node. There are 10 color options: teal, blue, purple, rose, amber, green, orange, pink, cyan, and slate. diff --git a/docs/features/stack-management.mdx b/docs/features/stack-management.mdx index 299aee46..20c81e04 100644 --- a/docs/features/stack-management.mdx +++ b/docs/features/stack-management.mdx @@ -16,25 +16,25 @@ Click **Create Stack** in the left sidebar. Enter a name and click **Create**. **Naming rules:** - Lowercase letters, numbers, and hyphens only (e.g. `my-app`, `nextcloud`) - No spaces or special characters -- Must be unique - duplicates are rejected +- Must be unique; duplicates are rejected Sencho creates a new directory inside `COMPOSE_DIR` with a blank `compose.yaml` file. You'll land in the editor automatically. ## The stack list -All discovered stacks appear in the left sidebar. Each shows a color-coded status dot: +All discovered stacks appear in the left sidebar. Each shows a color-coded status indicator: -| Color | Meaning | -|-------|---------| -| Green | All containers running | -| Red | One or more containers exited | -| Gray | No containers / status unknown | +| Indicator | Meaning | +|-----------|---------| +| `UP` (green) | All containers running | +| `DN` (red) | One or more containers exited | +| No indicator | No containers / status unknown | Use the **search box** above the list to filter stacks by name. ## Deploying a stack -Select a stack and click **Deploy** in the stack header. This runs `docker compose up -d` - pulling images if needed and creating or recreating containers. +Select a stack and click **Start** (or **Deploy** from the context menu) in the stack header. This runs `docker compose up -d`, pulling images if needed and creating or recreating containers. Stack editor with control buttons @@ -42,26 +42,37 @@ Select a stack and click **Deploy** in the stack header. This runs `docker compo ## Controlling a running stack -The stack header exposes four actions: +The stack header shows different actions depending on whether the stack is running or stopped. + +**When running:** | Button | Command | What it does | |--------|---------|--------------| | **Stop** | `docker compose stop` | Stops containers without removing them. State is preserved. | | **Restart** | `docker compose restart` | Restarts all containers in the stack. | | **Update** | `docker compose pull` + `up -d` | Pulls the latest image tags and recreates containers. | +| **Rollback** | Restores backup | Reverts compose and env files to the pre-deploy snapshot and redeploys. Only shown when a backup exists (Pro). | | **Delete** | `down --volumes` + removes files | Stops and removes containers and volumes, then deletes the stack directory. | +**When stopped:** + +| Button | Command | What it does | +|--------|---------|--------------| +| **Start** | `docker compose up -d` | Starts the stack. | +| **Update** | `docker compose pull` + `up -d` | Pulls the latest image tags and recreates containers. | +| **Delete** | Removes files | Deletes the stack directory. | + - **Delete** is irreversible. It removes the stack directory - including `compose.yaml`, `.env`, and any bind-mounted files stored there. Back up important files before deleting. + **Delete** is irreversible. It removes the stack directory, including `compose.yaml`, `.env`, and any bind-mounted files stored there. Back up important files before deleting. - Stack directories often contain root-owned files — either because Docker Compose creates them, or because the stacks were originally set up outside of Sencho with `sudo`. Sencho handles this automatically: if a normal deletion fails due to permissions, it uses Docker to clean up root-owned files. No manual intervention is needed in the standard setup. + Stack directories often contain root-owned files, either because Docker Compose creates them, or because the stacks were originally set up outside of Sencho with `sudo`. Sencho handles this automatically: if a normal deletion fails due to permissions, it uses Docker to clean up root-owned files. No manual intervention is needed in the standard setup. ## Stack context menu -Right-click or use the **⋮** button on any stack in the sidebar. The menu adapts to the stack's current state — only relevant actions are shown. +Right-click any stack in the sidebar to open the context menu. The menu adapts to the stack's current state; only relevant actions are shown. **Running stack:** @@ -77,15 +88,15 @@ Right-click or use the **⋮** button on any stack in the sidebar. The menu adap ### Available actions -- **Alerts** — configure metric-based alerting rules for this stack -- **Labels** — assign organizational labels (Pro) -- **Check for updates** — manually trigger an image update check -- **Open App** — open the stack's web interface in a new tab (only shown when the stack is running and exposes a web port) -- **Deploy** — start the stack (shown when stopped or not yet deployed) -- **Stop** — stop all containers (shown when running) -- **Restart** — restart all containers (shown when running) -- **Update** — pull latest images and recreate containers (shown when running) -- **Delete** — stop and remove the stack (admin only) +- **Alerts** - configure metric-based alerting rules for this stack +- **Labels** - assign organizational labels (Pro) +- **Check for updates** - manually trigger an image update check +- **Open App** - open the stack's web interface in a new tab (only shown when the stack is running and exposes a web port) +- **Deploy** - start the stack (shown when stopped) +- **Stop** - stop all containers (shown when running) +- **Restart** - restart all containers (shown when running) +- **Update** - pull latest images and recreate containers (shown when running) +- **Delete** - stop and remove the stack (admin only) All actions are disabled while another operation is in progress on that stack. @@ -99,14 +110,10 @@ Click the **folder-search icon** next to the "Create Stack" button in the sideba Scan stacks folder button in the sidebar -- **New stacks detected** — a success notification lists the newly discovered stack names, and they appear immediately in the sidebar -- **Stacks removed from disk** — an informational notification lists stacks that are no longer present in the directory -- **No changes** — a notification confirms no new stacks were found +- **New stacks detected** - a success notification lists the newly discovered stack names, and they appear immediately in the sidebar +- **Stacks removed from disk** - an informational notification lists stacks that are no longer present in the directory +- **No changes** - a notification confirms no new stacks were found Any subdirectory inside your `COMPOSE_DIR` that contains a `compose.yaml`, `compose.yml`, `docker-compose.yaml`, or `docker-compose.yml` file is recognized as a valid stack. - -## Converting a `docker run` command - -If you have an existing `docker run` command and want to turn it into a Compose stack, go to the **Home** tab and paste it into the "Convert Docker Run to Compose" field. Sencho converts it to YAML that you can save as a new stack. diff --git a/docs/features/webhooks.mdx b/docs/features/webhooks.mdx index 22cdd507..7cfe92fd 100644 --- a/docs/features/webhooks.mdx +++ b/docs/features/webhooks.mdx @@ -4,47 +4,66 @@ description: Trigger stack actions from CI/CD pipelines via HTTP webhooks with H --- - Webhooks require a Sencho Pro license. + Webhooks require a **Sencho Admiral** license. -Sencho webhooks let external systems trigger stack actions over HTTP. The typical use case: your CI pipeline builds a new image, then calls a Sencho webhook to deploy the updated stack - no manual intervention required. +Sencho webhooks let external systems trigger stack actions over HTTP. The typical use case: your CI pipeline builds a new image, then calls a Sencho webhook to deploy the updated stack, with no manual intervention required. ## How it works -1. You create a webhook in **Settings → Webhooks**, targeting a specific stack and action +1. You create a webhook in **Settings > Webhooks**, targeting a specific stack and action 2. Sencho generates a unique secret for HMAC-SHA256 signature validation 3. Your CI/CD system sends a `POST` request to the trigger URL with the correct signature 4. Sencho validates the signature and executes the action asynchronously ## Creating a webhook - - Webhooks settings panel - +Go to **Settings > Webhooks** and click **Create Webhook**. Fill in: -Open **Settings → Webhooks** and click **Create Webhook**. Fill in: + + Webhook creation form with Name, Stack, and Action fields + | Field | Description | |-------|-------------| | **Name** | A display name (e.g. "Deploy on push") | | **Stack** | The target stack to act on | -| **Action** | One of: `deploy`, `restart`, `stop`, `start`, `pull` | +| **Action** | One of the actions listed below | -After creation, Sencho shows the webhook secret **once**. Copy it immediately - it cannot be retrieved later. +After creation, Sencho shows the webhook secret **once** in a green banner. Copy it immediately; it cannot be retrieved later. The webhook list only shows the last four characters of the secret. -### Actions explained + + Secret reveal banner after creating a webhook, showing the full secret and a copy button + + +### Available actions | Action | What it does | |--------|-------------| -| **Deploy** | Runs `docker compose down` then `docker compose up -d` (full redeploy) | -| **Restart** | Runs `docker compose restart` | -| **Stop** | Runs `docker compose stop` | -| **Start** | Runs `docker compose start` | -| **Pull** | Pulls latest images and recreates changed containers | +| **Deploy (down + up)** | Stops and redeploys the entire stack | +| **Restart** | Restarts the stack's running containers | +| **Stop** | Stops the stack | +| **Start** | Starts a stopped stack | +| **Pull & Update** | Pulls the latest images and recreates changed containers | + +## Managing webhooks + +Each webhook appears as a card showing the webhook name, an action badge, a stack badge, the trigger URL with a copy button, and the masked secret. + + + Webhooks settings showing a configured webhook with trigger URL, masked secret, and controls + + +From the webhook card you can: + +- **Toggle** the webhook on or off with the switch +- **Delete** the webhook with the trash icon +- **Copy** the trigger URL with the clipboard button +- **View execution history** by clicking **Recent executions** ## Triggering a webhook -Send a POST request to the trigger URL with an HMAC-SHA256 signature: +Send a `POST` request to the trigger URL shown on the webhook card. Include an HMAC-SHA256 signature in the `X-Webhook-Signature` header: ``` POST /api/webhooks/{id}/trigger @@ -52,7 +71,7 @@ Content-Type: application/json X-Webhook-Signature: sha256={hmac} ``` -The signature is computed as `HMAC-SHA256(request_body, webhook_secret)` and sent in the `X-Webhook-Signature` header with a `sha256=` prefix. +The signature is computed as `HMAC-SHA256(request_body, webhook_secret)` and sent with a `sha256=` prefix. ### Example with curl @@ -61,7 +80,7 @@ SECRET="your-webhook-secret" BODY='{}' SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2) -curl -X POST https://your-sencho.com/api/webhooks/3/trigger \ +curl -X POST https://your-sencho.example.com/api/webhooks/3/trigger \ -H "Content-Type: application/json" \ -H "X-Webhook-Signature: sha256=$SIGNATURE" \ -d "$BODY" @@ -75,6 +94,8 @@ By default, the webhook executes the action configured at creation time. You can { "action": "restart" } ``` +Valid override values are: `deploy`, `restart`, `stop`, `start`, `pull`. + ### Response A successful trigger returns `202 Accepted` immediately. The action executes asynchronously in the background. @@ -114,19 +135,20 @@ deploy: ## Execution history -Each webhook tracks its last 100 executions. Click **Recent executions** on any webhook row to see: +Each webhook tracks its recent executions. Click **Recent executions** on any webhook card to expand the history, which shows: -- Status (success/failure) -- Action performed -- Execution time -- Duration -- Error message (if failed) +- **Status** icon (green check for success, red X for failure) +- **Action** that was performed +- **Timestamp** of the execution +- **Duration** in seconds +- **Error message** if the execution failed ## Security -- Webhook secrets are 64-character hex strings generated with `crypto.randomBytes(32)` -- Signature validation uses `crypto.timingSafeEqual` to prevent timing attacks -- Secrets are shown only once at creation - API responses return masked values -- Signature verification uses the raw request bytes, not re-serialized JSON, to prevent serialization-induced mismatches -- Webhook trigger endpoints are public (no session cookie required) but protected by HMAC signature validation -- Each webhook targets a single stack - there is no way to execute arbitrary commands +- Secrets are shown only once at creation. The webhook list displays only the last four characters. +- Trigger endpoints do not require a session cookie, but are protected by HMAC signature validation. +- Each webhook targets a single stack. There is no way to execute arbitrary commands through a webhook. + + + Webhooks only operate on the **local node**. You cannot trigger actions on remote nodes through webhooks. + diff --git a/docs/getting-started/configuration.mdx b/docs/getting-started/configuration.mdx index d063af95..6526da96 100644 --- a/docs/getting-started/configuration.mdx +++ b/docs/getting-started/configuration.mdx @@ -25,6 +25,7 @@ When you point `COMPOSE_DIR` at a directory, Sencho expects each stack to live i |----------|---------|-------------| | `PORT` | `3000` | Port the Sencho HTTP server listens on. | | `DATA_DIR` | `/app/data` | Directory where Sencho stores its SQLite database, node registry, and cached metrics. | +| `FRONTEND_URL` | *(empty)* | Frontend origin for CORS. Only needed if the UI is served from a different domain than the API. Leave empty for same-origin setups. | | `NODE_ENV` | `production` | Set automatically in the Docker image. Only change this for local development. | ## SSO environment variables @@ -78,15 +79,15 @@ When Sencho runs `docker compose up`, it does so on your **host machine**. Docke ```yaml # ✅ Correct - host path matches container path volumes: - - /home/boris/docker:/home/boris/docker + - /home/user/docker:/home/user/docker environment: - - COMPOSE_DIR=/home/boris/docker + - COMPOSE_DIR=/home/user/docker ``` ```yaml # ❌ Wrong - paths differ, relative volumes will break volumes: - - /home/boris/docker:/app/compose + - /home/user/docker:/app/compose environment: - COMPOSE_DIR=/app/compose ``` diff --git a/docs/getting-started/introduction.mdx b/docs/getting-started/introduction.mdx index 35c54ded..1c2ac3fe 100644 --- a/docs/getting-started/introduction.mdx +++ b/docs/getting-started/introduction.mdx @@ -21,12 +21,38 @@ Sencho is a self-hosted Docker Compose management dashboard. It gives you a clea ## What you can do -- **Deploy and control stacks** - create, start, stop, restart, and delete Compose stacks with one click -- **Edit files in-browser** - full Monaco editor for `compose.yaml` and `.env` files -- **Monitor in real-time** - live CPU, RAM, disk, and network stats with historical charts -- **Stream logs** - tail container logs individually or aggregate all stacks in one view -- **Manage resources** - browse, filter, and prune Docker images, volumes, and networks -- **Deploy from the App Store** - one-click deployment from a curated template registry -- **Run a host console** - interactive terminal on the host OS directly in the browser -- **Set alerts** - threshold-based notifications via Discord, Slack, or any webhook -- **Manage multiple servers** - add remote Sencho instances as nodes and switch between them seamlessly +### Stack lifecycle +- **Deploy and control stacks** - create, start, stop, restart, update, roll back, and delete Compose stacks with one click +- **Edit files in-browser** - full Monaco editor for `compose.yaml` and `.env` files with syntax highlighting, save-and-deploy in one step +- **Atomic deployments** - automatic backup and rollback on every deploy. If containers crash, the previous configuration is restored automatically +- **Stack labels** - organize stacks with custom labels for quick filtering and grouping + +### Monitoring & observability +- **Real-time dashboard** - live CPU, RAM, disk, and network stats with 24-hour historical charts +- **Global log aggregation** - stream logs from all containers across all stacks in a single view, with filtering by stack, level, and keyword search +- **Alerts & notifications** - threshold-based alerts (CPU, memory, network, restart count) routed to Discord, Slack, or any webhook endpoint +- **Notification routing** - fine-grained control over which alerts go to which channels +- **Audit log** - searchable trail of every mutating action with timestamps, user attribution, and node context + +### Infrastructure +- **Multi-node management** - add remote Sencho instances as nodes and manage them identically to your local machine +- **Fleet view** - monitor your entire infrastructure from a single screen with health metrics, container counts, and resource usage +- **Fleet-wide backups** - point-in-time snapshots of every compose and env file across all nodes, with per-stack restore +- **Remote updates** - check for and apply Sencho updates across your fleet from the dashboard + +### Resources & registry +- **Resource hub** - browse, filter, and prune Docker images, volumes, and networks with managed/external/unused classification +- **App Store** - deploy from 190+ pre-configured application templates with category filtering and one-click setup +- **Private registries** - store credentials for Docker Hub, GHCR, AWS ECR, or self-hosted registries with automatic injection during deploys + +### Automation & integration +- **Webhooks** - trigger stack actions from CI/CD pipelines via HTTP with HMAC-SHA256 authentication +- **Scheduled operations** - run stack actions on a cron schedule directly from the UI +- **Auto-update policies** - configure automatic image update checks and apply updates on your terms +- **API tokens** - create scoped tokens for programmatic access and external integrations + +### Administration +- **RBAC** - create viewer accounts with read-only access while keeping deploy and edit permissions locked to admins +- **SSO** - authenticate via external identity providers +- **Host console** - interactive terminal on the host OS directly in the browser; no SSH required +- **Docker Run converter** - paste any `docker run` command and convert it to a Compose stack diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx index 0e5c05e4..49de298b 100644 --- a/docs/getting-started/quickstart.mdx +++ b/docs/getting-started/quickstart.mdx @@ -15,24 +15,26 @@ docker run -d \ --name sencho \ -p 3000:3000 \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v /opt/compose:/app/compose \ + -v /opt/compose:/opt/compose \ -v sencho_data:/app/data \ - -e JWT_SECRET=change-me \ + -e COMPOSE_DIR=/opt/compose \ saelix/sencho:latest ``` Open `http://localhost:3000` in your browser. On first boot you'll be prompted to create an admin account. - Replace `/opt/compose` with the path to your Compose projects directory. Every subdirectory inside it becomes a stack in Sencho. + Replace `/opt/compose` with the path to your Compose projects directory. Every subdirectory inside it becomes a stack in Sencho. A `JWT_SECRET` is generated automatically on first boot; you do not need to provide one. ## Important: the 1:1 path rule -The `-v /opt/compose:/app/compose` mount above uses a simplified path for illustration. In practice, you must mount your compose directory at the **same path** inside and outside the container. See the [Configuration guide](/getting-started/configuration#compose-directory-the-11-path-rule) for details - this is the most common setup mistake. +The compose directory must be mounted at the **same path** inside and outside the container. The example above mounts `/opt/compose` to `/opt/compose`, which is correct. If your stacks live at a different path, adjust both sides of the mount to match. See the [Configuration guide](/getting-started/configuration#compose-directory-the-11-path-rule) for details. ## Next steps -- [Configuration](/getting-started/configuration) - full environment variable reference, reverse proxy setup +- [Configuration](/getting-started/configuration) - environment variables, volume mounts, reverse proxy setup +- [Features Overview](/features/overview) - tour of everything Sencho can do - [Stack Management](/features/stack-management) - create and deploy your first stack - [Multi-Node](/features/multi-node) - add a remote server to manage from this dashboard +- [App Store](/features/app-store) - deploy from 190+ pre-configured templates diff --git a/docs/getting-started/sso-quickstart.mdx b/docs/getting-started/sso-quickstart.mdx index b2cb69d3..41fca73a 100644 --- a/docs/getting-started/sso-quickstart.mdx +++ b/docs/getting-started/sso-quickstart.mdx @@ -93,7 +93,7 @@ Restart Sencho. A "Google" button will appear on the login page. - SSO_LDAP_DEFAULT_ROLE=viewer ``` -After starting Sencho, verify the connection in **Settings → SSO → Test Connection**. +After starting Sencho, verify the connection in **Settings > SSO** using the **Test Connection** button. If your LDAP server is on the Docker host (not in a container), use the host's LAN IP or `host.docker.internal` (Docker Desktop) instead of `localhost`. diff --git a/docs/images/alerts-notifications/alert-panel-remote.png b/docs/images/alerts-notifications/alert-panel-remote.png deleted file mode 100644 index 82092341..00000000 Binary files a/docs/images/alerts-notifications/alert-panel-remote.png and /dev/null differ diff --git a/docs/images/alerts-notifications/alert-panel.png b/docs/images/alerts-notifications/alert-panel.png index d17c13dc..ee17fe0a 100644 Binary files a/docs/images/alerts-notifications/alert-panel.png and b/docs/images/alerts-notifications/alert-panel.png differ diff --git a/docs/images/alerts-notifications/notification-popover.png b/docs/images/alerts-notifications/notification-popover.png new file mode 100644 index 00000000..edee97c2 Binary files /dev/null and b/docs/images/alerts-notifications/notification-popover.png differ diff --git a/docs/images/alerts-notifications/notifications-settings.png b/docs/images/alerts-notifications/notifications-settings.png index 776d9315..593e0fe2 100644 Binary files a/docs/images/alerts-notifications/notifications-settings.png and b/docs/images/alerts-notifications/notifications-settings.png differ diff --git a/docs/images/api-tokens/api-tokens-overview.png b/docs/images/api-tokens/api-tokens-overview.png index 6bc52fa2..98ec2a05 100644 Binary files a/docs/images/api-tokens/api-tokens-overview.png and b/docs/images/api-tokens/api-tokens-overview.png differ diff --git a/docs/images/app-store/app-store-deploy.png b/docs/images/app-store/app-store-deploy.png new file mode 100644 index 00000000..4f60b9aa Binary files /dev/null and b/docs/images/app-store/app-store-deploy.png differ diff --git a/docs/images/app-store/app-store-overview.png b/docs/images/app-store/app-store-overview.png index 9cfb6cdf..7a43ff41 100644 Binary files a/docs/images/app-store/app-store-overview.png and b/docs/images/app-store/app-store-overview.png differ diff --git a/docs/images/audit-log/audit-log-expanded.png b/docs/images/audit-log/audit-log-expanded.png index c7dd66d7..247bfdb6 100644 Binary files a/docs/images/audit-log/audit-log-expanded.png and b/docs/images/audit-log/audit-log-expanded.png differ diff --git a/docs/images/audit-log/audit-log-overview.png b/docs/images/audit-log/audit-log-overview.png index 4fb26472..aae64823 100644 Binary files a/docs/images/audit-log/audit-log-overview.png and b/docs/images/audit-log/audit-log-overview.png differ diff --git a/docs/images/audit-log/data-retention.png b/docs/images/audit-log/data-retention.png new file mode 100644 index 00000000..acaba573 Binary files /dev/null and b/docs/images/audit-log/data-retention.png differ diff --git a/docs/images/auto-update-policies/create-dialog.png b/docs/images/auto-update-policies/create-dialog.png index d865f8b7..1caae430 100644 Binary files a/docs/images/auto-update-policies/create-dialog.png and b/docs/images/auto-update-policies/create-dialog.png differ diff --git a/docs/images/auto-update-policies/overview.png b/docs/images/auto-update-policies/overview.png index 0f371815..9c35279b 100644 Binary files a/docs/images/auto-update-policies/overview.png and b/docs/images/auto-update-policies/overview.png differ diff --git a/docs/images/dashboard/dashboard-overview.png b/docs/images/dashboard/dashboard-overview.png index 48affe02..137c9499 100644 Binary files a/docs/images/dashboard/dashboard-overview.png and b/docs/images/dashboard/dashboard-overview.png differ diff --git a/docs/images/editor/container-actions.png b/docs/images/editor/container-actions.png index a10ffa55..304bbed9 100644 Binary files a/docs/images/editor/container-actions.png and b/docs/images/editor/container-actions.png differ diff --git a/docs/images/editor/editor-overview.png b/docs/images/editor/editor-overview.png index 777de8a1..cbdf5a36 100644 Binary files a/docs/images/editor/editor-overview.png and b/docs/images/editor/editor-overview.png differ diff --git a/docs/images/fleet-backups/browse-snapshots.png b/docs/images/fleet-backups/browse-snapshots.png index e71a0f00..8e725d7d 100644 Binary files a/docs/images/fleet-backups/browse-snapshots.png and b/docs/images/fleet-backups/browse-snapshots.png differ diff --git a/docs/images/fleet-backups/create-snapshot.png b/docs/images/fleet-backups/create-snapshot.png index 1d4f6953..bb40cef2 100644 Binary files a/docs/images/fleet-backups/create-snapshot.png and b/docs/images/fleet-backups/create-snapshot.png differ diff --git a/docs/images/fleet-backups/restore-dialog.png b/docs/images/fleet-backups/restore-dialog.png new file mode 100644 index 00000000..bb5c3639 Binary files /dev/null and b/docs/images/fleet-backups/restore-dialog.png differ diff --git a/docs/images/fleet-backups/snapshot-detail.png b/docs/images/fleet-backups/snapshot-detail.png new file mode 100644 index 00000000..7a79dfdd Binary files /dev/null and b/docs/images/fleet-backups/snapshot-detail.png differ diff --git a/docs/images/fleet-view/fleet-container-detail.png b/docs/images/fleet-view/fleet-container-detail.png new file mode 100644 index 00000000..782097e8 Binary files /dev/null and b/docs/images/fleet-view/fleet-container-detail.png differ diff --git a/docs/images/fleet-view/fleet-drill-down.png b/docs/images/fleet-view/fleet-drill-down.png index 9fc039e0..66be35ed 100644 Binary files a/docs/images/fleet-view/fleet-drill-down.png and b/docs/images/fleet-view/fleet-drill-down.png differ diff --git a/docs/images/fleet-view/fleet-node-updates.png b/docs/images/fleet-view/fleet-node-updates.png new file mode 100644 index 00000000..2f8f23d2 Binary files /dev/null and b/docs/images/fleet-view/fleet-node-updates.png differ diff --git a/docs/images/fleet-view/fleet-overview.png b/docs/images/fleet-view/fleet-overview.png index 55ee8cbf..75c38949 100644 Binary files a/docs/images/fleet-view/fleet-overview.png and b/docs/images/fleet-view/fleet-overview.png differ diff --git a/docs/images/fleet/check-updates-modal.png b/docs/images/fleet/check-updates-modal.png deleted file mode 100644 index 4db54871..00000000 Binary files a/docs/images/fleet/check-updates-modal.png and /dev/null differ diff --git a/docs/images/fleet/fleet-update-available.png b/docs/images/fleet/fleet-update-available.png deleted file mode 100644 index add0e127..00000000 Binary files a/docs/images/fleet/fleet-update-available.png and /dev/null differ diff --git a/docs/images/global-observability/global-observability-overview.png b/docs/images/global-observability/global-observability-overview.png index 82e6ca2f..2563f1b7 100644 Binary files a/docs/images/global-observability/global-observability-overview.png and b/docs/images/global-observability/global-observability-overview.png differ diff --git a/docs/images/host-console/host-console-overview.png b/docs/images/host-console/host-console-overview.png index 1a23242a..864b3fcc 100644 Binary files a/docs/images/host-console/host-console-overview.png and b/docs/images/host-console/host-console-overview.png differ diff --git a/docs/images/license-settings.png b/docs/images/license-settings.png deleted file mode 100644 index a2011afd..00000000 Binary files a/docs/images/license-settings.png and /dev/null differ diff --git a/docs/images/licensing/license-active.png b/docs/images/licensing/license-active.png new file mode 100644 index 00000000..85117aa8 Binary files /dev/null and b/docs/images/licensing/license-active.png differ diff --git a/docs/images/licensing/license-community.png b/docs/images/licensing/license-community.png new file mode 100644 index 00000000..514dc16c Binary files /dev/null and b/docs/images/licensing/license-community.png differ diff --git a/docs/images/licensing/profile-billing.png b/docs/images/licensing/profile-billing.png new file mode 100644 index 00000000..7e9d5b54 Binary files /dev/null and b/docs/images/licensing/profile-billing.png differ diff --git a/docs/images/multi-node/add-node-form.png b/docs/images/multi-node/add-node-form.png index 9c358ead..a47a34f9 100644 Binary files a/docs/images/multi-node/add-node-form.png and b/docs/images/multi-node/add-node-form.png differ diff --git a/docs/images/multi-node/http-warning.png b/docs/images/multi-node/http-warning.png index 48351e7e..39f661b9 100644 Binary files a/docs/images/multi-node/http-warning.png and b/docs/images/multi-node/http-warning.png differ diff --git a/docs/images/multi-node/node-manager.png b/docs/images/multi-node/node-manager.png index e8dbb496..5cd7be51 100644 Binary files a/docs/images/multi-node/node-manager.png and b/docs/images/multi-node/node-manager.png differ diff --git a/docs/images/multi-node/node-switcher-dropdown.png b/docs/images/multi-node/node-switcher-dropdown.png index ce790223..13dac7bf 100644 Binary files a/docs/images/multi-node/node-switcher-dropdown.png and b/docs/images/multi-node/node-switcher-dropdown.png differ diff --git a/docs/images/networks/create-network.png b/docs/images/networks/create-network.png index 4a8cf154..7ee7aac6 100644 Binary files a/docs/images/networks/create-network.png and b/docs/images/networks/create-network.png differ diff --git a/docs/images/networks/network-inspect.png b/docs/images/networks/network-inspect.png index 2d75faac..059f7997 100644 Binary files a/docs/images/networks/network-inspect.png and b/docs/images/networks/network-inspect.png differ diff --git a/docs/images/networks/network-topology.png b/docs/images/networks/network-topology.png index 953749ee..4b190240 100644 Binary files a/docs/images/networks/network-topology.png and b/docs/images/networks/network-topology.png differ diff --git a/docs/images/networks/networks-list.png b/docs/images/networks/networks-list.png index 9d485146..c143ae85 100644 Binary files a/docs/images/networks/networks-list.png and b/docs/images/networks/networks-list.png differ diff --git a/docs/images/notification-routing/notification-routing-dialog.png b/docs/images/notification-routing/notification-routing-dialog.png index d1944cfe..06a123d4 100644 Binary files a/docs/images/notification-routing/notification-routing-dialog.png and b/docs/images/notification-routing/notification-routing-dialog.png differ diff --git a/docs/images/notification-routing/notification-routing-overview.png b/docs/images/notification-routing/notification-routing-overview.png index 04665e1e..a2086949 100644 Binary files a/docs/images/notification-routing/notification-routing-overview.png and b/docs/images/notification-routing/notification-routing-overview.png differ diff --git a/docs/images/per-node-scheduling/nodes-table-overview.png b/docs/images/per-node-scheduling/nodes-table-overview.png index d9a40ff8..e054794a 100644 Binary files a/docs/images/per-node-scheduling/nodes-table-overview.png and b/docs/images/per-node-scheduling/nodes-table-overview.png differ diff --git a/docs/images/private-registries/registries-add-form.png b/docs/images/private-registries/registries-add-form.png index 2dc214c9..a4f8eb27 100644 Binary files a/docs/images/private-registries/registries-add-form.png and b/docs/images/private-registries/registries-add-form.png differ diff --git a/docs/images/private-registries/registries-with-entry.png b/docs/images/private-registries/registries-with-entry.png index bc73510c..c8ee6f0a 100644 Binary files a/docs/images/private-registries/registries-with-entry.png and b/docs/images/private-registries/registries-with-entry.png differ diff --git a/docs/images/rbac/role-selector-dropdown.png b/docs/images/rbac/role-selector-dropdown.png index 2b5aa36e..3e79b496 100644 Binary files a/docs/images/rbac/role-selector-dropdown.png and b/docs/images/rbac/role-selector-dropdown.png differ diff --git a/docs/images/rbac/role-selector.png b/docs/images/rbac/role-selector.png deleted file mode 100644 index 13170fea..00000000 Binary files a/docs/images/rbac/role-selector.png and /dev/null differ diff --git a/docs/images/rbac/user-create-form.png b/docs/images/rbac/user-create-form.png index 6112111a..6d32cfc2 100644 Binary files a/docs/images/rbac/user-create-form.png and b/docs/images/rbac/user-create-form.png differ diff --git a/docs/images/rbac/users-list.png b/docs/images/rbac/users-list.png new file mode 100644 index 00000000..c2d7ad0c Binary files /dev/null and b/docs/images/rbac/users-list.png differ diff --git a/docs/images/rbac/users-settings.png b/docs/images/rbac/users-settings.png deleted file mode 100644 index 6084cfc6..00000000 Binary files a/docs/images/rbac/users-settings.png and /dev/null differ diff --git a/docs/images/resources/resources-overview.png b/docs/images/resources/resources-overview.png index 77189b2d..139e7eca 100644 Binary files a/docs/images/resources/resources-overview.png and b/docs/images/resources/resources-overview.png differ diff --git a/docs/images/scheduled-operations/create-dialog.png b/docs/images/scheduled-operations/create-dialog.png index d2ebd0a4..46376d48 100644 Binary files a/docs/images/scheduled-operations/create-dialog.png and b/docs/images/scheduled-operations/create-dialog.png differ diff --git a/docs/images/scheduled-operations/overview.png b/docs/images/scheduled-operations/overview.png index ced9b124..0abbbf47 100644 Binary files a/docs/images/scheduled-operations/overview.png and b/docs/images/scheduled-operations/overview.png differ diff --git a/docs/images/scheduled-operations/per-service-restart.png b/docs/images/scheduled-operations/per-service-restart.png index 5df3d9b3..e3c155a6 100644 Binary files a/docs/images/scheduled-operations/per-service-restart.png and b/docs/images/scheduled-operations/per-service-restart.png differ diff --git a/docs/images/scheduled-operations/prune-label-filter.png b/docs/images/scheduled-operations/prune-label-filter.png index 46995e54..fbcbc051 100644 Binary files a/docs/images/scheduled-operations/prune-label-filter.png and b/docs/images/scheduled-operations/prune-label-filter.png differ diff --git a/docs/images/scheduled-operations/run-history.png b/docs/images/scheduled-operations/run-history.png index d55d3583..b57c5b15 100644 Binary files a/docs/images/scheduled-operations/run-history.png and b/docs/images/scheduled-operations/run-history.png differ diff --git a/docs/images/settings/settings-overview.png b/docs/images/settings/settings-overview.png index b8bf4e28..ea5bbfce 100644 Binary files a/docs/images/settings/settings-overview.png and b/docs/images/settings/settings-overview.png differ diff --git a/docs/images/sso/sso-settings-ldap.png b/docs/images/sso/sso-settings-ldap.png index 98b2b6c2..1d53e884 100644 Binary files a/docs/images/sso/sso-settings-ldap.png and b/docs/images/sso/sso-settings-ldap.png differ diff --git a/docs/images/sso/sso-settings-oidc.png b/docs/images/sso/sso-settings-oidc.png index 2f79d805..3e1a516d 100644 Binary files a/docs/images/sso/sso-settings-oidc.png and b/docs/images/sso/sso-settings-oidc.png differ diff --git a/docs/images/sso/sso-settings.png b/docs/images/sso/sso-settings.png index 54f2e0f4..02ee695d 100644 Binary files a/docs/images/sso/sso-settings.png and b/docs/images/sso/sso-settings.png differ diff --git a/docs/images/stack-labels/bulk-actions-menu.png b/docs/images/stack-labels/bulk-actions-menu.png new file mode 100644 index 00000000..2bbdf770 Binary files /dev/null and b/docs/images/stack-labels/bulk-actions-menu.png differ diff --git a/docs/images/stack-labels/context-menu-label-submenu-open.png b/docs/images/stack-labels/context-menu-label-submenu-open.png deleted file mode 100644 index bd3a9f32..00000000 Binary files a/docs/images/stack-labels/context-menu-label-submenu-open.png and /dev/null differ diff --git a/docs/images/stack-labels/context-menu-labels-submenu.png b/docs/images/stack-labels/context-menu-labels-submenu.png deleted file mode 100644 index d8f7ee05..00000000 Binary files a/docs/images/stack-labels/context-menu-labels-submenu.png and /dev/null differ diff --git a/docs/images/stack-labels/context-menu-labels.png b/docs/images/stack-labels/context-menu-labels.png new file mode 100644 index 00000000..82ffcdb3 Binary files /dev/null and b/docs/images/stack-labels/context-menu-labels.png differ diff --git a/docs/images/stack-labels/create-label-dialog.png b/docs/images/stack-labels/create-label-dialog.png new file mode 100644 index 00000000..21030bb2 Binary files /dev/null and b/docs/images/stack-labels/create-label-dialog.png differ diff --git a/docs/images/stack-labels/label-assign-popover.png b/docs/images/stack-labels/label-assign-popover.png deleted file mode 100644 index 3d01f4df..00000000 Binary files a/docs/images/stack-labels/label-assign-popover.png and /dev/null differ diff --git a/docs/images/stack-labels/settings-labels-fixed.png b/docs/images/stack-labels/settings-labels-fixed.png deleted file mode 100644 index 7656a537..00000000 Binary files a/docs/images/stack-labels/settings-labels-fixed.png and /dev/null differ diff --git a/docs/images/stack-labels/settings-labels-section.png b/docs/images/stack-labels/settings-labels-section.png deleted file mode 100644 index d749e6ef..00000000 Binary files a/docs/images/stack-labels/settings-labels-section.png and /dev/null differ diff --git a/docs/images/stack-labels/settings-labels.png b/docs/images/stack-labels/settings-labels.png new file mode 100644 index 00000000..b8e0e82b Binary files /dev/null and b/docs/images/stack-labels/settings-labels.png differ diff --git a/docs/images/stack-labels/sidebar-filtered-by-label.png b/docs/images/stack-labels/sidebar-filtered-by-label.png deleted file mode 100644 index 067a40da..00000000 Binary files a/docs/images/stack-labels/sidebar-filtered-by-label.png and /dev/null differ diff --git a/docs/images/stack-labels/sidebar-filtered.png b/docs/images/stack-labels/sidebar-filtered.png new file mode 100644 index 00000000..9dc14124 Binary files /dev/null and b/docs/images/stack-labels/sidebar-filtered.png differ diff --git a/docs/images/stack-labels/sidebar-label-pill-bar.png b/docs/images/stack-labels/sidebar-label-pill-bar.png deleted file mode 100644 index ad20acea..00000000 Binary files a/docs/images/stack-labels/sidebar-label-pill-bar.png and /dev/null differ diff --git a/docs/images/stack-labels/sidebar-with-label-dots.png b/docs/images/stack-labels/sidebar-with-label-dots.png deleted file mode 100644 index ba2cfdb9..00000000 Binary files a/docs/images/stack-labels/sidebar-with-label-dots.png and /dev/null differ diff --git a/docs/images/stack-labels/sidebar-with-labels.png b/docs/images/stack-labels/sidebar-with-labels.png new file mode 100644 index 00000000..cc17573d Binary files /dev/null and b/docs/images/stack-labels/sidebar-with-labels.png differ diff --git a/docs/images/stack-management/context-menu-running.png b/docs/images/stack-management/context-menu-running.png index 3a6847ea..5465a425 100644 Binary files a/docs/images/stack-management/context-menu-running.png and b/docs/images/stack-management/context-menu-running.png differ diff --git a/docs/images/stack-management/context-menu-stopped.png b/docs/images/stack-management/context-menu-stopped.png index 58ff0dd2..225a22ec 100644 Binary files a/docs/images/stack-management/context-menu-stopped.png and b/docs/images/stack-management/context-menu-stopped.png differ diff --git a/docs/images/stack-management/create-stack-dialog.png b/docs/images/stack-management/create-stack-dialog.png index 029b246e..24738083 100644 Binary files a/docs/images/stack-management/create-stack-dialog.png and b/docs/images/stack-management/create-stack-dialog.png differ diff --git a/docs/images/stack-scanning/scan-button-sidebar.png b/docs/images/stack-scanning/scan-button-sidebar.png index b2e12a68..532006f9 100644 Binary files a/docs/images/stack-scanning/scan-button-sidebar.png and b/docs/images/stack-scanning/scan-button-sidebar.png differ diff --git a/docs/images/webhooks/webhooks-create-form.png b/docs/images/webhooks/webhooks-create-form.png new file mode 100644 index 00000000..598b814e Binary files /dev/null and b/docs/images/webhooks/webhooks-create-form.png differ diff --git a/docs/images/webhooks/webhooks-secret-reveal.png b/docs/images/webhooks/webhooks-secret-reveal.png new file mode 100644 index 00000000..976caf6a Binary files /dev/null and b/docs/images/webhooks/webhooks-secret-reveal.png differ diff --git a/docs/images/webhooks/webhooks-settings.png b/docs/images/webhooks/webhooks-settings.png index a891fa5a..5f4e6d9c 100644 Binary files a/docs/images/webhooks/webhooks-settings.png and b/docs/images/webhooks/webhooks-settings.png differ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 055285fe..805c6f8e 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1828,7 +1828,7 @@ paths: operationId: getNodeMeta tags: [Nodes] summary: Get node capabilities - description: Returns the version and supported capabilities for a specific node. For local nodes, returns this instance's own metadata. For remote nodes, relays the response from the remote instance's `/api/meta` endpoint. Returns `{ version: null, capabilities: [] }` if the remote node is offline or doesn't support the meta endpoint. + description: "Returns the version and supported capabilities for a specific node. For local nodes, returns this instance's own metadata. For remote nodes, relays the response from the remote instance's `/api/meta` endpoint. Returns `{ version: null, capabilities: [] }` if the remote node is offline or doesn't support the meta endpoint." parameters: - $ref: "#/components/parameters/idPath" responses: diff --git a/docs/operations/backup.mdx b/docs/operations/backup.mdx index e4e4582c..e1c37450 100644 --- a/docs/operations/backup.mdx +++ b/docs/operations/backup.mdx @@ -3,7 +3,11 @@ 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. +Sencho stores all its state in two places: the **data directory** (SQLite database and encryption key) and your **compose directory** (your actual stack files). Both need to be backed up for a complete recovery. + + + Skipper and Admiral users also have access to [Fleet-Wide Backups](/features/fleet-backups), which snapshot compose files across all nodes directly from the dashboard. This page covers lower-level backup of the Sencho instance itself. + --- @@ -14,15 +18,18 @@ Sencho stores all its state in two places: the **data directory** (SQLite databa 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 +- `sencho.db` - SQLite database with all settings, users, nodes, alerts, metrics history, and notification config +- `encryption.key` - Key used to encrypt sensitive values (registry credentials, node API tokens) stored in the database -This single file is everything Sencho knows about itself. Back it up and you can fully restore any Sencho installation. + + Both files are required for a full restore. If you restore `sencho.db` without the matching `encryption.key`, any encrypted values in the database will be unreadable and you will need to re-enter registry credentials and re-generate node API tokens. + ### 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. +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. +This is your actual application data. It lives entirely outside Sencho and you almost certainly already back it up on a schedule, but include it in any Sencho backup plan. --- @@ -34,7 +41,7 @@ This is your actual application data. It lives entirely outside Sencho and you a # Stop Sencho to ensure no active transactions (recommended but not strictly required) docker stop sencho -# Copy the data directory +# Copy the data directory (includes both sencho.db and encryption.key) cp -r /path/to/sencho-data /path/to/backup/sencho-data-$(date +%Y%m%d) # Copy compose stacks @@ -45,7 +52,7 @@ docker start sencho ``` - Sencho uses SQLite's default journal mode (not WAL), so you will not see `-wal` or `-shm` sidecar files alongside `sencho.db`. If a `-journal` file exists when you copy, it indicates an interrupted write — SQLite will automatically resolve it the next time the database is opened. + Sencho uses SQLite's default journal mode (not WAL), so you will not see `-wal` or `-shm` sidecar files alongside `sencho.db`. If a `-journal` file exists when you copy, it indicates an interrupted write. SQLite will automatically resolve it the next time the database is opened. ### SQLite online backup (without stopping) @@ -56,13 +63,15 @@ SQLite supports hot backups via its `.backup` command. This is safe to run while sqlite3 /path/to/sencho-data/sencho.db ".backup '/path/to/backup/sencho.db'" ``` +Remember to also copy `encryption.key` from the same directory. + ### 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 +0 3 * * * cp /path/to/sencho-data/encryption.key /backups/encryption.key && 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. +This copies the encryption key, backs up the database at 3 AM daily, and deletes database backups older than 30 days. --- @@ -79,6 +88,7 @@ This backs up the database at 3 AM daily and deletes backups older than 30 days. ```bash rm -rf /path/to/sencho-data/* cp /path/to/backup/sencho.db /path/to/sencho-data/sencho.db + cp /path/to/backup/encryption.key /path/to/sencho-data/encryption.key ``` 3. Restore your compose directory if needed: @@ -135,9 +145,5 @@ If other Sencho instances were pointing to your old host as a remote node, updat | 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 | +| 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/self-hosting.mdx b/docs/operations/self-hosting.mdx index 8b055a66..25d13487 100644 --- a/docs/operations/self-hosting.mdx +++ b/docs/operations/self-hosting.mdx @@ -5,7 +5,7 @@ description: Volume mounts, Docker socket security, networking, and resource rec ## The 1:1 path rule -This is the most common setup mistake. When Sencho deploys a Docker Compose stack, Docker resolves bind-mount volume paths relative to the **host filesystem**, not the Sencho container. If your compose files reference relative paths like `./data:/app/data`, Docker looks for `./data` on the host — starting from the directory where the compose file lives on the host. +This is the most common setup mistake. When Sencho deploys a Docker Compose stack, Docker resolves bind-mount volume paths relative to the **host filesystem**, not the Sencho container. If your compose files reference relative paths like `./data:/app/data`, Docker looks for `./data` on the host, starting from the directory where the compose file lives on the host. This means the path to your compose directory **must be identical** inside and outside the container: @@ -32,12 +32,12 @@ Sencho requires three volume mounts to function correctly: | Mount | Purpose | Required | |-------|---------|----------| | `/var/run/docker.sock:/var/run/docker.sock` | Docker Engine access for managing containers | Yes | -| `./sencho-data:/app/data` | Persistent storage for SQLite database and encryption keys | Yes | +| `./sencho-data:/app/data` | Persistent storage for the database and encryption key | Yes | | `/opt/compose:/opt/compose` | Your compose project files (must follow 1:1 path rule) | Yes | - - The data directory contains your Sencho database and encryption keys. Losing this directory means losing your Sencho configuration entirely. - + + The data directory contains your Sencho database (`sencho.db`) and encryption key (`encryption.key`). Losing this directory means losing your Sencho configuration entirely. See the [Backup & Restore guide](/operations/backup) for backup procedures. + --- @@ -48,7 +48,7 @@ Mounting the Docker socket (`/var/run/docker.sock`) grants the container the abi Sencho mitigates this with privilege dropping: 1. The container starts as root to fix volume ownership and resolve Docker socket group permissions -2. The entrypoint script (`docker-entrypoint.sh`) then drops to a non-root `sencho` user via `su-exec` +2. The entrypoint script then drops to a non-root `sencho` user 3. All application code runs as the `sencho` user If your environment requires stricter isolation, consider: @@ -63,9 +63,9 @@ If your environment requires stricter isolation, consider: | Resource | Minimum | Recommended | Notes | |----------|---------|-------------|-------| -| CPU | 1 core | 1-2 cores | More cores help with concurrent stack operations | -| RAM | 256 MB | 512 MB | Higher for multi-node setups with many stacks | -| Disk | 100 MB | 500 MB | Database is typically < 50 MB; allocate headroom for metrics retention | +| CPU | 1 core | 2 cores | Compose operations spawn child processes that benefit from a second core | +| RAM | 128 MB | 256 MB | Baseline is around 100 MB at idle; increases with concurrent log streams and large fleets | +| Disk | 200 MB | 500 MB | The Docker image is around 200 MB; the database grows with metrics retention and fleet size | Sencho itself is lightweight. The majority of resource usage on your host comes from the Docker containers it manages, not from Sencho. @@ -73,7 +73,7 @@ Sencho itself is lightweight. The majority of resource usage on your host comes ## Networking -- **Listen port:** 3000 by default, configurable via the `PORT` environment variable +- **Listen port:** 3000 (fixed). Map it to any host port using Docker's `-p` flag or `ports` in your compose file - **Inbound:** Only the listen port needs to be reachable (directly or through a reverse proxy) - **Outbound:** No outbound connections are required for local-only setups. If you use multi-node management, Sencho needs HTTP/HTTPS access to remote Sencho instances on their configured API URLs - **Health check:** `GET /api/health` returns `200` when the application is ready. The Docker image includes a built-in `HEALTHCHECK` that polls this endpoint every 30 seconds @@ -86,11 +86,10 @@ Quick reference for all environment variables. See [Configuration](/getting-star | Variable | Default | Description | |----------|---------|-------------| -| `JWT_SECRET` | *(required)* | Secret key for signing JWT tokens | | `COMPOSE_DIR` | `/app/compose` | Path to compose project files (1:1 rule applies) | -| `PORT` | `3000` | HTTP server listen port | | `DATA_DIR` | `/app/data` | Persistent data directory | -| `NODE_ENV` | `production` | Set automatically in Docker image | | `FRONTEND_URL` | *(empty)* | Frontend origin for CORS; leave empty for same-origin | +| `API_RATE_LIMIT` | `100` | Maximum API requests per minute per IP (production only) | +| `NODE_ENV` | `production` | Set automatically in the Docker image | SSO variables are documented separately in the [SSO Quickstart](/getting-started/sso-quickstart). diff --git a/docs/operations/troubleshooting.mdx b/docs/operations/troubleshooting.mdx index 796dd58f..6dad324e 100644 --- a/docs/operations/troubleshooting.mdx +++ b/docs/operations/troubleshooting.mdx @@ -61,19 +61,19 @@ 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. +If the group is not `docker`, the auto-detection still works. Sencho reads the GID from the socket file at startup. --- ## "Permission denied" when deleting a stack -**Symptom:** Clicking Delete on a stack fails with a permission error mentioning `EACCES`. +**Symptom:** Clicking **Delete** on a stack fails with a permission error. -**Cause:** Stack directories often contain files owned by root — for example when Docker Compose was run with `sudo`, or when containers write config/data files into the stack directory. Since Sencho runs as a non-root user, the OS denies the removal. +**Cause:** Stack directories often contain files owned by root, for example when Docker Compose was run with `sudo`, or when containers write config/data files into the stack directory. Since Sencho runs as a non-root user, the OS denies the removal. This is especially common when installing Sencho on a server where stacks were originally created outside of Sencho (e.g. via `sudo docker compose up`). Those directories and their contents are root-owned, but Sencho can still delete them. -**How Sencho handles it:** Sencho automatically detects permission errors during deletion and falls back to a Docker-based cleanup. It spawns a short-lived Alpine container that bind-mounts the stack directory and removes the root-owned files. This happens transparently — no manual intervention is needed in the standard Docker setup. +**How Sencho handles it:** Sencho automatically detects permission errors during deletion and falls back to a Docker-based cleanup. It spawns a short-lived container that bind-mounts the stack directory and removes the root-owned files. This happens transparently, with no manual intervention needed in the standard Docker setup. **If automatic cleanup fails:** The error message will include the directory path. Remove it manually: @@ -81,7 +81,7 @@ This is especially common when installing Sencho on a server where stacks were o sudo rm -rf /path/to/your/compose/dir/stack-name ``` -**Prerequisites:** The Docker socket must be mounted (standard setup). If Sencho cannot access Docker, the fallback will not work — see [Permission denied on the Docker socket](#permission-denied-on-the-docker-socket). +**Prerequisites:** The Docker socket must be mounted (standard setup). If Sencho cannot access Docker, the fallback will not work. See ["Permission denied" on the Docker socket](#permission-denied-on-the-docker-socket). --- @@ -99,6 +99,26 @@ sudo rm -rf /path/to/your/compose/dir/stack-name --- +## Forgotten admin password + +Sencho has no password recovery flow. To regain access: + +1. Stop the Sencho container. +2. Delete the database file inside your data directory (`sencho.db`). You can find it in the volume you mounted to `/app/data`. + +```bash +# Example, adjust the path to match your data volume mount +rm /path/to/data/sencho.db +``` + +3. Restart the container. Sencho will detect the missing database and re-enter first-boot setup mode, prompting you to create a new admin account. + + + This resets all Sencho configuration: users, nodes, alert rules, notification settings, and labels. Your Docker stacks and their compose files are not affected (they live in `COMPOSE_DIR`, not the database). Sencho will re-discover your stacks on the next sidebar scan. + + +--- + ## 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. @@ -115,7 +135,7 @@ proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; ``` -Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends - no extra config needed. +Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends, so no extra config is needed. --- @@ -126,59 +146,34 @@ Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends - no extr **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`. +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. +To re-test connectivity after making changes, open **Profile > Settings > Nodes** and click the **wifi icon** on the node row. --- -## Pro features return 403 on remote nodes +## Paid features return 403 on remote nodes -**Symptom:** A Pro or Admiral feature works on the local node but returns "This feature requires Sencho Pro" (403) when you switch to a remote node. +**Symptom:** A Skipper or Admiral feature works on the local node but returns a 403 error when you switch to a remote node. **Checks in order:** -1. **Is your primary instance licensed?** Go to **Settings > License** on the primary instance and verify it shows an active Skipper or Admiral license. Remote nodes inherit the primary's tier — if the primary is on Community, all remote nodes will be Community too. +1. **Is your primary instance licensed?** Open **Profile > Settings > License** on the primary instance and verify it shows an active Skipper or Admiral license. Remote nodes inherit the primary's tier; if the primary is on Community, all remote nodes will be Community too. 2. **Is the remote node's token valid?** An expired or revoked token prevents the license tier from being transmitted. Regenerate the token on the remote instance and update the node config on the primary. -3. **Is the remote node running an up-to-date version of Sencho?** Distributed license enforcement requires both the primary and remote instances to be on v0.34.0 or later. Update the remote node if it's on an older version. +3. **Is the remote node running an up-to-date version of Sencho?** Distributed license enforcement requires both the primary and remote instances to be on a compatible version. Update the remote node if it's outdated. 4. **Are you accessing the remote node directly?** If you navigate directly to the remote Sencho instance's URL (bypassing the primary), it uses its own local license. License inheritance only works through the primary's proxy. --- -## 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. - - ---- - ## Scan stacks folder doesn't find my stacks **Symptom:** You placed Docker Compose files in the stacks directory and clicked the scan button, but "No new stacks found" appears. **Checks in order:** -1. **Is the compose file in a subdirectory?** Sencho only discovers stacks inside subdirectories of `COMPOSE_DIR`. A loose `compose.yaml` sitting directly in the root of `COMPOSE_DIR` is ignored — each stack must be in its own folder (e.g. `COMPOSE_DIR/my-app/compose.yaml`). +1. **Is the compose file in a subdirectory?** Sencho only discovers stacks inside subdirectories of `COMPOSE_DIR`. A loose `compose.yaml` sitting directly in the root of `COMPOSE_DIR` is ignored. Each stack must be in its own folder (e.g. `COMPOSE_DIR/my-app/compose.yaml`). 2. **Is the compose file named correctly?** Sencho recognizes these filenames only: - `compose.yaml` @@ -194,25 +189,15 @@ DELETE FROM global_settings WHERE key IN ('auth_username', 'auth_password_hash', --- -## Network creation fails with "name is required" +## Network creation fails -**Symptom:** Clicking Create in the Create Network dialog returns an error about a missing name. +**Symptom:** Clicking **Create** in the Create Network dialog returns an error about a missing or invalid name. -**Cause:** The network name field was left empty or contains only whitespace. +**Rules for network names:** -**Fix:** Enter a valid network name. Names must be non-empty and can contain letters, numbers, hyphens (`-`), underscores (`_`), and dots (`.`). Names cannot start with a dot or hyphen. - ---- - -## Network creation fails with "invalid name" - -**Symptom:** You enter a network name but the API rejects it as invalid. - -**Cause:** The name contains characters that are not allowed, or starts with a special character. - -**Allowed characters:** Letters, numbers, hyphens, underscores, and dots. The name must start with a letter, number, or underscore. - -**Examples:** +- Names must be non-empty and cannot contain only whitespace. +- Allowed characters: letters, numbers, hyphens (`-`), underscores (`_`), and dots (`.`). +- Names must start with a letter, number, or underscore. They cannot start with a dot or hyphen. | Name | Valid? | Reason | |------|--------|--------| @@ -229,25 +214,29 @@ DELETE FROM global_settings WHERE key IN ('auth_username', 'auth_password_hash', **Symptom:** The delete button is missing or disabled for certain networks. -**Expected behavior:** Docker system networks (`bridge`, `host`, `none`) cannot be deleted — they are created by the Docker daemon and are required for normal operation. Sencho intentionally hides the delete action for these networks. +**Expected behavior:** Docker system networks (`bridge`, `host`, `none`) cannot be deleted. They are created by the Docker daemon and are required for normal operation. Sencho intentionally hides the delete action for these networks. -If you need to clean up unused *user-created* networks, use the **Prune Networks** button at the top of the Networks tab. +If you need to clean up unused *user-created* networks, use the **Prune Dead Networks** button in the Quick Clean section at the top of the Resources page. --- ## Network inspect shows "Network not found" -**Symptom:** Clicking the inspect (eye) icon on a network row returns a "not found" error. +**Symptom:** Clicking the inspect icon (eye) on a network row returns a "not found" error. **Cause:** The network was deleted between the time the list loaded and when you clicked inspect. This can happen if another user or an external tool removed the network. -**Fix:** Refresh the Resources page to reload the current network list. +**Fix:** Switch to a different tab and back (or click another nav item and return to Resources) to reload the network list. --- ## Network topology is empty -**Symptom:** The Topology tab shows "No user-created networks found" even though you have running containers. +**Symptom:** Switching to the **Topology** view mode on the Networks tab shows "No user-created networks found" even though you have running containers. + + + Network Topology requires a Skipper or Admiral license. + **Possible causes:** @@ -272,6 +261,120 @@ After deploying, the topology will show these networks and their connected conta --- +## "Open App" doesn't appear in the context menu + +**Symptom:** You right-click a stack in the sidebar but "Open App" is not listed. + +**Cause:** The **Open App** option only appears when both conditions are met: + +1. The stack is **running** (status shows UP). +2. At least one container in the stack has a **published port** (a port mapped to the host). + +If your container uses host networking, doesn't expose ports, or only binds to internal Docker networks, the option won't appear. You can still access the app manually by checking the container's port mappings in the stack detail view. + +--- + +## Remote update button does not appear + +**Symptom:** A remote node in Fleet View has no **Update** button even though it is running an older version. + +**Cause:** The remote node does not advertise the `self-update` [capability](/features/node-compatibility). This happens when the node is not running inside a Docker Compose-managed container, or the Docker socket is not mounted. + +**Fix:** Ensure the remote node's `docker-compose.yml` includes the socket volume mount: + +```yaml +volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +Nodes running very old Sencho versions that predate the capability system need to be updated manually first. After that, future updates can be triggered from the dashboard. + +--- + +## Remote update times out + +**Symptom:** After clicking **Update** on a remote node, the status changes to **Timed out** instead of **Updated**. + +**Cause:** The image pull may be slow on the remote host, or the container failed to restart. + +**Fix:** Check the Docker logs on the remote host for errors. You can also update manually by running: + +```bash +docker compose pull && docker compose up -d +``` + +--- + +## Stack labels are not visible in the sidebar + +**Symptom:** You assigned labels to stacks but no label pills appear in the sidebar. + +**Checks:** + +1. **License tier**: Labels require a Skipper or Admiral license. Verify your tier in **Profile > Settings > License**. +2. **At least one label must exist**: Labels are managed in **Profile > Settings > Labels**. Create at least one label before assigning it to stacks. +3. **Downgrade**: If you downgraded from a paid tier to Community, the label UI is hidden but your data is preserved. Upgrading again restores all labels and assignments. + +--- + +## Notification routing rule matches but alerts still go to global channels + +**Symptom:** You created a routing rule for a stack, but alerts from that stack still arrive on the global Discord/Slack/Webhook channels. + +**Checks:** + +1. **Stack name match**: The stack name in the routing rule must match exactly. Stack names are case-sensitive and correspond to the directory name in your compose folder. +2. **Rule is enabled**: Check that the route's toggle is turned on in **Profile > Settings > Routing**. +3. **License tier**: Notification Routing requires an Admiral license. Skipper and Community users can only use global channels. + +--- + +## LDAP connection refused + +**Symptom:** Enabling LDAP SSO and testing the connection fails with a connection error. + +**Fix:** Verify the LDAP server is reachable from the Sencho container. If LDAP is on the host machine, use `host.docker.internal` (Docker Desktop) or the host's LAN IP address, not `localhost`. + +--- + +## TLS certificate errors (LDAP) + +**Symptom:** LDAP connection test fails with a TLS/certificate error. + +**Fix:** If your LDAP server uses a self-signed certificate, toggle off "Verify TLS certificate" in **Profile > Settings > SSO**. For production, install a trusted certificate instead. + +--- + +## OAuth callback URL mismatch + +**Symptom:** After authenticating with Google, GitHub, or Okta, the provider returns a "redirect URI mismatch" error. + +**Fix:** The redirect URI registered in your identity provider must exactly match what Sencho sends. Check: + +1. `SSO_CALLBACK_URL` is set to your external URL (e.g., `https://sencho.example.com`) +2. The callback URL in your provider's settings is `https://sencho.example.com/api/auth/sso/oidc//callback` +3. Protocol matches: don't mix `http` and `https` + +--- + +## SSO buttons not appearing on login page + +**Symptom:** You configured an SSO provider but the login page shows no SSO buttons. + +**Cause:** SSO providers only appear on the login page when they are both **configured** (saved with valid credentials) and **enabled** (toggle is on). + +**Fix:** Open **Profile > Settings > SSO** and verify the provider has an **Active** badge and its toggle is enabled. + +--- + +## "Check for updates" shows rate-limit error + +**Symptom:** Clicking "Check for updates" shows a toast error about waiting before checking again. + +**Cause:** Manual update checks are rate-limited to prevent excessive requests to container registries. The cooldown between manual checks is 2 minutes. Wait for it to elapse before checking again. Automatic background checks run every 6 hours regardless of this limit. + +--- + ## Checking the health endpoint Sencho exposes a health endpoint for monitoring and container health checks: @@ -294,20 +397,3 @@ 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. - -## "Open App" doesn't appear in the context menu - -**Symptom:** You right-click a stack in the sidebar but "Open App" is not listed. - -**Cause:** The **Open App** option only appears when both conditions are met: - -1. The stack is **running** (status shows UP). -2. At least one container in the stack has a **published port** (a port mapped to the host). - -If your container uses host networking, doesn't expose ports, or only binds to internal Docker networks, the option won't appear. You can still access the app manually by checking the container's port mappings in the stack detail view. - -## "Check for updates" shows rate-limit error - -**Symptom:** Clicking "Check for updates" shows a toast error about waiting before refreshing. - -**Cause:** Manual update checks are rate-limited to prevent excessive requests to container registries. Wait for the cooldown period to elapse before checking again. Automatic background checks run every 6 hours regardless of this limit. diff --git a/docs/operations/upgrade.mdx b/docs/operations/upgrade.mdx index 4cc86e9f..15494c1b 100644 --- a/docs/operations/upgrade.mdx +++ b/docs/operations/upgrade.mdx @@ -22,20 +22,22 @@ docker stop sencho && docker rm sencho Sencho will apply any necessary database migrations automatically on startup. No manual steps are required. + + Skipper and Admiral users can also update remote nodes directly from the Fleet View. See [Remote Updates](/features/remote-updates) for details. + + --- ## Automatic migrations -Sencho handles all schema changes internally. When the application starts, it runs a series of migration checks: +Sencho handles all schema changes internally. When the application starts, it checks whether the database needs updating and applies any pending migrations automatically. This covers: -- **Schema evolution** — New columns are added via `ALTER TABLE ADD COLUMN`. If a column already exists, the operation is silently skipped. -- **Legacy config migration** — If upgrading from a very early version that used a `sencho.json` file, the settings are automatically imported into SQLite. -- **Admin account migration** — Legacy admin credentials stored in `global_settings` are migrated to the `users` table. -- **Encryption migration** — Unencrypted node API tokens are automatically encrypted at rest using AES-256-GCM. -- **SSO columns** — SSO provider fields are added to the users table if not present. -- **Registry tables** — Private registry storage tables are created if they don't exist. -- **RBAC tables** — Role assignment tables are created for granular permissions. -- **Legacy cleanup** — Obsolete columns from pre-0.7 versions (SSH/TLS fields) are dropped. +- **New tables and columns** for features introduced in newer versions +- **Legacy config migration** from very early versions that used a JSON config file +- **Admin account migration** from single-admin storage to the multi-user system +- **Encryption of sensitive values** (node API tokens, registry credentials) that were previously stored in plaintext +- **SSO and RBAC setup** for single sign-on provider config and role-based access +- **Legacy cleanup** of obsolete fields from pre-0.7 versions (SSH/TLS columns) You never need to run SQL commands, migration scripts, or any manual database operations. @@ -43,10 +45,12 @@ You never need to run SQL commands, migration scripts, or any manual database op ## Backup before upgrading -Always back up your data directory before upgrading. If something goes wrong, restoring from backup is the only recovery path — Sencho does not support downgrading or rolling back database migrations. +Always back up your data directory before upgrading. If something goes wrong, restoring from backup is the only recovery path. Sencho does not support downgrading or rolling back database migrations. ```bash -sqlite3 /path/to/sencho-data/sencho.db ".backup '/path/to/backup/sencho-pre-upgrade.db'" +# Copy both the database and the encryption key +cp /path/to/sencho-data/sencho.db /path/to/backup/sencho-pre-upgrade.db +cp /path/to/sencho-data/encryption.key /path/to/backup/encryption-pre-upgrade.key ``` See the [Backup & Restore guide](/operations/backup) for full backup procedures. @@ -58,7 +62,7 @@ See the [Backup & Restore guide](/operations/backup) for full backup procedures. If you prefer to control exactly which version you run, pin the image tag in your `docker-compose.yml`: ```yaml -image: saelix/sencho:0.25.3 +image: saelix/sencho:0.38.0 ``` Check [GitHub Releases](https://github.com/AnsoCode/Sencho/releases) for available versions and changelogs. @@ -71,8 +75,8 @@ Sencho follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`): | Change type | Version bump | Example | |-------------|-------------|---------| -| Bug fixes, performance improvements | Patch | 0.25.0 → 0.25.1 | -| New features | Minor | 0.25.x → 0.26.0 | +| Bug fixes, performance improvements | Patch | 0.38.0 → 0.38.1 | +| New features | Minor | 0.38.x → 0.39.0 | | Breaking changes | Major | 0.x.y → 1.0.0 | diff --git a/docs/reference/architecture.mdx b/docs/reference/architecture.mdx deleted file mode 100644 index adb4726e..00000000 --- a/docs/reference/architecture.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Architecture Overview -description: System design, request flow, and deployment model. ---- - -## System overview - -Sencho is a self-contained application packaged as a single Docker container: - -- **Frontend:** React 19 single-page application built with Vite and served as static files -- **Backend:** Express.js (Node.js 22) REST API with WebSocket support -- **Database:** SQLite via `better-sqlite3` — no external database required -- **Container management:** Docker Engine API via the mounted Docker socket, plus Docker Compose CLI for stack operations - -There are no external dependencies. No Redis, no PostgreSQL, no message queues. All state lives in a single SQLite file inside the data directory. - ---- - -## Request flow - -### Browser sessions - -1. The browser loads the React SPA from the Express static file server -2. The frontend makes API calls, including which node should handle each request -3. The backend evaluates which node is targeted: - - **Local node:** The request passes through authentication and hits the local route handler, which communicates with Docker via the mounted socket - - **Remote node:** The request is securely proxied to the target Sencho instance with appropriate authentication -4. The response flows back through the same path to the browser - -### API token access - -External integrations (CI/CD pipelines, scripts) authenticate with Bearer tokens instead of cookies. The same route handlers process both authentication methods — the middleware accepts JWT tokens from either cookies or the `Authorization` header. - ---- - -## Authentication model - -| Method | Used by | Token storage | -|--------|---------|--------------| -| HTTP-only cookie (JWT) | Browser sessions | Set by Express on login, sent automatically | -| Bearer token (JWT) | API integrations, node-to-node proxy | Passed in `Authorization` header | - -API tokens have scopes that restrict their access: `read-only`, `deploy-only`, or `full-admin`. Tokens are hashed before storage. - -SSO is supported via LDAP, Google OIDC, GitHub OAuth, and Okta OIDC. SSO users are mapped to local accounts on first login. - ---- - -## Database - -Sencho stores all state in a single SQLite database — no external database required. The schema covers user identity, node configuration, automation rules, monitoring data, and security audit trails. Sensitive values (such as registry credentials and node tokens) are encrypted at rest. - -All schema migrations run automatically on startup. See [Upgrading Sencho](/operations/upgrade#automatic-migrations) for details. - ---- - -## Multi-node architecture - -Sencho uses a **Distributed API** model for managing multiple hosts: - -- **Local node:** Communicates directly with the Docker Engine via the mounted socket (`/var/run/docker.sock`) -- **Remote nodes:** Each remote host runs its own independent Sencho instance. The primary instance acts as a transparent HTTP proxy, routing requests to remote instances using stored API URLs and long-lived JWT tokens - -This means: -- No SSH, SFTP, or remote Docker TCP socket connections -- Each node is fully autonomous and can operate independently -- The primary instance proxies both HTTP requests and WebSocket connections -- Node routing is handled automatically by the frontend. API users can target a specific node using a request header or query parameter (see [API Overview](/api-reference/overview)) - ---- - -## WebSocket channels - -| Path | Purpose | Auth | -|------|---------|------| -| `/api/stacks/{stackName}/logs` | Live container log streaming | Cookie or query param token | -| `/ws` | Host console terminal (PTY) | Cookie-based, admin only | - -WebSocket connections are authenticated during the upgrade handshake using the same JWT credentials as HTTP requests. - ---- - -## Build and deployment - -The Docker image uses a multi-stage build: - -1. **Frontend build stage** — Compiles the React SPA with Vite -2. **Backend build stage** — Compiles TypeScript to JavaScript -3. **Native module stage** — Cross-compiles native dependencies (`bcrypt`, `better-sqlite3`, `node-pty`) for the target architecture -4. **Production stage** — Alpine-based Node.js 22 runtime with Docker CLI and Docker Compose installed - -The final image supports both `linux/amd64` and `linux/arm64` architectures and is published to [Docker Hub](https://hub.docker.com/r/saelix/sencho) as `saelix/sencho`. diff --git a/docs/reference/development.mdx b/docs/reference/development.mdx deleted file mode 100644 index 1ca7efd0..00000000 --- a/docs/reference/development.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: Development Guide -description: Set up a local development environment and contribute to Sencho. ---- - -## Prerequisites - -- **Node.js 22** or later -- **Docker** and **Docker Compose** installed and running -- **Git** - ---- - -## Setup - -```bash -# Clone the repository -git clone https://github.com/AnsoCode/Sencho.git -cd Sencho - -# Install backend dependencies -cd backend && npm install - -# Install frontend dependencies -cd ../frontend && npm install -``` - ---- - -## Running in development - -Open two terminal windows: - -**Terminal 1 — Backend** (Express + nodemon, port 3000): - -```bash -cd backend -npm run dev -``` - -**Terminal 2 — Frontend** (Vite dev server, port 5173): - -```bash -cd frontend -npm run dev -``` - -The Vite dev server proxies all `/api` and `/ws` requests to `localhost:3000`, so you access the app at `http://localhost:5173`. - -On first boot, you'll see a setup screen to create an admin account. - - - The backend requires a Docker socket to be available. On macOS and Linux this is `/var/run/docker.sock`. On Windows, ensure Docker Desktop is running. - - ---- - -## Running tests - -### Backend unit tests (Vitest) - -```bash -cd backend -npm test -``` - -Runs all test files in `src/__tests__/`. Each test file runs in an isolated forked process with its own database instance. - -### End-to-end tests (Playwright) - -```bash -# From the project root -npm run test:e2e -``` - -E2E tests run against a live development instance (backend on port 3000, frontend on port 5173). Make sure both are running before executing tests. - -For interactive test debugging: - -```bash -npm run test:e2e:ui -``` - ---- - -## Code style - -- **TypeScript** with `strict: true` in both packages. No `any` casts or `@ts-ignore`. -- **ESLint 9** flat config. Run `npm run lint` in both `backend/` and `frontend/` directories. -- **Frontend styling:** Tailwind CSS with [shadcn/ui](https://ui.shadcn.com/) components. See the design system section in `CLAUDE.md` for color, typography, and component patterns. -- **Backend patterns:** Express route handlers in `src/index.ts`, business logic in `src/services/`. All new endpoints must use `authMiddleware`. SQL must use parameterized queries. - ---- - -## Pull request workflow - -1. Create a branch from `main` (e.g. `feat/my-feature`, `fix/my-bug`) -2. Use [Conventional Commits](https://www.conventionalcommits.org/) for all commit messages: - - `feat:` — new user-facing feature (bumps minor version) - - `fix:` — bug fix (bumps patch version) - - `docs:` — documentation changes (no version bump) - - `chore:`, `ci:`, `refactor:`, `test:`, `perf:` — internal changes (no version bump) -3. Update `CHANGELOG.md` under `## [Unreleased]` for user-facing changes -4. Update or create documentation in `/docs` if behavior changes -5. Open a PR targeting `main` -6. Ensure CI passes before requesting review - -Keep PRs focused — one feature or fix per PR. - ---- - -## Project structure - -``` -Sencho/ -├── backend/ # Express.js API + Docker orchestration -│ ├── src/ -│ │ ├── index.ts # Route definitions (monolithic) -│ │ ├── services/ # Business logic (17 services) -│ │ └── __tests__/ # Vitest unit tests -│ └── package.json -├── frontend/ # React 19 + Vite SPA -│ ├── src/ -│ │ ├── components/ # UI components -│ │ ├── context/ # React context providers -│ │ ├── lib/ # Utilities (apiFetch, etc.) -│ │ └── App.tsx # Root router -│ └── package.json -├── docs/ # Mintlify documentation site -├── e2e/ # Playwright E2E test specs -├── Dockerfile # Multi-stage production build -├── docker-compose.yml # Quick-start deployment -└── package.json # Root scripts (test, test:e2e) -``` - -For more detail on how the components relate, see the [Architecture Overview](/reference/architecture). diff --git a/docs/reference/security-advisories.mdx b/docs/reference/security-advisories.mdx index 18f2df01..dcbf268a 100644 --- a/docs/reference/security-advisories.mdx +++ b/docs/reference/security-advisories.mdx @@ -3,28 +3,61 @@ title: Security Advisories description: Tracked CVEs, remediation status, and dependency security notes for Sencho's Docker image. --- -This page documents security-relevant changes across Sencho releases. +This page documents security-relevant changes across Sencho releases. All fixes are applied automatically when you upgrade. No manual action is required unless stated otherwise. -## April 2026 — Application Security Hardening +## April 2026 (v0.25.0 - v0.25.2) — Application Security Hardening -Version 0.25.2 includes application security hardening improvements: +A comprehensive security audit was performed before the Sencho paid tiers launch. Versions 0.25.0 through 0.25.2 include the following hardening: -- **Stricter file permissions** on sensitive files in the data directory, with automatic correction on startup -- **Stronger password requirements** aligned with [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) recommendations -- **Reduced information disclosure** in application logs to prevent leaking sensitive details to logging aggregators +### Input validation and path traversal + +- **Path traversal prevention** in `env_file` resolution, preventing reads outside the compose directory +- **Stack name validation** enforced on all routes, rejecting names with special characters or path components +- **Global API rate limiting** to protect against brute-force and abuse + +### Authentication and secrets + +- **Stronger password requirements** aligned with [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) (minimum 8 characters, up from 6) +- **1-year default expiry** on node proxy JWT tokens (previously issued without expiry) +- **Stricter file permissions** (0600) on encryption key files, with automatic correction on startup +- **NIST-recommended initialization vectors** for encryption (backward compatible with existing data) +- **Pattern-based environment variable filtering** in the host console, blocking variables that contain sensitive keywords + +### Information disclosure + +- **Reduced log verbosity** to prevent leaking file paths, stack names, and admin usernames to logging aggregators +- **CORS denied by default** when `FRONTEND_URL` is unset in production (previously allowed all origins) +- **Webhook HMAC verification** now uses raw request bytes instead of re-serialized JSON - Users on versions prior to 0.25.2 should upgrade promptly. These improvements are applied automatically — no manual action is required. + Users on versions prior to 0.25.0 should upgrade promptly. Existing passwords shorter than 8 characters remain valid until changed. --- +## March 2026 (v0.19.x - v0.24.0) — Dependency CVE Remediation + +### Docker CLI and Compose upgrades + +Sencho's Docker image bundles Docker CLI and Docker Compose as statically linked Go binaries. Vulnerabilities in Go's standard library or their Go dependencies surface as CVEs against the Sencho image even though Sencho itself contains no Go source code. + +The following dependency upgrades resolved all known CVEs at time of release: + +- **Docker CLI** upgraded to v29.3.1 (static binaries, replacing Alpine package) +- **Docker Compose** upgraded from v2.40.3 to v5.1.1 +- **Node.js dependencies** updated via Dependabot and Docker Scout audit + +### API token hardening (v0.19.x) + +- **Scope enforcement** tightened on API tokens, blocking access to sensitive endpoints (license management, user administration) +- **Token expiration** support added with configurable TTL + +--- + ## Dependency Security -Sencho's Docker image bundles Docker CLI and Docker Compose as statically linked Go binaries. Vulnerabilities in Go's standard library or their Go dependencies surface as CVEs against the Sencho image even though Sencho itself contains no Go source code. - -Sencho tracks and remediates these CVEs with each release. Dependency versions are pinned in the Dockerfile for reproducible builds and targeted remediation independent of Alpine's release cycle. +Sencho tracks and remediates dependency CVEs with each release. Dependency versions are pinned in the Dockerfile for reproducible builds and targeted remediation independent of Alpine's release cycle. - If you need specific CVE details for compliance or audit purposes, refer to the [GitHub release notes](https://github.com/SaelixCode/sencho/releases) where each release documents dependency changes. + If you need specific CVE details for compliance or audit purposes, refer to the [GitHub release notes](https://github.com/AnsoCode/Sencho/releases) where each release documents dependency changes. diff --git a/docs/reference/settings.mdx b/docs/reference/settings.mdx index f23f4e83..eae1b50b 100644 --- a/docs/reference/settings.mdx +++ b/docs/reference/settings.mdx @@ -3,7 +3,7 @@ title: Settings Reference description: Complete reference for every option in the Sencho Settings Hub. --- -Open the Settings Hub by clicking the **Profile** icon in the top-right corner and selecting **Settings**. The left sidebar lists all available sections. +Open the Settings Hub by clicking the **Profile** icon in the top bar and selecting **Settings**. The left sidebar lists all available sections. Some sections show a lock icon when they require a higher license tier. Settings Hub showing the Account tab and the full section sidebar @@ -31,25 +31,26 @@ Click **Update Password** to apply. The change takes effect immediately; existin **Scope:** Global -Manage your Sencho Pro license from this section. +Manage your Sencho license and subscription from this section. | Element | Description | |---------|-------------| -| **Current tier** | Shows whether you are on Community or Pro, with a tier badge | +| **Current tier** | Shows your current tier (Community, Skipper, or Admiral) with a tier badge | | **Trial status** | If on a trial, shows remaining days | -| **Customer / Plan / Key** | Displayed when a Pro license is active | | **Renews** | Next renewal date for active subscriptions | -| **Upgrade cards** | Dynamic plan cards with feature highlights and direct Lemon Squeezy checkout links. Community users see Skipper and Admiral; Skipper users see Admiral only | -| **Activate** | Enter a license key to activate Pro | -| **Manage Subscription** | Opens the billing portal (active Pro only) | -| **Deactivate License** | Reverts to Community features (active Pro only) | +| **Upgrade cards** | Dynamic plan cards with feature highlights and checkout links. Community users see Skipper and Admiral; Skipper users see Admiral only | +| **Activate** | Enter a license key to activate your plan (visible when no license is active) | +| **Manage Subscription** | Opens the Lemon Squeezy billing portal (Skipper / Admiral only) | +| **Deactivate License** | Reverts to Community features (Skipper / Admiral only) | + +See [Licensing & Billing](/features/licensing) for the full walkthrough. --- ## Users - Users management requires a Sencho Pro license and admin role. Community Edition supports a single admin account only. + User management requires a Sencho Skipper or Admiral license and admin role. Community supports a single admin account only. **Scope:** Global @@ -58,37 +59,103 @@ Create and manage user accounts with role-based access. | Action | Description | |--------|-------------| -| **Create user** | Add a new account with username, password, and role (Admin or Viewer) | +| **Create user** | Add a new account with username, password, and role | | **Edit user** | Change an existing user's password or role | -| **Delete user** | Remove a user account | +| **Delete user** | Remove a user account (you cannot delete your own account) | + +**Available roles:** + +| Role | Tier | Description | +|------|------|-------------| +| **Admin** | Skipper+ | Full access to all features | +| **Viewer** | Skipper+ | Read-only access to stacks and nodes | +| **Deployer** | Admiral | Can view stacks and trigger deployments | +| **Node Admin** | Admiral | Full stack and node management, no system settings | +| **Auditor** | Admiral | Read-only plus audit log access | See [RBAC & User Management](/features/rbac) for details on what each role can access. --- +## SSO + + + SSO requires a Sencho Admiral license. + + +**Scope:** Global + +Configure Single Sign-On providers (LDAP/AD and OIDC) for centralized authentication. Each provider type has its own configuration card with connection fields, a test button, and an active toggle. + +See [SSO](/features/sso) for the full configuration walkthrough. + +--- + +## API Tokens + + + API Tokens require a Sencho Admiral license. + + +**Scope:** Global + +Create and manage long-lived API tokens for external integrations and automation. Tokens can be scoped to specific permissions. + +See [API Tokens](/features/api-tokens) for the full walkthrough. + +--- + +## Registries + + + Private Registries require a Sencho Admiral license. + + +**Scope:** Global + +Configure private Docker registries so Sencho can pull images that require authentication. + +See [Private Registries](/features/private-registries) for the full walkthrough. + +--- + +## Labels + + + Stack Labels require a Sencho Skipper or Admiral license. + + +**Scope:** Global + +Create, edit, and delete labels used to organize and filter stacks across your fleet. Each label has a name and one of ten available colors. + +See [Stack Labels](/features/stack-labels) for the full walkthrough. + +--- + ## 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. +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. When viewing a remote node, a badge shows which node you are configuring. -| 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 | +| Setting | Default | Description | +|---------|---------|-------------| +| **Host CPU Alert Threshold** | 90% | CPU percentage above which the CPU card turns orange/red | +| **Host RAM Alert Threshold** | 90% | RAM percentage above which the RAM card turns orange/red | +| **Host Disk Alert Threshold** | 90% | Disk percentage above which the Disk card turns orange/red | +| **Docker Janitor Storage Threshold** | 5 GB | Alert when unused Docker data (reclaimable via prune) exceeds this size. Set to `0` to disable. | +| **Global Crash Detection** | On | Watch all containers for unexpected exits. 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. +Click **Save Limits** to apply. --- ## Notifications -**Scope:** Global +**Scope:** Per-node (each node has its own notification agents; remote nodes dispatch alerts through their own channels) -Configure external destinations for alert notifications. Three agent types are supported, each on its own sub-tab: **Discord**, **Slack**, and **Webhook**. +Configure external destinations for alert notifications. Three agent types are available on separate tabs: **Discord**, **Slack**, and **Webhook**. For each agent: @@ -103,10 +170,24 @@ At least one agent must be enabled for stack alerts to deliver notifications. Se --- +## Routing + + + Notification Routing requires a Sencho Admiral license. + + +**Scope:** Global + +Create routing rules that direct specific alert types to specific notification channels. Rules let you send critical alerts to one channel and informational alerts to another. + +See [Notification Routing](/features/notification-routing) for the full walkthrough. + +--- + ## Webhooks - Webhooks require a Sencho Pro license. + Webhooks require a Sencho Skipper or Admiral license. **Scope:** Global @@ -126,21 +207,29 @@ Quick reference: ## Developer -**Scope:** Per-node (applies to the currently selected node) +**Scope:** Per-node (streaming and polling settings), Global (data retention) -Advanced settings for log streaming behaviour and data retention. Most users can leave these at their defaults. +Advanced settings for log streaming behavior and data retention. Most users can leave these at their defaults. + +### Streaming | 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 | +| **Developer Mode** | Off | When on, the [Global Observability](/features/global-observability) view switches from polling to real-time SSE streaming | +| **Standard Log Polling Rate** | 5s | Polling interval in standard mode. Options: `1s`, `3s`, `5s`, `10s`. Disabled when Developer Mode is on. | -Click **Save** to apply. +### Data Retention + +| Setting | Default | Max | Description | +|---------|---------|-----|-------------| +| **Container Metrics Retention** | 24 hrs | 8,760 (1 year) | How long to keep per-container CPU, RAM, and network history for dashboard charts | +| **Notification Log Retention** | 30 days | 365 | How long to keep alert and notification history | +| **Audit Log Retention** | 90 days | 365 | How long to keep audit trail entries (Admiral only) | + +Click **Save Developer Settings** to apply. - Lower refresh rates (1s) increase backend CPU usage as Sencho polls Docker more frequently. Use only when actively debugging. + Lower polling rates (1s) increase backend CPU usage as Sencho polls Docker more frequently. Use only when actively debugging. --- @@ -149,7 +238,7 @@ Click **Save** to apply. **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. +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: @@ -167,11 +256,15 @@ Quick reference: **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. | +Configure the template source used by the App Store. -Click **Save** to update the URL. Click **Refresh Cache** to clear the cached template list and fetch fresh data from the registry immediately. +| Element | Description | +|---------|-------------| +| **Default Registry** | LinuxServer.io (used when no custom URL is set) | +| **Custom Registry URL** | A URL pointing to a Portainer v2 compatible template JSON file. Overrides the default registry. Leave empty to use the default. | +| **Reset to Default** | Clears the custom URL and reverts to LinuxServer.io | + +Click **Save & Refresh** to update the URL and immediately refresh the cached template list. See [App Store](/features/app-store#custom-template-registry) for more on custom registries. @@ -181,24 +274,26 @@ See [App Store](/features/app-store#custom-template-registry) for more on custom **Scope:** Global -Links to help resources available to all tiers, plus priority support channels for Pro users. +Links to help resources, with additional channels for Skipper and Admiral users. ### Resources (all tiers) | Resource | Description | |----------|-------------| -| **Documentation** | Opens docs.sencho.io - guides, reference, and tutorials | +| **Documentation** | Opens docs.sencho.io | | **GitHub Issues** | Report bugs and request features on GitHub | -### Pro support +### Paid tier support -Pro license holders get additional support channels: +Skipper and Admiral license holders see additional support channels: | Channel | Description | |---------|-------------| | **Email Support** | Direct email support (Skipper) | | **Priority Email Support** | Responses within 24 hours (Admiral) | +Community users see an upgrade prompt with a link to the pricing page. + --- ## About @@ -209,8 +304,9 @@ Displays instance information at a glance. | Field | Description | |-------|-------------| -| **Version** | Current Sencho version | -| **Tier** | Community or Pro tier badge | +| **Version** | Current Sencho version (e.g. v0.38.0) | +| **Tier** | Community, Skipper, or Admiral badge | | **License Status** | Active, trial, expired, or community | -| **Instance ID** | Unique identifier for this Sencho instance (shown when a license is active) | -| **Changelog** | Link to the full changelog on GitHub | +| **Instance ID** | Truncated unique identifier for this Sencho instance | + +The **Links** section contains a link to the full changelog on GitHub. diff --git a/frontend/src/components/settings/LicenseSection.tsx b/frontend/src/components/settings/LicenseSection.tsx index 62022406..c02e8655 100644 --- a/frontend/src/components/settings/LicenseSection.tsx +++ b/frontend/src/components/settings/LicenseSection.tsx @@ -162,7 +162,7 @@ export function LicenseSection() {
{/* Skipper Card - only for Community users */} {license?.tier !== 'pro' && ( -
+
Skipper @@ -170,7 +170,7 @@ export function LicenseSection() {

Professional tools for solo operators.

    - {['Fleet View with drill-down', 'RBAC viewer accounts (1 + 3)', 'Custom webhooks', 'Atomic deployment', 'Fleet-wide backups'].map((f) => ( + {['Fleet View with drill-down', 'Viewer accounts (1 admin + 3 viewers)', 'Webhooks & stack labels', 'Atomic deployments & backups', 'Auto-update policies'].map((f) => (
  • {f} @@ -179,7 +179,7 @@ export function LicenseSection() {