feat: change default listen port from 3000 to 1852 (#756)

Updates the backend listen port, Vite dev proxy target, Docker EXPOSE,
compose port mapping, .env.example default, GitHub Actions smoke-test
default, healthcheck URLs, and every doc/example reference. Test fixtures
that include example URLs were updated for consistency, though their
assertions are port-agnostic.

The rate-limit value of 3000 in middleware/rateLimiters.ts and the
3000 entry in WEB_UI_PORTS (which detects user containers like Grafana)
are intentionally untouched.
This commit is contained in:
Anso
2026-04-24 22:23:31 -04:00
committed by GitHub
parent d6b744e8e6
commit ed553f1f19
27 changed files with 72 additions and 72 deletions
+8 -8
View File
@@ -8,7 +8,7 @@ Sencho exposes a REST API for automating stack deployments, managing webhooks, m
## Base URL
```
https://your-sencho-instance:3000/api
https://your-sencho-instance:1852/api
```
Replace with your actual Sencho host and port. All API paths are prefixed with `/api`.
@@ -19,7 +19,7 @@ Authenticated endpoints require a **Bearer token** in the `Authorization` header
```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://your-sencho-instance:3000/api/stacks
https://your-sencho-instance:1852/api/stacks
```
<Note>
@@ -51,7 +51,7 @@ If omitted, the request targets the default node.
# Target node ID 2
curl -H "Authorization: Bearer TOKEN" \
-H "x-node-id: 2" \
https://your-sencho-instance:3000/api/stacks
https://your-sencho-instance:1852/api/stacks
```
## Error format
@@ -132,7 +132,7 @@ Sencho also provides real-time streaming via WebSocket connections. These are no
Stream live logs from a stack's containers.
**URL:** `wss://your-sencho-instance:3000/api/stacks/{stackName}/logs?nodeId={nodeId}`
**URL:** `wss://your-sencho-instance:1852/api/stacks/{stackName}/logs?nodeId={nodeId}`
**Authentication:** Pass the token as a cookie (`sencho_token`) or Bearer token. For WebSocket connections, authentication is verified during the upgrade handshake.
@@ -142,7 +142,7 @@ Stream live logs from a stack's containers.
import WebSocket from "ws";
const ws = new WebSocket(
"wss://your-sencho-instance:3000/api/stacks/my-app/logs",
"wss://your-sencho-instance:1852/api/stacks/my-app/logs",
{ headers: { Cookie: "sencho_token=YOUR_JWT" } }
);
@@ -156,7 +156,7 @@ curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Cookie: sencho_token=YOUR_JWT" \
https://your-sencho-instance:3000/api/stacks/my-app/logs
https://your-sencho-instance:1852/api/stacks/my-app/logs
```
</CodeGroup>
@@ -165,7 +165,7 @@ curl -i -N \
Open an interactive shell session inside a running container.
**URL:** `wss://your-sencho-instance:3000/ws`
**URL:** `wss://your-sencho-instance:1852/ws`
**Authentication:** Cookie-based JWT only. API tokens with `read-only` or `deploy-only` scope are blocked.
@@ -174,7 +174,7 @@ Open an interactive shell session inside a running container.
```javascript Node.js
import WebSocket from "ws";
const ws = new WebSocket("wss://your-sencho-instance:3000/ws", {
const ws = new WebSocket("wss://your-sencho-instance:1852/ws", {
headers: { Cookie: "sencho_token=YOUR_JWT" },
});
+9 -9
View File
@@ -21,7 +21,7 @@ Writes are admin-only and rejected on replica nodes (policies are managed on the
```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://your-sencho-instance:3000/api/security/policies
https://your-sencho-instance:1852/api/security/policies
```
**Response:**
@@ -60,7 +60,7 @@ curl -H "Authorization: Bearer YOUR_API_TOKEN" \
| `node_id` | number or `null` | no | Scope the policy to one node. `null` applies the policy fleet-wide. |
```bash
curl -X POST https://your-sencho-instance:3000/api/security/policies \
curl -X POST https://your-sencho-instance:1852/api/security/policies \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
@@ -89,7 +89,7 @@ curl -X POST https://your-sencho-instance:3000/api/security/policies \
Any of the create fields can be updated individually. Omitted fields are left unchanged.
```bash
curl -X PUT https://your-sencho-instance:3000/api/security/policies/1 \
curl -X PUT https://your-sencho-instance:1852/api/security/policies/1 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "block_on_deploy": 0 }'
@@ -106,7 +106,7 @@ curl -X PUT https://your-sencho-instance:3000/api/security/policies/1 \
**License:** Skipper or Admiral · **Role:** Admin
```bash
curl -X DELETE https://your-sencho-instance:3000/api/security/policies/1 \
curl -X DELETE https://your-sencho-instance:1852/api/security/policies/1 \
-H "Authorization: Bearer YOUR_API_TOKEN"
```
@@ -156,7 +156,7 @@ Response rows include an `active` boolean computed from the `expires_at` timesta
| `expires_at` | number or `null` | no | Unix timestamp in milliseconds. `null` for an indefinite suppression. |
```bash
curl -X POST https://your-sencho-instance:3000/api/security/suppressions \
curl -X POST https://your-sencho-instance:1852/api/security/suppressions \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
@@ -179,7 +179,7 @@ curl -X POST https://your-sencho-instance:3000/api/security/suppressions \
**License:** Skipper or Admiral · **Role:** Admin
```bash
curl -X DELETE https://your-sencho-instance:3000/api/security/suppressions/3 \
curl -X DELETE https://your-sencho-instance:1852/api/security/suppressions/3 \
-H "Authorization: Bearer YOUR_API_TOKEN"
```
@@ -201,7 +201,7 @@ Accepts an image reference and starts an asynchronous scan. The response returns
| `scanners` | `["vuln"]` or `["vuln","secret"]` | no | Omit for vuln-only. `secret` requires Skipper or Admiral. |
```bash
curl -X POST https://your-sencho-instance:3000/api/security/scan \
curl -X POST https://your-sencho-instance:1852/api/security/scan \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "imageRef": "nginx:1.27" }'
@@ -221,7 +221,7 @@ Supports filters: `imageRef`, `imageRefLike`, `status`, `limit`, `offset`. Respo
```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
"https://your-sencho-instance:3000/api/security/scans?imageRefLike=nginx&limit=20"
"https://your-sencho-instance:1852/api/security/scans?imageRefLike=nginx&limit=20"
```
## Stack deploy with policy
@@ -266,7 +266,7 @@ HTTP 409 Conflict. The response body is parseable JSON so CI pipelines can branc
Admins can bypass the gate on a per-deploy basis by passing `?ignorePolicy=true` on the deploy URL. The flag is only honored when the calling session resolves to an admin user; API tokens with read-only or deploy-only scope cannot bypass a policy.
```bash
curl -X POST "https://your-sencho-instance:3000/api/stacks/myapp/deploy?ignorePolicy=true" \
curl -X POST "https://your-sencho-instance:1852/api/stacks/myapp/deploy?ignorePolicy=true" \
-H "Authorization: Bearer ADMIN_API_TOKEN"
```
+6 -6
View File
@@ -39,7 +39,7 @@ On your **primary** Sencho instance, open **Settings → Nodes** and click **+ A
|-------|-------------|
| **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`) |
| **Sencho API URL** | The full HTTP/HTTPS URL of the remote instance (e.g. `http://192.168.1.50:1852`) |
| **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`) |
@@ -156,8 +156,8 @@ There are three recommended approaches depending on your deployment:
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
http://10.0.1.20:3000 ← safe inside a VPC
http://192.168.1.50:1852 ← safe on a private LAN
http://10.0.1.20:1852 ← safe inside a VPC
```
#### VPN tunnel (WireGuard, Tailscale)
@@ -169,7 +169,7 @@ http://10.0.1.20:3000 ← safe inside a VPC
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:
```
http://100.64.0.2:3000 ← Tailscale IP, encrypted by the VPN tunnel
http://100.64.0.2:1852 ← Tailscale IP, encrypted by the VPN tunnel
```
All traffic between nodes is encrypted by the VPN. Sencho does not need to do anything additional.
@@ -181,7 +181,7 @@ If you prefer TLS termination at each node, place a reverse proxy in front of ea
<CodeGroup>
```text Caddyfile
sencho.example.com {
reverse_proxy localhost:3000
reverse_proxy localhost:1852
}
```
@@ -194,7 +194,7 @@ server {
ssl_certificate_key /etc/letsencrypt/live/sencho.example.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_pass http://localhost:1852;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
+1 -1
View File
@@ -186,7 +186,7 @@ Only one policy is evaluated per deploy; use a single tight pattern rather than
Policy CRUD endpoints are documented in the [Security API reference](/api-reference/security). A typical create call from CI looks like this:
```bash
curl -X POST https://your-sencho-instance:3000/api/security/policies \
curl -X POST https://your-sencho-instance:1852/api/security/policies \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
+7 -7
View File
@@ -23,7 +23,7 @@ When you point `COMPOSE_DIR` at a directory, Sencho expects each stack to live i
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3000` | Port the Sencho HTTP server listens on. |
| `PORT` | `1852` | 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. |
@@ -140,7 +140,7 @@ services:
image: saelix/sencho:latest
restart: unless-stopped
ports:
- "3000:3000"
- "1852:1852"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./sencho-data:/app/data
@@ -180,7 +180,7 @@ server {
server_name sencho.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_pass http://localhost:1852;
proxy_http_version 1.1;
# WebSocket support
@@ -211,7 +211,7 @@ server {
ssl_certificate_key /etc/letsencrypt/live/sencho.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_pass http://localhost:1852;
proxy_http_version 1.1;
# WebSocket support
@@ -235,7 +235,7 @@ Use [Certbot](https://certbot.eff.org/) to obtain and auto-renew certificates: `
labels:
- "traefik.enable=true"
- "traefik.http.routers.sencho.rule=Host(`sencho.yourdomain.com`)"
- "traefik.http.services.sencho.loadbalancer.server.port=3000"
- "traefik.http.services.sencho.loadbalancer.server.port=1852"
```
### Traefik with SSL (Let's Encrypt)
@@ -246,7 +246,7 @@ labels:
- "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=3000"
- "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"
@@ -262,7 +262,7 @@ labels:
```
sencho.yourdomain.com {
reverse_proxy localhost:3000
reverse_proxy localhost:1852
}
```
+2 -2
View File
@@ -13,7 +13,7 @@ description: Get Sencho running in under five minutes.
```bash
docker run -d \
--name sencho \
-p 3000:3000 \
-p 1852:1852 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/compose:/opt/compose \
-v sencho_data:/app/data \
@@ -21,7 +21,7 @@ docker run -d \
saelix/sencho:latest
```
Open `http://localhost:3000` in your browser. On first boot you'll be prompted to create an admin account.
Open `http://localhost:1852` in your browser. On first boot you'll be prompted to create an admin account.
<Note>
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.
+1 -1
View File
@@ -162,7 +162,7 @@ services:
image: saelix/sencho:latest
restart: unless-stopped
ports:
- "3000:3000"
- "1852:1852"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./sencho-data:/app/data
+2 -2
View File
@@ -44,7 +44,7 @@ servers:
host:
default: localhost
port:
default: "3000"
default: "1852"
security:
- bearerAuth: []
@@ -1679,7 +1679,7 @@ paths:
api_url:
type: string
description: Remote Sencho instance URL (required for remote nodes).
example: https://sencho.example.com:3000
example: https://sencho.example.com:1852
api_token:
type: string
description: API token for authenticating with the remote Sencho instance.
+1 -1
View File
@@ -70,7 +70,7 @@ Sencho itself is lightweight. The majority of resource usage on your host comes
## Networking
- **Listen port:** 3000 (fixed). Map it to any host port using Docker's `-p` flag or `ports` in your compose file
- **Listen port:** 1852 (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
+1 -1
View File
@@ -557,7 +557,7 @@ docker compose pull && docker compose up -d
Sencho exposes a health endpoint for monitoring and container health checks:
```bash
curl http://localhost:3000/api/health
curl http://localhost:1852/api/health
# {"status":"ok","uptime":12345.67}
```