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:
+71
-1
@@ -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"]
|
||||
@@ -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 |
Executable
+40
@@ -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">▲ 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> — 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>
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user