Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
dc4593c
feat(deployments): track deployment completion
Lftobs Jul 20, 2026
f20e3fa
feat(api): add project configuration and build
Lftobs Jul 27, 2026
989263e
chore(web): add explicit keys to project creation
Lftobs Jul 27, 2026
e051377
chore: bump version to 0.2.1
Lftobs Jul 28, 2026
cb142e0
chore: switch docker-compose to use prebuilt
Lftobs Jul 28, 2026
921e051
Merge pull request #28 from Lftobs/bugs
Lftobs Jul 28, 2026
f55354b
chore: update installation command to use release
Lftobs Jul 28, 2026
13fc38a
chore(release): include scripts/auth files in release config bundle
Lftobs Jul 28, 2026
027e32d
feat(orchestrator): add support for Docker Compose
Lftobs Jul 31, 2026
6cddca1
feat(api): refactor database orchestration and
Lftobs Aug 3, 2026
e4f0b95
feat(deployments): track deployment completion
Lftobs Jul 20, 2026
9eb6a5b
feat(api): add project configuration and build
Lftobs Jul 27, 2026
00ab762
chore(web): add explicit keys to project creation
Lftobs Jul 27, 2026
1dd87b9
chore: bump version to 0.2.1
Lftobs Jul 28, 2026
df031b2
chore: switch docker-compose to use prebuilt
Lftobs Jul 28, 2026
f2c6846
chore: update installation command to use release
Lftobs Jul 28, 2026
4d22d8a
chore(release): include scripts/auth files in release config bundle
Lftobs Jul 28, 2026
52a1696
feat(api): refactor database orchestration and
Lftobs Aug 3, 2026
5b37f3a
feat(orchestrator): add support for Docker Compose
Lftobs Jul 31, 2026
88fa94b
Merge branch 'managed-db' of github.com:Lftobs/dequel into managed-db
Lftobs Aug 4, 2026
4d570f6
refactor(project): reorder project creation steps
Lftobs Aug 4, 2026
97d88cf
feat(orchestrator): improve Docker Compose
Lftobs Aug 4, 2026
c7e4873
chore: ignore local setup guide and lockfile
Lftobs Aug 4, 2026
a3f06a8
Merge branch 'feat/managed-db-and-compose' of github.com:Lftobs/deque…
Lftobs Aug 4, 2026
eb73891
feat(api): refactor database orchestration and
Lftobs Aug 3, 2026
3c2d519
refactor(project): reorder project creation steps
Lftobs Aug 4, 2026
c557c00
Merge branch 'managed-db' of github.com:Lftobs/dequel into managed-db
Lftobs Aug 4, 2026
343f207
feat(api): custom install command/output dir support and concise depl…
Lftobs Aug 4, 2026
049c364
chore(ui): redesign project creation UI with framework/database logos…
Lftobs Aug 4, 2026
c19ced0
feat(api): add install command and output dir to
Lftobs Aug 4, 2026
b57b04c
fix(db): implement database operation locking and
Lftobs Aug 4, 2026
e381b0e
fix(web): add compose service configuration to
Lftobs Aug 6, 2026
7cc969d
Merge pull request #33 from Lftobs/managed-db
Lftobs Aug 6, 2026
8b7bba7
Merge branch 'dev' into chore/ui
Lftobs Aug 7, 2026
4e3b43e
feat(orchestrator): auto-detect static sites via
Lftobs Aug 9, 2026
c399989
chore(orchestrator): improve static site detection
Lftobs Aug 11, 2026
80a1baa
refactor(web): consolidate project creation
Lftobs Aug 11, 2026
c1667ea
feat(project): add custom build commands and
Lftobs Aug 12, 2026
7ec5b92
Merge pull request #36 from Lftobs/chore/ui
Lftobs Aug 12, 2026
dc8e7b2
feat(agent): introduce remote deployment agent
Lftobs Aug 13, 2026
41b63c1
feat(agent): introduce remote deployment agent
Lftobs Aug 13, 2026
cd7599f
feat(orchestrator): add server preparation and
Lftobs Aug 21, 2026
6b16da8
refactor(api): inject dependencies in tests
Lftobs Aug 21, 2026
89d93ad
Merge remote-tracking branch 'origin/feat/multi-servers' into agent-a…
Lftobs Aug 21, 2026
6acb64f
refactor(db): migrate from SQLite to PostgreSQL
Lftobs Aug 24, 2026
22df367
refactore(db): migrate to PostgreSQL
Lftobs Aug 24, 2026
5bcbd13
fix(orchestrator): use HTTP health check instead of TCP for failover
Lftobs Aug 24, 2026
e6800ba
docs: add agent Caddy routes lifecycle documentation
Lftobs Aug 24, 2026
513c94f
feat(api): add domain DNS/TLS status check endpoint
Lftobs Aug 24, 2026
9029b3d
feat(web): add live DNS/TLS status badges to domains tab
Lftobs Aug 24, 2026
b21fcdb
feat(api): re-render all ingress routes when ingress server changes
Lftobs Aug 24, 2026
37db5b1
refactor(test): migrate integration tests to
Lftobs Aug 24, 2026
340b740
fix(api): add docker_tcp server support and
Lftobs Aug 24, 2026
0195b17
refactor(api): standardize API responses and
Lftobs Aug 24, 2026
0228a7f
chore: improve stability and environment security
Lftobs Aug 25, 2026
eaa9e7d
chore(release): v0.3.0-rc.1
Lftobs Aug 25, 2026
23ef255
fix(auth): add missing PAM service config for dequel group auth
Lftobs Aug 26, 2026
ff812f0
fix(e2e): resolve remote server deployment, buildkit, caddy ingress, …
Lftobs Aug 27, 2026
a3cacb8
fix(rc): use next tag for RC image testing
Lftobs Aug 28, 2026
e27b1b8
fix(rc): resolve login, caddy reload, and missing db migration
Lftobs Aug 28, 2026
a8389a9
fix(migration): make ssh_key migration idempotent for existing DBs
Lftobs Aug 28, 2026
32f7f8d
fix: add timeout to Loki fetch, default LogsTab to runtime mode
Lftobs Aug 28, 2026
c7acdcc
chore: bump version to v0.3.0-rc.4
Lftobs Aug 28, 2026
c24095f
refactor: remove Docker Compose profiles, start all services by default
Lftobs Aug 29, 2026
dfd99ce
chore: bump version to v0.3.0-rc.5
Lftobs Aug 29, 2026
3bca144
feat(ui): add SSH private key input to server form
Lftobs Aug 29, 2026
0e21aa4
chore: bump version to v0.3.0-rc.6
Lftobs Aug 29, 2026
9b73101
security: encrypt SSH private keys at rest
Lftobs Aug 29, 2026
133882a
chore: bump version to v0.3.0-rc.7
Lftobs Aug 29, 2026
54b9eed
chore: ignore local verify-dequel agent skills
Lftobs Aug 29, 2026
2627324
fix(ingress): default local ingress, emit :80 worker routes, plain ca…
Lftobs Aug 29, 2026
960ab4e
feat(cli): rc/prerelease update targets with zero-downtime rolling re…
Lftobs Aug 29, 2026
0b8fceb
Merge pull request #38 from Lftobs/feat/multi-servers
Lftobs Aug 30, 2026
f10f98c
feat(orchestrator): add server preparation and
Lftobs Aug 21, 2026
2cd3b78
refactor(api): inject dependencies in tests
Lftobs Aug 21, 2026
487254c
refactor(db): migrate from SQLite to PostgreSQL
Lftobs Aug 24, 2026
695aef6
refactore(db): migrate to PostgreSQL
Lftobs Aug 24, 2026
3574b01
fix(orchestrator): use HTTP health check instead of TCP for failover
Lftobs Aug 24, 2026
756e361
docs: add agent Caddy routes lifecycle documentation
Lftobs Aug 24, 2026
f687d0b
feat(api): add domain DNS/TLS status check endpoint
Lftobs Aug 24, 2026
2e52a1d
feat(web): add live DNS/TLS status badges to domains tab
Lftobs Aug 24, 2026
5f5d16e
feat(api): re-render all ingress routes when ingress server changes
Lftobs Aug 24, 2026
00a48e9
refactor(test): migrate integration tests to
Lftobs Aug 24, 2026
bda4358
fix(api): add docker_tcp server support and
Lftobs Aug 24, 2026
d627fe3
refactor(api): standardize API responses and
Lftobs Aug 24, 2026
9a9bb64
chore: improve stability and environment security
Lftobs Aug 25, 2026
e999e88
chore(release): v0.3.0-rc.1
Lftobs Aug 25, 2026
07a18f7
fix(auth): add missing PAM service config for dequel group auth
Lftobs Aug 26, 2026
a15dfc5
fix(e2e): resolve remote server deployment, buildkit, caddy ingress, …
Lftobs Aug 27, 2026
d2a2db7
fix(rc): use next tag for RC image testing
Lftobs Aug 28, 2026
d36cfa4
fix(rc): resolve login, caddy reload, and missing db migration
Lftobs Aug 28, 2026
98a5bac
fix(migration): make ssh_key migration idempotent for existing DBs
Lftobs Aug 28, 2026
07a5713
fix: add timeout to Loki fetch, default LogsTab to runtime mode
Lftobs Aug 28, 2026
409f7ce
chore: bump version to v0.3.0-rc.4
Lftobs Aug 28, 2026
0e4124e
refactor: remove Docker Compose profiles, start all services by default
Lftobs Aug 29, 2026
90bba70
chore: bump version to v0.3.0-rc.5
Lftobs Aug 29, 2026
52fef7b
feat(ui): add SSH private key input to server form
Lftobs Aug 29, 2026
05569ac
chore: bump version to v0.3.0-rc.6
Lftobs Aug 29, 2026
abcae4a
security: encrypt SSH private keys at rest
Lftobs Aug 29, 2026
e9f6755
chore: bump version to v0.3.0-rc.7
Lftobs Aug 29, 2026
33dbfc5
chore: ignore local verify-dequel agent skills
Lftobs Aug 29, 2026
bf97fcc
fix(ingress): default local ingress, emit :80 worker routes, plain ca…
Lftobs Aug 29, 2026
b843433
feat(cli): rc/prerelease update targets with zero-downtime rolling re…
Lftobs Aug 29, 2026
fe80e96
Merge pull request #43 from Lftobs/bugs-fixes
Lftobs Aug 30, 2026
d9ccd2c
fix(caddy): update domain and email configuration
Lftobs Aug 30, 2026
6e6b7aa
fix: skip empty string subdomain in compose service validation
Lftobs Aug 30, 2026
28af211
Merge branch 'bugs-fixes' of github.com:Lftobs/dequel into bugs-fixes
Lftobs Aug 30, 2026
134b05d
feat: add Docker Compose deployment support for remote SSH servers
Lftobs Aug 30, 2026
905719f
feat(ui): make dequel dashboard 100% mobile responsive
Lftobs Aug 30, 2026
c06e8ec
fix: use per-service ports and filter non-web containers in compose C…
Lftobs Aug 30, 2026
44be08c
fix: handle composeServices as both string and array (jsonb from Driz…
Lftobs Aug 30, 2026
c114ebd
fix: bind worker Caddy routes to HTTP :80 for ingress deployments
Lftobs Sep 1, 2026
9cf4ea1
fix(ci): bust GHA cache per-commit using BUILD_TIME arg
Lftobs Sep 1, 2026
a809798
fix: create ingress routes for compose subdomains (api, server, etc.)
Lftobs Sep 2, 2026
0393019
fix: include all compose services in webServices for ingress routing
Lftobs Sep 2, 2026
6459b28
fix: use actual container ports from remote compose result for Caddy …
Lftobs Sep 2, 2026
a5162e0
fix: use container-internal port for Caddy routes, not host-mapped port
Lftobs Sep 2, 2026
17ffcc5
fix: prevent empty catch-all domains in Caddy snippets
Lftobs Sep 2, 2026
1d52e18
feat(settings): add project deletion and
Lftobs Sep 3, 2026
f223ff5
Merge branch 'dev' into bugs-fixes
Lftobs Sep 3, 2026
af368aa
fix: add ON DELETE CASCADE to deployment_logs FK, bump to 0.3.0-rc.10
Lftobs Sep 3, 2026
aa194ec
fix: install docker compose plugin in API container for local compose…
Lftobs Sep 3, 2026
2145e66
fix: add Connect GitHub button to RepoPicker when session expires
Lftobs Sep 3, 2026
81de5e6
feat: persist GitHub OAuth sessions in DB with AES-256-GCM encryption
Lftobs Sep 3, 2026
8332ac8
fix(api): exclude database services from compose
Lftobs Sep 3, 2026
430384e
chore: release v0.3.0
Lftobs Sep 5, 2026
d1234b7
docs(changelog): add v0.3.0 release notes
Lftobs Sep 5, 2026
506bb22
Bugs fixes (#45)
Lftobs Sep 5, 2026
8c7f76b
feat: add shared environment variables and SSH key
Lftobs Sep 5, 2026
2ac7c3f
chore: add Biome linter + pre-commit hook, format codebase
Lftobs Sep 5, 2026
c6feaa9
test: verify pre-commit hook runs biome
Lftobs Sep 5, 2026
695a9fb
Revert "test: verify pre-commit hook runs biome"
Lftobs Sep 5, 2026
d6c75f9
test: verify biome fixes bad formatting
Lftobs Sep 5, 2026
d3f738d
Revert "test: verify biome fixes bad formatting"
Lftobs Sep 5, 2026
566f8b2
Merge branch 'dev' of github.com:Lftobs/dequel into dev
Lftobs Sep 5, 2026
765a199
refactor(web,api): redesign keys and settings
Lftobs Sep 11, 2026
3e6f917
Update docker-compose.yml
Lftobs Sep 11, 2026
e063837
Merge pull request #46 from Lftobs/bugs-fixes
Lftobs Sep 11, 2026
efc3dbf
Merge branch 'origin/dev' into feat/mobile-responsive
Lftobs Sep 11, 2026
80d43e5
fix(db): remove duplicate listRoutesByDeployment function
Lftobs Sep 11, 2026
3b477a9
feat(api): add automated database backup and
Lftobs Sep 11, 2026
1049120
feat(ui): make all settings sections, tables, tabs and dialogs fully …
Lftobs Sep 11, 2026
4c85cc3
Merge pull request #44 from Lftobs/feat/mobile-responsive
Lftobs Sep 12, 2026
0fd77c1
feat(db): database studio data viewer, database settings UI, backup c…
Lftobs Sep 12, 2026
8a7b5c7
merge: sync dev with Database Studio, backup system, and capsule sub-…
Lftobs Sep 12, 2026
650e1d8
refactor(web): remove delete projects tab and fix
Lftobs Sep 12, 2026
3cb6610
fix(backup): resolve container name, storage type display, and S3 prefix
Lftobs Sep 13, 2026
f38b1a6
style(web): increase SQL query editor rows and
Lftobs Sep 13, 2026
1c001d6
Merge pull request #48 from Lftobs/bugs-fix
Lftobs Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
20 changes: 20 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dequel Environment Configuration
# Copy to .env and fill in values. Never commit .env.

# PostgreSQL
POSTGRES_USER=dequel
POSTGRES_PASSWORD=changeme
POSTGRES_DB=dequel
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}

# Caddy
CADDY_BASE_DOMAIN=localhost
CADDY_EMAIL=

# Encryption
ENV_ENCRYPTION_KEY=changeme

# GitHub (optional)
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GITHUB_WEBHOOK_SECRET=
19 changes: 19 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail

# Pre-commit hook: format staged .ts/.tsx files with Biome
# Install: git config core.hooksPath .githooks

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx|json)$' || true)

