diff --git a/JOURNAL.md b/JOURNAL.md index d744f13..8f6e5ae 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -4,7 +4,7 @@ **Project**: TSYSDevStack-SupportStack-Cloudron **Goal**: Package ~57 applications for Cloudron PaaS platform **Start Date**: 2025-01-24 -**Current Status**: 10/~57 packages completed (~18%) +**Current Status**: 11/~57 packages completed (~19%) ## Completed Packages @@ -823,6 +823,78 @@ Dockerfile --- +### 11. Rathole (Infrastructure) ✅ +**Date**: 2026-09-01 +**Application**: Rathole — secure, high-performance reverse proxy for NAT +traversal (frp/ngrok class, Rust); this package runs the **server** side +**Package Size**: 3.51GB (cloudron/base 4.0.0 dominates) +**Ports**: 8000 (HTTP status), 2333 (control), 5200-5299 (tunnel exits) +**Addons**: localstorage (auth proxy, no database) + +**Key Learnings**: +- **Auth gate verdict**: NO user concept — no UI, no accounts, no SSO + hooks. Tunnels are authorized by mandatory per-service tokens + (random `default_token` seeded on first run), with optional Noise/TLS + transport encryption → `httpAuth.type = proxy` gates the only HTTP + surface (a static status page), the draw.io/Easy-Gate pattern for + user-less apps +- **Base-image glibc trap**: upstream dropped musl release builds in + v0.5.0 (TLS linking burden); the only linux/amd64 asset is + `x86_64-unknown-linux-gnu`, built on ubuntu-latest → needs glibc + >= 2.35 → `cloudron/base:4.0.0` (22.04). The 3.2.0 (20.04) base used + by earlier packages is too old for this binary +- **Strict TOML schema quirks**: v0.5.0 rejects `nodelay` directly under + `[server.transport]` (must nest under `[server.transport.tcp]`) and + rejects a server config with **zero** `[server.services.*]` blocks — + the seed config must ship one active placeholder service +- **Lazy service binding**: the server binds a service's exit port only + when its client registers — an empty listener table is normal until a + client connects +- **tcpPorts ranges**: CloudronManifest `portCount` allocates sequential + ports from `defaultValue` (max 1000) with `containerPort` bridging — + used for a 100-port tunnel exit range (5200-5299) that survives + admin-chosen external renumbering without touching server.toml +- **httpPort is required** (healthCheckPath too) even for headless TCP + apps: a tiny `python3 -m http.server` sidecar on the status page + satisfies both and gives the auth proxy something to gate + +**Build Process**: +- Upstream `rathole-org/rathole` v0.5.0 (rapiz1 redirects) release zip + downloaded in-Dockerfile behind a sha256 pin (pre-compiled-binaries + pattern, JOURNAL pattern #5) +- Logo: upstream wordmark (1080x291) resized/padded to 256x256 PNG via + ImageMagick in a throwaway `alpine:3.20` container (host stays clean) +- start.sh: seeds `/app/data/server.toml` (random default_token via + openssl + placeholder `[server.services.example]` on :5200), starts + the status-page sidecar, `exec rathole --server` (config hot-reloads + on save) + +**Validation**: +- `docker build --cgroup-parent ukrrs-batch.slice -t rathole-cloudron:test` + → green (sha256 gate + `rathole --version` inside the build) +- Runtime smoke: status page HTTP 200, control port :2333 reachable, + hot-reload detected an appended service within 3s +- **End-to-end tunnel test**: second container ran `rathole --client` + against the packaged server; `curl host:15200 → server:5200 → + client → client:9999` returned the client's page — token auth, + control channel, data plane, and lazy bind all proven + +**Files Created**: +- Dockerfile (pre-compiled binary, sha256-pinned, cloudron/base:4.0.0) +- CloudronManifest.json (manifestVersion 2, httpAuth proxy, tcpPorts: + CONTROL_PORT 2333 + SERVICE_PORT 5200 x100, localstorage) +- start.sh (config seed + status sidecar + exec) — committed executable +- status.html (auth-proxied landing/health page) +- README.md (auth story, ports, client quickstart) +- CHANGELOG.md +- .env.example (RUST_LOG knob) +- .dockerignore (excludes the whole cloned repo/ from context) +- logo.png (256x256) + +**Commit**: `feat: add Rathole Cloudron package (Infrastructure) [#650]` + +--- + ## Packaging Pattern: Download Pre-Compiled Binaries ### When to Use diff --git a/Package-Workspace/Infrastructure/rathole/.dockerignore b/Package-Workspace/Infrastructure/rathole/.dockerignore new file mode 100644 index 0000000..f606d5e --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/.dockerignore @@ -0,0 +1 @@ +repo diff --git a/Package-Workspace/Infrastructure/rathole/.env.example b/Package-Workspace/Infrastructure/rathole/.env.example new file mode 100644 index 0000000..890983a --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/.env.example @@ -0,0 +1,8 @@ +# Rathole Cloudron package — environment knobs +# +# Cloudron injects these at runtime (App -> Configure -> Environment); +# they are not secrets. + +# Log level for the rathole server: error | warn | info | debug | trace. +# Default when unset: info +RUST_LOG=info diff --git a/Package-Workspace/Infrastructure/rathole/CHANGELOG.md b/Package-Workspace/Infrastructure/rathole/CHANGELOG.md new file mode 100644 index 0000000..e82fde2 --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog — Rathole Cloudron Package + +## 1.0.0 (2026-09-01) + +Initial Cloudron package for Rathole 0.5.0 (server mode). + +- Pre-compiled-binaries pattern: upstream `x86_64-unknown-linux-gnu` + release zip downloaded at build time behind a sha256 pin (musl release + builds were dropped upstream in v0.5.0). +- Runtime `cloudron/base:4.0.0` (Ubuntu 22.04): the gnu binary requires + glibc >= 2.35, too new for the 3.x (20.04) base used by earlier + packages. +- `start.sh` seeds `/app/data/server.toml` on first run with a random + `default_token` (openssl) and a placeholder `[server.services.example]` + binding :5200 — upstream rejects a server config with zero services — + then execs `rathole --server`; the config hot-reloads on save. +- Verified end-to-end at build time: a client container tunneled its own + HTTP server through the packaged server (token auth, lazy service bind, + hot-reload of added services). +- TCP surface: control channel on 2333 + a 100-port tunnel exit range + (5200-5299) declared via `tcpPorts` with `containerPort`/`portCount`. +- No user concept → `httpAuth.type = proxy` gates a small static status + page served on the HTTP port (also serves as the platform health + check); tunnel access itself is controlled by rathole's mandatory + per-service tokens. +- Addons: `localstorage` only (config persistence; no database). +- Logo padded from the upstream wordmark to a 256x256 PNG. diff --git a/Package-Workspace/Infrastructure/rathole/CloudronManifest.json b/Package-Workspace/Infrastructure/rathole/CloudronManifest.json new file mode 100644 index 0000000..1f7f6f1 --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/CloudronManifest.json @@ -0,0 +1,43 @@ +{ + "manifestVersion": 2, + "type": "app", + "id": "io.cloudron.rathole", + "title": "Rathole", + "description": "Rathole is a secure, stable and high-performance reverse proxy for NAT traversal, written in Rust. This package runs the server side: clients behind NAT connect to the control port with per-service token authentication (optionally Noise/TLS encrypted) and expose their local services through tunnels on the reserved port range. Configuration lives in /app/data/server.toml and hot-reloads on save. No database required.", + "author": "rapiz1 / rathole-org", + "website": "https://github.com/rathole-org/rathole", + "documentationUrl": "https://github.com/rathole-org/rathole/blob/main/README.md", + "contactEmail": "cloudron@tsys.dev", + "tagline": "Secure, high-performance reverse-tunnel server for NAT traversal", + "version": "0.5.0", + "upstreamVersion": "0.5.0", + "healthCheckPath": "/", + "httpPort": 8000, + "httpAuth": { + "type": "proxy" + }, + "tcpPorts": { + "CONTROL_PORT": { + "title": "Control channel port", + "description": "TCP port that rathole clients connect to in order to establish tunnels. Change only if it collides with another exposed app on this Cloudron.", + "defaultValue": 2333, + "containerPort": 2333, + "portCount": 1 + }, + "SERVICE_PORT": { + "title": "Tunnel exit ports", + "description": "Start of the sequential port range reserved for tunneled services (100 ports by default: 5200-5299). Each [server.services.*] block in /app/data/server.toml binds one port from this range; the config hot-reloads, so services can be added without a restart.", + "defaultValue": 5200, + "containerPort": 5200, + "portCount": 100 + } + }, + "memoryLimit": 268435456, + "addons": { + "localstorage": {} + }, + "postInstallMessage": "Rathole is headless: there is nothing to click through. Open the **file manager** and edit **/app/data/server.toml** to define tunnel services (a random default token was generated on first start). The config hot-reloads on save. The client-side setup is documented in the package README.", + "mediaLinks": [], + "changelog": "Initial Cloudron package for Rathole 0.5.0 (server mode). Pre-compiled upstream binary with sha256 pin, token-authenticated tunnels on control port 2333 plus a 100-port service range (5200-5299), config with hot reload at /app/data/server.toml, and an auth-proxied status page on the HTTP port.", + "icon": "file://logo.png" +} diff --git a/Package-Workspace/Infrastructure/rathole/Dockerfile b/Package-Workspace/Infrastructure/rathole/Dockerfile new file mode 100644 index 0000000..0785731 --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/Dockerfile @@ -0,0 +1,48 @@ +# Rathole Cloudron Package +# +# Rathole is a secure, stable and high-performance reverse proxy for NAT +# traversal (frp/ngrok class, written in Rust). This package runs the +# SERVER side: the Cloudron box is the public-IP endpoint, rathole clients +# behind NAT dial the control port (2333) and expose their local services +# through token-authenticated tunnels on the 5200+ port range. +# +# Upstream: https://github.com/rathole-org/rathole (v0.5.0) +# - Ships a prebuilt x86_64-unknown-linux-gnu release binary (musl +# release builds were dropped upstream in v0.5.0) +# - No database, no user accounts; per-service tokens are mandatory +# +# Authentication: Rathole has NO user concept (tunnels are authorized by +# per-service tokens, optionally Noise/TLS encrypted at the transport +# layer). The status page on the HTTP port is gated by Cloudron's +# authentication proxy (httpAuth.type = proxy). +# +# Base image: cloudron/base:4.0.0 (Ubuntu 22.04). The upstream gnu binary +# is built on ubuntu-latest, so the runtime needs glibc >= 2.35 — +# cloudron/base:3.2.0 (20.04) is too old for it. +FROM cloudron/base:4.0.0 + +ARG RATHOLE_VERSION=0.5.0 +ARG RATHOLE_SHA256=3e7d0d0f365120cd3cd351d147d1a12ee960c8068b464d4dd533a3821873b80e + +# Pre-compiled-binaries pattern (see JOURNAL.md): download the pinned +# upstream release, verify the sha256 gate, install the binary. +RUN curl -fsSL -o /tmp/rathole.zip \ + "https://github.com/rathole-org/rathole/releases/download/v${RATHOLE_VERSION}/rathole-x86_64-unknown-linux-gnu.zip" \ + && echo "${RATHOLE_SHA256} /tmp/rathole.zip" | sha256sum -c - \ + && unzip -o /tmp/rathole.zip -d /usr/local/bin \ + && chmod +x /usr/local/bin/rathole \ + && rm -f /tmp/rathole.zip \ + && /usr/local/bin/rathole --version + +# Static status page served on the Cloudron HTTP port (platform health +# check + auth-proxied landing page). start.sh seeds /app/data/server.toml +# on first run and execs rathole in server mode. start.sh is made +# executable on the host, not at build time (Cloudron gotcha). +COPY status.html /app/code/status/index.html +COPY start.sh /app/start.sh + +WORKDIR /app/data + +EXPOSE 8000 2333 5200-5299 + +CMD ["/bin/bash", "/app/start.sh"] diff --git a/Package-Workspace/Infrastructure/rathole/README.md b/Package-Workspace/Infrastructure/rathole/README.md new file mode 100644 index 0000000..9196783 --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/README.md @@ -0,0 +1,95 @@ +# Rathole — Cloudron Package + +[Rathole](https://github.com/rathole-org/rathole) is a secure, stable and +high-performance reverse proxy for NAT traversal (frp/ngrok class, written +in Rust). This package runs the **server** side: the Cloudron box is the +public-IP endpoint, rathole clients behind NAT dial the control port, and +their local services are exposed through token-authenticated tunnels. + +## Packaging overview + +| Aspect | Choice | +|--------|--------| +| Pattern | Pre-compiled binaries (JOURNAL pattern #5) | +| Base image | `cloudron/base:4.0.0` (Ubuntu 22.04) | +| Upstream binary | `rathole-x86_64-unknown-linux-gnu.zip`, v0.5.0, sha256-pinned in Dockerfile | +| Addons | `localstorage` only (config persistence; no database) | +| Auth | No user concept → `httpAuth.type = proxy` (see below) | +| Runtime | `start.sh` seeds config, serves status page, execs rathole `--server` | + +Why pre-compiled: upstream ships release binaries and **dropped the musl +builds in v0.5.0** (only `x86_64-unknown-linux-gnu` remains for Linux +amd64). The gnu binary is built on ubuntu-latest, so the runtime needs +glibc >= 2.35 — hence `cloudron/base:4.0.0` (22.04) instead of the 3.x +series (20.04). Compiling from source would need a full Rust toolchain +build stage for no benefit. + +## Authentication (auth gate verdict: proxy) + +- Rathole has **no user concept**: no web UI, no accounts, no SSO hooks. +- Tunnels are authorized by **mandatory per-service tokens** (a random + `default_token` is generated into `/app/data/server.toml` on first + start). Transport can additionally be encrypted via Noise or TLS. +- The manifest declares `httpAuth: {"type": "proxy"}`: Cloudron's auth + proxy gates the HTTP status page, which is the only HTTP surface this + app has. The raw TCP tunnel ports cannot be HTTP-gated by design; the + token layer is their access control. + +## Ports + +| Port | Type | Purpose | +|------|------|---------| +| 8000 | `httpPort` | Status/health page (behind Cloudron auth proxy) | +| 2333 | `tcpPorts` | Control channel — rathole clients connect here | +| 5200–5299 | `tcpPorts` (100-port range) | Tunnel exit ports — one per `[server.services.*]` | + +With default install settings Cloudron bridges these 1:1 (external +5200-5299 → container 5200-5299). If the admin picks a different +`SERVICE_PORT` start value, the *container* ports stay 5200+ and only the +external numbering shifts — `server.toml` never needs editing for that. + +## Configuration + +`/app/data/server.toml`, seeded on first run, **hot-reloaded on save** +(add/remove services without restarting the app). The seed contains a +placeholder `[server.services.example]` on :5200 — rathole rejects a +server config with zero services, so keep at least one block. Example +service: + +```toml +[server.services.my_nas_ssh] +token = "" +bind_addr = "0.0.0.0:5200" +``` + +Client side (machine behind NAT): + +```toml +[client] +remote_addr = "your-cloudron.example.com:2333" + +[client.services.my_nas_ssh] +token = "" +local_addr = "127.0.0.1:22" +``` + +Then `ssh -p 5200 user@your-cloudron.example.com` reaches the NAS. + +Knob: `RUST_LOG` (error|warn|info|debug|trace, default `info`) via +Cloudron environment settings — see `.env.example`. + +## Build & test + +```bash +docker build --cgroup-parent ukrrs-batch.slice -t rathole-cloudron:test Package-Workspace/Infrastructure/rathole/ +docker run --rm --entrypoint /usr/local/bin/rathole rathole-cloudron:test --version +``` + +## Files + +- `Dockerfile` — pinned release download + sha256 gate on cloudron/base:4.0.0 +- `CloudronManifest.json` — manifestVersion 2, httpAuth proxy, tcpPorts (control + 100-port service range) +- `start.sh` — config seeding, status page, exec rathole server mode +- `status.html` — auth-proxied landing/health page +- `.env.example` — runtime knobs +- `logo.png` — 256x256, padded from upstream wordmark diff --git a/Package-Workspace/Infrastructure/rathole/logo.png b/Package-Workspace/Infrastructure/rathole/logo.png new file mode 100644 index 0000000..c623d58 Binary files /dev/null and b/Package-Workspace/Infrastructure/rathole/logo.png differ diff --git a/Package-Workspace/Infrastructure/rathole/start.sh b/Package-Workspace/Infrastructure/rathole/start.sh new file mode 100755 index 0000000..08774cd --- /dev/null +++ b/Package-Workspace/Infrastructure/rathole/start.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -euo pipefail + +# Rathole runs in SERVER mode on Cloudron: the box has the public IP and +# rathole clients behind NAT dial in on the control port (container port +# 2333, bridged 1:1 by default). Tunneled services bind container ports +# 5200-5299, which Cloudron exposes in sequence from the SERVICE_PORT +# value chosen at install time. +# +# Rathole has no HTTP interface of its own, so a tiny static status page +# is served on the Cloudron HTTP port. That gives the platform a health +# check endpoint and gives the admin an auth-proxied landing page +# (httpAuth.type = proxy gates it at the platform edge). + +export RATHOLE_CONFIG="/app/data/server.toml" + +if [[ ! -f "${RATHOLE_CONFIG}" ]]; then + default_token="$(openssl rand -hex 24)" + cat > "${RATHOLE_CONFIG}" < + + + + +Rathole (server) + + + +
+

