mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-27 12:18:59 +00:00
865d792874
* feat(pricing): collapse to two tiers (Community + Admiral) Collapse Sencho's pricing from three tiers (Community / Skipper / Admiral) to two: a generous free Community tier and a single paid Admiral tier. The Skipper tier is removed. Now free in Community: auto-heal, auto-update, scheduled operations, webhooks, notification routing, Fleet Actions and bulk operations, SSO preset providers (Google / GitHub / Okta), unlimited users with admin and viewer roles, and deploy safety (atomic deploys, auto-rollback, and one-click rollback). Admiral (paid) is focused on running and governing a fleet: blueprints, Fleet Secrets, deploy enforcement, vulnerability report export, audit log, host console, private registries, mesh networking, node cordon, managed cloud backup, LDAP / Active Directory SSO, and the advanced RBAC roles (deployer, node-admin, auditor) with per-resource scoped assignments. Internally the license variant distinction is removed so tier is binary (community / paid). License validation still verifies the Lemon Squeezy store and product before granting paid status. Docs and the contributor guide are updated to the two-tier model. * docs(pricing): correct licensing page to two-tier pricing and tidy stale tier wording The licensing docs page kept the old Admiral pricing plus a Founder Lifetime column and an Enterprise paragraph after the two-tier collapse. Update it to $12/month or $99/year, drop the lifetime and Enterprise content, and link to the pricing page for current pricing. Also fix stale "Skipper" wording in CLA.md, SUPPORT.md, one test title, and three test comments. Historical CHANGELOG entries and the retired-Skipper license-guard test are intentionally left as-is. * docs: align licensing and SSO pages with the two-tier model Correct the SSO overview so the Google, GitHub, and Okta presets read as available on every tier, matching the provider table; only LDAP and Active Directory require Sencho Admiral. Remove the lifetime-plan references from the licensing, settings, and troubleshooting pages so they reflect subscription-only Admiral pricing. * fix(rbac): omit scoped permissions from /me on the Community tier Scoped role assignments only take effect on the paid tier, but GET /api/permissions/me returned them unconditionally, so a downgraded instance with leftover assignments rendered per-resource affordances the API then rejected with 403. The endpoint now mirrors the permission middleware and includes scoped permissions only on the paid tier. Adds a regression test covering the downgrade case. * docs: use custom-pricing wording on the contact page The two-tier model has no Enterprise tier; reword the contact page's enterprise pricing/deals to custom pricing/deals so it does not imply a tier that no longer exists.
303 lines
12 KiB
Plaintext
303 lines
12 KiB
Plaintext
---
|
|
title: Configuration
|
|
description: Environment variables, volume mounts, and the 1:1 path rule.
|
|
---
|
|
|
|
Sencho is configured entirely through environment variables and Docker volume mounts. There is no config file to edit inside the container.
|
|
|
|
## Required environment variables
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `COMPOSE_DIR` | Absolute path to the directory that contains your Compose stacks. Every subdirectory inside becomes a stack in Sencho. Falls back to `/app/compose` if unset, but per the [1:1 path rule](#compose-directory-the-11-path-rule) you should always set this explicitly to match the host path you mount. |
|
|
|
|
<Note>
|
|
**JWT_SECRET is generated automatically.** Sencho creates a secure random signing key during initial setup and stores it in its database. You do not need to provide one.
|
|
</Note>
|
|
|
|
### How Sencho organizes your compose directory
|
|
|
|
When you point `COMPOSE_DIR` at a directory, Sencho expects each stack to live in its own subdirectory. If you create a stack through the UI, Sencho automatically creates a subfolder and places a blank `compose.yaml` inside it. Sencho does not move or "capture" existing files; it simply treats every subdirectory as a separate stack.
|
|
|
|
## Optional environment variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `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. |
|
|
| `SENCHO_USER` | *(unset)* | When set to a username present inside the container (`sencho` is pre-created for this purpose), the entrypoint drops privileges to that user at startup instead of running as `root`. See [Running as a non-root user](#running-as-a-non-root-user) below. |
|
|
| `API_RATE_LIMIT` | `200` | Global API requests per minute per user session. Applies in production only; development uses a fixed higher cap. Authenticated requests are keyed by user ID, unauthenticated by IP. Internal node-to-node traffic bypasses this limit. |
|
|
| `API_POLLING_RATE_LIMIT` | `300` | Rate limit for dashboard polling endpoints, in requests per minute. Applies in production only; development uses a fixed higher cap. Raise it for environments with many concurrent browser sessions behind shared NAT. |
|
|
|
|
## Listen port
|
|
|
|
Sencho always listens on `1852` inside the container. The port is fixed and is not read from an environment variable. To expose Sencho on a different host port, remap with Docker's `-p` flag (or the `ports:` key in your compose file):
|
|
|
|
```yaml
|
|
ports:
|
|
- "8080:1852" # host 8080 to container 1852
|
|
```
|
|
|
|
Behind a reverse proxy you can keep the standard mapping and let the proxy own the public port.
|
|
|
|
## Container user
|
|
|
|
Sencho runs as `root` inside the container by default, matching Portainer, Dockge, Komodo, and Yacht. This is required so Sencho can always write to your compose folders, even when a stack container (commonly anything from `linuxserver/*`) has chowned its own bind mount to another UID. Mounting `/var/run/docker.sock` already grants root-equivalent access to the host, so running the Sencho process itself as root does not change the effective privilege boundary.
|
|
|
|
**What this means for you:**
|
|
|
|
- Files Sencho creates inside your compose directory (new stacks, edited `compose.yaml`, generated `.env` files) will be owned by `root` on the host. If you edit those files outside Sencho using your own editor, you will need `sudo` or a one-time `chown`.
|
|
- The `/app/data` directory is internal to Sencho; its ownership does not matter for host-side tooling.
|
|
|
|
### Running as a non-root user
|
|
|
|
If organisational policy, compliance scanners, or a rootless Docker setup requires the container to drop privileges, set `SENCHO_USER=sencho` in the environment. The entrypoint will chown `/app/data` to the sencho user, match the host's Docker socket group, and exec Node under that user.
|
|
|
|
```yaml
|
|
services:
|
|
sencho:
|
|
image: saelix/sencho:latest
|
|
environment:
|
|
- COMPOSE_DIR=/opt/compose
|
|
- SENCHO_USER=sencho # opt into non-root mode
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- /opt/compose:/opt/compose
|
|
- ./sencho-data:/app/data
|
|
```
|
|
|
|
<Warning>
|
|
Non-root mode can cause filesystem write failures for any stack whose compose folder is owned by a UID other than `sencho`. If you hit "Failed to save stack" or similar errors after opting in, either `chown` the affected stack folder to the sencho user inside the container, or unset `SENCHO_USER` to return to the default (root) mode.
|
|
</Warning>
|
|
|
|
## SSO environment variables
|
|
|
|
If you use SSO, configure your identity providers via environment variables:
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `SSO_LDAP_ENABLED` | Enable LDAP/AD authentication |
|
|
| `SSO_OIDC_GOOGLE_ENABLED` | Enable Google SSO |
|
|
| `SSO_OIDC_GITHUB_ENABLED` | Enable GitHub SSO |
|
|
| `SSO_OIDC_OKTA_ENABLED` | Enable Okta SSO |
|
|
| `SSO_CALLBACK_URL` | External base URL for OAuth callbacks (required behind reverse proxy) |
|
|
|
|
For end-to-end provider setup walkthroughs, see the [SSO Quickstart →](/getting-started/sso-quickstart). For the full feature reference, see [SSO Authentication →](/features/sso).
|
|
|
|
## Required volume mounts
|
|
|
|
### Docker socket
|
|
|
|
Sencho needs access to the Docker daemon to manage containers:
|
|
|
|
```yaml
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
```
|
|
|
|
### Data directory
|
|
|
|
Sencho's database persists all your settings, nodes, alerts, and metrics history. Mount a named volume or host path so it survives container restarts:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ./sencho-data:/app/data
|
|
```
|
|
|
|
<Warning>
|
|
Without a persistent data mount, Sencho will lose all configuration (including registered nodes, alerts, and settings) every time the container restarts.
|
|
</Warning>
|
|
|
|
### Compose directory - the 1:1 path rule
|
|
|
|
<Warning>
|
|
This is the most common source of deployment problems. Read carefully.
|
|
</Warning>
|
|
|
|
When Sencho runs `docker compose up`, it does so on your **host machine**. Docker resolves relative volume paths in your Compose files relative to the **host** path of the stack directory, not the path inside the Sencho container.
|
|
|
|
**The rule:** Mount your Compose directory at the **exact same path** inside the container as it exists on your host.
|
|
|
|
```yaml
|
|
# ✅ Correct - host path matches container path
|
|
volumes:
|
|
- /home/user/docker:/home/user/docker
|
|
environment:
|
|
- COMPOSE_DIR=/home/user/docker
|
|
```
|
|
|
|
```yaml
|
|
# ❌ Wrong - paths differ, relative volumes will break
|
|
volumes:
|
|
- /home/user/docker:/app/compose
|
|
environment:
|
|
- COMPOSE_DIR=/app/compose
|
|
```
|
|
|
|
If you use a simple path like `/opt/compose` on your host, mount it at `/opt/compose` in the container:
|
|
|
|
```yaml
|
|
volumes:
|
|
- /opt/compose:/opt/compose
|
|
environment:
|
|
- COMPOSE_DIR=/opt/compose
|
|
```
|
|
|
|
## Full docker-compose.yml example
|
|
|
|
```yaml
|
|
services:
|
|
sencho:
|
|
image: saelix/sencho:latest
|
|
restart: unless-stopped
|
|
ports:
|
|
- "1852:1852"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- ./sencho-data:/app/data
|
|
- /opt/compose:/opt/compose # 1:1 path rule
|
|
environment:
|
|
- COMPOSE_DIR=/opt/compose
|
|
- DATA_DIR=/app/data
|
|
```
|
|
|
|
## Optional: global environment file
|
|
|
|
If your Compose stacks share common variables (e.g. `PUID`, `PGID`, `TZ`), you can pass an `env_file` to the Sencho container so those variables are available in the host environment when `docker compose` runs:
|
|
|
|
```yaml
|
|
services:
|
|
sencho:
|
|
image: saelix/sencho:latest
|
|
env_file:
|
|
- /opt/compose/globals.env # shared vars for all stacks
|
|
environment:
|
|
- COMPOSE_DIR=/opt/compose
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- /opt/compose:/opt/compose
|
|
- ./sencho-data:/app/data
|
|
```
|
|
|
|
## Reverse proxy setup
|
|
|
|
Sencho works behind any reverse proxy. The only requirement is that WebSocket connections are forwarded correctly (used for live logs, container terminals, and the host console).
|
|
|
|
### Nginx
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name sencho.yourdomain.com;
|
|
|
|
location / {
|
|
proxy_pass http://localhost:1852;
|
|
proxy_http_version 1.1;
|
|
|
|
# WebSocket support
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_read_timeout 3600s;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Nginx with SSL (Let's Encrypt)
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name sencho.yourdomain.com;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
server_name sencho.yourdomain.com;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/sencho.yourdomain.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/sencho.yourdomain.com/privkey.pem;
|
|
|
|
location / {
|
|
proxy_pass http://localhost:1852;
|
|
proxy_http_version 1.1;
|
|
|
|
# WebSocket support
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 3600s;
|
|
}
|
|
}
|
|
```
|
|
|
|
Use [Certbot](https://certbot.eff.org/) to obtain and auto-renew certificates: `certbot --nginx -d sencho.yourdomain.com`.
|
|
|
|
### Traefik (Docker labels)
|
|
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.sencho.rule=Host(`sencho.yourdomain.com`)"
|
|
- "traefik.http.services.sencho.loadbalancer.server.port=1852"
|
|
```
|
|
|
|
### Traefik with SSL (Let's Encrypt)
|
|
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.sencho.rule=Host(`sencho.yourdomain.com`)"
|
|
- "traefik.http.routers.sencho.entrypoints=websecure"
|
|
- "traefik.http.routers.sencho.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.sencho.loadbalancer.server.port=1852"
|
|
# HTTP to HTTPS redirect
|
|
- "traefik.http.routers.sencho-http.rule=Host(`sencho.yourdomain.com`)"
|
|
- "traefik.http.routers.sencho-http.entrypoints=web"
|
|
- "traefik.http.routers.sencho-http.middlewares=redirect-to-https"
|
|
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
|
```
|
|
|
|
<Note>
|
|
Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends. No extra configuration needed.
|
|
</Note>
|
|
|
|
### Caddy
|
|
|
|
```
|
|
sencho.yourdomain.com {
|
|
reverse_proxy localhost:1852
|
|
}
|
|
```
|
|
|
|
Caddy automatically obtains and renews SSL certificates via Let's Encrypt. WebSocket connections are forwarded without additional configuration.
|
|
|
|
## First boot
|
|
|
|
After starting Sencho, open `http://localhost:1852` in a browser. On a fresh install you land on the **Cold start** card to create the first admin account; every subsequent visit goes to the regular sign-in screen. The [Quickstart](/getting-started/quickstart#first-boot) shows it in detail.
|
|
|
|
## Where to next
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Stack management" icon="layer-group" href="/features/stack-management">
|
|
Deploy, edit, restart, update, and roll back stacks from the cockpit.
|
|
</Card>
|
|
<Card title="Multi-node" icon="sitemap" href="/features/multi-node">
|
|
Add a remote Sencho instance and manage it from the same console.
|
|
</Card>
|
|
<Card title="Self-hosting" icon="server" href="/operations/self-hosting">
|
|
Resource recommendations, networking, and Docker socket security.
|
|
</Card>
|
|
<Card title="SSO Quickstart" icon="key" href="/getting-started/sso-quickstart">
|
|
End-to-end provider setup for OIDC, LDAP, and Active Directory.
|
|
</Card>
|
|
</CardGroup>
|