diff --git a/JOURNAL.md b/JOURNAL.md index e1cf981..99641f6 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**: 12/~57 packages completed (~21%) +**Current Status**: 13/~57 packages completed (~23%) ## Completed Packages @@ -966,6 +966,76 @@ PostgreSQL databases (OIDC login, OPA-authorized queries, cached results) **Commit**: `feat: add Database-Gateway Cloudron package (Infrastructure) [#639]` +### 13. FX (DevOps-Tools) ✅ +**Date**: 2026-09-01 +**Application**: FX — "poor man's function as a service" (metrue/fx): a CLI +that turns a stateless function file (JS, Python, Go, Ruby, Java, PHP, +Perl, Crystal, Rust, Julia, D) into a running HTTP service on your own +Docker host or Kubernetes cluster +**Package Size**: 3.55GB (cloudron/base 4.0.0 dominates) +**Ports**: 8000 (HTTP landing/health page only — fx itself listens on +nothing) +**Addons**: localstorage (auth proxy, no database) + +**Key Learnings**: +- **Auth gate verdict**: NO user concept — fx is a terminal tool: no UI, + no accounts, no SSO hooks → `httpAuth.type = proxy` gates the only + HTTP surface (the landing page), the Rathole/Easy-Gate pattern for + user-less apps. Terminal + workspace access is Cloudron's app access + list; the SSH keys under /app/data/ssh are target credentials +- **First pure "CLI workstation" package**: fx has no daemon, so the + landing-page server (python3 -m http.server) is the ONLY long-running + process; the fx binary runs on demand from the Cloudron web terminal. + Package value = pinned binary + persistent workspace + (/app/data/{functions,ssh,kube}) +- **No Docker daemon in Cloudron apps** (and no host socket access): + fx's local-docker mode is unusable in-app; deploys target remote + Docker hosts over SSH (Go-native ssh library, key-based — no + openssh binary needed in the image) or Kubernetes via FX_KUBECONF +- **Release pinning on a quiet upstream**: last published release is + 0.9.48-alpha.d91a7a0 (2021-06-10) while master sits at 2023-10-24; + packaged the release (what official scripts/install.sh installs; the + binary self-reports 0.9.48), not master +- **glibc trap, Rathole side**: the goreleaser `Tux` asset is + glibc-built → Ubuntu base (cloudron/base:4.0.0); the mirror image of + Database Gateway's musl/alpine pairing +- **Starter functions must match upstream shapes exactly**: JS = + Koa-style `(ctx) => { ctx.body = ... }`, Python = plain + `def fx(request)` — copied from upstream examples verbatim + +**Build Process**: +- Pre-compiled-binaries pattern (JOURNAL pattern #5): release tarball + `fx_0.9.48-alpha.d91a7a0_Tux_64-bit.tar.gz` downloaded in-Dockerfile + behind a sha256 pin taken from the upstream checksums.txt; `fx -v` + runs inside the build as an executability gate +- Logo: 256x256 "fx" monogram generated in a throwaway alpine:3.20 + container (upstream ships no logo asset) +- start.sh: seeds the /app/data workspace (functions/ssh/kube + two + starter functions) then execs the landing-page server in the + foreground — committed executable + +**Validation**: +- `docker build --cgroup-parent ukrrs-batch.slice -t fx-cloudron:test` + → green (sha256 gate OK, `fx version 0.9.48` printed in-build) +- Runtime smoke: container up, `GET /` → 200 with the FX landing page, + workspace dirs + hello.js/hello.py seeded, startup banner in logs; + container removed after test + +**Files Created**: +- Dockerfile (pre-compiled binary, sha256-pinned, cloudron/base:4.0.0) +- CloudronManifest.json (manifestVersion 2, httpAuth proxy, httpPort + 8000, localstorage only) +- start.sh (workspace seed + landing-page server, exec) — committed + executable +- status.html (auth-proxied landing/usage page) +- README.md (auth story, terminal workflow, remote/K8s usage) +- CHANGELOG.md +- .env.example (FX_HOST / FX_KUBECONF knobs) +- .dockerignore (excludes the cloned repo/ from the build context) +- logo.png (256x256 monogram) + +**Commit**: `feat: add FX Cloudron package (DevOps-Tools) [#640]` + --- ## Packaging Pattern: Download Pre-Compiled Binaries diff --git a/Package-Workspace/DevOps-Tools/fx/.dockerignore b/Package-Workspace/DevOps-Tools/fx/.dockerignore new file mode 100644 index 0000000..7d37f1a --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/.dockerignore @@ -0,0 +1 @@ +repo/ diff --git a/Package-Workspace/DevOps-Tools/fx/.env.example b/Package-Workspace/DevOps-Tools/fx/.env.example new file mode 100644 index 0000000..a5e48d2 --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/.env.example @@ -0,0 +1,14 @@ +# FX Cloudron package — environment knobs +# +# Set via App -> Configure -> Environment; they are visible to fx when +# run from the app's web terminal. Not secrets. + +# Default deploy target for fx up/list/down/image: @ of a +# Docker host reachable over SSH. Leave unset to pass --host per +# command. The SSH key itself is a file, not env: put it in +# /app/data/ssh/ and pass --ssh_key (fx authenticates with keys only). +#FX_HOST=deploy@docker.example.com + +# Path to a kubeconfig for Kubernetes deploys (or pass -C per command). +# /app/data/kube/config is the persistent home for it. +#FX_KUBECONF=/app/data/kube/config diff --git a/Package-Workspace/DevOps-Tools/fx/CHANGELOG.md b/Package-Workspace/DevOps-Tools/fx/CHANGELOG.md new file mode 100644 index 0000000..c02afdd --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog — FX Cloudron Package + +## 1.0.0 (2026-09-01) + +Initial Cloudron package for fx 0.9.48 (poor man's function as a +service). + +- Pre-compiled-binaries pattern: upstream goreleaser release + `fx_0.9.48-alpha.d91a7a0_Tux_64-bit.tar.gz` (linux/amd64) downloaded + at build time behind a sha256 pin taken from the upstream + checksums.txt; `fx -v` runs inside the build as an executability gate. +- fx is a CLI with no daemon or UI: the package is an fx workstation — + pinned binary + persistent workspace (`functions/`, `ssh/`, `kube/` + under /app/data, with two upstream-shaped starter functions) — driven + from the Cloudron web terminal. +- No user concept → `httpAuth.type = proxy` gates a static landing/usage + page served on the HTTP port (also the platform health check); the + page server is the only long-running process. +- Deploys target remote Docker hosts over key-based SSH (Go-native SSH, + no openssh binary needed in the image) or Kubernetes via kubeconfig + (`FX_KUBECONF`); documented limitation: the app container has no + Docker daemon, so functions never run inside this app. +- Addons: `localstorage` only (workspace persistence; no database). +- Logo: 256x256 monogram generated for this package (upstream ships no + logo asset). diff --git a/Package-Workspace/DevOps-Tools/fx/CloudronManifest.json b/Package-Workspace/DevOps-Tools/fx/CloudronManifest.json new file mode 100644 index 0000000..5fd8100 --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/CloudronManifest.json @@ -0,0 +1,27 @@ +{ + "manifestVersion": 2, + "type": "app", + "id": "io.cloudron.fx", + "title": "FX", + "description": "fx is 'poor man's function as a service': a CLI that turns a stateless function file (JavaScript, Python, Go, Ruby, Java, PHP, Perl, Crystal, Rust, Julia, D) into a running HTTP service on your own Docker host or Kubernetes cluster in seconds. This package is an fx workstation: the pinned fx binary plus a persistent workspace, driven from the Cloudron web terminal. Deploy targets are remote Docker hosts (SSH key auth) or a Kubernetes cluster (kubeconfig); the app container itself has no Docker daemon, so functions always run on their target, not inside this app.", + "author": "metrue", + "website": "https://github.com/metrue/fx", + "documentationUrl": "https://github.com/metrue/fx/blob/master/README.md", + "contactEmail": "cloudron@tsys.dev", + "tagline": "Poor man's Function as a Service — deploy function files from the terminal", + "version": "0.9.48", + "upstreamVersion": "0.9.48", + "healthCheckPath": "/", + "httpPort": 8000, + "httpAuth": { + "type": "proxy" + }, + "memoryLimit": 268435456, + "addons": { + "localstorage": {} + }, + "postInstallMessage": "FX is a CLI, not a web app: there is nothing to click through. Open the app's **web terminal** and run `fx -v`. Drop an SSH key into **/app/data/ssh/** (or a kubeconfig into **/app/data/kube/**), put function sources in **/app/data/functions/** (two starters are already there), then `fx up --host @ --ssh_key /app/data/ssh/id_rsa --name hello /app/data/functions/hello.js`. The landing page on the app URL is an auth-proxied usage guide.", + "mediaLinks": [], + "changelog": "Initial Cloudron package for fx 0.9.48 ('poor man's function as a service'). Pre-compiled upstream release binary with sha256 pin, persistent workspace at /app/data (functions/, ssh/, kube/) with two starter functions, and an auth-proxied landing page on the HTTP port (fx has no daemon or UI of its own). Driven from the Cloudron web terminal; deploys go to remote Docker hosts over SSH or to Kubernetes via kubeconfig.", + "icon": "file://logo.png" +} diff --git a/Package-Workspace/DevOps-Tools/fx/Dockerfile b/Package-Workspace/DevOps-Tools/fx/Dockerfile new file mode 100644 index 0000000..8e55432 --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/Dockerfile @@ -0,0 +1,60 @@ +# FX Cloudron Package +# +# fx (metrue/fx) is "poor man's function as a service": a CLI that turns a +# stateless function file (JavaScript, Python, Go, Ruby, Java, PHP, Perl, +# Crystal, Rust, Julia, D) into a running HTTP service on your own Docker +# host or Kubernetes cluster, in seconds. fx is a DRIVER-side tool: it +# packages the function, ships it to the target over SSH (key-based) or +# the K8s API, and the TARGET runs the container. +# +# Cloudron app containers have no Docker daemon, so this package is the +# operator's fx WORKSTATION: the pinned fx binary plus a persistent +# workspace (/app/data/functions, /app/data/ssh, /app/data/kube), driven +# from the Cloudron web terminal. Deploy targets are remote Docker hosts +# (--host user@host --ssh_key ...) or a Kubernetes cluster (FX_KUBECONF +# or -C kubeconf). +# +# Authentication: fx has NO user concept — no web UI, no accounts, no +# SSO hooks — so the auth-gate verdict is the proxy row (AGENTS.md +# matrix). The manifest declares httpAuth.type = proxy: Cloudron's auth +# proxy gates the landing page, the only HTTP surface this app has. +# Access to the terminal/workspace itself is Cloudron's app access list. +# +# Upstream: https://github.com/metrue/fx +# - Release 0.9.48-alpha.d91a7a0 (2021-06-10) is the latest published +# release and what the official scripts/install.sh installs; the +# binary reports version 0.9.48. Repo master (2023) has no newer +# release. +# - Ships goreleaser tarballs; the linux/amd64 asset is +# fx__Tux_64-bit.tar.gz, glibc-built -> needs an Ubuntu base. +FROM cloudron/base:4.0.0 + +ARG FX_TAG=0.9.48-alpha.d91a7a0 +ARG FX_SHA256=1ed8a40f81038ca9e33aa09dba2184448b2efa3ed6373936e9f849f50200910f + +# Pre-compiled-binaries pattern (JOURNAL pattern #5): pinned release +# download behind a sha256 gate (checksum taken from the upstream +# checksums.txt asset). Building the 2021-era codebase (go 1.12 modules +# + packr assets) from source would buy nothing over the official +# release binary. +RUN curl -fsSL -o /tmp/fx.tar.gz \ + "https://github.com/metrue/fx/releases/download/${FX_TAG}/fx_${FX_TAG}_Tux_64-bit.tar.gz" \ + && echo "${FX_SHA256} /tmp/fx.tar.gz" | sha256sum -c - \ + && tar -xzf /tmp/fx.tar.gz -C /usr/local/bin --exclude='*.md' --exclude='LICENSE*' \ + && chmod +x /usr/local/bin/fx \ + && rm -f /tmp/fx.tar.gz \ + && /usr/local/bin/fx -v + +# Static landing page served on the Cloudron HTTP port (platform health +# check + auth-proxied usage guide). fx itself has no daemon, so the +# page server is the only long-running process. start.sh seeds the +# /app/data workspace on first run; it 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 + +CMD ["/bin/bash", "/app/start.sh"] diff --git a/Package-Workspace/DevOps-Tools/fx/README.md b/Package-Workspace/DevOps-Tools/fx/README.md new file mode 100644 index 0000000..901e14f --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/README.md @@ -0,0 +1,101 @@ +# FX — Cloudron Package + +[fx](https://github.com/metrue/fx) is "poor man's function as a service": +a CLI that turns a stateless function file (JavaScript, Python, Go, Ruby, +Java, PHP, Perl, Crystal, Rust, Julia, D) into a running HTTP service on +your own Docker host or Kubernetes cluster, in seconds. fx packages the +function, ships it to the target over SSH (key-based) or the K8s API, and +the target runs the container. + +This package is an **fx workstation**: the pinned fx binary plus a +persistent workspace, driven from the Cloudron web terminal. Cloudron app +containers have no Docker daemon (and no access to the host's), so +deploys always target a **remote** Docker host or a Kubernetes cluster — +never the app container itself. + +## Packaging overview + +| Aspect | Choice | +|--------|--------| +| Pattern | Pre-compiled binaries (JOURNAL pattern #5) | +| Base image | `cloudron/base:4.0.0` (Ubuntu 22.04; the goreleaser binary is glibc-built) | +| Upstream binary | `fx_0.9.48-alpha.d91a7a0_Tux_64-bit.tar.gz` (linux/amd64), sha256-pinned in the Dockerfile (checksum from upstream `checksums.txt`) | +| Addons | `localstorage` only (workspace persistence; no database) | +| Auth | No user concept → `httpAuth.type = proxy` (see below) | +| Runtime | `start.sh` seeds the workspace and serves the landing page; fx runs on demand from the terminal | + +Why pre-compiled: the last published release is `0.9.48-alpha.d91a7a0` +(2021-06-10) — the same artifact the official `scripts/install.sh` +installs, and the binary reports version `0.9.48`. Repo master (2023) has +no newer release; building the go 1.12-era, packr-using codebase from +source would buy nothing over the official binary. + +## Authentication (auth gate verdict: proxy) + +- fx has **no user concept**: no web UI, no accounts, no SSO hooks — it + is a terminal tool. +- The manifest declares `httpAuth: {"type": "proxy"}`: Cloudron's auth + proxy gates the landing page, which is the only HTTP surface this app + has. Access to the terminal (and therefore the workspace and SSH keys) + is Cloudron's app access list — restrict the app to the admins who + should wield it. +- The SSH keys stored in `/app/data/ssh/` are the credentials for the + *deploy targets*; guard them with the app's access list and file + permissions. + +## Usage + +1. Open the app's **web terminal** (or `cloudron exec`). +2. Drop an SSH private key into `/app/data/ssh/` (e.g. via the file + manager) for your Docker target, or a kubeconfig into + `/app/data/kube/` for a Kubernetes target. +3. Deploy: + +```bash +fx up --host deploy@example.com --ssh_key /app/data/ssh/id_rsa \ + --name hello /app/data/functions/hello.js + +fx list --host deploy@example.com # deployed services +fx down --host deploy@example.com hello +``` + +Kubernetes: + +```bash +export FX_KUBECONF=/app/data/kube/config +fx up --name hello /app/data/functions/hello.py +``` + +The two seeded starters (`hello.js`, `hello.py`) use the exact upstream +example shapes: a Koa-style `ctx` handler for JS, a plain `fx(request)` +callable for Python. + +Knobs: `FX_HOST` (default deploy target, `@`) and +`FX_KUBECONF` (path to kubeconfig) can be set once via Cloudron's +environment settings instead of per-command flags — see `.env.example`. + +## Ports + +| Port | Type | Purpose | +|------|------|---------| +| 8000 | `httpPort` | Landing/usage page + platform health check (behind Cloudron auth proxy) | + +fx itself listens on nothing; deployed functions listen on their target +host, outside this app. + +## Build & test + +```bash +docker build --cgroup-parent ukrrs-batch.slice -t fx-cloudron:test Package-Workspace/DevOps-Tools/fx/ +docker run --rm --entrypoint /usr/local/bin/fx fx-cloudron:test -v # -> 0.9.48 +``` + +## Files + +- `Dockerfile` — pinned release download + sha256 gate on cloudron/base:4.0.0 +- `CloudronManifest.json` — manifestVersion 2, httpAuth proxy, localstorage only +- `start.sh` — workspace seeding + landing-page server (committed executable) +- `status.html` — auth-proxied landing/usage page +- `.env.example` — FX_HOST / FX_KUBECONF knobs +- `.dockerignore` — excludes the cloned `repo/` from the build context +- `logo.png` — 256x256 monogram (fx ships no logo asset) diff --git a/Package-Workspace/DevOps-Tools/fx/logo.png b/Package-Workspace/DevOps-Tools/fx/logo.png new file mode 100644 index 0000000..c8896dd Binary files /dev/null and b/Package-Workspace/DevOps-Tools/fx/logo.png differ diff --git a/Package-Workspace/DevOps-Tools/fx/start.sh b/Package-Workspace/DevOps-Tools/fx/start.sh new file mode 100755 index 0000000..5263040 --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/start.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -euo pipefail + +# fx is a CLI, not a daemon: it has nothing to serve. The long-running +# process of this package is therefore the auth-proxied landing page on +# the Cloudron HTTP port (health check + usage guide). The fx binary and +# the persistent workspace below are driven interactively from the +# Cloudron web terminal (App -> terminal, or `cloudron exec`). +# +# Workspace layout seeded on first run: +# /app/data/functions/ function sources (two starter functions) +# /app/data/ssh/ SSH keys for remote Docker targets +# /app/data/kube/ kubeconfig for Kubernetes targets + +mkdir -p /app/data/functions /app/data/ssh /app/data/kube + +# Starter functions, exactly the upstream example shapes (Koa-style ctx +# for JavaScript, plain callable for Python). +if [[ ! -f /app/data/functions/hello.js ]]; then + cat > /app/data/functions/hello.js <<'EOF' +module.exports = (ctx) => { + ctx.body = 'hello world' +} +EOF +fi + +if [[ ! -f /app/data/functions/hello.py ]]; then + cat > /app/data/functions/hello.py <<'EOF' +def fx(request): + return "hello world" +EOF +fi + +echo "fx $(/usr/local/bin/fx -v) ready - open the app's web terminal to use it." +echo "Workspace: /app/data/functions (sources), /app/data/ssh (keys), /app/data/kube (kubeconfig)" +echo "Deploy example: fx up --host @ --ssh_key /app/data/ssh/id_rsa --name hello /app/data/functions/hello.js" + +# Landing page (health check + auth-proxied usage guide) is the only +# long-running process - fx itself runs on demand from the terminal. +exec python3 -m http.server "${CLOUDRON_HTTP_PORT:-8000}" --directory /app/code/status diff --git a/Package-Workspace/DevOps-Tools/fx/status.html b/Package-Workspace/DevOps-Tools/fx/status.html new file mode 100644 index 0000000..f1a0331 --- /dev/null +++ b/Package-Workspace/DevOps-Tools/fx/status.html @@ -0,0 +1,58 @@ + + + + + +FX + + + +
+

