From 10e558500f32343ea375f95dc417243aa7d88db0 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Thu, 30 Jul 2026 16:15:23 -0500 Subject: [PATCH] feat: add Windmill Cloudron package (Automation) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windmill is an open-source workflow-automation / internal-apps platform that turns scripts (Python, JS/TS, Go, Bash, SQL, Rust, ...) into HTTP endpoints, scheduled jobs, and visual flows. It is PostgreSQL-only — it uses Postgres LISTEN/NOTIFY for job queuing, so no Redis is required, making it a clean Cloudron fit. - Wraps the official ghcr.io/windmill-labs/windmill:1.514.1 image in single-container server mode (embedded default worker) - start.sh composes DATABASE_URL from the Cloudron postgresql addon and waits for the DB (bash /dev/tcp, no pg_isready dependency) - HTTP port 8000, health check on /api/version, 2GB memory limit - OIDC/SAML supported via the in-app Admin Settings UI (post-install) - Validated end-to-end: throwaway postgres + windmill ran migrations and returned /api/version => "CE v1.514.1", HTTP 200 Gardening: STATUS/README/JOURNAL updated (9/~57 packaged; Automation 1/4). Windmill logged as a new OIDC-preferred completed package. 💘 Generated with Crush Assisted-by: Crush:glm-5.2 --- JOURNAL.md | 49 +++++++++++ .../Automation/windmill/.env.example | 5 ++ .../Automation/windmill/CHANGELOG.md | 11 +++ .../Automation/windmill/CloudronManifest.json | 25 ++++++ .../Automation/windmill/Dockerfile | 25 ++++++ .../Automation/windmill/README.md | 78 ++++++++++++++++++ .../Automation/windmill/logo.png | Bin 0 -> 13682 bytes .../Automation/windmill/start.sh | 25 ++++++ README.md | 9 +- STATUS.md | 22 ++--- 10 files changed, 235 insertions(+), 14 deletions(-) create mode 100644 Package-Workspace/Automation/windmill/.env.example create mode 100644 Package-Workspace/Automation/windmill/CHANGELOG.md create mode 100644 Package-Workspace/Automation/windmill/CloudronManifest.json create mode 100644 Package-Workspace/Automation/windmill/Dockerfile create mode 100644 Package-Workspace/Automation/windmill/README.md create mode 100644 Package-Workspace/Automation/windmill/logo.png create mode 100755 Package-Workspace/Automation/windmill/start.sh diff --git a/JOURNAL.md b/JOURNAL.md index ce5479b..c24e9a5 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -723,6 +723,55 @@ Dockerfile --- +### 9. Windmill (Automation) ✅ +**Date**: 2026-07-30 +**Application**: Windmill — open-source workflow automation / internal-apps platform +**Package Size**: ~2GB (bundles Python, Go, Rust runtimes for user scripts) +**Port**: 8000 +**Addons**: localstorage, postgresql + +**Key Learnings**: +- Official-image wrapper around `ghcr.io/windmill-labs/windmill:1.514.1` +- **PostgreSQL-only**: Windmill uses Postgres `LISTEN/NOTIFY` for job queuing, + so **no Redis is required** (unlike NetBox). This makes it a clean Cloudron fit. +- Single-container **server mode** embeds a default worker (no separate worker + container needed) +- `DATABASE_URL` is composed at runtime in `start.sh` from the Cloudron + PostgreSQL addon env vars — Windmill has no per-var DB config, just the URI +- **OIDC/SAML are configured in the in-app Admin Settings UI** (persisted to + the DB), not via environment variables — so the package supports OIDC but + the admin enables it post-install + +**Build Process**: +- Base: `ghcr.io/windmill-labs/windmill:1.514.1` (pinned, verified) +- Image config inspected (no full pull) via `docker buildx imagetools inspect` + to confirm WorkingDir `/usr/src/app`, binary `windmill` on PATH, port 8000 +- `start.sh` waits for Postgres (bash `/dev/tcp`, no `pg_isready` dependency), + then `exec windmill` +- Logo extracted from inside the image (`/static_frontend/logo.svg`) and + converted to PNG with ImageMagick + +**Validation (full integration test)**: +- `docker build` → success +- Ran a throwaway `postgres:14-alpine` + the windmill image on a shared network +- Migrations completed (`v2 finalization step successfully applied`) +- `GET /api/version` → `CE v1.514.1`, HTTP 200 ✅ +- Non-fatal: logs an embeddings-DB error when no AI API key is set (expected; + Windmill runs fine without AI embeddings) + +**Files Created**: +- Dockerfile (official-image wrapper) +- CloudronManifest.json (port 8000, postgresql + localstorage, healthCheckPath /api/version, 2GB memory) +- start.sh (DB wait + DATABASE_URL composition) — committed executable +- README.md (OIDC post-install setup, features, addons) +- CHANGELOG.md +- .env.example +- logo.png (brand icon from upstream image, SVG→PNG) + +**Commit**: `feat: add Windmill Cloudron package (Automation)` + +--- + ## Packaging Pattern: Download Pre-Compiled Binaries ### When to Use diff --git a/Package-Workspace/Automation/windmill/.env.example b/Package-Workspace/Automation/windmill/.env.example new file mode 100644 index 0000000..4051c83 --- /dev/null +++ b/Package-Workspace/Automation/windmill/.env.example @@ -0,0 +1,5 @@ +# Windmill derives DATABASE_URL from the Cloudron PostgreSQL addon at runtime. +# Only MODE is overridable; the default (server) embeds a worker. + +# Run mode: server (server + default worker), worker, or indexer. +MODE=server diff --git a/Package-Workspace/Automation/windmill/CHANGELOG.md b/Package-Workspace/Automation/windmill/CHANGELOG.md new file mode 100644 index 0000000..9983044 --- /dev/null +++ b/Package-Workspace/Automation/windmill/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +## 1.514.1 — Initial Cloudron package + +- First Cloudron package for Windmill +- Wraps the official `ghcr.io/windmill-labs/windmill:1.514.1` image +- Single-container server mode (embedded default worker) +- PostgreSQL-backed via the Cloudron `postgresql` addon (no Redis required) +- `start.sh` derives `DATABASE_URL` from Cloudron env and waits for the DB +- HTTP port 8000, health check on `/api/version` +- OIDC/SAML supported via the in-app Admin Settings UI (post-install config) diff --git a/Package-Workspace/Automation/windmill/CloudronManifest.json b/Package-Workspace/Automation/windmill/CloudronManifest.json new file mode 100644 index 0000000..96eacf5 --- /dev/null +++ b/Package-Workspace/Automation/windmill/CloudronManifest.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "manifestVersion": 2, + "type": "app", + "id": "io.cloudron.windmill", + "title": "Windmill", + "description": "Windmill is an open-source workflow automation platform. Turn scripts (Python, JS/TS, Go, Bash, SQL, PHP, Rust, PowerShell) into sharable HTTP endpoints and background jobs, chain them into flows, and build internal apps on top. Uses PostgreSQL for state and queuing (no Redis required).", + "author": "Windmill Labs", + "website": "https://www.windmill.dev", + "contactEmail": "cloudron@tsys.dev", + "tagline": "Open-source workflow automation and internal apps platform", + "version": "1.514.1", + "healthCheckPath": "/api/version", + "httpPort": 8000, + "memoryLimit": 2048, + "addons": { + "localstorage": true, + "postgresql": { + "version": "14" + } + }, + "mediaLinks": [], + "changelog": "Initial Cloudron package for Windmill. PostgreSQL-backed (no Redis); single-container server mode with embedded worker. OIDC/SAML supported via the in-app Admin Settings.", + "icon": "file://logo.png" +} diff --git a/Package-Workspace/Automation/windmill/Dockerfile b/Package-Workspace/Automation/windmill/Dockerfile new file mode 100644 index 0000000..42f6ecb --- /dev/null +++ b/Package-Workspace/Automation/windmill/Dockerfile @@ -0,0 +1,25 @@ +# Windmill Cloudron Package +# +# Windmill is an open-source workflow automation platform (scripts, flows, +# apps, schedules) that turns scripts into sharable HTTP endpoints and +# background jobs. The server embeds a default worker for single-container use. +# +# Upstream image: ghcr.io/windmill-labs/windmill:1.514.1 +# - WorkingDir /usr/src/app, binary `windmill` on PATH, listens on 8000 +# - Requires PostgreSQL (job queue uses Postgres LISTEN/NOTIFY; NO Redis) +# - Auto-runs SQL migrations on startup +# +# Authentication: Windmill supports OIDC and SAML natively. OIDC is configured +# in the Admin Settings UI (persisted in the database), not via env vars. See +# README.md for the post-install OIDC setup steps. +FROM ghcr.io/windmill-labs/windmill:1.514.1 + +ENV MODE=server + +# start.sh builds DATABASE_URL from the Cloudron PostgreSQL addon, waits for +# the DB, then execs the windmill server. Made executable on the host. +COPY start.sh /app/start.sh + +EXPOSE 8000 + +CMD ["/bin/bash", "/app/start.sh"] diff --git a/Package-Workspace/Automation/windmill/README.md b/Package-Workspace/Automation/windmill/README.md new file mode 100644 index 0000000..2bb63a8 --- /dev/null +++ b/Package-Workspace/Automation/windmill/README.md @@ -0,0 +1,78 @@ +# Windmill Cloudron Package + +## Description + +Windmill is an open-source developer platform to turn scripts into workflows +and internal apps. Write scripts in Python, JavaScript/TypeScript, Go, Bash, +SQL, PHP, Rust, PowerShell, or Deno; Windmill turns them into sharable HTTP +endpoints, cron-scheduled jobs, and steps in visual **Flows**. It also +generates internal apps from those flows. + +This package wraps the official `ghcr.io/windmill-labs/windmill` image in +single-container **server mode** (the server embeds a default worker, so no +separate worker container is needed). + +State lives entirely in **PostgreSQL** (Cloudron `postgresql` addon). Windmill +uses Postgres `LISTEN/NOTIFY` for job queuing, so **no Redis is required**. + +## Authentication + +Windmill supports **OIDC** and **SAML** natively. Unlike many apps, these are +configured in the **in-app Admin Settings UI** (persisted in the database), +not via environment variables. + +### Post-install OIDC setup (recommended) + +1. Open the Windmill app and sign in as the bootstrap superadmin (the first run + prints a `SUPERADMIN_SECRET` / creates an admin — see Windmill docs). +2. Go to **Admin Settings → Auth → OIDC**. +3. Enter your identity provider details (Cloudron's OIDC provider issuer, + client ID, and client secret). The platform OIDC issuer / client creds come + from your Cloudron instance's app SSO configuration. +4. Save; users can then log in via OIDC. + +> OIDC is the preferred auth path for this app. Until OIDC is configured, + access is limited to the local superadmin account. + +## Features + +- **Scripts to endpoints**: any script becomes a typed HTTP API + background job +- **Flows**: visually chain scripts with branching, loops, retries, error handling +- **Schedules**: cron-based job scheduling +- **Apps**: generate internal UIs from flows +- **Multi-language**: Python, JS/TS, Go, Bash, SQL, PHP, Rust, PowerShell, Deno +- **Secrets**: encrypted secret management with inheritance +- **Queuing**: Postgres `LISTEN/NOTIFY` (no external broker) + +## Configuration + +### Ports +- **8000**: Windmill web UI + REST API + +### Addons +- **postgresql** (v14): all persistent state, jobs, flows, users, queue +- **localstorage** (`/app/data`): ephemeral job working files + +### Environment Variables +The `start.sh` entrypoint derives `DATABASE_URL` automatically from the +Cloudron PostgreSQL addon. The only fixed knob is: + +| Variable | Default | Purpose | +|----------|---------|---------| +| `MODE` | `server` | Run mode (server embeds a default worker) | + +`DATABASE_URL` is composed at runtime as +`postgres://$USER:$PASS@$HOST:$PORT/$DB?sslmode=disable`. + +## Usage + +1. Install the package on Cloudron (provisions a PostgreSQL database). +2. On first boot, Windmill runs migrations and bootstraps a superadmin. +3. Sign in, then immediately configure OIDC under Admin Settings (above). +4. Create a script, expose it as a flow/app, schedule it, or call its HTTP endpoint. + +## Upstream + +- **Repository**: https://github.com/windmill-labs/windmill +- **Image**: `ghcr.io/windmill-labs/windmill:1.514.1` +- **Docs**: https://www.windmill.dev/docs diff --git a/Package-Workspace/Automation/windmill/logo.png b/Package-Workspace/Automation/windmill/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0abb8df09c0e3cdf83abf09b7b756b6233867108 GIT binary patch literal 13682 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 SNK(Kb0#ubW6l>+d5&r{bHPAEw literal 0 HcmV?d00001 diff --git a/Package-Workspace/Automation/windmill/start.sh b/Package-Workspace/Automation/windmill/start.sh new file mode 100755 index 0000000..a896972 --- /dev/null +++ b/Package-Workspace/Automation/windmill/start.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -euo pipefail + +# Build the PostgreSQL connection URL from the Cloudron postgresql addon. +export DATABASE_URL="postgres://${CLOUDRON_POSTGRESQL_USERNAME}:${CLOUDRON_POSTGRESQL_PASSWORD}@${CLOUDRON_POSTGRESQL_HOST}:${CLOUDRON_POSTGRESQL_PORT}/${CLOUDRON_POSTGRESQL_DATABASE}?sslmode=disable" + +# Single-container server mode (server embeds a default worker). +export MODE="${MODE:-server}" + +# Wait for PostgreSQL to accept connections before starting. Windmill runs SQL +# migrations on startup, so the DB must be reachable. Uses bash /dev/tcp (no +# pg_isready dependency). +echo "Waiting for PostgreSQL at ${CLOUDRON_POSTGRESQL_HOST}:${CLOUDRON_POSTGRESQL_PORT} ..." +for i in $(seq 1 60); do + if (exec 3<>"/dev/tcp/${CLOUDRON_POSTGRESQL_HOST}/${CLOUDRON_POSTGRESQL_PORT}") 2>/dev/null; then + exec 3>&- 3<&- || true + echo "PostgreSQL is reachable." + break + fi + echo " not ready yet, retrying in 2s ($i/60)" + sleep 2 +done + +cd /usr/src/app +exec windmill diff --git a/README.md b/README.md index ffa6595..43cc97c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application ### 📊 Current Progress - **Total Applications**: ~57 (see [GitUrlList.txt](GitUrlList.txt)) -- **Completed Packages**: 8/~57 (~14%) +- **Completed Packages**: 9/~57 (~16%) - **Packaging Templates**: Created ✅ - **Packages Committed & Pushed**: 7 ✅ @@ -27,6 +27,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application | 6 | Puter | Development | 361MB | 4100 | localstorage, postgresql | ✅ Committed | | 7 | Corteza | Low-Code | 436MB | 80 | localstorage, postgresql | ✅ Committed | | 8 | draw.io | Documentation-Tools | — | 8080 | none (auth proxy) | ✅ Committed | +| 9 | Windmill | Automation | ~2GB | 8000 | localstorage, postgresql | ✅ Committed | ### 📦 Packages in Development @@ -60,7 +61,7 @@ None currently in development. ### ⚡ Productivity Metrics -- **Packages Completed**: 8/~57 (~14%) +- **Packages Completed**: 9/~57 (~16%) - **Average Package Time**: ~30 minutes - **Success Rate**: 100% (all packages built successfully) - **Commits Pushed**: 100% (all packages pushed to remote) @@ -75,7 +76,7 @@ Applications are organized by function rather than programming language: | Functional Category | Description | App Count | Packages Completed | |---|---|---|---| | **API-Gateway** | API management and gateway solutions | 2 | 2/2 (100%) ✅ | -| **Automation** | Workflow automation and scripting tools | 4 | 0/4 (0%) | +| **Automation** | Workflow automation and scripting tools | 4 | 1/4 (25%) | | **Business-Apps** | Enterprise business applications | 9 | 0/9 (0%) | | **Collaboration** | Team collaboration and communication | 2 | 0/2 (0%) | | **Communication** | Messaging and communication platforms | 2 | 0/2 (0%) | @@ -151,7 +152,7 @@ Applications are organized by function rather than programming language: | [SDRangel](https://github.com/f4exb/sdrangel) | [GitHub](https://github.com/f4exb/sdrangel) | Software defined radio application | Infrastructure | | [No-Code Architects Toolkit](https://github.com/stephengpope/no-code-architects-toolkit) | [GitHub](https://github.com/stephengpope/no-code-architects-toolkit) | No-code development toolkit | Low-Code | | [Warp](https://github.com/sebo-b/warp) | [GitHub](https://github.com/sebo-b/warp) | Terminal and shell enhancement tool | Development | | -| [Windmill](https://github.com/windmill-labs/windmill) | [GitHub](https://github.com/windmill-labs/windmill) | Open-source workflow automation platform | Automation | +| [Windmill](https://github.com/windmill-labs/windmill) | [GitHub](https://github.com/windmill-labs/windmill) | Open-source workflow automation platform | Automation | ✅ Packaged | | [Corteza](https://github.com/cortezaproject/corteza) | [GitHub](https://github.com/cortezaproject/corteza) | Open-source low-code platform | Low-Code | | [Security Awareness Training](https://github.com/security-companion/security-awareness-training) | [GitHub](https://github.com/security-companion/security-awareness-training) | Security awareness training platform | Security | | [Comply](https://github.com/strongdm/comply) | [GitHub](https://github.com/strongdm/comply) | Compliance and audit management | Security | diff --git a/STATUS.md b/STATUS.md index 815017b..b4eb30f 100644 --- a/STATUS.md +++ b/STATUS.md @@ -3,16 +3,16 @@ > **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-07-30 by Crush (GLM-5.2) — draw.io packaged (auth-proxy -> pattern); mandatory auth policy established. +> **Last updated:** 2026-07-30 by Crush (GLM-5.2) — Windmill packaged (OIDC, +> PostgreSQL, no Redis); draw.io + Windmill validated end-to-end with docker. ## Current State: STABLE (packaging phase, ongoing) -Cloudron packaging pipeline is operational. 8 of ~57 upstream applications are +Cloudron packaging pipeline is operational. 9 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. -## Completed Packages (8) +## Completed Packages (9) | # | Application | Category | Pattern | Port(s) | Addons | |---|-------------|----------|---------|---------|--------| @@ -24,6 +24,7 @@ patterns. The gardening protocol (this file + AGENTS.md) keeps docs in sync. | 6 | Puter | Development | Multi-stage (Node.js) | 4100 | localstorage, postgresql | | 7 | Corteza | Low-Code | Pre-compiled binaries | 80 | localstorage, postgresql | | 8 | draw.io | Documentation-Tools | Official-image wrapper + auth proxy | 8080 | none (stateless) | +| 9 | Windmill | Automation | Official-image wrapper + start.sh | 8000 | localstorage, postgresql | Each package lives in `Package-Workspace///` and contains a `Dockerfile`, `CloudronManifest.json`, `README.md`, `CHANGELOG.md`, `logo.png`, @@ -49,7 +50,7 @@ Full write-ups of each pattern + challenges are in [`JOURNAL.md`](JOURNAL.md). | Documentation-Tools | 3 | 2/3 | wireviz-web, draw.io done | | Low-Code | 3 | 1/3 | corteza done | | Monitoring | 6 | 1/6 | healthchecks done | -| Automation | 4 | 0/4 | | +| Automation | 4 | 1/4 | windmill done | | Business-Apps | 8 | 0/8 | | | Collaboration | 2 | 0/2 | | | Communication | 1 | 0/1 | | @@ -71,7 +72,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 (7) +### Completed packages (9) | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| @@ -82,21 +83,22 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only | WireViz Web | n/a | n/a | 🔄 proxy-eligible | Stateless, no users; **auth-gap: needs `httpAuth` proxy added** | | Puter | no | no | ❌ risk | Own user system, no SSO federation — needs revisit | | Corteza | yes | no | ✅ preferred | Native OIDC via `auth.external.providers.openid-connect.*` | +| 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) | ### Candidates researched | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| -| docker-drawio | n/a | n/a | 🔄 proxy-eligible | Stateless diagramming; package with `httpAuth` proxy | -| Windmill | yes | no | ✅ preferred | OIDC native; configured via Admin Settings UI (no env vars) | | NetBox | yes | yes | ✅ auth, ❌ Redis | OIDC+LDAP native, but HARD Redis dep (Cloudron has none) — Complex | | Gophish | no | no | ❌ blocked | Local admin login only, no SSO — do not package until auth added | -**Immediate queue:** Windmill (OIDC). +**Immediate queue:** research next OIDC/auth-proxy candidates (Sentry, SigNoz, +Langfuse, Fleet, InvenTree, GoAlert) and pick the cleanest wins. **Deferred:** NetBox (bundle Valkey+supervisor — significant), Gophish (blocked-on-auth). **Tech debt:** add `httpAuth` proxy to Webhook + WireViz Web (stateless apps); -revise Puter auth. draw.io ✅ packaged with auth proxy. +revise Puter auth. ## Known Issues