Rathole ▲ server running

+

Secure, high-performance reverse-tunnel server for NAT traversal

+ +

Rathole is headless — this page exists so Cloudron has a health + endpoint and you have a landing spot. Configuration is file-based and + hot-reloads on save: edit + /app/data/server.toml with the Cloudron file manager to add + or remove tunnel services. A random default_token was + generated on first start; copy it from that file.

+ + + + + + +
PortPurpose
2333Control channel — rathole clients connect here
5200–5299Tunnel exit ports — one per [server.services.*] block
HTTP (this page)Status/health only, gated by the Cloudron auth proxy
+ +

Client side (on the machine behind NAT), with a matching service block on the server:

+
[client]
+remote_addr = "your-cloudron.example.com:2333"
+
+[client.services.my_nas_ssh]
+token = "<same token as the server>"
+local_addr = "127.0.0.1:22"
+ +

Upstream docs: + github.com/rathole-org/rathole

+
+ + diff --git a/README.md b/README.md index c79a21c..d41f8d3 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ The Cloudron component focuses on packaging upstream free/libre/open application ### 📊 Current Progress - **Total Applications**: ~57 (see [GitUrlList.txt](GitUrlList.txt)) -- **Completed Packages**: 10/~57 (~18%) +- **Completed Packages**: 11/~57 (~19%) - **Packaging Templates**: Created ✅ -- **Packages Committed & Pushed**: 10 ✅ +- **Packages Committed & Pushed**: 11 ✅ - **Build Tickets**: 46 filed (#633-#678, umbrella [#632](https://projects.knownelement.com/issues/632), Redmine project 55); grist-core excluded (packaged upstream) @@ -32,6 +32,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application | 8 | draw.io | Documentation-Tools | — | 8080 | none (auth proxy) | ✅ Committed | | 9 | Windmill | Automation | ~2GB | 8000 | localstorage, postgresql | ✅ Committed | | 10 | Easy-Gate | Infrastructure | 3.18GB | 8080 | localstorage (auth proxy) | ✅ Committed | +| 11 | Rathole | Infrastructure | 3.51GB | 8000, 2333, 5200-5299 | localstorage (auth proxy) | ✅ Committed | ### 📦 Packages in Development @@ -65,7 +66,7 @@ None currently in development. ### ⚡ Productivity Metrics -- **Packages Completed**: 10/~57 (~18%) +- **Packages Completed**: 11/~57 (~19%) - **Average Package Time**: ~30 minutes - **Success Rate**: 100% (all packages built successfully) - **Commits Pushed**: 100% (all packages pushed to remote) @@ -90,7 +91,7 @@ Applications are organized by function rather than programming language: | **Documentation-Tools** | Documentation and diagramming tools | 3 | 1/3 (33%) | | **Financial-Payments** | Payment processing and financial infrastructure | 1 | 0/1 (0%) | | **Financial-Trading** | Trading and financial algorithm platforms | 1 | 0/1 (0%) | -| **Infrastructure** | Infrastructure and networking tools | 6 | 1/6 (17%) | +| **Infrastructure** | Infrastructure and networking tools | 6 | 2/6 (33%) | | **Legal** | Legal and compliance applications | 1 | 0/1 (0%) | | **Low-Code** | Low-code and no-code platforms | 3 | 1/3 (33%) | | **Monitoring** | Monitoring and observability tools | 6 | 1/6 (17%) | @@ -127,7 +128,7 @@ Applications are organized by function rather than programming language: | [Fleet](https://github.com/fleetdm/fleet) | [GitHub](https://github.com/fleetdm/fleet) | Device management and monitoring | Monitoring | | [NetBox](https://github.com/netbox-community/netbox) | [GitHub](https://github.com/netbox-community/netbox) | IP address management (IPAM) and data center infrastructure management | Infrastructure | | [SeaTunnel](https://github.com/apache/seatunnel) | [GitHub](https://github.com/apache/seatunnel) | Data integration and streaming platform | Data-Management | -| [Rathole](https://github.com/rapiz1/rathole) | [GitHub](https://github.com/rapiz1/rathole) | Lightweight and high-performance reverse proxy | Infrastructure | +| [Rathole](https://github.com/rapiz1/rathole) | [GitHub](https://github.com/rapiz1/rathole) | Lightweight and high-performance reverse proxy | Infrastructure | ✅ Packaged | | [Easy-Gate](https://github.com/wiredlush/easy-gate) | [GitHub](https://github.com/wiredlush/easy-gate) | Gateway and proxy solution | Infrastructure | ✅ Packaged | | [Huginn](https://github.com/huginn/huginn) | [GitHub](https://github.com/huginn/huginn) | Agents that do things for you automatically | Automation | | [ConsulDemocracy](https://github.com/consuldemocracy/consuldemocracy) | [GitHub](https://github.com/consuldemocracy/consuldemocracy) | Open-source citizen participation platform | Collaboration | diff --git a/STATUS.md b/STATUS.md index 2e0d883..78eabfc 100644 --- a/STATUS.md +++ b/STATUS.md @@ -3,20 +3,20 @@ > **Human read-only. Agents maintain this file automatically after each work > session.** Do not edit by hand — the next agent run will overwrite it. > -> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — Easy-Gate packaged -> (#651, Infrastructure, 10th package); auth gate verdict: no user concept, -> shipped behind the Cloudron auth proxy. +> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — Rathole packaged +> (#650, Infrastructure, 11th package); auth gate verdict: no user concept, +> status page behind the Cloudron auth proxy, tunnels token-authenticated. ## Current State: STABLE (packaging phase, ongoing) -Cloudron packaging pipeline is operational. 10 of ~57 upstream applications are +Cloudron packaging pipeline is operational. 11 of ~57 upstream applications are packaged, committed, and pushed. Packaging templates exist for the core patterns. The gardening protocol (this file + AGENTS.md) keeps docs in sync. All remaining apps now carry build tickets (#633-#678) under umbrella [#632](https://projects.knownelement.com/issues/632) in Redmine project 55 — ready for the sequential grind-driver pattern. -## Completed Packages (10) +## Completed Packages (11) | # | Application | Category | Pattern | Port(s) | Addons | |---|-------------|----------|---------|---------|--------| @@ -30,6 +30,7 @@ ready for the sequential grind-driver pattern. | 8 | draw.io | Documentation-Tools | Official-image wrapper + auth proxy | 8080 | none (stateless) | | 9 | Windmill | Automation | Official-image wrapper + start.sh | 8000 | localstorage, postgresql | | 10 | Easy-Gate | Infrastructure | Multi-stage (Go) + auth proxy | 8080 | localstorage | +| 11 | Rathole | Infrastructure | Pre-compiled binaries + auth proxy | 8000, 2333, 5200-5299 | localstorage | Each package lives in `Package-Workspace///` and contains a `Dockerfile`, `CloudronManifest.json`, `README.md`, `CHANGELOG.md`, `logo.png`, @@ -118,7 +119,7 @@ Full write-ups of each pattern + challenges are in [`JOURNAL.md`](JOURNAL.md). | DevOps-Tools | 1 | 0/1 | | | Financial-Payments | 1 | 0/1 | | | Financial-Trading | 1 | 0/1 | | -| Infrastructure | 6 | 1/6 | easy-gate done | +| Infrastructure | 6 | 2/6 | easy-gate, rathole done | | Legal | 1 | 0/1 | | | Project-Management | 1 | 0/1 | | | Scientific-Computing | 2 | 0/2 | | @@ -132,7 +133,7 @@ Auth capability is a hard gate before packaging (see LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only (unacceptable / blocked-on-auth). -### Completed packages (10) +### Completed packages (11) | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| @@ -146,6 +147,7 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only | draw.io | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` (no users, stateless) | | Windmill | yes | no | ✅ preferred | **Packaged**; OIDC configured via Admin Settings UI (no env vars) | | Easy-Gate | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` (no user concept; IP-subnet groups only) | +| Rathole | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` on the status page; tunnels secured by mandatory per-service tokens (Noise/TLS optional) | ### Candidates researched