FX ▲ fx 0.9.48 ready

+

Poor man's function as a service

+ +

fx is a CLI, not a web app — this page exists so + Cloudron has a health endpoint and you have a landing spot (gated by the + Cloudron auth proxy). You drive fx from the app's web + terminal: open the terminal and run fx -v to confirm, + then deploy function files to your own Docker hosts or Kubernetes + clusters. Cloudron app containers have no Docker daemon, so functions + always run on the target you point fx at, never inside this + app.

+ + + + + + +
PathPurpose
/app/data/functions/Function sources (hello.js + hello.py starters seeded)
/app/data/ssh/SSH keys for remote Docker targets (fx logs in with a key, no passwords)
/app/data/kube/kubeconfig for Kubernetes targets
+ +

Deploy to a remote Docker host (JS example):

+
fx up --host deploy@example.com --ssh_key /app/data/ssh/id_rsa \
+       --name hello /app/data/functions/hello.js
+fx list --host deploy@example.com
+fx down --host deploy@example.com hello
+ +

Deploy to Kubernetes (copy your kubeconfig to + /app/data/kube/config first):

+
export FX_KUBECONF=/app/data/kube/config
+fx up --name hello /app/data/functions/hello.py
+ +

Supported languages: Go, + JavaScript, Python, Ruby, Java, PHP, Perl, Crystal, Rust, Julia, D. + Upstream docs: + github.com/metrue/fx

