Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0218f3d
docs: add agent operating rules
nomed Aug 21, 2026
7b7da14
docs: add context manifest
nomed Aug 21, 2026
fa3f78e
docs: add context system
nomed Aug 21, 2026
f39a084
docs: accept stack packaging architecture
nomed Aug 21, 2026
905afb2
feat: serve web client with Caddy
nomed Aug 21, 2026
59850a6
feat: add Caddy web runtime config
nomed Aug 21, 2026
b5dfcf1
chore: remove nginx runtime config
nomed Aug 21, 2026
f57524f
feat: package extracted web assets with Caddy
nomed Aug 21, 2026
d0f3f8d
feat: add full rustdesk stack chart
nomed Aug 21, 2026
7430c52
feat: define rustdesk stack values
nomed Aug 21, 2026
be7aefa
feat: add chart helpers
nomed Aug 21, 2026
a73fdfb
feat: add web workload
nomed Aug 21, 2026
f69c7dd
feat: add hbbs workload
nomed Aug 21, 2026
27ccdef
feat: add hbbr workload
nomed Aug 21, 2026
2e04b5f
feat: add Gateway API routing
nomed Aug 21, 2026
e1e986a
fix: wire rustdesk key secret as environment
nomed Aug 21, 2026
f5de36c
fix: pin released rustdesk server image
nomed Aug 21, 2026
1a78129
fix: version rustdesk stack chart
nomed Aug 21, 2026
f3327f9
feat: publish web image and stack chart under OCI prefix
nomed Aug 21, 2026
8e42a65
ci: validate full stack and publish web snapshots under prefix
nomed Aug 21, 2026
51d0ebd
chore: remove obsolete web-only chart
nomed Aug 21, 2026
b25384a
chore: remove obsolete web-only chart values
nomed Aug 21, 2026
df760d6
chore: remove obsolete web deployment template
nomed Aug 21, 2026
3b0eed7
chore: remove obsolete web service template
nomed Aug 21, 2026
315b85f
docs: describe full stack architecture and OCI layout
nomed Aug 21, 2026
de55314
docs: record full stack implementation session
nomed Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .context/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# rustdesk-web-stack Context System

`.context/` is the durable operating memory for humans and coding agents working on this repository.

## Source precedence

1. explicit human instruction in the current task;
2. accepted decisions in `.context/decisions/`;
3. project architecture and standards;
4. root and nearest `AGENTS.md`;
5. governing GitHub issue and pull request;
6. latest handoff;
7. session records;
8. temporary notes.

A session, handoff, issue comment or pull-request discussion does not change architecture by itself. Material decisions must be promoted to an ADR and accepted through human review.

## Structure

- `manifest.yaml`: machine-readable precedence, record and release policy.
- `decisions/`: architectural decision records. Accepted records are immutable.
- `sessions/`: chronological implementation/evidence records.
- `handoffs/`: durable continuation notes between people or agents.

## Required workflow

Before meaningful implementation: read the manifest and AGENTS rules, identify the governing issue, load relevant accepted decisions, and inspect pinned upstream evidence rather than assuming current defaults.

After meaningful work: record a session, link the governing issue/PR, list checks performed, record unresolved risks, and create a handoff when the work is not complete.
31 changes: 31 additions & 0 deletions .context/decisions/ADR-0001-stack-packaging-and-deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ADR-0001: Stack packaging and deployment model

Status: Accepted
Date: 2026-08-21
Governing issue: #9

## Context

The project must ship a reproducible RustDesk browser client together with a maintainable Kubernetes deployment for the self-hosted RustDesk server components. The upstream RustDesk server project provides container images and historical/WIP Helm work, but no current maintained full-stack Helm chart. The web client build path also requires project-owned packaging.

## Decision

