feat: add FX Cloudron package (DevOps-Tools) [#640]

FX 0.9.48 ("poor man's function as a service") as the 13th package:
pre-compiled goreleaser release binary with sha256 pin on
cloudron/base:4.0.0. fx is a CLI with no user concept, so the package
is a workstation: pinned binary + persistent workspace
(functions/ssh/kube) driven from the Cloudron web terminal, with an
auth-proxied landing page as the only HTTP surface (httpAuth proxy).
Deploys target remote Docker hosts over key-based SSH or Kubernetes
via FX_KUBECONF. Build green; runtime smoke (landing page, workspace
seeding, fx -v) green. Docs gardened to 13 packages.

Ticket: https://projects.knownelement.com/issues/640
This commit is contained in:
2026-09-01 19:39:53 -05:00
parent 3d38c507e8
commit 10e2b7c7ed
12 changed files with 412 additions and 13 deletions
+71 -1
View File
@@ -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
@@ -0,0 +1 @@
repo/
@@ -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: <user>@<host> 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
@@ -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).
@@ -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 <user>@<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"
}
@@ -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_<tag>_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"]
+101
View File
@@ -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, `<user>@<host>`) 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)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+40
View File
@@ -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 <user>@<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
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FX</title>
<style>
body { font-family: -apple-system, "Segoe UI", Roboto, sans-serif; background: #14171c; color: #d8dee6; margin: 0; display: flex; min-height: 100vh; align-items: center; justify-content: center; }
main { max-width: 640px; padding: 2rem; }
h1 { color: #ffffff; font-size: 1.6rem; margin-bottom: 0.25rem; }
p.tagline { color: #7f8c9b; margin-top: 0; }
code { background: #1f242c; border: 1px solid #2d3440; border-radius: 4px; padding: 0.1rem 0.35rem; font-size: 0.85rem; color: #9ecbff; }
table { border-collapse: collapse; width: 100%; margin: 1rem 0; font-size: 0.9rem; }
th, td { text-align: left; padding: 0.5rem 0.75rem; border-bottom: 1px solid #2d3440; }
th { color: #7f8c9b; font-weight: 600; }
pre { background: #1f242c; border: 1px solid #2d3440; border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: 0.8rem; line-height: 1.5; }
.ok { color: #6bc46d; }
</style>
</head>
<body>
<main>
<h1>FX <span class="ok">&#9650; fx 0.9.48 ready</span></h1>
<p class="tagline">Poor man's function as a service</p>
<p>fx is a <strong>CLI, not a web app</strong> &mdash; 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 <strong>web
terminal</strong>: open the terminal and run <code>fx -v</code> 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 <em>target</em> you point fx at, never inside this
app.</p>
<table>
<tr><th>Path</th><th>Purpose</th></tr>
<tr><td><code>/app/data/functions/</code></td><td>Function sources (<code>hello.js</code> + <code>hello.py</code> starters seeded)</td></tr>
<tr><td><code>/app/data/ssh/</code></td><td>SSH keys for remote Docker targets (fx logs in with a key, no passwords)</td></tr>
<tr><td><code>/app/data/kube/</code></td><td>kubeconfig for Kubernetes targets</td></tr>
</table>
<p>Deploy to a remote Docker host (JS example):</p>
<pre>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</pre>
<p>Deploy to Kubernetes (copy your kubeconfig to
<code>/app/data/kube/config</code> first):</p>
<pre>export FX_KUBECONF=/app/data/kube/config
fx up --name hello /app/data/functions/hello.py</pre>
<p style="color:#7f8c9b;font-size:0.85rem;">Supported languages: Go,
JavaScript, Python, Ruby, Java, PHP, Perl, Crystal, Rust, Julia, D.
Upstream docs:
<a style="color:#9ecbff" href="https://github.com/metrue/fx">github.com/metrue/fx</a></p>
</main>
</body>
</html>
+6 -5
View File
@@ -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 |
+9 -7
View File
@@ -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/<Category>/<app>/` 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