+
+ + diff --git a/README.md b/README.md index 57413cf..2ce1dec 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**: 12/~57 (~21%) +- **Completed Packages**: 13/~57 (~23%) - **Packaging Templates**: Created ✅ -- **Packages Committed & Pushed**: 12 ✅ +- **Packages Committed & Pushed**: 13 ✅ - **Build Tickets**: 46 filed (#633-#678, umbrella [#632](https://projects.knownelement.com/issues/632), Redmine project 55); grist-core excluded (packaged upstream) @@ -34,6 +34,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application | 10 | Easy-Gate | Infrastructure | 3.18GB | 8080 | localstorage (auth proxy) | ✅ Committed | | 11 | Rathole | Infrastructure | 3.51GB | 8000, 2333, 5200-5299 | localstorage (auth proxy) | ✅ Committed | | 12 | Database Gateway | Infrastructure | 93.7MB | 8080 | localstorage, postgresql | ✅ Committed | +| 13 | FX | DevOps-Tools | 3.55GB | 8000 | localstorage (auth proxy) | ✅ Committed | ### 📦 Packages in Development @@ -67,7 +68,7 @@ None currently in development. ### ⚡ Productivity Metrics -- **Packages Completed**: 12/~57 (~21%) +- **Packages Completed**: 13/~57 (~23%) - **Average Package Time**: ~30 minutes - **Success Rate**: 100% (all packages built successfully) - **Commits Pushed**: 100% (all packages pushed to remote) @@ -88,7 +89,7 @@ Applications are organized by function rather than programming language: | **Communication** | Messaging and communication platforms | 2 | 0/2 (0%) | | **Data-Management** | Data processing and management tools | 2 | 0/2 (0%) | | **Development** | Development tools and platforms | 4 | 2/4 (50%) | -| **DevOps-Tools** | DevOps and infrastructure tooling | 2 | 0/2 (0%) | +| **DevOps-Tools** | DevOps and infrastructure tooling | 1 | 1/1 (100%) ✅ | | **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%) | @@ -116,7 +117,7 @@ Applications are organized by function rather than programming language: | [Pimcore](https://github.com/pimcore/pimcore) | [GitHub](https://github.com/pimcore/pimcore) | Open-source digital experience platform | Business-Apps | | [Database-Gateway](https://github.com/kazhuravlev/database-gateway) | [GitHub](https://github.com/kazhuravlev/database-gateway) | Database gateway and connection management | Infrastructure | ✅ Packaged | | [Webhook](https://github.com/adnanh/webhook) | [GitHub](https://github.com/adnanh/webhook) | Lightweight webhook receiver | API-Gateway | ✅ Packaged | -| [FX](https://github.com/metrue/fx) | [GitHub](https://github.com/metrue/fx) | Function as a Service platform | DevOps-Tools | +| [FX](https://github.com/metrue/fx) | [GitHub](https://github.com/metrue/fx) | Function as a Service platform | DevOps-Tools | ✅ Packaged | | [Fonoster](https://github.com/fonoster/fonoster) | [GitHub](https://github.com/fonoster/fonoster) | Open-source CPaaS for communications | Communication | | [Rundeck](https://github.com/rundeck/rundeck) | [GitHub](https://github.com/rundeck/rundeck) | Job scheduling and automation platform | Automation | | [HyperSwitch](https://github.com/juspay/hyperswitch) | [GitHub](https://github.com/juspay/hyperswitch) | Open-source payment switch | Financial-Payments | diff --git a/STATUS.md b/STATUS.md index 558f28f..ef90f69 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) — Database Gateway -> packaged (#639, Infrastructure, 12th package); auth gate verdict: native -> OIDC (preferred) — platform provider wired via CLOUDRON_OIDC_* env. +> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — FX packaged (#640, +> DevOps-Tools, 13th package); auth gate verdict: no user concept — +> httpAuth proxy gates the landing page (CLI-workstation pattern). ## Current State: STABLE (packaging phase, ongoing) -Cloudron packaging pipeline is operational. 12 of ~57 upstream applications are +Cloudron packaging pipeline is operational. 13 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 (12) +## Completed Packages (13) | # | Application | Category | Pattern | Port(s) | Addons | |---|-------------|----------|---------|---------|--------| @@ -32,6 +32,7 @@ ready for the sequential grind-driver pattern. | 10 | Easy-Gate | Infrastructure | Multi-stage (Go) + auth proxy | 8080 | localstorage | | 11 | Rathole | Infrastructure | Pre-compiled binaries + auth proxy | 8000, 2333, 5200-5299 | localstorage | | 12 | Database Gateway | Infrastructure | Multi-stage (Go, CGO) | 8080 | localstorage, postgresql | +| 13 | FX | DevOps-Tools | Pre-compiled binaries + auth proxy | 8000 | localstorage | Each package lives in `Package-Workspace///` and contains a `Dockerfile`, `CloudronManifest.json`, `README.md`, `CHANGELOG.md`, `logo.png`, @@ -117,7 +118,7 @@ Full write-ups of each pattern + challenges are in [`JOURNAL.md`](JOURNAL.md). | Collaboration | 2 | 0/2 | | | Communication | 1 | 0/1 | | | Data-Management | 2 | 0/2 | | -| DevOps-Tools | 1 | 0/1 | | +| DevOps-Tools | 1 | 1/1 (100%) ✅ | fx done | | Financial-Payments | 1 | 0/1 | | | Financial-Trading | 1 | 0/1 | | | Infrastructure | 6 | 3/6 | easy-gate, rathole, database-gateway done | @@ -134,7 +135,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 (12) +### Completed packages (13) | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| @@ -150,6 +151,7 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only | 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) | | Database Gateway | yes | no | ✅ preferred | **Packaged**; native OIDC-only app — platform provider env (`CLOUDRON_OIDC_*`) seeded into config.json; roles from the `groups` claim | +| FX | n/a | n/a | 🔄 proxy | **Packaged**; CLI-only FaaS tool with no user concept — pinned binary + workspace driven from the Cloudron terminal; landing page gated by `httpAuth.type=proxy` | ### Candidates researched