1. Release Please owns one semantic version for this repository's stack artifacts.
2. A release publishes:
- `ghcr.io/nomed/rustdesk-web-stack/web:<version>`;
- `oci://ghcr.io/nomed/rustdesk-web-stack/charts/rustdesk-stack:<version>`;
- GitHub tag/release `v<version>`.
3. The Helm chart is named `rustdesk-stack` and deploys the complete stack: web client, `hbbs`, `hbbr`, persistence/secrets and networking.
4. RustDesk server image/version is configured and pinned independently from the stack version.
5. The web runtime uses Caddy rather than NGINX.
6. Kubernetes Gateway API is the preferred HTTP/WSS exposure contract. The chart does not install or require a specific Gateway controller; Envoy Gateway and Traefik are reference implementations.
7. Native RustDesk TCP/UDP endpoints remain independently exposable through Kubernetes Services; TCPRoute/UDPRoute may be added optionally when controller support is appropriate.
8. Upstream `rustdesk/rustdesk-server#399` is reference material only, not a Helm dependency.
9. Upstream source and tooling inputs used for released artifacts must be pinned and reviewable; `latest` is not a release default.

## Consequences

- Stack and upstream RustDesk versions evolve independently.
- Cluster operators retain control over GatewayClass/controller choice.
- The chart owns more server deployment logic but avoids depending on an abandoned upstream chart.
- Release validation must lint/template the full stack and publish both OCI artifacts atomically from the same Release Please version.
44 changes: 44 additions & 0 deletions .context/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
schema_version: 1
project: rustdesk-web-stack
context_root: .context

precedence:
- current_human_instruction
- accepted_decisions
- project_architecture_and_standards
- nearest_agents_md
- governing_issue_and_pull_request
- latest_handoff
- sessions
- temporary_notes

records:
decisions:
path: .context/decisions
id_pattern: "ADR-{number:04d}"
statuses: [Draft, Proposed, Accepted, Deprecated, Superseded, Rejected, Withdrawn]
immutable_after_acceptance: true
handoffs:
path: .context/handoffs
id_pattern: "HANDOFF-{date}-{sequence:02d}"
authoritative: false
sessions:
path: .context/sessions
id_pattern: "SESSION-{date}-{sequence:02d}"
authoritative: false

write_policy:
sessions: agents_allowed
handoffs: agents_allowed
decisions: proposal_allowed_human_acceptance_required
accepted_records_rewrite: forbidden
architecture_change_without_record: forbidden
release_or_packaging_change_without_record: forbidden
destructive_operation_without_explicit_approval: forbidden

release_contract:
version_authority: release_please
tag_pattern: "v{version}"
web_image: "ghcr.io/nomed/rustdesk-web-stack/web:{version}"
helm_chart: "oci://ghcr.io/nomed/rustdesk-web-stack/charts/rustdesk-stack:{version}"
stack_version_independent_from_upstream: true
54 changes: 54 additions & 0 deletions .context/sessions/SESSION-2026-08-21-01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SESSION-2026-08-21-01

Governing issue: #9
Branch: `feat/full-rustdesk-stack`

## Objective

Implement the approved full-stack packaging/deployment model and introduce durable `.context` / `AGENTS.md` repository governance.

## Evidence inspected

- `retex-iconic/rgk` `AGENTS.md`, `.context/manifest.yaml` and `.context/README.md` as the operating-context reference model.
- `rustdesk/rustdesk-server#399` as historical/WIP Helm reference for separate `hbbs`/`hbbr` workloads and official ports.
- RustDesk Server current release/package evidence: 1.1.16 is the latest published release/container; 1.1.17 exists in master but is unreleased.

## Decisions applied

ADR-0001 records the accepted contract:

- one Release Please stack version;
- OCI web image under `ghcr.io/nomed/rustdesk-web-stack/web`;
- OCI chart under `ghcr.io/nomed/rustdesk-web-stack/charts/rustdesk-stack`;
- full `rustdesk-stack` chart with web, hbbs and hbbr;
- Caddy web runtime;
- Gateway API without bundled controller;
- independently pinned RustDesk Server release.

## Changes

- added `AGENTS.md` and `.context` operating memory;
- replaced the NGINX runtime with Caddy;
- changed the baseline build to use upstream packaging as a builder only, then build the project-owned Caddy image;
- added `charts/rustdesk-stack` with web/hbbs/hbbr, persistence, Services and optional Gateway/HTTPRoute;
- pinned the default official RustDesk Server image to `ghcr.io/rustdesk/rustdesk-server:1.1.16`;
- changed Release Please chart version target and OCI publication paths;
- updated CI to lint/template the full chart and publish web snapshots under the new prefix;
- removed the old web-only chart.

## Validation

Validation is delegated to the pull-request CI:

