diff --git a/JOURNAL.md b/JOURNAL.md index c24e9a5..d744f13 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**: 7/~57 packages completed (~12%) +**Current Status**: 10/~57 packages completed (~18%) ## Completed Packages @@ -770,6 +770,57 @@ Dockerfile **Commit**: `feat: add Windmill Cloudron package (Automation)` +### 10. Easy-Gate (Infrastructure) ✅ +**Date**: 2026-09-01 +**Application**: Easy Gate — web dashboard hub for self-hosted infrastructure +(config-file driven, real-time hot reload, IP-subnet group visibility) +**Package Size**: 3.18GB (cloudron/base 3.2.0 dominates) +**Port**: 8080 +**Addons**: localstorage (auth proxy, no database) + +**Key Learnings**: +- **Auth gate verdict**: Easy Gate has NO user model at all — visibility is + purely IP-subnet based (groups with CIDR ranges), no login/OIDC/LDAP + anywhere in the codebase → packaged with `httpAuth.type = proxy` (the + draw.io pattern for user-less apps) +- Multi-stage Go build from the cloned repo (Webhook pattern): + `golang:1.23-alpine` builder, `CGO_ENABLED=0 -trimpath -ldflags="-w -s"` + (mirrors upstream Makefile), static binary onto `cloudron/base:3.2.0` +- Config-driven design: the app re-parses `easy-gate.json` every second — + no restart needed on config edits; start.sh only seeds the first copy +- `behind_proxy: true` matters on Cloudron: group subnet matching uses + `X-Forwarded-For` (Cloudron's nginx passes the real client IP) +- No `.env.example` shipped: the only knob is the JSON config file itself + (documented in the package README instead) +- Package-root `.dockerignore` (`repo/.git`, `repo/.github`, ...) keeps the + cloned repo's git history out of the build context (webhook shipped + without one and paid the context-size cost) + +**Build Process**: +- Upstream `wiredlush/easy-gate` v2.0.3 cloned into `repo/` (gitignored) +- `go mod download` cached before `COPY repo/ .` for layer reuse +- Logo converted from upstream `assets/logo.svg` to a 234x256 PNG via + ImageMagick on the host +- start.sh: seeds `/app/data/easy-gate.json` on first run, then + `exec /usr/local/bin/easy-gate` (env `EASY_GATE_CONFIG_PATH`) + +**Validation**: +- `docker build --cgroup-parent ukrrs-batch.slice -t easy-gate-cloudron:test` → green +- Throwaway smoke container: `GET /` → HTTP 200, seeded config verified + (`behind_proxy: true`), container removed after test + +**Files Created**: +- Dockerfile (multi-stage Go build) +- CloudronManifest.json (port 8080, localstorage only, httpAuth proxy, + healthCheckPath /, 256MB memory) +- start.sh (first-run config seed) — committed executable +- README.md (auth story, config table, usage) +- CHANGELOG.md +- .dockerignore (build-context hygiene) +- logo.png (upstream logo.svg → PNG) + +**Commit**: `feat: add Easy-Gate Cloudron package (Infrastructure) [#651]` + --- ## Packaging Pattern: Download Pre-Compiled Binaries diff --git a/Package-Workspace/Infrastructure/easy-gate/.dockerignore b/Package-Workspace/Infrastructure/easy-gate/.dockerignore new file mode 100644 index 0000000..4bce12f --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/.dockerignore @@ -0,0 +1,4 @@ +repo/.git +repo/.github +repo/build +repo/dist diff --git a/Package-Workspace/Infrastructure/easy-gate/CHANGELOG.md b/Package-Workspace/Infrastructure/easy-gate/CHANGELOG.md new file mode 100644 index 0000000..e4c4fa1 --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog — Easy Gate Cloudron Package + +## 1.0.0 (2026-09-01) + +Initial Cloudron package for Easy Gate 2.0.3. + +- Multi-stage build: Go 1.23 builder (`CGO_ENABLED=0`, upstream Makefile + flags) producing a static binary on `cloudron/base:3.2.0`. +- `start.sh` seeds `/app/data/easy-gate.json` on first run with + `behind_proxy: true` (Cloudron nginx passes the real client IP via + `X-Forwarded-For` for group subnet matching), then execs the binary. +- `httpAuth.type = proxy`: Easy Gate has no user model, so Cloudron's + authentication proxy gates access. +- Addons: `localstorage` only (config persistence; no database). +- Logo converted from upstream `assets/logo.svg` to a 256px PNG. diff --git a/Package-Workspace/Infrastructure/easy-gate/CloudronManifest.json b/Package-Workspace/Infrastructure/easy-gate/CloudronManifest.json new file mode 100644 index 0000000..40f3073 --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/CloudronManifest.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "manifestVersion": 2, + "type": "app", + "id": "io.cloudron.easygate", + "title": "Easy Gate", + "description": "Easy Gate is a web application that serves as the central hub for your self-hosted infrastructure. Services and notes are parsed in real time from a JSON/YAML config file (hot reload, no restarts), and items can be assigned to user groups that only see them based on their IP subnet. No database required.", + "author": "wiredlush", + "website": "https://github.com/wiredlush/easy-gate", + "contactEmail": "cloudron@tsys.dev", + "tagline": "A gate to your self-hosted infrastructure", + "version": "2.0.3", + "healthCheckPath": "/", + "httpPort": 8080, + "httpAuth": { + "type": "proxy" + }, + "memoryLimit": 256, + "addons": { + "localstorage": true + }, + "mediaLinks": [], + "changelog": "Initial Cloudron package for Easy Gate 2.0.3. Config-driven dashboard hub with no user model, fronted by the Cloudron authentication proxy; configuration persists at /app/data/easy-gate.json with real-time hot reload.", + "icon": "file://logo.png" +} diff --git a/Package-Workspace/Infrastructure/easy-gate/Dockerfile b/Package-Workspace/Infrastructure/easy-gate/Dockerfile new file mode 100644 index 0000000..94fc5bf --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/Dockerfile @@ -0,0 +1,38 @@ +# Easy Gate Cloudron Package +# +# Easy Gate is a web dashboard that acts as the central hub for self-hosted +# infrastructure: services and notes are parsed in real time (hot reload, +# once per second) from a JSON/YAML config file, and items can be assigned +# to user groups which only see them based on their IP subnet. +# +# Upstream: https://github.com/wiredlush/easy-gate (v2.0.3, Go 1.23, Fiber) +# - Single static binary (CGO_ENABLED=0), listens on 0.0.0.0:8080 +# - No database, no user accounts, no migrations +# +# Authentication: Easy Gate has NO user concept (IP-subnet grouping only). +# Packaged behind Cloudron's authentication proxy (httpAuth.type = proxy). +FROM golang:1.23-alpine AS builder + +WORKDIR /easy-gate + +# Cache dependency downloads separately from source changes. +COPY repo/go.mod repo/go.sum ./ +RUN go mod download + +# Build the static binary (mirrors upstream Makefile flags). +COPY repo/ . +RUN CGO_ENABLED=0 go build -trimpath -ldflags="-w -s" -o build/easy-gate cmd/easy-gate/main.go + +FROM cloudron/base:3.2.0 + +COPY --from=builder /easy-gate/build/easy-gate /usr/local/bin/easy-gate + +# start.sh seeds /app/data/easy-gate.json on first run (behind_proxy: true) +# and execs the binary. Made executable on the host, not at build time. +COPY start.sh /app/start.sh + +WORKDIR /app/data + +EXPOSE 8080 + +CMD ["/bin/bash", "/app/start.sh"] diff --git a/Package-Workspace/Infrastructure/easy-gate/README.md b/Package-Workspace/Infrastructure/easy-gate/README.md new file mode 100644 index 0000000..9485727 --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/README.md @@ -0,0 +1,75 @@ +# Easy Gate Cloudron Package + +## Description + +Easy Gate is a simple web application that serves as the central hub for +your self-hosted infrastructure. Services and notes are parsed in real time +from a JSON/YAML configuration file — Easy Gate re-reads it every second, so +changes apply immediately without restarts. Services and notes can be +organized into categories and assigned to user groups, so items are shown +only to users matching specific IP subnets (e.g. LAN vs VPN). + +This package builds the upstream Go source (v2.0.3) as a static binary and +runs it on the Cloudron base image. + +## Authentication + +Easy Gate has **no built-in user model** — visibility is controlled by +IP-subnet groups, not accounts. This package therefore uses **Cloudron's +authentication proxy** (`httpAuth.type = proxy` in `CloudronManifest.json`). +The Cloudron admin restricts which platform users/groups may reach the app; +authorized users must present Cloudron credentials before the dashboard +loads. This is the recommended pattern for utility apps without their own +user directory. + +Because Cloudron fronts the app with its reverse proxy, the seeded config +sets `behind_proxy: true` so group matching uses the real client IP from +`X-Forwarded-For`. + +## Features + +- Real-time config parsing (JSON or YAML) with no application restarts +- Group-based visibility of services and notes by client IP subnet +- Service categories, themes, and custom CSS support +- Standalone static Go binary with no external dependencies +- No database required + +## Configuration + +### Ports +- **8080**: Easy Gate HTTP (the only exposed port) + +### Config file +All configuration lives in **`/app/data/easy-gate.json`** (created with a +sane default on first start). Edit it with the Cloudron file manager; +changes are picked up within a second. Key options: + +| Option | Purpose | +|--------|---------| +| `title` | Dashboard title | +| `theme.background` / `theme.foreground` | Colors; or `theme.custom_css` for a custom stylesheet | +| `groups[].name` / `groups[].subnet` | Groups defined by client IP subnet (CIDR) | +| `services[]` | Entries: `name`, `url`, `category`, `groups`, `icon` | +| `notes[]` | Entries: `name`, `text`, `groups` | +| `behind_proxy` | Keep `true` on Cloudron (real client IP via X-Forwarded-For) | + +Items with an empty `groups` list are visible to everyone (whoever passes +the Cloudron auth proxy). + +### Storage +- **`/app/data`** (localstorage addon) holds the config file. Nothing else + is persisted; no database addon is used. + +## Usage + +1. Install the package on Cloudron. +2. In the Cloudron access control, grant the desired users/groups access. +3. Open the app location — you'll be prompted for Cloudron credentials. +4. Edit `/app/data/easy-gate.json` to list your services and notes; the + dashboard updates within a second. + +## Upstream + +- **Repository**: https://github.com/wiredlush/easy-gate +- **Version packaged**: 2.0.3 (Go 1.23, Fiber) +- **License**: MIT diff --git a/Package-Workspace/Infrastructure/easy-gate/logo.png b/Package-Workspace/Infrastructure/easy-gate/logo.png new file mode 100644 index 0000000..3ee2e45 Binary files /dev/null and b/Package-Workspace/Infrastructure/easy-gate/logo.png differ diff --git a/Package-Workspace/Infrastructure/easy-gate/start.sh b/Package-Workspace/Infrastructure/easy-gate/start.sh new file mode 100755 index 0000000..6fbf73f --- /dev/null +++ b/Package-Workspace/Infrastructure/easy-gate/start.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -euo pipefail + +# Easy Gate is entirely config-file driven. The config lives in /app/data so +# it survives restarts and updates; seed a Cloudron-friendly default on first +# run. "behind_proxy" is true because Cloudron fronts the app with its nginx: +# X-Forwarded-For carries the real client IP, which the group subnet matching +# relies on. + +export EASY_GATE_CONFIG_PATH="/app/data/easy-gate.json" + +if [[ ! -f "${EASY_GATE_CONFIG_PATH}" ]]; then + cat > "${EASY_GATE_CONFIG_PATH}" <<'EOF' +{ + "addr": "0.0.0.0:8080", + "use_tls": false, + "cert_file": "", + "key_file": "", + "behind_proxy": true, + "title": "Easy Gate", + "theme": { + "background": "#FFFFFF", + "foreground": "#000000" + }, + "groups": [ + { + "name": "lan", + "subnet": "192.168.0.0/16" + } + ], + "services": [ + { + "name": "Cloudron", + "category": "Platform", + "url": "https://my.example.com", + "groups": [] + } + ], + "notes": [ + { + "name": "How to configure", + "text": "Edit /app/data/easy-gate.json with the Cloudron file manager. Easy Gate re-parses the config every second: changes apply immediately, no restart needed.", + "groups": [] + } + ] +} +EOF + echo "Seeded default config at ${EASY_GATE_CONFIG_PATH}" +fi + +exec /usr/local/bin/easy-gate diff --git a/README.md b/README.md index 554a39b..c79a21c 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**: 9/~57 (~16%) +- **Completed Packages**: 10/~57 (~18%) - **Packaging Templates**: Created ✅ -- **Packages Committed & Pushed**: 9 ✅ +- **Packages Committed & Pushed**: 10 ✅ - **Build Tickets**: 46 filed (#633-#678, umbrella [#632](https://projects.knownelement.com/issues/632), Redmine project 55); grist-core excluded (packaged upstream) @@ -31,6 +31,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application | 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 | +| 10 | Easy-Gate | Infrastructure | 3.18GB | 8080 | localstorage (auth proxy) | ✅ Committed | ### 📦 Packages in Development @@ -64,7 +65,7 @@ None currently in development. ### ⚡ Productivity Metrics -- **Packages Completed**: 9/~57 (~16%) +- **Packages Completed**: 10/~57 (~18%) - **Average Package Time**: ~30 minutes - **Success Rate**: 100% (all packages built successfully) - **Commits Pushed**: 100% (all packages pushed to remote) @@ -89,7 +90,7 @@ Applications are organized by function rather than programming language: | **Documentation-Tools** | Documentation and diagramming tools | 3 | 1/3 (33%) | | **Financial-Payments** | Payment processing and financial infrastructure | 1 | 0/1 (0%) | | **Financial-Trading** | Trading and financial algorithm platforms | 1 | 0/1 (0%) | -| **Infrastructure** | Infrastructure and networking tools | 6 | 0/6 (0%) | +| **Infrastructure** | Infrastructure and networking tools | 6 | 1/6 (17%) | | **Legal** | Legal and compliance applications | 1 | 0/1 (0%) | | **Low-Code** | Low-code and no-code platforms | 3 | 1/3 (33%) | | **Monitoring** | Monitoring and observability tools | 6 | 1/6 (17%) | @@ -127,7 +128,7 @@ Applications are organized by function rather than programming language: | [NetBox](https://github.com/netbox-community/netbox) | [GitHub](https://github.com/netbox-community/netbox) | IP address management (IPAM) and data center infrastructure management | Infrastructure | | [SeaTunnel](https://github.com/apache/seatunnel) | [GitHub](https://github.com/apache/seatunnel) | Data integration and streaming platform | Data-Management | | [Rathole](https://github.com/rapiz1/rathole) | [GitHub](https://github.com/rapiz1/rathole) | Lightweight and high-performance reverse proxy | Infrastructure | -| [Easy-Gate](https://github.com/wiredlush/easy-gate) | [GitHub](https://github.com/wiredlush/easy-gate) | Gateway and proxy solution | Infrastructure | +| [Easy-Gate](https://github.com/wiredlush/easy-gate) | [GitHub](https://github.com/wiredlush/easy-gate) | Gateway and proxy solution | Infrastructure | ✅ Packaged | | [Huginn](https://github.com/huginn/huginn) | [GitHub](https://github.com/huginn/huginn) | Agents that do things for you automatically | Automation | | [ConsulDemocracy](https://github.com/consuldemocracy/consuldemocracy) | [GitHub](https://github.com/consuldemocracy/consuldemocracy) | Open-source citizen participation platform | Collaboration | | [BOINC](https://github.com/BOINC/boinc) | [GitHub](https://github.com/BOINC/boinc) | Open-source software for volunteer computing | Scientific-Computing | diff --git a/STATUS.md b/STATUS.md index 37aecaa..2e0d883 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) — 46 build tickets filed -> (#633-#678, umbrella #632, Redmine project 55); clone-repos.sh repaired -> and re-run; Cloudron redis-addon correction (NetBox re-rated viable). +> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — Easy-Gate packaged +> (#651, Infrastructure, 10th package); auth gate verdict: no user concept, +> shipped behind the Cloudron auth proxy. ## Current State: STABLE (packaging phase, ongoing) -Cloudron packaging pipeline is operational. 9 of ~57 upstream applications are +Cloudron packaging pipeline is operational. 10 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 (9) +## Completed Packages (10) | # | Application | Category | Pattern | Port(s) | Addons | |---|-------------|----------|---------|---------|--------| @@ -29,6 +29,7 @@ ready for the sequential grind-driver pattern. | 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 | +| 10 | Easy-Gate | Infrastructure | Multi-stage (Go) + auth proxy | 8080 | 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). | DevOps-Tools | 1 | 0/1 | | | Financial-Payments | 1 | 0/1 | | | Financial-Trading | 1 | 0/1 | | -| Infrastructure | 6 | 0/6 | | +| Infrastructure | 6 | 1/6 | easy-gate done | | Legal | 1 | 0/1 | | | Project-Management | 1 | 0/1 | | | Scientific-Computing | 2 | 0/2 | | @@ -131,7 +132,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 (9) +### Completed packages (10) | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| @@ -144,6 +145,7 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only | 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) | +| Easy-Gate | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` (no user concept; IP-subnet groups only) | ### Candidates researched