if [ -z "$STAGED_FILES" ]; then
exit 0
fi

echo "Formatting staged files with Biome..."
echo "$STAGED_FILES" | xargs ./node_modules/.bin/biome format --write --no-errors-on-unmatched 2>/dev/null || true

# Re-stage formatted files
echo "$STAGED_FILES" | xargs git add 2>/dev/null || true

echo "Biome format passed."
53 changes: 41 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Extract version from tag
- name: Extract version and release type
id: version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
run: |
VERSION="${GITHUB_REF_NAME#v}"
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
if [[ "$VERSION" =~ [-] ]]; then
echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT
else
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
fi

- name: Set image names
run: |
REPO_LC="${REPO,,}"
echo "API_IMAGE=ghcr.io/${REPO_LC}/api" >> $GITHUB_ENV
echo "WEB_IMAGE=ghcr.io/${REPO_LC}/web" >> $GITHUB_ENV
echo "AGENT_IMAGE=ghcr.io/${REPO_LC}/agent" >> $GITHUB_ENV
env:
REPO: ${{ github.repository }}

Expand All @@ -46,11 +54,13 @@ jobs:
with:
context: apps/api
push: true
build-args: |
BUILD_TIME=${{ github.sha }}
tags: |
${{ env.API_IMAGE }}:${{ steps.version.outputs.VERSION }}
${{ env.API_IMAGE }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
${{ steps.version.outputs.IS_PRERELEASE == 'false' && format('{0}:latest', env.API_IMAGE) || format('{0}:next', env.API_IMAGE) }}
cache-from: type=gha,scope=api-${{ github.sha }}
cache-to: type=gha,scope=api-${{ github.sha }},mode=max

- name: Build and push Web image
uses: docker/build-push-action@v6
Expand All @@ -59,35 +69,54 @@ jobs:
push: true
build-args: |
DEQUEL_VERSION=${{ steps.version.outputs.VERSION }}
BUILD_TIME=${{ github.sha }}
tags: |
${{ env.WEB_IMAGE }}:${{ steps.version.outputs.VERSION }}
${{ env.WEB_IMAGE }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
${{ steps.version.outputs.IS_PRERELEASE == 'false' && format('{0}:latest', env.WEB_IMAGE) || format('{0}:next', env.WEB_IMAGE) }}
cache-from: type=gha,scope=web-${{ github.sha }}
cache-to: type=gha,scope=web-${{ github.sha }},mode=max

- name: Build and push Agent image
uses: docker/build-push-action@v6
with:
context: apps/agent
push: true
build-args: |
BUILD_TIME=${{ github.sha }}
tags: |
${{ env.AGENT_IMAGE }}:${{ steps.version.outputs.VERSION }}
${{ steps.version.outputs.IS_PRERELEASE == 'false' && format('{0}:latest', env.AGENT_IMAGE) || format('{0}:next', env.AGENT_IMAGE) }}
cache-from: type=gha,scope=agent-${{ github.sha }}
cache-to: type=gha,scope=agent-${{ github.sha }},mode=max

- name: Build config tarball
run: |
VERSION="${{ steps.version.outputs.VERSION }}"
TAR_DIR=_tar
mkdir -p "$TAR_DIR/infra/caddy" "$TAR_DIR/infra/monitoring/grafana/datasources"
mkdir -p "$TAR_DIR/infra/caddy" "$TAR_DIR/infra/monitoring/grafana/datasources" "$TAR_DIR/scripts/auth"
cp docker-compose.yml "$TAR_DIR/"
cp scripts/dequel "$TAR_DIR/dequel"
cp infra/caddy/Caddyfile "$TAR_DIR/infra/caddy/"
cp -r infra/monitoring "$TAR_DIR/infra/"
cp -r scripts/auth/* "$TAR_DIR/scripts/auth/"
cd "$TAR_DIR" && tar -czf "../dequel-config-${VERSION}.tar.gz" .

- name: Extract changelog entry for this version
run: |
VERSION="${{ steps.version.outputs.VERSION }}"
awk '/^## \['"$VERSION"'\] -/{flag=1; next} /^## \[/{if(flag) exit} flag' CHANGELOG.md > release-notes.md
if [ ! -s release-notes.md ]; then
echo "No changelog entry for v$VERSION, will use auto-generated notes"
CHANGELOG="apps/docs/src/content/changelogs/v${VERSION}.md"
if [ -f "$CHANGELOG" ]; then
sed '1,/^---$/d' "$CHANGELOG" | sed '1,/^---$/d' > release-notes.md
echo "Extracted changelog from $CHANGELOG"
else
echo "No changelog file at $CHANGELOG, will use auto-generated notes"
fi

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: v${{ steps.version.outputs.VERSION }}
prerelease: ${{ steps.version.outputs.IS_PRERELEASE == 'true' }}
body_path: release-notes.md
generate_release_notes: true
files: |
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ bump.sh
scripts/workflow/bump.sh
__pycache__
.tegami/changes-*
SETUP_GUIDE.md
bun.lock
apps/docs/.blume/
FEATURES.md
.agents
.worktrees/
artifacts
15 changes: 7 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Self-hosted deployment platform. Deploy apps from Git, ZIP, or Docker Compose wi
- **Backend**: ElysiaJS (`apps/api/`) — TypeScript, port 3001
- **Frontend**: React 18 + Vite + TanStack Router + TanStack Query (`apps/web/`) — port 3000
- **Docs**: Astro 4 + Tailwind CSS (`apps/docs/`) — deployed to Vercel
- **Database**: SQLite (`data/dequel.db`) — raw SQL
- **Database**: PostgreSQL (via Drizzle ORM + node-postgres)
- **Queue**: Redis (`ioredis`) for async job queue
- **Container build**: Railpack CLI + BuildKit daemon
- **Container runtime**: Docker Engine API (mounted Docker socket)
Expand All @@ -20,12 +20,12 @@ Self-hosted deployment platform. Deploy apps from Git, ZIP, or Docker Compose wi
Caddy ──▶ API ──▶ Buildkit
│ │
▼ ▼
Web SQLite Redis
Web PostgreSQL Redis

Observability: cAdvisor → Prometheus → Grafana / Loki
```

Services run in Docker Compose: Caddy, API, Web, Buildkit, Redis, cAdvisor, Prometheus, Loki, Promtail, Grafana.
Services run in Docker Compose: Caddy, API, Web, Buildkit, PostgreSQL, Redis, cAdvisor, Prometheus, Loki, Promtail, Grafana.

## Directory Structure

Expand Down Expand Up @@ -61,7 +61,6 @@ Services run in Docker Compose: Caddy, API, Web, Buildkit, Redis, cAdvisor, Prom
├── scripts/
│ ├── install.sh # One-command install script
│ └── dequel # CLI for managing the platform
├── data/ # SQLite database (persisted)
├── workspace/ # Build staging area
├── docker-compose.yml
├── VERSION # Single source of truth for version
Expand All @@ -75,7 +74,7 @@ Services run in Docker Compose: Caddy, API, Web, Buildkit, Redis, cAdvisor, Prom
|------|---------|
| `apps/api/src/index.ts` | API entry point — bootstraps DB, queue, scaling engine, etc. |
| `apps/api/src/db/schema.ts` | Drizzle ORM schema definitions (all tables) |
| `apps/api/src/db/drizzle.ts` | Drizzle client wrapper (wraps `bun:sqlite`) |
| `apps/api/src/db/db-provider.ts` | Database DI provider (setDbProvider/getDb) |
| `apps/api/src/db/migrations/` | Drizzle Kit migration files (`drizzle-kit generate` outputs here) |
| `apps/api/drizzle.config.ts` | Drizzle Kit configuration |
| `apps/web/src/main.tsx` | Frontend entry point |
Expand Down Expand Up @@ -115,7 +114,7 @@ docker compose up -d # Start full stack
docker compose up -d --build # Rebuild and start

# Install / Manage
curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/scripts/install.sh | sh
curl -fsSL https://github.com/Lftobs/dequel/releases/latest/download/install.sh | bash
scripts/dequel start # Start platform
scripts/dequel uninstall # Remove everything (prompts)

Expand Down Expand Up @@ -176,7 +175,7 @@ Requires secrets: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3001` | API listen port |
| `DATABASE_PATH` | `./data/dequel.db` | SQLite database |
| `DATABASE_URL` | `postgresql://dequel:dequel@localhost:5432/dequel` | PostgreSQL connection string |
| `WORKSPACE_ROOT` | `./workspace` | Build staging |
| `CADDY_ROUTES_DIR` | `./infra/caddy/routes` | Caddy route output |
| `CADDY_BASE_DOMAIN` | `localhost` | Base domain for deployment subdomains. Set to a real domain (e.g. `example.com`) for Let's Encrypt auto-SSL. |
Expand All @@ -189,7 +188,7 @@ Requires secrets: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`

- Never commit secrets or `.env` files
- Drizzle ORM for migrations; raw SQL is still used in `repo.ts` for queries (may be migrated incrementally)
- Database: SQLite with `bun:sqlite` (future: Drizzle ORM + PostgreSQL)
- Database: PostgreSQL (via Drizzle ORM + node-postgres)
- `.gitignore` ignores `infra/caddy/routes/`, NOT `apps/web/src/routes/`
- Always run `bun test` in `apps/api/` before committing API changes
- Docs landing page (`index.astro`) is standalone — no shared layout
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.0-rc.1] - 2026-08-25

### Added

- Multi-server architecture supporting Direct SSH (`mode: 'ssh'`) and Direct P2P WireGuard Agent (`mode: 'agent'`) modes
- Target-aware container deployment and remote SFTP Caddy route synchronization
- Cross-server autoscaling with fleet load evaluation and spillover placement
- Direct WireGuard P2P tunneling (`10.200.0.x`) with Curve25519 key generation and real-time metric sync
- Domain verification with A/CNAME record matching against assigned target server IPs
- Safe pre-release CI/CD workflow preventing pre-release images from overriding `:latest`

### Changed

- Migrated platform database from SQLite to PostgreSQL with Drizzle ORM
- Streamlined server connection modes strictly to Direct SSH and Direct P2P WireGuard Agent

## [0.1.1] - 2026-06-19

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ and in the `apps/docs/` directory of this repository.
## Quick Start

```bash
curl -fsSL https://raw.githubusercontent.com/Lftobs/dequel/main/scripts/install.sh | sh
curl -fsSL https://github.com/Lftobs/dequel/releases/latest/download/install.sh | bash
```

Once installed, manage Dequel with the `dequel` CLI:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.0
0.3.0
22 changes: 22 additions & 0 deletions apps/agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM oven/bun:1

ARG BUILD_TIME=0

RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl git caddy gnupg iproute2 wireguard-tools \
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \
&& chmod a+r /etc/apt/keyrings/docker.asc \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends docker-ce-cli docker-buildx-plugin docker-compose-plugin \
&& rm -rf /var/lib/apt/lists/*

RUN curl -sSL https://railpack.com/install.sh | sh -s -- --bin-dir /usr/local/bin

WORKDIR /app
COPY package.json ./
COPY src ./src

RUN mkdir -p /var/lib/dequel/workspace

CMD ["bun", "src/index.ts"]
11 changes: 11 additions & 0 deletions apps/agent/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "dequel-agent",
"version": "0.3.0",
"private": true,
"type": "module",
"scripts": {
"dev": "bun --watch src/index.ts",
"start": "bun src/index.ts",
"test": "bun test"
}
}
35 changes: 35 additions & 0 deletions apps/agent/src/capabilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { spawn } from "node:child_process";
import { statfs } from "node:fs/promises";
import { arch, availableParallelism, freemem, totalmem } from "node:os";
import type { AgentCapabilities } from "./protocol";

const succeeds = (command: string, args: string[]) =>
new Promise<boolean>((resolve) => {
const child = spawn(command, args, { stdio: "ignore", timeout: 10_000 });
child.on("error", () => resolve(false));
child.on("close", (code) => resolve(code === 0));
});

export const collectCapabilities = async (): Promise<AgentCapabilities> => {
const [docker, buildkit, caddy, compose, disk] = await Promise.all([
succeeds("docker", ["info"]),
succeeds("docker", ["buildx", "version"]),
succeeds("caddy", ["version"]),
succeeds("docker", ["compose", "version"]),
statfs("/").catch(() => null),
]);
return {
docker,
buildkit,
caddy,
compose,
architectures: [arch()],
cpuCount: availableParallelism(),
memoryBytes: totalmem(),
diskBytes: disk ? disk.blocks * disk.bsize : 0,
};
};

export const collectResourceUsage = () => ({
memoryUsedMb: Math.round((totalmem() - freemem()) / 1024 / 1024),
});
27 changes: 27 additions & 0 deletions apps/agent/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { homedir } from "node:os";
import { join } from "node:path";

export interface WireGuardPeerConfig {
peerIp: string;
privateKey: string;
serverPublicKey: string;
serverEndpoint: string;
allowedIps: string;
}

export const config = {
controlPlaneUrl: process.env.DEQUEL_CONTROL_PLANE?.replace(/\/+$/, "") || "",
tunnelUrl: process.env.DEQUEL_AGENT_TUNNEL_URL?.replace(/\/+$/, "") || "",
registrationToken: process.env.DEQUEL_REGISTRATION_TOKEN,
credentialPath: process.env.DEQUEL_AGENT_CREDENTIAL_PATH || join(homedir(), ".dequel", "agent.json"),
agentVersion: process.env.DEQUEL_AGENT_VERSION || "0.2.1",
publicHost: process.env.DEQUEL_AGENT_PUBLIC_HOST,
workspaceRoot: process.env.DEQUEL_AGENT_WORKSPACE || "/var/lib/dequel/workspace",
caddyRoutesDir: process.env.DEQUEL_AGENT_CADDY_ROUTES || "/etc/dequel/caddy/routes",
dockerNetwork: process.env.DEQUEL_DOCKER_NETWORK || "dequel_net",
};

export const requireControlPlaneUrl = () => {
if (!config.controlPlaneUrl) throw new Error("DEQUEL_CONTROL_PLANE is required");
return config.controlPlaneUrl;
};
Loading
Loading