- Helm lint;
- Helm template with default values;
- Helm template with Gateway API enabled;
- pinned web baseline build;
- generated artifact checks including Caddy runtime provenance.

## Open risks / next actions

- confirm the baseline upstream builder still produces the expected static path before the Caddy repackaging step;
- validate a real browser session through Gateway API to hbbs/hbbr WebSocket ports;
- decide/test production-native exposure patterns (LoadBalancer versus optional TCPRoute/UDPRoute) across Envoy Gateway and Traefik;
- consider digest pinning for the RustDesk Server image after initial functional validation.
25 changes: 17 additions & 8 deletions .github/workflows/build-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ on:
- "build/**"
- "container/**"
- "charts/**"
- ".context/**"
- "AGENTS.md"
- ".github/workflows/build-web.yml"
- "README.md"
pull_request:
paths:
- "build/**"
- "container/**"
- "charts/**"
- ".context/**"
- "AGENTS.md"
- ".github/workflows/build-web.yml"
- "README.md"

Expand All @@ -40,8 +44,12 @@ jobs:
shell: bash
run: |
set -euo pipefail
helm lint charts/rustdesk-web
helm template rustdesk-web charts/rustdesk-web >/dev/null
helm lint charts/rustdesk-stack
helm template rustdesk charts/rustdesk-stack >/dev/null
helm template rustdesk charts/rustdesk-stack \
--set gateway.enabled=true \
--set gateway.gatewayName=public \
--set gateway.hostname=rustdesk.example.com >/dev/null

- name: Load pinned baseline versions
id: versions
Expand Down Expand Up @@ -69,8 +77,8 @@ jobs:
test -s dist/web/index.html
test -s dist/web/main.dart.js || test -s dist/web/flutter_bootstrap.js
test -s dist/web/BUILD-INFO.txt
grep -q '^Runtime: Caddy$' dist/web/BUILD-INFO.txt
test -d dist/web/js
find dist/web -maxdepth 2 -type f | sort | head -100

- name: Upload web artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand All @@ -88,14 +96,15 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Publish baseline image
- name: Publish baseline web snapshot
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
shell: bash
run: |
set -euo pipefail
short_ref="${{ steps.versions.outputs.web_client_ref }}"
short_ref="${short_ref:0:12}"
docker tag rustdesk-web-stack:ci ghcr.io/nomed/rustdesk-web-stack:latest
docker tag rustdesk-web-stack:ci "ghcr.io/nomed/rustdesk-web-stack:web-${short_ref}"
docker push ghcr.io/nomed/rustdesk-web-stack:latest
docker push "ghcr.io/nomed/rustdesk-web-stack:web-${short_ref}"
base='ghcr.io/nomed/rustdesk-web-stack/web'
docker tag rustdesk-web-stack:ci "${base}:edge"
docker tag rustdesk-web-stack:ci "${base}:web-${short_ref}"
docker push "${base}:edge"
docker push "${base}:web-${short_ref}"
34 changes: 20 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,23 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build release image
- name: Build release web image
shell: bash
env:
IMAGE_TAG: ghcr.io/nomed/rustdesk-web-stack:${{ needs.release-please.outputs.version }}
IMAGE_TAG: ghcr.io/nomed/rustdesk-web-stack/web:${{ needs.release-please.outputs.version }}
run: bash build/build-baseline-image.sh

- name: Publish release image
- name: Publish release web image
shell: bash
run: |
set -euo pipefail
version='${{ needs.release-please.outputs.version }}'
docker push "ghcr.io/nomed/rustdesk-web-stack:${version}"
docker tag "ghcr.io/nomed/rustdesk-web-stack:${version}" "ghcr.io/nomed/rustdesk-web-stack:v${version}"
docker tag "ghcr.io/nomed/rustdesk-web-stack:${version}" ghcr.io/nomed/rustdesk-web-stack:latest
docker push "ghcr.io/nomed/rustdesk-web-stack:v${version}"
docker push ghcr.io/nomed/rustdesk-web-stack:latest
base='ghcr.io/nomed/rustdesk-web-stack/web'
docker push "${base}:${version}"
docker tag "${base}:${version}" "${base}:v${version}"
docker tag "${base}:${version}" "${base}:latest"
docker push "${base}:v${version}"
docker push "${base}:latest"

