diff --git a/AGENTS.md b/AGENTS.md index 1cc881d..9727100 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -137,6 +137,7 @@ bun run sync-versions # Syncs VERSION → sub-package.json files - No emojis in code or UI unless explicitly requested - Functional components with hooks (React) - Tailwind CSS for styling (both web and docs) +- All new UI created (both web and docs) must be mobile responsive across all viewport sizes (mobile, tablet, and desktop) with no horizontal overflow or broken navigation ## Adding a Doc Page diff --git a/apps/docs/blume.config.ts b/apps/docs/blume.config.ts index 1ef703d..c70d4ea 100644 --- a/apps/docs/blume.config.ts +++ b/apps/docs/blume.config.ts @@ -33,22 +33,45 @@ export default defineConfig({ "/docs", "/docs/installation", "/docs/quickstart", - "/docs/configuration", { - label: "Core Architecture", - items: ["/docs/deployments", "/docs/env-vars", "/docs/scaling", "/docs/system-config"], + label: "Projects", + items: [ + "/docs/deployments", + "/docs/configuration", + "/docs/env-vars", + "/docs/shared-env-vars", + "/docs/volumes", + "/docs/domains", + "/docs/scaling", + ], }, { - label: "Deployment", - items: ["/docs/ai-diagnosis", "/docs/agent-caddy-routes"], + label: "Data", + items: ["/docs/databases", "/docs/backups"], }, { - label: "Cluster Storage & Data", - items: ["/docs/databases", "/docs/volumes"], + label: "Multi-Server", + items: ["/docs/servers", "/docs/agent-caddy-routes"], }, { - label: "Networking & Security", - items: ["/docs/auth", "/docs/domains", "/docs/ssl"], + label: "AI & Diagnosis", + items: ["/docs/ai-diagnosis"], + }, + { + label: "Observability", + items: ["/docs/observability", "/docs/alerts"], + }, + { + label: "Integrations", + items: ["/docs/github", "/docs/settings"], + }, + { + label: "Security", + items: ["/docs/auth", "/docs/keys", "/docs/ssl"], + }, + { + label: "Platform", + items: ["/docs/system-config", "/docs/cli"], }, { label: "Release", diff --git a/apps/docs/components/CTA.astro b/apps/docs/components/CTA.astro index 1d1fcc6..3323bda 100644 --- a/apps/docs/components/CTA.astro +++ b/apps/docs/components/CTA.astro @@ -1,11 +1,11 @@ --- --- -
-
+
+
-
- +
+ @@ -18,25 +18,25 @@
-

+

Ready to own your deployment platform?

-

+

Spin up Dequel on your server in seconds with zero third-party dependencies.

-
+
curl -fsSL https://dequel.intrep.xyz/install.sh | bash - 1-Line Install +
-
- + diff --git a/apps/docs/components/Comparison.astro b/apps/docs/components/Comparison.astro index e90d149..ef545ed 100644 --- a/apps/docs/components/Comparison.astro +++ b/apps/docs/components/Comparison.astro @@ -1,77 +1,77 @@ --- --- -
-
+
+
PaaS Paradigm Shift
-

+

Stop fighting infrastructure.
Start shipping instantly.

-

+

Dequel replaces fragmented DevOps tools with a unified self-hosted platform.

-
+
-
+
-
+
TRADITIONAL DEVOPS
-

+

More tools. More upkeep.

-
    -
  • +
      +
    • — Maintain scripts, manifests, and ingress rules
    • -
    • +
    • — Renew certificates and route domains by hand
    • -
    • +
    • — Stitch together logs, metrics, and alerts
-
+
High overhead · Fragmented stack
-
+
-
+
WITH DEQUEL
-

+

One command. One platform.

-
    -
  • +
      +
    • ✓ Deploy from Git, ZIP, or Docker Compose
    • -
    • +
    • ✓ Automate builds, SSL, routing, and scaling
    • -
    • +
    • ✓ Keep complete control on your own VPS
-
+
Zero lock-in · 100% owned by you
diff --git a/apps/docs/components/Features.astro b/apps/docs/components/Features.astro index fff052c..b298327 100644 --- a/apps/docs/components/Features.astro +++ b/apps/docs/components/Features.astro @@ -88,20 +88,20 @@ scaling_policy: ]; --- -
-
+
+
Platform Capabilities
-

+

Everything you need to ship.
Powered by your infrastructure.

-

+

Explore Dequel's core PaaS engines built into a single lightweight control plane.

-
+
{tabs.map((tab, idx) => ( ))} @@ -123,24 +123,24 @@ scaling_policy: id={`tab-panel-${tab.id}`} class={`tab-panel ${idx === 0 ? 'block' : 'hidden'} transition-all duration-300`} > -
+
-
+
PaaS Module: {tab.id}
-

+

{tab.title}

-

+

{tab.description}

-
    +
      {tab.highlights.map((item) => (
    • - ✓ + ✓ {item}
    • ))} @@ -155,13 +155,13 @@ scaling_policy:
-
-
-
- - {tab.label} Preview +
+
+
+ + {tab.label} Preview
-
+
Dequel v1.0
-
{tab.codePreview}
+
{tab.codePreview}
Status: Active Zero Config Required diff --git a/apps/docs/components/Hero.astro b/apps/docs/components/Hero.astro index 84ad598..2d66199 100644 --- a/apps/docs/components/Hero.astro +++ b/apps/docs/components/Hero.astro @@ -12,25 +12,25 @@ const { } = Astro.props; --- -
+
-

+

{titleNormal}. {titleItalic}

-

+

{subText}