- name: Set up Helm
uses: azure/setup-helm@v4.3.1
Expand All @@ -70,18 +71,22 @@ jobs:
shell: bash
run: |
set -euo pipefail
helm lint charts/rustdesk-web
helm template rustdesk-web charts/rustdesk-web >/dev/null
helm lint charts/rustdesk-stack
helm template rustdesk charts/rustdesk-stack >/dev/null
helm template rustdesk charts/rustdesk-stack \
--set gateway.enabled=true \
--set gateway.gatewayName=public \
--set gateway.hostname=rustdesk.example.com >/dev/null

- name: Package Helm chart
shell: bash
run: |
set -euo pipefail
version='${{ needs.release-please.outputs.version }}'
test "$(awk '/^version:/ {print $2}' charts/rustdesk-web/Chart.yaml)" = "${version}"
test "$(awk -F'\"' '/^appVersion:/ {print $2}' charts/rustdesk-web/Chart.yaml)" = "${version}"
test "$(awk '/^version:/ {print $2}' charts/rustdesk-stack/Chart.yaml)" = "${version}"
test "$(awk -F'\"' '/^appVersion:/ {print $2}' charts/rustdesk-stack/Chart.yaml)" = "${version}"
mkdir -p dist/chart
helm package charts/rustdesk-web --destination dist/chart
helm package charts/rustdesk-stack --destination dist/chart

- name: Log in to GHCR for Helm
shell: bash
Expand All @@ -93,4 +98,5 @@ jobs:
run: |
set -euo pipefail
version='${{ needs.release-please.outputs.version }}'
helm push "dist/chart/rustdesk-web-${version}.tgz" oci://ghcr.io/nomed/charts
helm push "dist/chart/rustdesk-stack-${version}.tgz" \
oci://ghcr.io/nomed/rustdesk-web-stack/charts
48 changes: 48 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# rustdesk-web-stack Agent Operating Rules

These instructions apply to humans and coding agents working in this repository.

## Before acting

1. Read `.context/manifest.yaml` and `.context/README.md`.
2. Identify the governing GitHub issue and linked pull request.
3. Load accepted decisions relevant to the task.
4. When continuing previous work, read the latest relevant handoff/session.
5. Surface conflicts, missing evidence and upstream uncertainty instead of guessing.

## Source precedence

When sources conflict, follow `.context/manifest.yaml`. Current explicit human instruction and accepted architectural decisions outrank repository guidance, issue discussion, sessions and temporary notes.

## Required workflow

- Every meaningful change must be governed by a GitHub issue.
- Work on a focused branch and pull request; do not implement directly on `main`.
- Record material architecture, deployment, security, compatibility or release/packaging decisions as an ADR before or with implementation.
- Accepted ADRs are immutable; supersede them with a new record.
- Pin upstream source/image/tooling versions used for released artifacts. Do not silently track `latest` or an upstream default branch.
- Record meaningful implementation work in `.context/sessions/` and create a handoff when continuation is expected.
- Conventional commits are required because Release Please owns stack versioning.

## Project boundaries

- This repository packages and deploys RustDesk-derived components; it is not an official RustDesk project.
- Keep upstream source code out of this repository whenever practical. Prefer pinned upstream references plus reproducible build/packaging logic.
- The stack version is independent from RustDesk upstream versions.
- `rustdesk-stack` is the deployment product: web client, `hbbs`, `hbbr`, networking, persistence and secrets.
- The Helm chart must not install or depend on a specific ingress/gateway controller. Kubernetes Gateway API is the preferred L7 contract.
- Native RustDesk TCP/UDP exposure must remain usable independently from the HTTP/WSS gateway path.

## Release contract

A Release Please release publishes the same stack version for:

- `ghcr.io/nomed/rustdesk-web-stack/web:<version>`;
- `oci://ghcr.io/nomed/rustdesk-web-stack/charts/rustdesk-stack:<version>`;
- GitHub tag/release `v<version>`.

The chart pins/configures its RustDesk server version separately from the stack version.

## Completion evidence

At the end of meaningful work record: governing issue/PR, files changed, tests/checks, upstream evidence, decisions applied, unresolved risks and next actions.
Loading
Loading