-
- +
+ Get Started in 1 Command → @@ -38,10 +38,10 @@ const { href="https://github.com/Lftobs/dequel" target="_blank" rel="noopener noreferrer" - class="cf-pill-btn-glass flex items-center gap-2" + class="cf-pill-btn-glass flex items-center justify-center gap-2 w-full sm:w-auto" >
- $ - curl -fsSL https://dequel.intrep.xyz/install.sh | bash + $ + curl -fsSL https://dequel.intrep.xyz/install.sh | bash - +
diff --git a/apps/docs/components/HowItWorks.astro b/apps/docs/components/HowItWorks.astro index 3df7847..bd47872 100644 --- a/apps/docs/components/HowItWorks.astro +++ b/apps/docs/components/HowItWorks.astro @@ -2,31 +2,31 @@ import ArchCanvas from "./architecture/ArchCanvas.astro"; --- -
+
-
+
Engine Architecture
-

+

Your own PaaS, running on your own servers.

-

+

Dequel orchestrates raw Docker containers, Buildkit compilation, Redis job queues, PostgreSQL persistence, and dynamic Caddy routing into one unified platform.

-
+
-
+
- + DEQUEL ENGINE TOPOLOGY - • - dequel_net bridge + +
+ ← Swipe diagram →
-
+
-
+
-
+
STAGE 01: INGESTION • Zero DevOps overhead
-

+

01. Multi-Channel Trigger Ingestion

@@ -108,8 +109,9 @@ import ArchCanvas from "./architecture/ArchCanvas.astro"; .dq-step-pill { display: inline-flex; align-items: center; - gap: 0.5rem; - padding: 0.45rem 0.95rem; + justify-content: center; + gap: 0.45rem; + padding: 0.5rem 0.85rem; border-radius: 9999px; background: #111115; border: 1px solid #222228; @@ -117,6 +119,7 @@ import ArchCanvas from "./architecture/ArchCanvas.astro"; cursor: pointer; transition: all 180ms ease; user-select: none; + white-space: nowrap; } .dq-step-pill:hover { border-color: #3f3f46; @@ -129,6 +132,7 @@ import ArchCanvas from "./architecture/ArchCanvas.astro"; border-radius: 50%; background-color: #52525b; transition: all 180ms ease; + flex-shrink: 0; } .dq-step-pill .step-num { font-family: 'JetBrains Mono', monospace; @@ -137,7 +141,7 @@ import ArchCanvas from "./architecture/ArchCanvas.astro"; } .dq-step-pill .step-label { font-family: 'Space Grotesk', sans-serif; - font-size: 12.5px; + font-size: 12px; font-weight: 600; } .dq-step-pill.active { diff --git a/apps/docs/components/Stats.astro b/apps/docs/components/Stats.astro index 448df86..aafcc11 100644 --- a/apps/docs/components/Stats.astro +++ b/apps/docs/components/Stats.astro @@ -7,19 +7,19 @@ const stats = [ ]; --- -

+
-
+
{stats.map((stat) => ( -
-
+
+
{stat.value}
-
+
{stat.label}
-
+
{stat.sub}
diff --git a/apps/docs/components/TerminalDemo.astro b/apps/docs/components/TerminalDemo.astro index 14085d3..e8e9bf3 100644 --- a/apps/docs/components/TerminalDemo.astro +++ b/apps/docs/components/TerminalDemo.astro @@ -1,11 +1,11 @@ --- --- -
-
-
+
+
+
Developer Experience
-

+

From git push to production
in under 4 seconds.

@@ -25,7 +25,7 @@
-
+
@@ -35,7 +35,7 @@ dequel cli v1.0.0 bash
-
+
$ diff --git a/apps/docs/components/architecture/ArchCanvas.astro b/apps/docs/components/architecture/ArchCanvas.astro index db6c58c..3debce3 100644 --- a/apps/docs/components/architecture/ArchCanvas.astro +++ b/apps/docs/components/architecture/ArchCanvas.astro @@ -1,11 +1,11 @@ --- --- -
+
diff --git a/apps/docs/components/architecture/archController.ts b/apps/docs/components/architecture/archController.ts index 015e0ac..9f602af 100644 --- a/apps/docs/components/architecture/archController.ts +++ b/apps/docs/components/architecture/archController.ts @@ -75,6 +75,15 @@ export function initArchController() { chipV4.setAttribute("stroke", "#ea580c"); } } + + // 6. Auto-pan horizontal scroll container on mobile viewports + const scrollEl = document.getElementById("dq-arch-scroll"); + if (scrollEl && scrollEl.scrollWidth > scrollEl.clientWidth) { + const ratios = [0, 0.25, 0.48, 0.72, 1.0, 0.48]; + const ratio = ratios[stepIndex - 1] ?? 0; + const maxScroll = scrollEl.scrollWidth - scrollEl.clientWidth; + scrollEl.scrollTo({ left: maxScroll * ratio, behavior: "smooth" }); + } } function startTimer() { diff --git a/apps/docs/docs/alerts.md b/apps/docs/docs/alerts.md new file mode 100644 index 0000000..94db969 --- /dev/null +++ b/apps/docs/docs/alerts.md @@ -0,0 +1,39 @@ +--- +title: Alerts +category: Observability +description: CPU, memory, and downtime alert rules with email, Slack, and webhook channels. +slug: alerts +--- + +The project's **Alerts** tab defines rules evaluated continuously in +the background. When a rule fires, Dequel notifies the channel you +chose — and failure emails link straight back to the logs. + +## Rule types + +- **CPU** — fires when average CPU % exceeds your threshold (default + 80%) for the window. +- **Memory** — same for memory % (default 85%). +- **Downtime** — fires immediately when the deployment stops responding. + +Create a rule with a metric, threshold (1–100), and channel. Toggle +rules on/off without deleting them. + +## Channels + +- **Email** — delivered through your [SMTP settings](/docs/settings). + Failure notifications include a link to the relevant logs. +- **Slack** — posts to an incoming webhook URL (Slack webhook format). +- **Webhook** — generic HTTPS POST to any URL for PagerDuty, Opsgenie, + or custom receivers. + +## Evaluation cadence + +Rules evaluate on the platform interval (`ALERT_EVAL_INTERVAL_MS`, +default 60s; see [System Configuration](/docs/system-config)). +Thresholds combine with duration so brief spikes do not page you. + +## Next steps + +- Read [Settings](/docs/settings) to configure the SMTP relay. +- Read [Observability](/docs/observability) to watch the underlying metrics. diff --git a/apps/docs/docs/auth.md b/apps/docs/docs/auth.md index 704e7fa..d520a5a 100644 --- a/apps/docs/docs/auth.md +++ b/apps/docs/docs/auth.md @@ -1,54 +1,64 @@ --- title: Authentication & Access Control -category: Networking & Security -description: Secure your Dequel dashboard with PAM-based authentication, session management, and API keys. +category: Security +description: Linux-user login, short-lived sessions, and scoped API keys. slug: auth --- -Dequel authenticates users against the **Linux system user database** via PAM (Pluggable Authentication Modules). Only users who are members of the `dequel` group can sign in. +Dequel has two credential types: interactive login for the dashboard +(Linux users) and API keys for programmatic access (CI, scripts). -## User Setup +## Dashboard login -Create a Linux user and add them to the `dequel` group: +Dequel authenticates dashboard users against the host's Linux accounts +through PAM. Only members of the `dequel` group can sign in. Create a +user after installing: ```bash +sudo groupadd -f dequel sudo useradd -m -s /bin/bash sudo passwd sudo usermod -aG dequel ``` -The user signs into the Dequel dashboard with their Linux username and password. +## Sessions -## Session Management +- **Access token** — a JWT in the `dequel_session` cookie, valid 15 + minutes (`HttpOnly`, `SameSite=Lax`, `Secure` behind HTTPS). +- **Refresh token** — a rotating opaque token in the `dequel_refresh` + cookie, valid 7 days. Logging out invalidates it immediately. +- The dashboard silently refreshes the session and redirects to + `/login` when both tokens are gone. -- **Access tokens**: Short-lived (15 min) HMAC-SHA256 JWTs stored in an `httpOnly` cookie. -- **Refresh tokens**: Long-lived (7 days) random tokens stored in the database. Automatically rotated on refresh. -- **Token blacklisting**: Logging out or refreshing invalidates the old refresh token immediately. -- **JWT secret**: Auto-generated on first API startup, stored at `data/.jwt_secret` (0600 permissions). Deleting this file invalidates all sessions. +## API keys -## API Keys +For CI pipelines, scripts, and external tools, create keys on the +**Keys → API Tokens** page (see [Keys](/docs/keys)): -For programmatic access (CI/CD, CLI tools), Dequel uses pre-shared API keys: - -1. Go to **Settings → API Keys** in the dashboard. -2. Create a new key — the full token is shown once. -3. Use it as a Bearer token in the `Authorization` header: +1. Generate a token with a label and scope (CI/CD, monitoring, or full + admin). +2. Copy the `dql_...` token — it is shown once and stored hashed. +3. Send it as a Bearer token: ```bash -curl -H "Authorization: Bearer dqk_" https://dequel.example.com/api/projects +curl -H "Authorization: Bearer dql_" https://dequel.example.com/api/projects ``` -API keys are scoped to the entire platform with the same permissions as the user who created them. +Keys carry read/write scopes enforced per HTTP method. Revoke a key any +time from the same page; deleting it breaks its integrations +immediately. -## Endpoints +## API endpoints | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/auth/login` | None | Sign in with username/password | -| `POST` | `/api/auth/logout` | Session | Sign out, blacklist refresh token | +| `POST` | `/api/auth/logout` | Session | Sign out, invalidate refresh token | | `POST` | `/api/auth/refresh` | Session | Rotate refresh token | -| `GET` | `/api/auth/me` | None | Check current session status | +| `GET` | `/api/auth/me` | None | Current session status | | `GET` | `/api/health` | None | Health check | -The web dashboard redirects to `/login` when no valid session is detected. +## Next steps +- Read [Keys](/docs/keys) for API tokens and the SSH key pool. +- Read [GitHub](/docs/github) for the OAuth repo connection. diff --git a/apps/docs/docs/backups.md b/apps/docs/docs/backups.md new file mode 100644 index 0000000..c31fd09 --- /dev/null +++ b/apps/docs/docs/backups.md @@ -0,0 +1,51 @@ +--- +title: Backups +category: Data +description: Scheduled and on-demand backups with one-click restore. +slug: backups +--- + +Dequel backs up managed databases on a schedule you set per database, +plus the platform's own internal database. Every snapshot can be +restored to its container from the dashboard, the API, or the CLI. + +## Storage + +Configure where backups land under **Settings → Backups**: + +- **Local** — a path on the control plane (default `/data/backups`). +- **S3** — bucket, endpoint, region, and credentials (works with AWS S3 + and S3-compatible stores like R2). + +## Database backups + +Each database carries a backup schedule: enable it during provisioning +or later in the database **Settings** tab, with a cron preset (every 6 +hours, every 12 hours, daily) and a retention window (1–30 snapshots). +The database **Backups** tab lists snapshots with engine, size, and +date, and offers **Take Backup Now** (while running), **Restore**, and +**Delete**. + +Restoring replaces the container's data with the snapshot. Triggering +and restoring are also API calls (`POST /backups/:id/trigger`, +`POST /backups/:id/restore`). + +## System backups + +The platform database itself is snapshotted on its own cron (hourly to +weekly presets) with its own retention, configured in the same settings +section. **Backup System Database Now** takes an immediate snapshot. + +From a shell, the CLI covers the same flows (see [CLI](/docs/cli)): + +```bash +dequel backup # back up the internal database now +dequel backup # back up a managed database now +dequel backup list # list snapshots +dequel backup restore # restore a snapshot +``` + +## Next steps + +- Read [Managed Databases](/docs/databases) for engine operations. +- Read [CLI](/docs/cli) for shell-driven backup commands. diff --git a/apps/docs/docs/cli.md b/apps/docs/docs/cli.md new file mode 100644 index 0000000..e08ffd9 --- /dev/null +++ b/apps/docs/docs/cli.md @@ -0,0 +1,58 @@ +--- +title: CLI Reference +category: Platform +description: Manage Dequel from the shell with the dequel command. +slug: cli +--- + +The installer places the `dequel` command on your `PATH`. It manages +the compose stack, updates, and backups. Configuration lives in +`~/.dequel` (override with `DEQUEL_HOME`). + +## Lifecycle + +| Command | Description | +|---------|-------------| +| `dequel start` | Start all services | +| `dequel stop` | Stop all services | +| `dequel restart` | Restart all services | +| `dequel status` | Show service status | +| `dequel logs [service]` | Follow service logs | +| `dequel uninstall` | Remove everything (prompts first) | +| `dequel --version` | Show version | +| `dequel --help` | Show help | + +## Updates + +```bash +dequel update # latest stable (rolling restart) +dequel update --pre # latest pre-release +dequel update --rc # latest release candidate +dequel update vX.Y.Z # a specific version +``` + +## Backups + +```bash +dequel backup # back up the internal database now +dequel backup # back up a managed database now +dequel backup list # list snapshots +dequel backup restore # restore a snapshot +``` + +Snapshots land in the storage configured under **Settings → Backups** +(see [Backups](/docs/backups)). + +## API access from scripts + +The CLI manages the platform, not your apps. For automation against +your projects, use [API keys](/docs/keys) with `curl`: + +```bash +curl -H "Authorization: Bearer dql_" https://dequel.example.com/api/projects +``` + +## Next steps + +- Read [Installation](/docs/installation) for setup. +- Read [Backups](/docs/backups) for the dashboard backup flows. diff --git a/apps/docs/docs/configuration.md b/apps/docs/docs/configuration.md index 26fbc0a..7e8fc55 100644 --- a/apps/docs/docs/configuration.md +++ b/apps/docs/docs/configuration.md @@ -1,46 +1,62 @@ --- -title: Configuration -category: Getting Started -description: Configure compute bounds, custom ports, and service specs. +title: Project Configuration +category: Projects +description: Build settings, ports, and resource limits for your project. slug: configuration --- -Dequel provides fine-grained control over container resources and network routing to ensure optimal application performance and stability. +Each project carries its build and runtime configuration. You set most of +it in the creation wizard and can change it later on the project's +**Settings** tab (`PATCH /projects/:id`). -## Resource Limits +## Build settings -Configure boundary limits under the Settings layout to avoid cluster resource starvation or application OOM (Out Of Memory) crashes: +**Build strategy** is either `railpack` (automatic single-service build) +or `compose` (multi-container from your repo-root `docker-compose.yml`). +Railpack auto-detects the framework and proposes install, build, and +start commands plus the output directory and port — every field stays +editable for frameworks it guesses wrong. -- **CPU Limit (cores):** The maximum amount of CPU shares a container replica can consume. Specifying `1.0` permits a full single core. -- **Memory Limit (MB):** The boundary RAM limit allocated. If a container exceeds this, it is automatically terminated with an OOM error code and restarted. Recommended default: `512MB`. +Useful fields: -## Port Configurations +- **Root directory** — build a subdirectory of the repo (monorepos). +- **Port** — the port your app listens on inside the container. Railpack + usually detects this; override it when it does not. +- **Output directory** — for static sites, the folder served after build. +- **Project type** — `web` (long-running server) or `static` (built + assets served directly). +- **Compose service mapping** — for Compose builds, one row per + internet-facing service: service name, port, and subdomain. The first + row is the entry service on the project's main domain; the rest get + `.`. -Dequel's edge router (Caddy) uses reverse proxy routing to map incoming HTTP request traffic to your container. +## Ports and routing -
- ⚠️ Crucial Note: Internal Ports -

Your application inside the container must bind to the environment-injected PORT variable. Hardcoding listen ports to 3000 or 8080 without reading the environment variable will result in a 502 Bad Gateway error, as Caddy's dynamic routing target won't match.

-
+Your app must listen on the configured port on all interfaces +(`0.0.0.0`). A typical Node entrypoint reads it from the environment: -## Example: Express server +```js +const PORT = process.env.PORT || 3000; +app.listen(PORT, "0.0.0.0"); +``` -
-
- server.js -
-
const express = require('express');
-const app = express();
+Caddy reverse-proxies the project domain to that port. If the app binds
+`localhost` only or a different port, the route returns `502 Bad
+Gateway` — check the [route files](/docs/agent-caddy-routes) and the
+container's runtime logs.
 
-// ALWAYS read from process.env.PORT
-const PORT = process.env.PORT || 3000;
+## Resource limits
+
+On the **Scaling** tab, the resource card sets per-container bounds:
+
+- **CPU limit (cores)** — for example `1.0` for one full core.
+- **Memory limit (MB)** — for example `512`. A container that exceeds it
+  is killed with an OOM error and restarted.
 
-app.get('/', (req, res) => {
-  res.send('Hello from Dequel!');
-});
+Autoscaling requires a CPU limit to be set, since the engine scales on
+CPU utilization. See [Scaling](/docs/scaling).
 
-app.listen(PORT, '0.0.0.0', () => {
-  console.log(`Server listening on port ${PORT}`);
-});
-
+## Next steps +- Read [Deployments](/docs/deployments) for the deploy lifecycle. +- Read [Environment Variables](/docs/env-vars) for config injection. diff --git a/apps/docs/docs/control-plane.md b/apps/docs/docs/control-plane.md deleted file mode 100644 index 8d8dccf..0000000 --- a/apps/docs/docs/control-plane.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Control Plane Setup -category: Getting Started -description: Install Dequel and connect remote servers for deployment. -slug: control-plane ---- - -The control plane (dashboard + API) runs on any machine with Docker. All builds, containers, and Caddy routing happen on the **servers** you connect; the control plane only orchestrates them over SSH or the P2P WireGuard agent. - -## Install - -The install script sets up all services (`api`, `web`, `caddy`, `redis`, `buildkit`, and the monitoring stack): - -```bash -curl -fsSL https://github.com/Lftobs/dequel/releases/latest/download/install.sh | bash -dequel start -``` - -Open `http://localhost` to access the dashboard. - -## Connecting servers - -### SSH mode (recommended) - -1. In **Settings → Servers**, add your server with its IP/hostname, SSH port, and SSH user (defaults to `root`). -2. The server only needs SSH access from the control plane — Docker, Caddy, and Railpack are installed for you. -3. Click **Prepare** on the server row. Dequel streams live progress as it: - - Connects over SSH and detects the OS - - Installs Docker if missing - - Installs Caddy and configures `/etc/caddy/routes/` - - Installs the Railpack CLI -4. When the stream reports success, the server is ready to deploy to. - -Prepare is idempotent — re-running it skips anything already installed. - -### Agent mode (firewalled nodes) - -For servers without open SSH ports, add the server as **Agent**, then click **Prepare**. Dequel generates a registration token and shows a `docker run` command — run it on the target server. The agent registers back over the control plane and establishes a direct WireGuard tunnel. The prepare stream waits until the agent reports connected. - -## Shared base domain - -All servers share a single base domain. Set it once on the control plane: - -``` -CADDY_BASE_DOMAIN=example.com -``` - -Every project defaults to `.` (e.g. `api.example.com`) **regardless of which server it is deployed to** — Dequel generates identical route hostnames everywhere. - -DNS setup: point `*.example.com` at your servers. With multiple servers behind one wildcard, either: - -- Point the wildcard record at a single ingress server, or -- Add per-deployment A records (`api.example.com → server-ip`) for finer control - -Projects with a custom domain configured bypass the base domain entirely. \ No newline at end of file diff --git a/apps/docs/docs/deployments.md b/apps/docs/docs/deployments.md index 811d51f..04a9387 100644 --- a/apps/docs/docs/deployments.md +++ b/apps/docs/docs/deployments.md @@ -1,31 +1,59 @@ --- title: Deployments -category: Core Architecture -description: Trigger builds, view active execution logs, and roll back code changes. +category: Projects +description: Trigger builds, follow live logs, and roll back releases. slug: deployments --- -Dequel supports two primary methods for deploying code changes: automated tracking via **Git repository branches**, and **manual zip uploads** directly from the local filesystem. +A deployment is one build-and-run cycle of your project. The project's +**Deployments** tab lists the full history with status, source, branch, +duration, and age, and lets you manage each one. -## Git Integration +## Deployment sources -Configure a Git repository URL (e.g. `github.com/my-org/my-project`) and specify a branch name (e.g. `main`). +**Git.** Point the project at a repository URL and branch (or pick a repo +through the GitHub integration). New pushes rebuild automatically when +the webhook is connected — toggle **Auto-deploy** on the Deployments +tab. **Manual Deploy** rebuilds from the latest commit or a specific +SHA, with an option to clear the BuildKit cache. -- **Automated webhook updates:** Dequel listens to push events to rebuild automatically. -- **Manual triggers:** Click the **Deploy Branch** CTA in the UI to manually queue a build of the latest commit. +**Upload.** Drop a `.zip` (at creation) or `.zip` / `.tar` / `.tar.gz` +(on the Deployments tab) to deploy local code. An upload project can be +migrated to Git later from the same tab without losing history. -## Manual File Directory Uploads +**Docker Compose.** Repos with a `docker-compose.yml` build all services +together; only the mapped ingress services get public URLs (see +[Project Configuration](/docs/configuration)). -If your code is not stored in a public repository, or you want to test local modifications immediately: +## Lifecycle -1. Drag and drop your local directory as a compressed `.zip` archive. -2. Dequel uploads the file payload directly to the builder API node. -3. The archive is unpacked and fed straight into the Docker build engine. +Deployments move through `pending` → `building` → `deploying` → +`running`. A failed build ends in `failed`; you can `cancel` a queued or +active build. Only one deployment is live per project — each successful +deploy replaces the previous container. -## Active Logs & Rollbacks +Click a row to expand its **build logs**, streamed live while the build +runs and stored afterwards. The **Runtime Logs** view (under the +**Logs** tab) shows the running container's stdout instead. -Each deployment creates an isolated, immutable build artifact. +## Redeploy, rollback, delete -- **Build Logs:** View the live compiler steps as Docker pulls layers, executes commands, and builds cache images. -- **Zero-Downtime Rollbacks:** Instantly switch traffic back to a previous build artifact by clicking the **Promote** button on any previously successful deployment. +- **Redeploy** clones the currently running deployment (same image and + config) — the standard way to apply changed env vars or volumes. +- **Rollback** points the route back at an earlier deployment's image. + Images are kept, so rollback is instant and does not rebuild. +- **Delete** destroys a deployment's containers. The running deployment + cannot be deleted. +## Failed builds and AI diagnosis + +If a deployment fails, the log header shows a **Diagnose** button. It +opens the AI diagnosis sheet: pick a configured LLM provider and model, +and the agent investigates the logs, decides whether the fault is your +code or the platform, and can open a fix pull request on your repo. See +[AI Diagnosis](/docs/ai-diagnosis). + +## Next steps + +- Read [AI Diagnosis](/docs/ai-diagnosis) for the failure workflow. +- Read [Observability](/docs/observability) for logs and metrics. diff --git a/apps/docs/docs/domains.mdx b/apps/docs/docs/domains.mdx index 168b905..0f497f1 100644 --- a/apps/docs/docs/domains.mdx +++ b/apps/docs/docs/domains.mdx @@ -1,31 +1,51 @@ --- title: Custom Domains -category: Networking & Security -description: Point custom web addresses to container deployment endpoints using DNS records. +category: Projects +description: Point your own domains at Dequel projects with automatic HTTPS. slug: domains --- -Dequel provides public routing endpoints. You can route external domain request traffic (e.g. `app.mycompany.com`) by pointing DNS records to Dequel cluster host IP addresses. - -## Step 1: Add Domain in Dequel Console - -Under the **Domains** tab, click **Add Domain**, enter your custom domain address (e.g., `blog.mydomain.com`), and save. - -## Step 2: Configure DNS Records - -In your DNS registrar's control panel (Cloudflare, GoDaddy, Namecheap, etc.), add the record displayed in the instructions box: - -- **For Subdomains:** Add a `CNAME` record pointing your subdomain (e.g. `blog`) to the cluster's base domain. -- **For Apex/Root Domains:** Add an `A` record pointing `@` directly to the Dequel cluster server IP. - -:::note[DNS Propagation] -DNS changes can take up to 24–48 hours to propagate globally. Dequel will run automated validation checks in the background until the records resolve correctly. +Every project gets a default URL on your base domain +(`.`). Add **custom domains** on the +project's **Domains** tab to serve the app on addresses you own, like +`app.mycompany.com`. + +## Adding a domain + +1. Click **Add Domain** and enter the domain. +2. For Docker Compose projects, pick the target service and port; for + single-service projects the running container is the target. +3. Dequel shows DNS instructions. Create the record at your registrar: + - **Subdomain** (`app.mycompany.com`): a `CNAME` pointing at your + base domain, or an `A` record pointing at the server IP. + - **Apex domain** (`mycompany.com`): an `A` record pointing at the + server IP (find it under **Settings → Servers** or + `GET /server/ip`). +4. Dequel verifies DNS in the background and marks the domain + `verified`. Caddy then serves it with an automatic Let's Encrypt + certificate (see [SSL](/docs/ssl)). + +The Domains tab shows live status per domain: validation state, SSL +state, whether DNS resolves, and whether TLS handshakes succeed (polled +continuously). + +:::note[DNS propagation] +New records can take minutes to hours to propagate. Dequel keeps +re-checking until they resolve — you don't need to click anything while +waiting. ::: +## Validation states + +- **Pending** — waiting for DNS to resolve to the server. +- **Verified** — DNS matches and the route is live. +- **Failed** — records point somewhere else. Fix the DNS values and + Dequel re-checks. -## Validation Statuses +Remove a domain any time with the delete action; its route is removed +on the next Caddy reload. -- **Pending:** Dequel is awaiting DNS propagation. -- **Verified:** DNS records resolve correctly. The proxy router is configured. -- **Failed:** Resolving record targets did not match the required target targets. Check your DNS values. +## Next steps +- Read [SSL](/docs/ssl) for certificate details. +- Read [Agent Caddy Routes](/docs/agent-caddy-routes) for the routing internals. diff --git a/apps/docs/docs/env-vars.mdx b/apps/docs/docs/env-vars.mdx index cb32ee8..3e8457f 100644 --- a/apps/docs/docs/env-vars.mdx +++ b/apps/docs/docs/env-vars.mdx @@ -1,28 +1,39 @@ --- title: Environment Variables -category: Core Architecture -description: Inject configuration values, API keys, and connection credentials securely into container environments. +category: Projects +description: Inject per-environment config and secrets into your containers. slug: env-vars --- -Environment variables decouple application configurations from source code repositories. Secrets (like payment gateways, SMTP credentials, or database passwords) must always be injected this way to preserve security. +Environment variables decouple configuration from code. API keys, +database URLs, and feature flags go here instead of the repository. +Values are encrypted at rest with `ENV_ENCRYPTION_KEY` and masked in +the UI until you reveal them. -## Adding Variables +## Managing variables -In the project console, click the **Environment Variables** tab: +Open the project and switch to the **Env Variables** tab: -- Enter a key name (e.g. `STRIPE_SECRET_KEY`). Key names should contain only alphanumeric characters and underscores. -- Enter the value. All values are securely stored and encrypted in the cluster database. -- Click **Add Variable**. +- **Add** one variable or several at once, each scoped to an environment + (for example `production`). Keys are conventionally uppercase. +- **Import** a local `.env` file to bulk-load variables. +- **Reveal** a masked value with the eye icon (decrypts on demand), or + copy it without revealing. +- **Edit** a value inline or **delete** the variable. -:::note[Masked Displays] -For security, all environment variable values are masked on load. Click the eye icon to reveal them, or copy them securely via the copy badge. -::: +Variables are injected when the container starts, so adding, editing, or +deleting one requires a restart. Dequel shows a redeploy banner at the +top of the tab after any change — click **Redeploy** to roll the new +config out. +## Shared variables -## Redeployment Prompts +Variables needed by several projects (a shared API key, a common feature +flag) live once in the **Shared Env** library and are linked into +projects. A project-level variable with the same key wins over the +shared one. See [Shared Env Vars](/docs/shared-env-vars). -Because environment variables are injected during container startup, modifying or deleting variables requires a container restart to take effect. - -Dequel displays a **Redeployment Warning Banner** at the top of the tab whenever variables are mutated. Click the **Redeploy Now** button on the banner to execute a zero-downtime rolling update with the new configurations. +## Next steps +- Read [Shared Env Vars](/docs/shared-env-vars) for cross-project config. +- Read [Deployments](/docs/deployments) for the redeploy flow. diff --git a/apps/docs/docs/github.md b/apps/docs/docs/github.md new file mode 100644 index 0000000..a9d8d5c --- /dev/null +++ b/apps/docs/docs/github.md @@ -0,0 +1,42 @@ +--- +title: GitHub Integration +category: Integrations +description: Repo picker, push-to-deploy webhooks, and fix pull requests. +slug: github +--- + +Connect a GitHub OAuth app once, and Dequel picks repos, installs +push-to-deploy webhooks, and opens AI fix pull requests on your behalf. + +## Setup + +Open **Settings → GitHub** and save the OAuth app credentials (client +ID, client secret, app name, webhook secret). The page shows the exact +callback URL to register in **GitHub → Settings → Developer settings → +OAuth Apps** and walks through creating the app. + +Then click **Connect GitHub** (in Settings or in the project wizard) to +authorize with `repo`, `read:org`, and `admin:repo_hook` scopes. +Dequel stores the token server-side and shows a connected badge. + +## What it unlocks + +- **Repo picker** — in the project wizard, choose **GitHub Account** + instead of pasting URLs: search your repos, and Dequel fills in the + clone URL, branch, and project name. +- **Push-to-deploy** — toggle **Auto-deploy** on the Deployments tab. + Dequel registers a webhook (`/api/github/webhook`, HMAC-verified with + your secret) that rebuilds the project on every push to the tracked + branch. +- **Fix pull requests** — [AI Diagnosis](/docs/ai-diagnosis) can open a + `dequel-fix/*` branch and PR against your repo when it determines the + failure is in your code. Requires the connected account to have push + access. + +Disconnect any time from the same tab; webhooks already installed keep +working until removed. + +## Next steps + +- Read [Deployments](/docs/deployments) for manual and auto deploys. +- Read [AI Diagnosis](/docs/ai-diagnosis) for the fix-PR flow. diff --git a/apps/docs/docs/index.mdx b/apps/docs/docs/index.mdx index 3539979..49b38c1 100644 --- a/apps/docs/docs/index.mdx +++ b/apps/docs/docs/index.mdx @@ -4,26 +4,37 @@ category: Getting Started slug: docs --- -Dequel provides developers with a Heroku-like platform experience on top of virtualized docker runtimes and cluster node providers. You get the simplicity of automated Git triggers, built-in let’s encrypt SSL proxy routing, and direct persistent volume attachments without wrestling with complex Kubernetes configurations. - -## Core Philosophy - -- **Zero-Config Routing:** Incoming traffic is automatically proxied to active deployments based on project configuration. -- **State Isolation:** Web containers are designed to be ephemeral. Persistent state is kept cleanly separated in managed databases or mapped node volumes. -- **Self-Healing Runtimes:** Failed container instances are automatically replaced, and scaling adjustments occur automatically based on CPU usage. - -:::note[Key Concept: Projects] -A Project in Dequel represents a single service (a container build) along with its environment configurations, database attachments, routing domains, and active deployments. +Dequel is a self-hosted deployment platform. You connect your servers, +push code from Git or a ZIP file, and Dequel builds, runs, routes, and +monitors your apps — with automatic HTTPS, managed databases, horizontal +autoscaling, and AI-assisted failure diagnosis built in. + +If you have used Heroku, Render, or Railway, Dequel gives you that same +push-to-deploy workflow on infrastructure you own. There is no control +plane phoning home: the dashboard, API, builders, and observability stack +all run as containers on your machine. + +## How Dequel works + +When you create a project and trigger a deployment: + +1. Dequel fetches your code from a Git repository (or unpacks your ZIP + upload) into a build workspace. +2. It detects your framework automatically with Railpack — no Dockerfile + required — or follows your `docker-compose.yml` for multi-container + projects, then builds the image with BuildKit. +3. It starts your container on the target server (the control plane + itself, a server you connected over SSH, or a WireGuard agent node) + and injects your environment variables and volume mounts. +4. It writes a Caddy route file so your app is reachable at + `https://.` with an automatic Let's Encrypt + certificate, or at `http://.localhost` in local setups. +5. It keeps watching: request logs, runtime logs, CPU and memory metrics, + alert rules, and autoscaling policies all run against the deployment. + +:::note[Key concept: projects] +A project in Dequel is a single service — its source, build settings, +environment variables, volumes, domains, scaling policy, alert rules, +and deployment history. Databases are separate managed resources you +attach to projects. ::: - - -## How Dequel Works - -When you connect a repository or upload a folder: - -1. Dequel reads your project's code directory and looks for a `Dockerfile` or builder configurations. -2. It initiates a secure cluster builder environment to package your container image. -3. The container image is pushed to the local cluster registry and distributed across running nodes. -4. Caddy routing endpoints are automatically updated to direct traffic to the newly created instance ports. - - diff --git a/apps/docs/docs/installation.md b/apps/docs/docs/installation.md index 8c24ea7..49c8bfd 100644 --- a/apps/docs/docs/installation.md +++ b/apps/docs/docs/installation.md @@ -5,159 +5,129 @@ description: Install Dequel on your own infrastructure. slug: installation --- +You install Dequel with one command. The installer sets up the control +plane (dashboard, API, builders, databases engine, and monitoring) as +Docker containers on your machine. Your apps can run on that same machine, +or on additional servers you connect later (see +[Servers](/docs/servers)). + ## Prerequisites -- **Docker** installed on your system -- **Docker Compose v2** (`docker compose` command) +- **Docker** and **Docker Compose v2** (`docker compose`) +- A Linux server with ports `80` and `443` reachable if you want public + HTTPS URLs (not needed for local-only use) -## Install Script +## Install -The quickest way to get Dequel running: +Run the install script: ```bash curl -fsSL https://github.com/Lftobs/dequel/releases/latest/download/install.sh | bash ``` -This will: - -1. Check that Docker and Docker Compose are installed -2. Create a config directory at `~/.dequel` -3. Download `docker-compose.yml` and monitoring configs -4. Pull pre-built Docker images from GitHub Container Registry -5. Install the `dequel` CLI to `/usr/local/bin` +The script checks for Docker and Compose, creates a config directory at +`~/.dequel`, generates a unique `ENV_ENCRYPTION_KEY`, downloads the +`docker-compose.yml` and monitoring configs, pulls the pre-built images +from GitHub Container Registry, installs the `dequel` CLI, and asks for +an optional admin email (Let's Encrypt notifications) and base domain +(public app URLs). -After installation, start the platform: +Then start the platform: ```bash dequel start ``` -Open `http://localhost` to access the dashboard (or the configured `CADDY_BASE_DOMAIN` in production). +Open `https://` to access the dashboard. If you configured a base +domain during install, the dashboard is also served on it. + +![Dequel login page](/screenshots/login.png) -## Post-Installation: User Setup +## Create your login user -Dequel authenticates against Linux system users in the `dequel` group. After install, create a user: +Dequel authenticates against Linux system users in the `dequel` group. +Create the group and a user after installing: ```bash +sudo groupadd -f dequel sudo useradd -m -s /bin/bash sudo passwd sudo usermod -aG dequel ``` -See [Authentication & Access Control](/docs/auth) for details on session management and API keys. - -## Manual Setup (no install script) - -If the installer fails, set up the platform manually with just Docker Compose and the config files: - -```bash -# Create the installation directory -mkdir -p ~/.dequel/data ~/.dequel/workspace \ - ~/.dequel/infra/caddy/routes \ - ~/.dequel/infra/monitoring/grafana/datasources - -# Download config files -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/docker-compose.yml \ - -o ~/.dequel/docker-compose.yml -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/caddy/Caddyfile \ - -o ~/.dequel/infra/caddy/Caddyfile -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/monitoring/prometheus.yml \ - -o ~/.dequel/infra/monitoring/prometheus.yml -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/monitoring/loki-config.yml \ - -o ~/.dequel/infra/monitoring/loki-config.yml -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/monitoring/promtail-config.yml \ - -o ~/.dequel/infra/monitoring/promtail-config.yml -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/monitoring/grafana/datasources/loki.yml \ - -o ~/.dequel/infra/monitoring/grafana/datasources/loki.yml -curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/infra/monitoring/grafana/datasources/prometheus.yml \ - -o ~/.dequel/infra/monitoring/grafana/datasources/prometheus.yml - -# Start all services -docker compose -f ~/.dequel/docker-compose.yml up -d -``` - -The compose file uses pre-built images from GitHub Container Registry, so no source code checkout is needed. Access the dashboard at `http://localhost` (or your configured `CADDY_BASE_DOMAIN`). - -## Manual Setup with Docker Compose (with source) +Sign in with that username and password. See +[Authentication](/docs/auth) for sessions, API keys, and programmatic +access. -Clone the repository and build from source: +## Production setup -```bash -git clone https://github.com/Lftobs/dequel.git -cd dequel -docker compose up -d --build -``` - -## Production Setup +To serve public HTTPS traffic: -To make Dequel publicly accessible with auto-SSL: - -1. Set `CADDY_BASE_DOMAIN` and `CADDY_EMAIL` in `~/.dequel/.env`: - ``` +1. Set the base domain and contact email in `~/.dequel/.env` (the + installer already wrote these if you provided them): + ```bash CADDY_BASE_DOMAIN=example.com CADDY_EMAIL=admin@example.com ``` -2. Configure a wildcard DNS `*.example.com` pointing to your server's IP. +2. Point a wildcard DNS record (`*.example.com`) at your server's IP. 3. Ensure ports `80` and `443` are open in your firewall. -4. Restart Dequel: `dequel restart` +4. Restart with `dequel restart`. -Deployed apps will be reachable at `https://.example.com` with auto-provisioned Let's Encrypt certificates. The dashboard is available at both `http://example.com` and `https://example.com`. +Deployed apps become reachable at `https://.example.com` +with automatic Let's Encrypt certificates. -## The `dequel` CLI +## Configuration directory -The `dequel` command manages the platform lifecycle: +Dequel stores its state in `~/.dequel` (override with `DEQUEL_HOME`): -| Command | Description | -|---------|-------------| -| `dequel start` | Start all Dequel services | -| `dequel stop` | Stop all services | -| `dequel status` | Show service status | -| `dequel logs` | Follow service logs | -| `dequel update` | Pull latest images and restart | -| `dequel restart` | Restart all services | -| `dequel --help` | Show all commands | - -## Configuration Directory - -Dequel stores its configuration in `~/.dequel` (or `$DEQUEL_HOME` if set): - -``` +```text ~/.dequel/ ├── docker-compose.yml -├── .env # Optional environment overrides -├── data/ # SQLite database +├── .env # CADDY_BASE_DOMAIN, CADDY_EMAIL, ENV_ENCRYPTION_KEY +├── data/ +│ ├── dequel.json # File-based platform config (0600) +│ └── ... # Postgres data, backups, instance id ├── workspace/ # Build staging area +├── scripts/auth/ # PAM auth server files └── infra/ ├── caddy/ │ ├── Caddyfile - │ └── routes/ - └── monitoring/ - ├── prometheus.yml - ├── loki-config.yml - └── grafana/ + │ └── routes/ # Generated per-project route files + └── monitoring/ # Prometheus, Loki, Grafana configs ``` -## Building from Source +PostgreSQL holds all platform state (projects, deployments, env vars, +databases, users). It runs as the `postgres` container with a persisted +volume — there is no SQLite file to manage. -For local development, run the API and web dashboard directly. The API uses -fixed paths for build staging and Caddy routes, so create them once: +## The `dequel` CLI -```bash -sudo mkdir -p /app/workspace /caddy/routes -sudo chown -R "$USER" /app/workspace /caddy/routes -``` +The CLI manages the platform lifecycle. See the full +[CLI reference](/docs/cli) for update channels and backups. -The API writes build artifacts to `/app/workspace` and Caddy route files to -`/caddy/routes`, so your user must own both directories when you run the API -without `sudo`. +| Command | Description | +|---------|-------------| +| `dequel start` | Start all services | +| `dequel stop` | Stop all services | +| `dequel restart` | Restart all services | +| `dequel status` | Show service status | +| `dequel logs` | Follow service logs | +| `dequel update` | Update to the latest release | +| `dequel backup` | Back up the internal database | +| `dequel uninstall` | Remove everything (prompts first) | -```bash -# Terminal 1 — API -bun apps/api/src/index.ts +## Manual setup -# Terminal 2 — Web -bun apps/web/src/main.tsx -``` +If the installer does not fit your environment, replicate what it does: +create the directory layout above, download `docker-compose.yml` and the +`infra/` configs from the latest GitHub release, write your `.env` with +`CADDY_BASE_DOMAIN`, `CADDY_EMAIL`, and a generated +`ENV_ENCRYPTION_KEY`, then run +`docker compose -f ~/.dequel/docker-compose.yml up -d`. + +To build from source instead, clone the repository and run +`docker compose up -d --build`. For local development of the API and +dashboard directly, see the commands in `AGENTS.md`. ## Updating @@ -165,5 +135,10 @@ bun apps/web/src/main.tsx dequel update ``` -This pulls the latest images from GitHub Container Registry and recreates the services. +This pulls the latest images and recreates services with a rolling +restart. Pin a version with `dequel update vX.Y.Z`. + +## Next steps +- Follow the [Quickstart](/docs/quickstart) to deploy your first app. +- Connect more machines under [Servers](/docs/servers). diff --git a/apps/docs/docs/keys.md b/apps/docs/docs/keys.md new file mode 100644 index 0000000..a331d17 --- /dev/null +++ b/apps/docs/docs/keys.md @@ -0,0 +1,44 @@ +--- +title: Keys & Tokens +category: Security +description: API tokens for automation and the SSH key pool for servers. +slug: keys +--- + +The **Keys** page is the credential control center: API tokens for +programmatic access, and the SSH key pool that server connections draw +from. + +![Keys page](/screenshots/keys.png) + +## API tokens + +Generate a token with a label and a scope preset (CI/CD pipeline, +monitoring and logs, or full admin). The `dql_...` token is shown +**once** — copy it immediately; afterwards only its hash prefix is +listed. Send it as a Bearer token: + +```bash +curl -H "Authorization: Bearer dql_" https://dequel.example.com/api/projects +``` + +Scopes are enforced per HTTP method (read vs write). Revoke a token +from the table when it leaks or is no longer needed. The **CLI guide** +tab shows copy-paste `curl` snippets and secret-handling practices. + +## SSH key pool + +Servers connected over SSH authenticate with a key from this pool, not +with per-server pastes. Add a PEM/OpenSSH private key (paste or upload +`.pem` / `.key`); Dequel detects Ed25519/RSA formats, fingerprints the +key, and rejects duplicates. Private material is never displayed again +— only name, fingerprint, tags, and date. + +When you add a server (**Settings → Servers**), pick its key from the +pool dropdown. Rotating a server's access means updating the pool entry +it points at. + +## Next steps + +- Read [Authentication](/docs/auth) for login sessions. +- Read [Servers](/docs/servers) to attach keys to machines. diff --git a/apps/docs/docs/observability.md b/apps/docs/docs/observability.md new file mode 100644 index 0000000..d777d01 --- /dev/null +++ b/apps/docs/docs/observability.md @@ -0,0 +1,49 @@ +--- +title: Observability +category: Observability +description: Metrics, request logs, and runtime logs for every project. +slug: observability +--- + +Each project has an **Observability** tab (metrics) and a **Logs** tab +(request + runtime logs). The dashboard also links out to the full +Grafana instance at `/grafana`. + +![Project observability](/screenshots/observability.png) + +## Metrics + +The Observability tab charts the last 6 hours from Prometheus (fed by +cAdvisor): memory, CPU %, network in/out per container, plus an edge +request-load chart from the API's own Loki-backed request matrix. Cards +refresh every 15 seconds. An empty state means nothing is deployed yet +— deploy to render telemetry. + +Behind the scenes, `GET /projects/:id/status` aggregates health over a +configurable window, and `GET /prometheus/query...` proxies arbitrary +PromQL for custom dashboards. + +## Request logs + +The Logs tab's **Request Monitoring** view tails the Caddy access log +for the project domain via Loki: method, path, status, latency, and a +30×1-minute histogram. Filter by date range (pauses the live tail), +full-text search, and level checkboxes, or click a row for the +slide-over detail. A live/paused toggle controls the SSE stream. + +## Runtime logs + +The **Runtime Logs** view follows the running container's stdout +(`docker logs -f`) over SSE — what your app actually printed, as +opposed to what the edge proxy saw. Same search and filter controls. + +## Grafana + +**Open Grafana** (sidebar, under Observability) jumps to the platform +Grafana with Prometheus and Loki data sources pre-wired, for ad-hoc +queries across all projects and infrastructure. + +## Next steps + +- Read [Alerts](/docs/alerts) to get notified on CPU, memory, or downtime. +- Read [Deployments](/docs/deployments) for build logs (as opposed to runtime logs). diff --git a/apps/docs/docs/quickstart.mdx b/apps/docs/docs/quickstart.mdx index 6ce6c57..3435e1d 100644 --- a/apps/docs/docs/quickstart.mdx +++ b/apps/docs/docs/quickstart.mdx @@ -1,50 +1,74 @@ --- title: Quickstart Guide category: Getting Started -description: Deploy your first containerized application to Dequel in under 5 minutes. +description: Deploy your first application to Dequel in under 5 minutes. slug: quickstart --- -In this guide, we'll configure a project, push the codebase, and verify that the container is running with active routing. +This guide takes you from an empty dashboard to a live HTTPS app. You +need a running Dequel installation and a login user (see +[Installation](/docs/installation)). No Dockerfile is required — Dequel +detects your framework automatically. -## Step 1: Create a Project +## Step 1: Create a project -Navigate to the Dequel dashboard (at `http://localhost` or your configured `CADDY_BASE_DOMAIN`) and click the **+ Create Project** button in the upper right corner. +Open the dashboard and click **New Project**. -- Enter a unique project name (e.g. `my-web-app`). -- Configure CPU limit boundaries (e.g., `0.5 cores`) and Memory bounds (e.g., `512MB`). -- Click **Create** to initialize the project namespace. +![Dequel dashboard](/screenshots/dashboard.png) -## Step 2: Add a Dockerfile +Fill in the wizard: -Dequel builds applications using a standard container blueprint. Ensure your project includes a valid `Dockerfile` in its root directory: +1. **Source** — pick **Git** (paste an HTTPS clone URL and branch, or + connect your GitHub account to pick a repo) or **Upload** (a `.zip` + of your code). +2. **Name** — a unique project name. It becomes your default URL: + `.`. +3. **Target server** — where the app runs. `local` (this machine) works + out of the box; other servers appear after you connect them (see + [Servers](/docs/servers)). +4. **Build strategy** — **Automatic (Railpack)** for a single service, + or **Docker Compose** if your repo root has a `docker-compose.yml`. +5. For Railpack builds, confirm the detected framework settings (install + and start commands, output directory, port). -```dockerfile Dockerfile -FROM node:18-alpine -WORKDIR /app -COPY package*.json ./ -RUN npm install -COPY . . -RUN npm run build -ENV PORT=3000 -EXPOSE 3000 -CMD ["npm", "run", "start"] -``` +![New project wizard](/screenshots/create-project.png) -:::tip[Custom Ports] -Dequel reads the `PORT` environment variable inside your container to automatically route incoming traffic. Ensure your app listens on the port specified by this variable. -::: +Click **Launch Deployment**. Dequel creates the project, links any +selected shared env vars, and immediately starts the first deployment. +## Step 2: Watch the build -## Step 3: Trigger the Deploy +The project page opens on the **Deployments** tab. Build logs stream +live as Railpack detects the framework, BuildKit builds the image, and +the container starts. Deployments move through `pending` → `building` → +`deploying` → `running` (or `failed` if something breaks). -On the deployments page, you can choose between connecting your GitHub repository or performing a local directory upload: +![Deployment build logs](/screenshots/deployments.png) -1. Enter your repository URL and set the branch to `main`. -2. Click **Deploy Branch**. -3. Follow the build stages in real-time under the **Active Build Logs** window. +If the build fails, click **Diagnose** in the log header to hand the +failure to an AI agent — see [AI Diagnosis](/docs/ai-diagnosis). -## Step 4: Verify Routing +## Step 3: Open your app -Once the deployment changes status from `BUILDING` to `READY`, click the external link button near your custom domain or the auto-generated base domain to see your running web container. +Once the deployment is `running`, click the live URL pill in the +project header. Locally that is +`http://.localhost`; with a base domain configured it is +`https://.` with a valid certificate. +## Step 4: Push updates + +- **Git projects:** push to the tracked branch and Dequel rebuilds + automatically (via the GitHub webhook), or click **Manual Deploy** to + rebuild from the latest commit or a specific SHA. +- **Upload projects:** drop a new archive on the Deployments tab. + +Previous builds keep their images, so you can **Rollback** to any +earlier deployment from the history table. + +## Next steps + +- Add [environment variables](/docs/env-vars) and link + [shared env vars](/docs/shared-env-vars). +- Attach a [custom domain](/docs/domains) with automatic SSL. +- Provision a [managed database](/docs/databases). +- Set [resource limits and autoscaling](/docs/scaling). diff --git a/apps/docs/docs/scaling.md b/apps/docs/docs/scaling.md index cafb7d8..21ccc2a 100644 --- a/apps/docs/docs/scaling.md +++ b/apps/docs/docs/scaling.md @@ -1,30 +1,49 @@ --- -title: Scaling Policies -category: Core Architecture -description: Adjust running container replicas automatically to handle high traffic and preserve cluster efficiency. +title: Scaling +category: Projects +description: Resource limits and CPU-based autoscaling for your containers. slug: scaling --- -Dequel supports two types of container instance scaling: **Manual Scaling** (fixed replica count) and **Auto-scaling** (load-based replica counts). +The project's **Scaling** tab holds two cards: resource limits and the +autoscaling policy. -## Manual Scaling +![Scaling tab](/screenshots/scaling.png) -Configure a static replica limit for your service (e.g. `3 replicas`). The orchestrator will verify that exactly three instances are running on cluster nodes. If an instance crashes, it will be automatically replaced immediately. +## Resource limits -## Auto-scaling Policies +Set per-container bounds that are enforced on every deployment: -Auto-scaling lets you scale compute bounds in response to real-time resource demands: +- **CPU limit (cores)** — for example `1.0` for one full core. +- **Memory limit (MB)** — for example `512`. A container that exceeds it + is killed with an OOM error and restarted. -- **Min Replicas:** The baseline floor of instances always running. -- **Max Replicas:** The maximum horizontal scale ceiling allowed under load. -- **Target CPU Utilization (%):** The load threshold trigger. If average CPU utilization exceeds this value (e.g. `70%`), new container replicas are provisioned. If the load falls below the target, containers are scaled down. +Autoscaling requires a CPU limit, because the engine scales on CPU +utilization. -
- ⚠️ Warning: Stateless Design Required -

To scale horizontally, your application container must be completely stateless. Avoid writing file records directly to the local filesystem; use persistent volumes or managed databases instead.

-
+## Autoscaling policy -## Configuration Modal +Click **Enable autoscaling** and configure: -To disable auto-scaling policies or switch back to static scaling, click **Delete Policy** in the scaling panel. Confirm the change in the custom Radix confirmation dialog to update the scaling configuration safely. +- **Min replicas** — the floor of instances always running (at least 1). +- **Max replicas** — the ceiling under load. +- **CPU threshold (%)** — when average CPU utilization across replicas + exceeds this for the evaluation window, Dequel adds a replica; when + load falls, it removes replicas down to the floor. +- **Cooldown** — quiet period between scaling actions so the system does + not flap. +Disable the policy any time to return to a single replica. The engine +evaluates policies continuously in the background +(`ALERT_EVAL_INTERVAL_MS` controls the platform-wide cadence). + +:::note[Stateless services scale best] +Horizontal replicas do not share local files. Keep uploads and caches on +[persistent volumes](/docs/volumes) or in [managed databases](/docs/databases) +so any replica can serve any request. +::: + +## Next steps + +- Read [Observability](/docs/observability) to watch CPU and memory. +- Read [Alerts](/docs/alerts) to get notified on resource pressure. diff --git a/apps/docs/docs/servers.md b/apps/docs/docs/servers.md new file mode 100644 index 0000000..ebd7f99 --- /dev/null +++ b/apps/docs/docs/servers.md @@ -0,0 +1,70 @@ +--- +title: Servers +category: Multi-Server +description: Run apps on multiple machines over SSH or WireGuard agents. +slug: servers +--- + +Dequel is not limited to the machine it is installed on. Connect extra +servers and pick a target per project or database: builds run there, +containers live there, and Caddy routes point at them. The control plane +itself is just the default `local` target. + +![Servers settings](/screenshots/servers.png) + +## Connection modes + +**Direct SSH (recommended).** The control plane shells into the server +and runs Docker commands remotely. The server needs outbound internet +and SSH reachable from the control plane — Docker, Caddy, BuildKit, and +Railpack are installed for you by the Prepare step. + +**WireGuard agent (firewalled nodes).** For servers with no open SSH +port, Dequel shows a `docker run` command for the Dequel agent. Run it +on the target: the agent registers back with a one-time token and opens +a WireGuard tunnel to the control plane. All orchestration then flows +through the mesh. + +## Adding a server + +Open **Settings → Servers** and click **Connect Server**: + +1. Choose **Direct SSH** (host, port, user, and an SSH key from your + [key pool](/docs/keys)) or **WireGuard P2P Agent** (a name — Dequel + mints the registration token). +2. Click **Prepare Node**. Dequel streams live progress: OS detection, + Docker install, Caddy + `/etc/caddy/routes/` setup, BuildKit, and + Railpack CLI. Prepare is idempotent — re-run it any time to heal a + node. +3. When the stream reports success, the server appears as a deployment + target in the project wizard and the database provisioner. + +Use **Test** to check connectivity without preparing, and remove a +server with the delete action when it is decommissioned. + +## Ingress and shared domains + +All servers share one base domain (`CADDY_BASE_DOMAIN`). A project gets +the same hostname (`.`) no matter which server runs it — +Dequel renders that hostname into the route file on the owning server. +Point the wildcard DNS at your servers (see [Installation](/docs/installation)), +or add per-deployment A records for finer control. Custom domains bypass +the base domain entirely. The **Settings → Servers** view (or +**Settings → Ingress** state) controls which server is the ingress +entrypoint; route internals are documented under +[Agent Caddy Routes](/docs/agent-caddy-routes). + +## Failover + +A project can fail over to an alternate server: the control plane +redeploys the project's Git source on the new target and removes the +old containers. Trigger it from the project API +(`POST /projects/:id/failover`). Automatic failover runs on the +`FAILOVER_MIN_INTERVAL_MS` cadence unless `FAILOVER_DISABLED` is set +(see [System Configuration](/docs/system-config)). + +## Next steps + +- Read [Keys](/docs/keys) for the SSH key pool servers draw from. +- Read [Agent Caddy Routes](/docs/agent-caddy-routes) for route files. +- Read [Deployments](/docs/deployments) for targeting a server per deploy. diff --git a/apps/docs/docs/settings.md b/apps/docs/docs/settings.md new file mode 100644 index 0000000..b49e105 --- /dev/null +++ b/apps/docs/docs/settings.md @@ -0,0 +1,58 @@ +--- +title: Platform Settings +category: Integrations +description: SMTP, ingress, backup storage, GitHub, servers, and AI keys. +slug: settings +--- + +**Settings** (sidebar) is where the platform itself is configured. A +banner counts registered nodes and flags integrations that still need +attention. + +## Servers + +Connect machines over SSH or WireGuard agents, prepare them with Docker +/ Caddy / BuildKit, and pick deployment targets. Documented in full +under [Servers](/docs/servers). + +## Backups + +Local-path or S3 storage plus the internal database schedule. See +[Backups](/docs/backups). + +## GitHub + +OAuth app credentials, connect/disconnect, and the callback URL. See +[GitHub](/docs/github). + +## SMTP + +The relay for alert emails and failure notifications: host, port, user, +password (encrypted at rest), and sender address, with presets for +Resend, SendGrid, Postmark, Mailgun, and AWS SES. **Send Test Email** +verifies the setup before you depend on it. + +Without SMTP, email-channel [alert rules](/docs/alerts) cannot deliver +— Slack and webhook channels work independently. + +## AI + +Provider keys for [AI Diagnosis](/docs/ai-diagnosis): OpenAI, Anthropic, +Gemini, Groq, self-hosted Ollama, or any custom OpenAI-compatible +endpoint (base URL). Keys are AES-256-GCM encrypted and never shown +after saving; leaving the field blank keeps the stored key. **Save & +Sync Models** pulls the provider's model catalog so the diagnosis sheet +offers real model names. + +![AI provider settings](/screenshots/settings-ai.png) + +## Ingress + +The ingress view shows which server terminates public traffic and the +failover state. App hostnames stay identical across servers regardless +(see [Servers](/docs/servers)). + +## Next steps + +- Read [System Configuration](/docs/system-config) for env/file settings. +- Read [Alerts](/docs/alerts) to wire SMTP into notifications. diff --git a/apps/docs/docs/shared-env-vars.md b/apps/docs/docs/shared-env-vars.md new file mode 100644 index 0000000..f541d62 --- /dev/null +++ b/apps/docs/docs/shared-env-vars.md @@ -0,0 +1,40 @@ +--- +title: Shared Env Vars +category: Projects +description: One secret library linked into many projects. +slug: shared-env-vars +--- + +**Shared Env** is a global variable library. Define a value once — a +third-party API key, a common feature flag, a shared endpoint — and +link it into any number of projects instead of pasting it everywhere. +Rotating the shared value updates every linked project on its next +redeploy. + +![Shared env vars](/screenshots/shared-env.png) + +## Creating shared variables + +Open **Shared Env** in the sidebar and add a variable with a key, +value, description, and optional tags. Values are encrypted at rest and +masked in the UI, exactly like project variables — reveal or copy them +per row. + +## Linking into projects + +Link variables from the project's **Env Variables** tab (linked section) +or while creating a project (the env step lists the library). Linking +is by reference: editing the shared value changes what linked projects +receive next time they start. + +When a project-level variable and a shared variable share a key, the +**project value wins**. Use that for per-project overrides of a shared +default. + +Unlink any time from the same section; the project keeps its own +variables untouched. + +## Next steps + +- Read [Environment Variables](/docs/env-vars) for project-level config. +- Read [Deployments](/docs/deployments) to roll out rotated values. diff --git a/apps/docs/docs/ssl.mdx b/apps/docs/docs/ssl.mdx index f788b35..eeeb3bc 100644 --- a/apps/docs/docs/ssl.mdx +++ b/apps/docs/docs/ssl.mdx @@ -1,34 +1,43 @@ --- title: SSL Certificates -category: Networking & Security -description: Secure external traffic automatically with Let's Encrypt TLS/SSL certificates. +category: Security +description: Automatic HTTPS via Let's Encrypt for every routed domain. slug: ssl --- -Dequel enforces HTTPS encryption for all public endpoints. The cluster edge routing layer manages keys, handshakes, and automatic certificate acquisitions behind the scenes. +Dequel serves every routed hostname over HTTPS with certificates from +**Let's Encrypt**. There is nothing to buy, upload, or renew manually. -## How Certificates are Provisioned +## How provisioning works -Dequel interfaces directly with **Let's Encrypt** (a free, automated, open Certificate Authority): +1. A project domain (default `.` or a verified + [custom domain](/docs/domains)) appears in a Caddy route file. +2. On first request, Caddy completes an ACME HTTP-01 challenge and + obtains a certificate. +3. Caddy stores the certificate and renews it automatically before the + 90-day expiry. -1. When a custom domain is successfully verified, Dequel triggers Caddy's ACME certificate client. -2. Caddy performs an HTTP-01 challenge verification with Let's Encrypt servers. -3. Upon challenge completion, Let's Encrypt signs a valid SSL certificate. -4. Caddy saves the certificate to the cluster storage path and starts enforcing TLS/HTTPS handshakes. +For this to work, the domain must resolve to the server and ports `80` +and `443` must be reachable — the challenge runs over plain HTTP. If +you terminate TLS in front of Dequel (for example Cloudflare proxy), +use DNS-01 challenges or pause proxying until the first certificate is +issued. -## Automatic Renewals +## Local development -Let's Encrypt certificates are valid for 90 days. Dequel's router checks certificates once daily and schedules automatic renewals 30 days before expiration, ensuring zero downtime and avoiding manual keys management. +On `localhost` there is no public CA involved: Caddy serves plain HTTP +for `.localhost` URLs, and the dashboard is available over both +HTTP and HTTPS when a base domain is configured. -:::note[Key Security Spec] -Dequel configures modern TLS 1.3 as the default cipher suite block, providing maximum security, fast TLS handshakes, and strict protection against legacy protocol exploits. -::: +## Troubleshooting +- **Domain shows TLS pending** — confirm DNS resolves to the server IP + and that no CDN is intercepting `/.well-known/acme-challenge/`. +- **Certificate errors on managed databases** — database TLS uses the + gateway's own certificate, not Let's Encrypt. See + [Managed Databases](/docs/databases) for the client flags. -## Troubleshooting SSL - -If your domain status is stuck on `PENDING_SSL`: - -- Verify that your DNS CNAME/A records have fully propagated. -- Ensure that no CDN service (e.g. Cloudflare proxy) is blocking HTTP ACME challenge endpoints (`/.well-known/acme-challenge/`). +## Next steps +- Read [Custom Domains](/docs/domains) to add domains. +- Read [Managed Databases](/docs/databases) for database TLS behavior. diff --git a/apps/docs/docs/system-config.md b/apps/docs/docs/system-config.md index 2d3b7af..4784726 100644 --- a/apps/docs/docs/system-config.md +++ b/apps/docs/docs/system-config.md @@ -1,111 +1,106 @@ --- title: System Configuration -category: Core Architecture -description: How Dequel resolves configuration across fixed system values, environment-only secrets, and editable tunables. +category: Platform +description: Environment variables and the dequel.json file for platform settings. slug: system-config --- -Dequel splits platform configuration into three tiers: fixed system values that -are compiled into the API, environment-only secrets that never come from a -config file, and tunables that you can set through environment variables or a -`dequel.json` file. For tunables, environment variables take precedence over -file values. +The API reads platform settings from environment variables first, then +from a `dequel.json` file. Environment variables always win. -## Fixed system values +## Config file location + +The API loads the first `dequel.json` it finds: + +1. The path in `DEQUEL_CONFIG` +2. `$XDG_CONFIG_HOME/dequel/dequel.json` (usually + `~/.config/dequel/dequel.json`) +3. `./dequel.json` (next to the process working directory) +4. `./data/dequel.json` (what the installer writes, mode `0600`) -These values are compiled into the API. Environment variables and `dequel.json` -entries with the same names are ignored. +The installer generates `data/dequel.json` with your base domain and a +random `ENV_ENCRYPTION_KEY`. -| Key | Value | Description | -|-----|-------|-------------| -| `port` | `3001` | API listen port. Caddy, container health checks, and Prometheus target this port. | -| `appInternalPort` | `3000` | Port injected into deployed applications as `PORT`, used for reverse-proxy targets. | -| `workspaceRoot` | `/app/workspace` | Build staging directory. | -| `caddyRoutesDir` | `/caddy/routes` | Directory for local Caddy route files. | -| `caddyDataDir` | `/caddy-data/caddy` | Caddy data mount used to detect real TLS certificates. | -| `gatewayCertDir` | `/app/data` | Directory where the gateway stores its self-signed TLS certificate. | -| `dockerNetwork` | `dequel_net` | Docker network for deployments. | -| `buildkitHost` | `tcp://buildkit:1234` | Buildkit daemon address. | -| `redisUrl` | `redis://redis:6379` | Redis queue address. | +## Reference -Remote servers receive route files through SSH or the agent job queue, which -write to `/etc/caddy/routes` on the remote host. +### Identity and domains -## Environment-only settings +| Variable | Default | Source | Description | +|----------|---------|--------|-------------| +| `CADDY_BASE_DOMAIN` | `localhost` | env or file | Base domain for app URLs (`.`). Set a real domain with wildcard DNS for auto-SSL. | +| `CADDY_EMAIL` | _(empty)_ | env (Caddy) | Contact for Let's Encrypt notifications. Read by Caddy, not the API. | +| `CONTROL_PLANE_URL` | _(empty)_ | env or file | Public URL of this control plane, used for links and agent registration. | +| `DATABASE_URL` | _(empty)_ | env | PostgreSQL connection string. Empty fails fast with a clear error. | -These settings are read from environment variables only. `dequel.json` never -overrides them. +### Secrets + +| Variable | Default | Source | Description | +|----------|---------|--------|-------------| +| `ENV_ENCRYPTION_KEY` | `dev-env-key-change-me` | env | Encrypts env vars, SMTP passwords, and LLM keys at rest. The API **refuses to start in production** with the default — set a unique value. | + +### Background engines | Variable | Default | Description | |----------|---------|-------------| -| `DATABASE_URL` | `""` | PostgreSQL connection string. The install script generates a random database password, and Docker Compose passes the assembled URL to the API and gateway. | -| `ENV_ENCRYPTION_KEY` | `dev-env-key-change-me` | Key that encrypts secrets at rest: environment variables, SSH keys, LLM provider keys, SMTP passwords, S3 credentials, and GitHub session tokens. The install script generates a random key and stores it in `.env`. | +| `QUEUE_CONCURRENCY` | `3` | Parallel jobs (builds, provisions, failovers). | +| `QUEUE_RETRY_MAX` | `5` | Retries per failed job. | +| `QUEUE_RETRY_BASE_MS` | `5000` | Base backoff between retries. | +| `ALERT_EVAL_INTERVAL_MS` | `60000` | Alert-rule evaluation cadence. | +| `FAILURE_SWEEP_INTERVAL_MS` | `60000` | Failed-deployment sweep cadence. | +| `FAILOVER_DISABLED` | _(empty)_ | Set to disable automatic failover. | +| `FAILOVER_MIN_INTERVAL_MS` | `600000` | Minimum time between failovers. | -On boot, the API re-encrypts any stored secrets that were written with the -default key so a fresh install key takes effect without manual migration. +### Observability -## Tunables +| Variable | Default | Description | +|----------|---------|-------------| +| `GRAFANA_URL` | `http://grafana:3000` | Grafana origin for dashboard links. | +| `GRAFANA_USER` / `GRAFANA_PASS` | `admin` / `admin` | Grafana credentials. | -Set tunables through environment variables or the config file. In Docker -installs, Compose passes a subset (such as `CADDY_BASE_DOMAIN` and -`GRAFANA_URL`) from `.env`; add others to the api service's `environment` list -in `docker-compose.yml` to make them effective. +### Agent networking | Variable | Default | Description | |----------|---------|-------------| -| `CADDY_BASE_DOMAIN` | `localhost` | Base domain for deployment subdomains. Deployed apps are reachable at `https://.`. Set a real domain and configure wildcard DNS for auto-SSL. | -| `CONTROL_PLANE_URL` | `""` | Public URL of this control plane, used by remote agents. | -| `AGENT_TUNNEL_URL` | `""` | Tunnel endpoint for agent connections. | -| `QUEUE_CONCURRENCY` | `3` | Number of deployment jobs processed in parallel. | -| `QUEUE_RETRY_MAX` | `5` | Maximum retry attempts for failed jobs. | -| `QUEUE_RETRY_BASE_MS` | `5000` | Base delay between job retries. | -| `ALERT_EVAL_INTERVAL_MS` | `60000` | How often alert rules are evaluated. | -| `FAILURE_SWEEP_INTERVAL_MS` | `60000` | How often failed deployments are swept for notifications. | -| `GRAFANA_URL` | `http://grafana:3000` | Grafana base URL shown in the dashboard. | -| `GRAFANA_USER` | `admin` | Grafana sign-in user. | -| `GRAFANA_PASS` | `admin` | Grafana sign-in password. | -| `WIREGUARD_SERVER_CONTAINER` | `""` | Container name of the WireGuard server. | -| `WIREGUARD_SERVER_PUBLIC_KEY` | `""` | Public key of the WireGuard server. | -| `WIREGUARD_SERVER_ENDPOINT` | `""` | WireGuard server endpoint. | -| `WIREGUARD_SERVER_IP` | `10.200.0.1` | WireGuard server IP address. | -| `WIREGUARD_PEER_CIDR` | `10.200.0.0/24` | CIDR range assigned to WireGuard peers. | -| `FAILOVER_DISABLED` | `""` | Set to a non-empty value to disable the failover monitor. | -| `FAILOVER_MIN_INTERVAL_MS` | `600000` | Minimum interval between failover checks for a deployment. | - -`CADDY_EMAIL` is a separate Compose-level setting: set it in `.env` to receive -Let's Encrypt certificate expiration notices from the Caddy service. +| `AGENT_TUNNEL_URL` | _(empty)_ | Tunnel endpoint agents dial back on. | +| `WIREGUARD_SERVER_CONTAINER` | _(empty)_ | WireGuard server container name. | +| `WIREGUARD_SERVER_PUBLIC_KEY` | _(empty)_ | Server public key for agent peers. | +| `WIREGUARD_SERVER_ENDPOINT` | _(empty)_ | Public endpoint agents connect to. | +| `WIREGUARD_SERVER_IP` | `10.200.0.1` | Server address inside the mesh. | +| `WIREGUARD_PEER_CIDR` | `10.200.0.0/24` | Agent address range. | -## Config file location +### Telemetry -The API looks for `dequel.json` when resolving tunables, in the following -order: +Dequel collects anonymous usage telemetry (PostHog) to guide +development. Disable it with either variable: -1. `DEQUEL_CONFIG` environment variable pointing to an explicit path -2. `~/.config/dequel/dequel.json` -3. `./dequel.json` (next to the process working directory) -4. `./data/dequel.json` +```bash +DEQUEL_TELEMETRY_DISABLED=1 +DO_NOT_TRACK=1 +``` + +### What is configured in the dashboard instead -File keys use the same names as the environment variables, in upper snake -case, for example `QUEUE_CONCURRENCY`. Numeric values must be JSON numbers, -not strings. +These have no environment equivalent — set them under +[Settings](/docs/settings): + +- GitHub OAuth app (client ID/secret, webhook secret) +- SMTP relay and sender address +- Backup storage (local path or S3) +- LLM provider keys and models +- Ingress server selection + +## Full file example ```json { "CADDY_BASE_DOMAIN": "example.com", - "QUEUE_CONCURRENCY": 5, - "ALERT_EVAL_INTERVAL_MS": 120000 + "CONTROL_PLANE_URL": "https://dequel.example.com", + "QUEUE_CONCURRENCY": 3, + "FAILOVER_MIN_INTERVAL_MS": 600000 } ``` -## GitHub integration - -Configure GitHub OAuth and webhooks from **Settings** in the dashboard. Dequel -stores the client ID, client secret, app name, and webhook secret in the -database. No environment variables or config file keys are read for GitHub. - -## SMTP +## Next steps -SMTP settings are not read from environment variables or the config file. -Configure them from the Settings page in the dashboard, where you can also -send a test email to verify the setup. The password is encrypted at rest with -`ENV_ENCRYPTION_KEY`. +- Read [Settings](/docs/settings) for dashboard-managed config. +- Read [Servers](/docs/servers) for multi-server networking. diff --git a/apps/docs/docs/volumes.mdx b/apps/docs/docs/volumes.mdx index 9dde140..1cb7828 100644 --- a/apps/docs/docs/volumes.mdx +++ b/apps/docs/docs/volumes.mdx @@ -1,28 +1,43 @@ --- title: Persistent Volumes -category: Cluster Storage & Data -description: Mount persistent cluster disk pathways inside container runtimes to preserve storage across updates. +category: Projects +description: Keep data across deployments with mounted Docker volumes. slug: volumes --- -Dequel container instances are ephemeral by default. When a new deployment occurs, the old container is deleted, taking all local filesystem changes with it. +Containers are ephemeral: each new deployment replaces the old +container, and anything written to its local filesystem disappears with +it. Mount a **persistent volume** for uploads, caches, SQLite files, or +any data that must survive redeploys. -To store uploaded assets, databases, or local file caches, mount a **Persistent Volume**. +## Adding a volume -## Creating a Volume Mount +Open the project and switch to the **Volumes** tab, then click **Add +Volume**: -Under the **Volumes** tab, click **Add Volume**: +1. Enter the mount path inside the container (for example + `/app/uploads`). +2. Save. Dequel creates a Docker volume on the deployment's server and + records the mount. -1. Enter a mount path inside the container environment (e.g. `/app/uploads`). -2. Click **Add Volume**. -3. Dequel allocates block storage space on the cluster nodes and maps it to your container's target folder. +Mount changes apply on the next container start. The tab shows a +redeploy banner after you add or delete a volume — click **Redeploy** to +roll it out. Deleting a volume unmounts it; the volume record can be +removed separately. -:::note[Redeployment Requirement] -Adding or deleting volumes modifies the low-level container host bindings. To apply these mount pathways, you must trigger a container restart via the **Redeploy Now** prompt banner at the top of the volumes tab. +:::note[Volumes live on the deployment's server] +Volumes are created on whichever server runs the deployment. If you move +a project to another server (see [Servers](/docs/servers)), its data +does not move with it — plan a copy step for stateful moves. ::: +## Databases vs volumes -## Data Security & Backups +- Use a [managed database](/docs/databases) for structured data with + querying, credentials, backups, and remote access. +- Use a volume for flat files your app reads and writes directly. -Because data is tied directly to cluster block volumes, data persists even if you update environment variables, scale container replicas, or deploy code rollbacks. +## Next steps +- Read [Managed Databases](/docs/databases) for the database option. +- Read [Backups](/docs/backups) for snapshot and restore flows. diff --git a/apps/docs/pages/index.astro b/apps/docs/pages/index.astro index 7f356c6..497a883 100644 --- a/apps/docs/pages/index.astro +++ b/apps/docs/pages/index.astro @@ -43,99 +43,87 @@ import CTA from "../components/CTA.astro"; Dequel — Self-Hosted PaaS Engine & Container Platform - + + +
@@ -146,82 +134,27 @@ import CTA from "../components/CTA.astro";
-