diff --git a/.opencode/command/libs-update-app.md b/.opencode/command/libs-update-app.md index 6ededf522..cd89ff7c2 100644 --- a/.opencode/command/libs-update-app.md +++ b/.opencode/command/libs-update-app.md @@ -1,16 +1,16 @@ --- description: Implement an approved update for one app and produce a short report agent: build -argument-hint: [app name] [target version] +argument-hint: [app name] [target version optional] --- Use the `app-update` skill to run the app update workflow. The slash command stays action-first (`libs-update-app`) even though the shared skill label is `app-update`. -Usage: /libs-update-app +Usage: /libs-update-app [target version] -If the task input is `help` or empty, echo the usage line, then ask the user for the app name and target version. +If the task input is `help` or empty, echo the usage line, then ask the user for the app name. The target version is optional: when omitted, detect the best candidate stable version, continue automatically when the choice is clear, and ask for confirmation only when the candidate is ambiguous, risky, or review-first. If the task input is present, treat it as the workflow input. diff --git a/apps/activemq/variables.json b/apps/activemq/variables.json index 154533fab..367bdcf19 100644 --- a/apps/activemq/variables.json +++ b/apps/activemq/variables.json @@ -25,10 +25,6 @@ "web": { "port": 8161, "path": "/" - }, - "admin": { - "port": 8161, - "path": "/admin" } }, "requirements": { diff --git a/apps/activepieces/variables.json b/apps/activepieces/variables.json index 4a41f4fb4..54a056931 100644 --- a/apps/activepieces/variables.json +++ b/apps/activepieces/variables.json @@ -24,6 +24,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "database": { "type": "postgresql", "supported_modes": [ diff --git a/apps/airbyte/variables.json b/apps/airbyte/variables.json index eb1717bf4..7a8c10f5a 100644 --- a/apps/airbyte/variables.json +++ b/apps/airbyte/variables.json @@ -19,6 +19,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 30080, + "path": "/" + } + }, "requirements": { "cpu": "4", "memory": "8", diff --git a/apps/akeneo/variables.json b/apps/akeneo/variables.json index 5b31a1700..8428c3057 100644 --- a/apps/akeneo/variables.json +++ b/apps/akeneo/variables.json @@ -24,6 +24,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/apache/variables.json b/apps/apache/variables.json index 6e81eb24d..7da7f44e9 100644 --- a/apps/apache/variables.json +++ b/apps/apache/variables.json @@ -23,5 +23,12 @@ "cpu": "1", "memory": "1", "disk": "2" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/arangodb/variables.json b/apps/arangodb/variables.json index a68519589..50f5f79a7 100644 --- a/apps/arangodb/variables.json +++ b/apps/arangodb/variables.json @@ -18,6 +18,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8529, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/bookstack/variables.json b/apps/bookstack/variables.json index bba5f4c5c..819c13c29 100644 --- a/apps/bookstack/variables.json +++ b/apps/bookstack/variables.json @@ -19,10 +19,6 @@ "web": { "port": 80, "path": "/" - }, - "admin": { - "port": 80, - "path": "/login" } }, "requirements": { diff --git a/apps/caddy/variables.json b/apps/caddy/variables.json index 8089e12d6..8c19016a9 100644 --- a/apps/caddy/variables.json +++ b/apps/caddy/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/caddy" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/canvas/variables.json b/apps/canvas/variables.json index fe82a55df..c0f4a1953 100644 --- a/apps/canvas/variables.json +++ b/apps/canvas/variables.json @@ -26,10 +26,6 @@ "web": { "port": 80, "path": "/" - }, - "admin": { - "port": 80, - "path": "/login/canvas" } }, "requirements": { diff --git a/apps/chroma/variables.json b/apps/chroma/variables.json index ae0687566..553f196b0 100644 --- a/apps/chroma/variables.json +++ b/apps/chroma/variables.json @@ -27,5 +27,12 @@ "https://docs.trychroma.com/reference/server-env-vars", "https://github.com/chroma-core/chroma/releases/tag/1.5.9" ] + }, + "access": { + "defaultScheme": "http", + "api": { + "port": 8000, + "path": "/" + } } } diff --git a/apps/ckan/variables.json b/apps/ckan/variables.json index bdeedc2fc..332d692bc 100644 --- a/apps/ckan/variables.json +++ b/apps/ckan/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 5000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/cmak/variables.json b/apps/cmak/variables.json index b82e602bd..70417eb03 100644 --- a/apps/cmak/variables.json +++ b/apps/cmak/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/hlebalbau/kafka-manager" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 9000, + "path": "/" + } } } diff --git a/apps/commafeed/variables.json b/apps/commafeed/variables.json index 55fffdc57..1f7a2f965 100644 --- a/apps/commafeed/variables.json +++ b/apps/commafeed/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/athou/commafeed" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8082, + "path": "/" + } } } diff --git a/apps/compreface/variables.json b/apps/compreface/variables.json index da67625bb..bb619fd4a 100644 --- a/apps/compreface/variables.json +++ b/apps/compreface/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/exadel/compreface-core" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/couchbase/variables.json b/apps/couchbase/variables.json index ea56f5ed5..6d6c71484 100644 --- a/apps/couchbase/variables.json +++ b/apps/couchbase/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8091, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/coze/variables.json b/apps/coze/variables.json index 249b9bd21..dc38b460f 100644 --- a/apps/coze/variables.json +++ b/apps/coze/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/cozedev/coze-studio-server" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/dashy/variables.json b/apps/dashy/variables.json index f21c3d922..94bbcd9b3 100644 --- a/apps/dashy/variables.json +++ b/apps/dashy/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/datahub/variables.json b/apps/datahub/variables.json index 5216d90d3..f066cc82a 100644 --- a/apps/datahub/variables.json +++ b/apps/datahub/variables.json @@ -14,5 +14,12 @@ "cpu": "2", "memory": "8", "disk": "10" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 9002, + "path": "/" + } } } diff --git a/apps/ddnsgo/variables.json b/apps/ddnsgo/variables.json index c22930895..7624586e4 100644 --- a/apps/ddnsgo/variables.json +++ b/apps/ddnsgo/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/jeessy/ddns-go" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 9876, + "path": "/" + } } } diff --git a/apps/dify/variables.json b/apps/dify/variables.json index de4448468..2427e8592 100644 --- a/apps/dify/variables.json +++ b/apps/dify/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/docusaurus/variables.json b/apps/docusaurus/variables.json index 6913e3581..575301dc7 100644 --- a/apps/docusaurus/variables.json +++ b/apps/docusaurus/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/awesometic/docusaurus" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/dotnet/variables.json b/apps/dotnet/variables.json index 239f74f50..7715063d8 100644 --- a/apps/dotnet/variables.json +++ b/apps/dotnet/variables.json @@ -21,5 +21,12 @@ }, "upstream": { "image": "https://mcr.microsoft.com/en-us/product/dotnet/sdk" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/drawio/variables.json b/apps/drawio/variables.json index b5eec1c95..ee4f1c724 100644 --- a/apps/drawio/variables.json +++ b/apps/drawio/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/drupal/.env b/apps/drupal/.env index 5aa0ca9f3..6dc32934e 100644 --- a/apps/drupal/.env +++ b/apps/drupal/.env @@ -1,17 +1,46 @@ W9_REPO=drupal -W9_DIST='community' -W9_VERSION='11.2.2-apache' +W9_DIST=community +W9_VERSION=11.4-apache W9_POWER_PASSWORD='T86d82T!i3mO3B7P' +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='drupal' + +W9_ID=drupal W9_HTTP_PORT=80 -W9_HTTP_PORT_SET='9001' +W9_HTTP_PORT_SET=9001 # Container name's suffix must use one of the value -W9_DB_EXPOSE="mysql" -W9_DB_VERSION="8.0" -W9_URL='example.youdomain.com' +W9_DB_EXPOSE=mysql +W9_DB_VERSION=8.0 +W9_URL=example.youdomain.com W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### + +#W9_NAME="" +#W9_RCODE="" + +# ============================================================ +# Drupal image environment variables +# Docs: https://hub.docker.com/_/drupal +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +MYSQL_ROOT_PASSWORD=${W9_POWER_PASSWORD} +MYSQL_DATABASE=drupal +MYSQL_USER=drupal +MYSQL_PASSWORD=${W9_POWER_PASSWORD} + +# Not used by default; enable only when needed: +# DRUPAL_DB_HOST= +# DRUPAL_DB_NAME= +# DRUPAL_DB_USER= +# DRUPAL_DB_PASSWORD= +# PHP_MEMORY_LIMIT= diff --git a/apps/drupal/CHANGELOG.md b/apps/drupal/CHANGELOG.md index 582cf46c5..370f936f1 100644 --- a/apps/drupal/CHANGELOG.md +++ b/apps/drupal/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Updated Drupal from `11.2.2-apache` to `11.4-apache`. +- Normalized `.env` and `docker-compose.yml` to current repository policy. +- Added app-specific validation coverage for the installer path. diff --git a/apps/drupal/README.md b/apps/drupal/README.md index 4b6fef194..18f8d2d37 100644 --- a/apps/drupal/README.md +++ b/apps/drupal/README.md @@ -1,26 +1,88 @@ -# Drupal on Docker +# Drupal on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Drupal: +## Quick Start +### Deploy Verification - - community: 11.0.5-apache, 10.3.2-apache +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Drupal**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Drupal admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 2 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Drupal by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Drupal Docker image](https://hub.docker.com/_/drupal) and makes some improvements below. -If you want use Drupal with **Websoft9 Business Support** free, you can [subscribe Drupal](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Drupal Administrator Guide](https://support.websoft9.com/docs/drupal) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 11.4-apache, 11.2.2-apache, 10.3.2-apache. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 80 | + + +### Data Directory + + +- `modules` → `/var/www/html/modules` +- `profiles` → `/var/www/html/profiles` +- `themes` → `/var/www/html/themes` +- `sites` → `/var/www/html/sites` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Drupal Administrator Guide](https://support.websoft9.com/docs/drupal) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/drupal) + +- [Releases](https://www.drupal.org/project/drupal/releases) + +- [Official docs](https://www.drupal.org/project/drupal/releases) + +- [GitHub docs](https://github.com/docker-library/docs/blob/master/drupal/README.md) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/drupal/docker-compose.yml b/apps/drupal/docker-compose.yml index 9817630ca..12424e38b 100644 --- a/apps/drupal/docker-compose.yml +++ b/apps/drupal/docker-compose.yml @@ -1,14 +1,9 @@ -# image: https://hub.docker.com/_/drupal -# docs:https://github.com/docker-library/docs/blob/master/drupal/README.md - -version: '3.8' - services: drupal: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} ports: - - $W9_HTTP_PORT_SET:80 + - "${W9_HTTP_PORT_SET}:80" # Web Console volumes: - modules:/var/www/html/modules - profiles:/var/www/html/profiles @@ -18,22 +13,23 @@ services: env_file: .env mysql: - image: mysql:$W9_DB_VERSION - container_name: $W9_ID-mysql + image: mysql:${W9_DB_VERSION} + container_name: ${W9_ID}-mysql restart: unless-stopped + env_file: .env environment: - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD - MYSQL_DATABASE: drupal - MYSQL_USER: drupal - MYSQL_PASSWORD: $W9_POWER_PASSWORD - + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true volumes: modules: profiles: themes: - sites: \ No newline at end of file + sites: diff --git a/apps/drupal/tests/cases.yml b/apps/drupal/tests/cases.yml new file mode 100644 index 000000000..b4e0215fb --- /dev/null +++ b/apps/drupal/tests/cases.yml @@ -0,0 +1,4 @@ +custom: + - id: install-page + type: script + script: smoke-install-page.sh diff --git a/apps/drupal/tests/smoke-install-page.sh b/apps/drupal/tests/smoke-install-page.sh new file mode 100755 index 000000000..1febecafb --- /dev/null +++ b/apps/drupal/tests/smoke-install-page.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +tmp_file="$(mktemp)" +trap 'rm -f "${tmp_file}"' EXIT + +curl -fsSL "${BASE_URL}" -o "${tmp_file}" +grep -qi "drupal" "${tmp_file}" diff --git a/apps/drupal/variables.json b/apps/drupal/variables.json index f745330eb..8e408b3cc 100644 --- a/apps/drupal/variables.json +++ b/apps/drupal/variables.json @@ -6,18 +6,29 @@ { "dist": "community", "version": [ - "11.2.2-apache", - "11.0.5-apache", - "10.3.2-apache" + "11.4", + "latest" ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", "disk": "2" }, "upstream": { - "image": "https://hub.docker.com/_/drupal" + "image": "https://hub.docker.com/_/drupal", + "releases": "https://www.drupal.org/project/drupal/releases", + "docs": [ + "https://www.drupal.org/project/drupal/releases", + "https://github.com/docker-library/docs/blob/master/drupal/README.md" + ] } } diff --git a/apps/dsh/variables.json b/apps/dsh/variables.json index 45dcd1814..d24be29fc 100644 --- a/apps/dsh/variables.json +++ b/apps/dsh/variables.json @@ -14,7 +14,10 @@ "edition": [ { "dist": "community", - "version": ["0.1.7-rc.2", "latest"] + "version": [ + "0.1.7-rc.2", + "latest" + ] } ], "access": { @@ -22,10 +25,6 @@ "web": { "port": 3080, "path": "/" - }, - "admin": { - "port": 3080, - "path": "/?token=xxxx" } }, "requirements": { diff --git a/apps/duplicati/variables.json b/apps/duplicati/variables.json index ff7e77d12..997dd517b 100644 --- a/apps/duplicati/variables.json +++ b/apps/duplicati/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/linuxserver/duplicati" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8200, + "path": "/" + } } } diff --git a/apps/ejbca/variables.json b/apps/ejbca/variables.json index 2727dde9b..3523142fa 100644 --- a/apps/ejbca/variables.json +++ b/apps/ejbca/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/keyfactor/ejbca-ce" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/erpnext/variables.json b/apps/erpnext/variables.json index e72ac6575..c9b9cb155 100644 --- a/apps/erpnext/variables.json +++ b/apps/erpnext/variables.json @@ -14,10 +14,6 @@ "web": { "port": 8080, "path": "/" - }, - "admin": { - "port": 8080, - "path": "/app" } }, "requirements": { diff --git a/apps/espocrm/.env b/apps/espocrm/.env index d2bc015f5..a3704b5ef 100644 --- a/apps/espocrm/.env +++ b/apps/espocrm/.env @@ -1,25 +1,54 @@ -W9_REPO=espocrm/espocrm -W9_DIST='community' -W9_VERSION='9.2.2' +W9_REPO=espocrm +W9_DIST=community +W9_VERSION=10.0 W9_POWER_PASSWORD='QnMU9I!XW8pQovRV' +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='espocrm' + +W9_ID=espocrm W9_HTTP_PORT=80 -W9_HTTP_PORT_SET='9001' +W9_HTTP_PORT_SET=9001 W9_LOGIN_USER=admin -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD -W9_DB_EXPOSE="mariadb" +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} +W9_DB_EXPOSE=mariadb W9_DB_VERSION=10.6 -W9_URL='example.youdomain.com' +W9_URL=example.youdomain.com +W9_URL_REPLACE=true W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### -ESPOCRM_DATABASE_HOST=$W9_ID-mariadb +#W9_NAME="" +#W9_RCODE="" + +# ============================================================ +# EspoCRM image environment variables +# Docs: https://hub.docker.com/_/espocrm +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +MARIADB_DATABASE=espocrm +MARIADB_USER=espocrm +MARIADB_PASSWORD=${W9_POWER_PASSWORD} +MARIADB_ROOT_PASSWORD=${W9_POWER_PASSWORD} +ESPOCRM_DATABASE_HOST=${W9_ID}-mariadb ESPOCRM_DATABASE_USER=espocrm -ESPOCRM_DATABASE_PASSWORD=$W9_POWER_PASSWORD +ESPOCRM_DATABASE_PASSWORD=${W9_POWER_PASSWORD} ESPOCRM_DATABASE_NAME=espocrm -ESPOCRM_ADMIN_USERNAME=$W9_LOGIN_USER -ESPOCRM_ADMIN_PASSWORD=$W9_POWER_PASSWORD -ESPOCRM_SITE_URL=http://$W9_URL +ESPOCRM_ADMIN_USERNAME=${W9_LOGIN_USER} +ESPOCRM_ADMIN_PASSWORD=${W9_POWER_PASSWORD} +ESPOCRM_SITE_URL=http://${W9_URL} + +# Not used by default; enable only when needed: +# ESPOCRM_CONFIG_USE_CACHE= +# ESPOCRM_CONFIG_USE_CRON= +# ESPOCRM_CONFIG_DEFAULT_LANGUAGE= +# ESPOCRM_CONFIG_TIME_ZONE= +# ESPOCRM_CONFIG_DATE_FORMAT= diff --git a/apps/espocrm/CHANGELOG.md b/apps/espocrm/CHANGELOG.md index 582cf46c5..f4f4fc265 100644 --- a/apps/espocrm/CHANGELOG.md +++ b/apps/espocrm/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Updated EspoCRM from `9.2.2` to `10.0`. +- Normalized `.env` and `docker-compose.yml` to current repository policy. +- Recorded first-startup-only admin and site URL settings. +- Migrated volume mounts for EspoCRM 10 so image-provided application files are no longer shadowed by a full `/var/www/html` volume. +- Added app-specific validation coverage for the installer path. diff --git a/apps/espocrm/Notes.md b/apps/espocrm/Notes.md deleted file mode 100644 index 865c9812e..000000000 --- a/apps/espocrm/Notes.md +++ /dev/null @@ -1,6 +0,0 @@ -## About - -- deamon container for cron -- websocket container for mobile message push - -docs: [installation by Script](https://docs.espocrm.com/administration/installation-by-script/) diff --git a/apps/espocrm/README.md b/apps/espocrm/README.md index d94143fe1..101e3f018 100644 --- a/apps/espocrm/README.md +++ b/apps/espocrm/README.md @@ -1,26 +1,91 @@ -# EspoCRM on Docker +# EspoCRM on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for EspoCRM: +## Quick Start +### Deploy Verification - - community: 9.1.5, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **EspoCRM**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the EspoCRM admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://docs.espocrm.com/administration/installation-by-script/): +### Change Password -* **RAM**: 2 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 8 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this EspoCRM by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [EspoCRM Docker image](https://hub.docker.com/_/espocrm) and makes some improvements below. -If you want use EspoCRM with **Websoft9 Business Support** free, you can [subscribe EspoCRM](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[EspoCRM Administrator Guide](https://support.websoft9.com/docs/espocrm) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 10.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 80 | + + +### Data Directory + + +- `mariadb` → `/var/lib/mysql` +- `espocrm-data` → `/var/www/html/data` +- `espocrm-custom` → `/var/www/html/custom` +- `espocrm-custom-client` → `/var/www/html/client/custom` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `ESPOCRM_ADMIN_USERNAME`, `ESPOCRM_ADMIN_PASSWORD`, `ESPOCRM_SITE_URL` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [EspoCRM Administrator Guide](https://support.websoft9.com/docs/espocrm) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/espocrm) + +- [Releases](https://github.com/espocrm/espocrm/releases) + +- [Official docs](https://docs.espocrm.com/administration/docker/installation/#install-espocrm-with-docker-compose) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/espocrm/docker-compose.yml b/apps/espocrm/docker-compose.yml index b4077c862..8c0ed5c34 100644 --- a/apps/espocrm/docker-compose.yml +++ b/apps/espocrm/docker-compose.yml @@ -1,44 +1,49 @@ -# image: https://hub.docker.com/r/espocrm/espocrm -# dockfile: https://github.com/espocrm/espocrm-docker -# docs: https://docs.espocrm.com/administration/installation-by-script/ -# docker compose: https://docs.espocrm.com/administration/docker/installation/#install-espocrm-with-docker-compose - -version: '3.8' - services: mariadb: - image: mariadb:$W9_DB_VERSION - container_name: $W9_ID-mariadb + image: mariadb:${W9_DB_VERSION} + container_name: ${W9_ID}-mariadb restart: unless-stopped command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb_log_buffer_size=30M volumes: - mariadb:/var/lib/mysql + env_file: + - .env environment: - MARIADB_DATABASE: espocrm - MARIADB_USER: espocrm - MARIADB_PASSWORD: $W9_POWER_PASSWORD - MARIADB_ROOT_PASSWORD: $W9_POWER_PASSWORD + MARIADB_DATABASE: ${MARIADB_DATABASE} + MARIADB_USER: ${MARIADB_USER} + MARIADB_PASSWORD: ${MARIADB_PASSWORD} + MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD} espocrm: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} env_file: - .env volumes: - - espocrm:/var/www/html + - espocrm-data:/var/www/html/data + - espocrm-custom:/var/www/html/custom + - espocrm-custom-client:/var/www/html/client/custom restart: unless-stopped ports: - - ${W9_HTTP_PORT_SET}:80 + - "${W9_HTTP_PORT_SET}:80" # Web Console + depends_on: + - mariadb # This is need for Cron espocrm-daemon: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID-daemon + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID}-daemon + env_file: + - .env volumes: - - espocrm:/var/www/html + - espocrm-data:/var/www/html/data + - espocrm-custom:/var/www/html/custom + - espocrm-custom-client:/var/www/html/client/custom restart: unless-stopped entrypoint: docker-daemon.sh + depends_on: + - espocrm networks: default: @@ -47,4 +52,6 @@ networks: volumes: mariadb: - espocrm: + espocrm-data: + espocrm-custom: + espocrm-custom-client: diff --git a/apps/espocrm/tests/cases.yml b/apps/espocrm/tests/cases.yml new file mode 100644 index 000000000..b4e0215fb --- /dev/null +++ b/apps/espocrm/tests/cases.yml @@ -0,0 +1,4 @@ +custom: + - id: install-page + type: script + script: smoke-install-page.sh diff --git a/apps/espocrm/tests/smoke-install-page.sh b/apps/espocrm/tests/smoke-install-page.sh new file mode 100755 index 000000000..7a01f2644 --- /dev/null +++ b/apps/espocrm/tests/smoke-install-page.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +tmp_file="$(mktemp)" +trap 'rm -f "${tmp_file}"' EXIT + +curl -fsSL "${BASE_URL}" -o "${tmp_file}" +grep -qi "EspoCRM" "${tmp_file}" diff --git a/apps/espocrm/variables.json b/apps/espocrm/variables.json index 6623a4feb..f58853cfc 100644 --- a/apps/espocrm/variables.json +++ b/apps/espocrm/variables.json @@ -6,7 +6,7 @@ { "dist": "community", "version": [ - "9.2.2", + "10.0", "latest" ] } @@ -16,7 +16,25 @@ "memory": "2", "disk": "8" }, + "env": { + "first_startup_only": [ + "ESPOCRM_ADMIN_USERNAME", + "ESPOCRM_ADMIN_PASSWORD", + "ESPOCRM_SITE_URL" + ] + }, "upstream": { - "image": "https://hub.docker.com/r/espocrm/espocrm" + "image": "https://hub.docker.com/_/espocrm", + "releases": "https://github.com/espocrm/espocrm/releases", + "docs": [ + "https://docs.espocrm.com/administration/docker/installation/#install-espocrm-with-docker-compose" + ] + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/excalidraw/variables.json b/apps/excalidraw/variables.json index 3b34ea0c4..2d9a17f92 100644 --- a/apps/excalidraw/variables.json +++ b/apps/excalidraw/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/excalidraw/excalidraw" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/filepizza/variables.json b/apps/filepizza/variables.json index 80c4b8d76..4941585ab 100644 --- a/apps/filepizza/variables.json +++ b/apps/filepizza/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/kern/filepizza" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/filerun/variables.json b/apps/filerun/variables.json index b11d1f0bb..949e4dc8a 100644 --- a/apps/filerun/variables.json +++ b/apps/filerun/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/firecrawl/variables.json b/apps/firecrawl/variables.json index 510b3ce20..fdbbe10b3 100644 --- a/apps/firecrawl/variables.json +++ b/apps/firecrawl/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3002, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/focalboard/variables.json b/apps/focalboard/variables.json index e7411bc69..fed459a04 100644 --- a/apps/focalboard/variables.json +++ b/apps/focalboard/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/formbricks/variables.json b/apps/formbricks/variables.json index ad569827c..235a0a843 100644 --- a/apps/formbricks/variables.json +++ b/apps/formbricks/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/frappe/variables.json b/apps/frappe/variables.json index 36de1080f..cc6c2f8b8 100644 --- a/apps/frappe/variables.json +++ b/apps/frappe/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "8", diff --git a/apps/freshrss/variables.json b/apps/freshrss/variables.json index d98fb4ccc..3f5f95d4c 100644 --- a/apps/freshrss/variables.json +++ b/apps/freshrss/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/frigate/variables.json b/apps/frigate/variables.json index f3668de74..fcc4f1878 100644 --- a/apps/frigate/variables.json +++ b/apps/frigate/variables.json @@ -14,5 +14,12 @@ "cpu": "2", "memory": "4", "disk": "10" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/geoserver/variables.json b/apps/geoserver/variables.json index 2624bc3bb..6908b7b84 100644 --- a/apps/geoserver/variables.json +++ b/apps/geoserver/variables.json @@ -14,5 +14,12 @@ "cpu": "1", "memory": "2", "disk": "1" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/ghost/.env b/apps/ghost/.env index f400c63ca..3a9432b2c 100644 --- a/apps/ghost/.env +++ b/apps/ghost/.env @@ -1,28 +1,46 @@ -W9_POWER_PASSWORD='upxOisMYI5V!0UXx' W9_REPO=ghost -W9_VERSION='6.9' -W9_DIST='community' +W9_DIST=community +W9_VERSION=6.65 +W9_POWER_PASSWORD="upxOisMYI5V!0UXx" #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='ghost' + +W9_ID=ghost + W9_HTTP_PORT=2368 -W9_HTTP_PORT_SET='9001' -W9_DB_EXPOSE="mysql" -W9_DB_VERSION="8.0" -W9_NETWORK=websoft9 -# This is use for View Sites link at backend, no use for frontend -W9_URL='appname.example.com' -W9_URL_REPLACE=true -# Access admin page to create administrator account +W9_HTTP_PORT_SET=9001 + +W9_DB_EXPOSE=mysql +W9_DB_VERSION=8.0 + +# Access admin page to create the administrator account W9_ADMIN_PATH="/ghost" -W9_EMAIL=websoft9@example.com + +W9_URL=appname.example.com +W9_URL_REPLACE=true + +W9_NETWORK=websoft9 #### --------------------------------------------------------------------------------------- #### +# ============================================================ +# Ghost image environment variables +# Docs: https://ghost.org/docs/config/ +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# ============================================================ + +# Used by docker-compose.yml: + NODE_ENV=production -# see https://ghost.org/docs/config/#configuration-options database__client=mysql -database__connection__host=$W9_ID-mysql -database__connection__user=$W9_ID -database__connection__password="$W9_POWER_PASSWORD" -database__connection__database=$W9_ID -url=http://$W9_URL +database__connection__host=${W9_ID}-mysql +database__connection__user=${W9_ID} +database__connection__password="${W9_POWER_PASSWORD}" +database__connection__database=${W9_ID} +url=http://${W9_URL} + +# Not used by default; enable only when needed: +# database__connection__port=3306 +# database__pool__min=2 +# database__pool__max=20 +# mail__transport=SMTP +# mail__from=websoft9@example.com diff --git a/apps/ghost/CHANGELOG.md b/apps/ghost/CHANGELOG.md index 582cf46c5..a56b58810 100644 --- a/apps/ghost/CHANGELOG.md +++ b/apps/ghost/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-29 +- Update Ghost community to 6.65. +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, dead variable cleanup, and refreshed metadata. +- Add an app-specific admin console check in `tests/cases.yml`. diff --git a/apps/ghost/README.md b/apps/ghost/README.md index 5c20c0e7c..e9eab051d 100644 --- a/apps/ghost/README.md +++ b/apps/ghost/README.md @@ -1,26 +1,93 @@ -# Ghost on Docker +# Ghost on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Ghost: +## Quick Start +### Deploy Verification - - community: 5.125.1, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Ghost**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### First-Time Setup -## System Requirements +1. Open the admin URL in a browser, for example `http://:9001/ghost/`. +2. On first run, create the administrator account (name, email, password) in the setup wizard. +3. After setup completes, sign in to the Ghost admin console with the account you created. -The following are the minimal [recommended requirements](https://hub.docker.com/_/ghost): +### Usage -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 4 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the admin console, create a post under **Posts** and publish it. +2. Open the site root URL to verify the published post appears. -## Install +### Change Password -You can install this Ghost by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +1. In the Ghost admin console, open **Settings → Staff** and select your account. +2. Change the password there. Ghost stores the admin password in its own database, not in `.env`. + -If you want use Ghost with **Websoft9 Business Support** free, you can [subscribe Ghost](https://www.websoft9.com/apps) on Cloud platform +## Configuration Reference -## Documentation +Websoft9 packages this app from the official [Ghost Docker image](https://hub.docker.com/_/ghost) and makes some improvements below. -[Ghost Administrator Guide](https://support.websoft9.com/docs/ghost) powered by Websoft9 \ No newline at end of file + + + + +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 6.65, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Ghost web site and admin console | 2368 | + + +### Data Directory + + +- `ghost` → `/var/lib/ghost` +- `mysql` → `/var/lib/mysql` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Ghost Administrator Guide](https://support.websoft9.com/docs/ghost) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/ghost) + +- [Releases](https://github.com/TryGhost/Ghost/releases) + +- [Official docs](https://ghost.org/docs/config/) + +- [Official docs](https://ghost.org/docs/install/docker/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/ghost/docker-compose.yml b/apps/ghost/docker-compose.yml index d7a8fce1e..ee7b33616 100644 --- a/apps/ghost/docker-compose.yml +++ b/apps/ghost/docker-compose.yml @@ -1,14 +1,12 @@ -# image: https://hub.docker.com/_/ghost - version: '3.8' services: ghost: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:2368 + - "${W9_HTTP_PORT_SET}:2368" # Ghost web site and admin console env_file: .env volumes: - ghost:/var/lib/ghost @@ -16,17 +14,17 @@ services: - mysql mysql: - image: mysql:$W9_DB_VERSION - container_name: $W9_ID-mysql + image: mysql:${W9_DB_VERSION} + container_name: ${W9_ID}-mysql restart: unless-stopped command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - mysql:/var/lib/mysql environment: - MYSQL_DATABASE: $W9_ID - MYSQL_USER: $W9_ID - MYSQL_PASSWORD: $W9_POWER_PASSWORD - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD + MYSQL_DATABASE: ${W9_ID} + MYSQL_USER: ${W9_ID} + MYSQL_PASSWORD: ${W9_POWER_PASSWORD} + MYSQL_ROOT_PASSWORD: ${W9_POWER_PASSWORD} networks: default: diff --git a/apps/ghost/tests/cases.yml b/apps/ghost/tests/cases.yml new file mode 100644 index 000000000..0893bbf8c --- /dev/null +++ b/apps/ghost/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: admin-console + type: web-access + path: /ghost/ + expect_status: 200 diff --git a/apps/ghost/variables.json b/apps/ghost/variables.json index a3b6e1f82..625f3e948 100644 --- a/apps/ghost/variables.json +++ b/apps/ghost/variables.json @@ -3,13 +3,18 @@ "trademark": "Ghost", "release": true, "upstream": { - "image": "https://hub.docker.com/_/ghost" + "image": "https://hub.docker.com/_/ghost", + "releases": "https://github.com/TryGhost/Ghost/releases", + "docs": [ + "https://ghost.org/docs/config/", + "https://ghost.org/docs/install/docker/" + ] }, "edition": [ { "dist": "community", "version": [ - "6.9", + "6.65", "latest" ] } @@ -29,5 +34,8 @@ "cpu": "1", "memory": "1", "disk": "4" + }, + "help": { + "login": "First run: open /ghost and create the administrator account in the browser, then log in with those credentials." } } diff --git a/apps/go/variables.json b/apps/go/variables.json index 4dc8681c1..80eaa90c3 100644 --- a/apps/go/variables.json +++ b/apps/go/variables.json @@ -22,5 +22,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/golang" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/gocd/variables.json b/apps/gocd/variables.json index 5f0e94e97..8dbd2707a 100644 --- a/apps/gocd/variables.json +++ b/apps/gocd/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8153, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/graylog/.env b/apps/graylog/.env index 58750d319..f767f7a12 100644 --- a/apps/graylog/.env +++ b/apps/graylog/.env @@ -1,43 +1,58 @@ -# Two method for you to create SHA-256 hash of our password -#1 echo -n 'password' | sha256sum | awk '{ print $1 }' -#2 echo -n "Enter Password: " && head -1 +### First-Time Initialization -## System Requirements +1. On the first startup, read the temporary admin password from the container logs: `docker logs graylog`. +2. Open the login URL and sign in as `admin` with that temporary password to finish the setup wizard. +3. After initialization completes, log in with the account and password shown in the **Access** tab (`admin` / `admin`). -The following are the minimal [recommended requirements](https://go2docs.graylog.org/current/downloading_and_installing_graylog/docker_installation.htm?tocpath=Install%20Graylog%7C_____2#Prerequisites): +### Usage -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. Make sure you are signed in to the Graylog admin console. +2. Try a core feature. -## Install +### Change Password -You can install this Graylog by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -If you want use Graylog with **Websoft9 Business Support** free, you can [subscribe Graylog](https://www.websoft9.com/apps) on Cloud platform +## Configuration Reference -## Documentation +Websoft9 packages this app from the official [Graylog Docker image](https://hub.docker.com/r/graylog/graylog) and makes some improvements below. -[Graylog Administrator Guide](https://support.websoft9.com/docs/graylog) powered by Websoft9 \ No newline at end of file + + + + +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 7.1. + + +### Ports + +| Purpose | Port | +| --- | --- | + + +### Data Directory + + +- `mongodb_data` → `/data/db` +- `graylog_data` → `/usr/share/graylog/data/` +- `graylog_plugin` → `/usr/share/graylog/plugin` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Graylog Administrator Guide](https://support.websoft9.com/docs/graylog) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/graylog/graylog) + +- [Official docs](https://go2docs.graylog.org/current/downloading_and_installing_graylog/docker_installation.htm) + +- [Official docs](https://go2docs.graylog.org/current/upgrading_graylog/upgrading_graylog_in_docker.htm) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/graylog/docker-compose.yml b/apps/graylog/docker-compose.yml index a3e38e10f..daefb30a4 100644 --- a/apps/graylog/docker-compose.yml +++ b/apps/graylog/docker-compose.yml @@ -1,17 +1,14 @@ -# docker-compose: https://github.com/Graylog2/docker-compose/blob/main/open-core/docker-compose.yml -# image: https://hub.docker.com/r/graylog/graylog/ - version: '3.8' services: mongodb: - image: mongo:${W9_MONGO_VERSION} + image: mongo:${W9_DB_VERSION} container_name: ${W9_ID}-mongodb restart: "on-failure" volumes: - mongodb_data:/data/db datanode: - image: graylog/graylog-datanode:${W9_DATANODE_VERSION} + image: graylog/graylog-datanode:${W9_VERSION} container_name: ${W9_ID}-datanode environment: GRAYLOG_DATANODE_NODE_ID_FILE: "/var/lib/graylog-datanode/node-id" @@ -34,30 +31,32 @@ services: restart: "on-failure" graylog: - image: $W9_REPO:${W9_VERSION} + image: ${W9_REPO}:${W9_VERSION} container_name: ${W9_ID} env_file: .env entrypoint: "/usr/bin/tini -- /docker-entrypoint.sh" environment: - GRAYLOG_NODE_ID_FILE: "/usr/share/graylog/data/data/node-id" + GRAYLOG_NODE_ID_FILE: "/usr/share/graylog/data/config/node-id" GRAYLOG_PASSWORD_SECRET: ${GRAYLOG_PASSWORD_SECRET} GRAYLOG_ROOT_PASSWORD_SHA2: ${GRAYLOG_ROOT_PASSWORD_SHA2} GRAYLOG_HTTP_BIND_ADDRESS: "0.0.0.0:9000" - GRAYLOG_HTTP_EXTERNAL_URI: "http://localhost:9000/" + GRAYLOG_HTTP_EXTERNAL_URI: ${GRAYLOG_HTTP_EXTERNAL_URI} GRAYLOG_MONGODB_URI: ${GRAYLOG_MONGODB_URI} restart: unless-stopped depends_on: mongodb: condition: "service_started" + datanode: + condition: "service_started" ports: - "${W9_BEATS_TCP_PORT_SET}:5044/tcp" # Beats - - "${W9_SYSLOG_TCP_PORT_SET}:5140/udp" # Syslog + - "${W9_SYSLOG_UDP_PORT_SET}:5140/udp" # Syslog UDP - "${W9_SYSLOG_TCP_PORT_SET}:5140/tcp" # Syslog - "${W9_RAW_TCP_PORT_SET}:5555/tcp" # RAW TCP - - "${W9_RAW_TCP_PORT_SET}:5555/udp" # RAW UDP - - "${W9_HTTP_PORT_SET}:9000/tcp" # Server API + - "${W9_RAW_UDP_PORT_SET}:5555/udp" # RAW UDP + - "${W9_HTTP_PORT_SET}:9000/tcp" # Web Console and API - "${W9_GELF_TCP_PORT_SET}:12201/tcp" # GELF TCP - - "${W9_GELF_TCP_PORT_SET}:12201/udp" # GELF UDP + - "${W9_GELF_UDP_PORT_SET}:12201/udp" # GELF UDP #- "10000:10000/tcp" # Custom TCP port #- "10000:10000/udp" # Custom UDP port - "${W9_FORWARDER_DATA_TCP_PORT_SET}:13301/tcp" # Forwarder data diff --git a/apps/graylog/src/get_version.sh b/apps/graylog/src/get_version.sh deleted file mode 100644 index 840b0568f..000000000 --- a/apps/graylog/src/get_version.sh +++ /dev/null @@ -1,2 +0,0 @@ -sudo echo "graylog version:" $(docker image inspect graylog/graylog:$(docker images | grep graylog |awk '{print $2}') | jq .[].Config.Labels | grep "org.label-schema.version" | cut -d ":" -f 2 | sed 's/\"//g') |sudo tee -a /data/logs/install_version.txt - diff --git a/apps/graylog/tests/cases.yml b/apps/graylog/tests/cases.yml new file mode 100644 index 000000000..7c10dabac --- /dev/null +++ b/apps/graylog/tests/cases.yml @@ -0,0 +1,4 @@ +custom: + - id: graylog-web-ui + type: script + script: check.sh diff --git a/apps/graylog/tests/check.sh b/apps/graylog/tests/check.sh new file mode 100755 index 000000000..0035acb6a --- /dev/null +++ b/apps/graylog/tests/check.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +base="${BASE_URL:?BASE_URL is required}" +body="$(mktemp)" +trap 'rm -f "$body"' EXIT + +code="$(curl -sS -L -o "$body" -w '%{http_code}' "${base}/" || true)" + +case "$code" in + 200|302) ;; + *) + echo "unexpected HTTP ${code} from Graylog web UI" >&2 + exit 1 + ;; +esac + +if ! grep -Eqi 'graylog|initial configuration|sign in|login' "$body"; then + echo "response does not look like a Graylog setup or login page" >&2 + exit 1 +fi + +echo "Graylog web UI responded with HTTP ${code}" diff --git a/apps/graylog/variables.json b/apps/graylog/variables.json index 384ff12a2..cdcebddde 100644 --- a/apps/graylog/variables.json +++ b/apps/graylog/variables.json @@ -2,20 +2,44 @@ "name": "graylog", "trademark": "Graylog", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/graylog/graylog", + "docs": [ + "https://go2docs.graylog.org/current/downloading_and_installing_graylog/docker_installation.htm", + "https://go2docs.graylog.org/current/upgrading_graylog/upgrading_graylog_in_docker.htm" + ] + }, "edition": [ { "dist": "community", "version": [ - "7.0" + "7.1" ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 9000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", "disk": "1" }, - "upstream": { - "image": "https://hub.docker.com/r/graylog/graylog" + "credentials": { + "username": { + "source": "inline", + "value": "admin" + }, + "password": { + "source": "container-env", + "name": "W9_LOGIN_PASSWORD" + } + }, + "help": { + "login": "First run: read the temporary admin password from the container logs (docker logs graylog) to complete initialization, then log in with the account and password shown below." } } diff --git a/apps/immich/variables.json b/apps/immich/variables.json index 7c5e2f33b..7a879b655 100644 --- a/apps/immich/variables.json +++ b/apps/immich/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3001, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/influxdb/variables.json b/apps/influxdb/variables.json index 3130a9cf5..fcb786b65 100644 --- a/apps/influxdb/variables.json +++ b/apps/influxdb/variables.json @@ -23,6 +23,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8086, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/jellyfin/variables.json b/apps/jellyfin/variables.json index 6b1e5ec3a..46cdb9d68 100644 --- a/apps/jellyfin/variables.json +++ b/apps/jellyfin/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8096, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "8", diff --git a/apps/jitsu/variables.json b/apps/jitsu/variables.json index 38952654c..c3f9588f3 100644 --- a/apps/jitsu/variables.json +++ b/apps/jitsu/variables.json @@ -28,10 +28,6 @@ "port": 3000, "path": "/" }, - "admin": { - "port": 3000, - "path": "/login" - }, "api": { "port": 3049 } diff --git a/apps/kavita/variables.json b/apps/kavita/variables.json index 5a29cd807..59c2250f9 100644 --- a/apps/kavita/variables.json +++ b/apps/kavita/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 5000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/keep/variables.json b/apps/keep/variables.json index 0cc8d864b..769275001 100644 --- a/apps/keep/variables.json +++ b/apps/keep/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "us-central1-docker.pkg.dev/keephq/keep/keep-api" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/keila/variables.json b/apps/keila/variables.json index 2dd551ba1..5db4c252b 100644 --- a/apps/keila/variables.json +++ b/apps/keila/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 4000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/kener/variables.json b/apps/kener/variables.json index 85e0bbe76..2e29f6cd0 100644 --- a/apps/kener/variables.json +++ b/apps/kener/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/keploy/variables.json b/apps/keploy/variables.json index 7ab2c28e7..36433e7c5 100644 --- a/apps/keploy/variables.json +++ b/apps/keploy/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "ghcr.io/keploy/keploy" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/kestra/variables.json b/apps/kestra/variables.json index 634ad780e..d1872182b 100644 --- a/apps/kestra/variables.json +++ b/apps/kestra/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/khoj/variables.json b/apps/khoj/variables.json index c51610c48..d8bb680d9 100644 --- a/apps/khoj/variables.json +++ b/apps/khoj/variables.json @@ -14,5 +14,12 @@ "cpu": "2", "memory": "4", "disk": "10" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/killbill/variables.json b/apps/killbill/variables.json index 64b14203b..74aa7a069 100644 --- a/apps/killbill/variables.json +++ b/apps/killbill/variables.json @@ -11,6 +11,17 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + }, + "api": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/knowage/variables.json b/apps/knowage/variables.json index 8355e8fc4..ed6d9b755 100644 --- a/apps/knowage/variables.json +++ b/apps/knowage/variables.json @@ -18,10 +18,6 @@ "web": { "port": 8080, "path": "/" - }, - "admin": { - "port": 8080, - "path": "/knowage" } }, "requirements": { diff --git a/apps/kodbox/variables.json b/apps/kodbox/variables.json index d2f9d0ddf..6ef241bcc 100644 --- a/apps/kodbox/variables.json +++ b/apps/kodbox/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/koishi/variables.json b/apps/koishi/variables.json index 11f490f69..224d7c551 100644 --- a/apps/koishi/variables.json +++ b/apps/koishi/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 5140, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/komga/variables.json b/apps/komga/variables.json index 92d5776ed..4fde69836 100644 --- a/apps/komga/variables.json +++ b/apps/komga/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 25600, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/kopia/variables.json b/apps/kopia/variables.json index c4b2328e1..ac7a9ee81 100644 --- a/apps/kopia/variables.json +++ b/apps/kopia/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 51515, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/langflow/variables.json b/apps/langflow/variables.json index d2ecfa224..4cb055a88 100644 --- a/apps/langflow/variables.json +++ b/apps/langflow/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 7860, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/langfuse/variables.json b/apps/langfuse/variables.json index a26c4c43c..7b04b8f5a 100644 --- a/apps/langfuse/variables.json +++ b/apps/langfuse/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/langfuse/langfuse" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/lemmy/variables.json b/apps/lemmy/variables.json index cd16cbaac..75deb21bd 100644 --- a/apps/lemmy/variables.json +++ b/apps/lemmy/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8536, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/listmonk/variables.json b/apps/listmonk/variables.json index d1b6bc577..6c4899e78 100644 --- a/apps/listmonk/variables.json +++ b/apps/listmonk/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/listmonk/listmonk" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 9000, + "path": "/" + } } } diff --git a/apps/lobehub/variables.json b/apps/lobehub/variables.json index 6e1df8957..f9b6702d2 100644 --- a/apps/lobehub/variables.json +++ b/apps/lobehub/variables.json @@ -41,5 +41,12 @@ "cpu": "2", "memory": "4", "disk": "10" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 3210, + "path": "/" + } } } diff --git a/apps/localai/variables.json b/apps/localai/variables.json index 118e49fb5..8337daff9 100644 --- a/apps/localai/variables.json +++ b/apps/localai/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/logstash/variables.json b/apps/logstash/variables.json index c16cb04ad..e0b078e00 100644 --- a/apps/logstash/variables.json +++ b/apps/logstash/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/logstash" + }, + "access": { + "defaultScheme": "http", + "api": { + "port": 9600, + "path": "/" + } } } diff --git a/apps/mage/variables.json b/apps/mage/variables.json index d78971262..cdfccb689 100644 --- a/apps/mage/variables.json +++ b/apps/mage/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 6789, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/manageiq/variables.json b/apps/manageiq/variables.json index 6b4ee0124..c74a72abc 100644 --- a/apps/manageiq/variables.json +++ b/apps/manageiq/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "https", + "web": { + "port": 443, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/mathesar/variables.json b/apps/mathesar/variables.json index 5008e90a8..d64262061 100644 --- a/apps/mathesar/variables.json +++ b/apps/mathesar/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/mathesar/mathesar" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/" + } } } diff --git a/apps/matlab/variables.json b/apps/matlab/variables.json index 3e31dd059..ab011a40b 100644 --- a/apps/matlab/variables.json +++ b/apps/matlab/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8888, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/matomo/variables.json b/apps/matomo/variables.json index 960b16850..29a24ce3a 100644 --- a/apps/matomo/variables.json +++ b/apps/matomo/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/mattermost/.env b/apps/mattermost/.env index 4bc401ef8..fd021ff08 100644 --- a/apps/mattermost/.env +++ b/apps/mattermost/.env @@ -1,25 +1,43 @@ -# mattermost/mattermost-team-edition, mattermost-enterprise-edition -W9_POWER_PASSWORD='OkPYp5wZKL2p5Kl!' W9_REPO=mattermost/mattermost-team-edition -W9_VERSION='11.1' -W9_DIST='community' +W9_DIST=community +W9_VERSION=11.11 + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='mattermost' + +W9_ID=mattermost W9_HTTP_PORT=8065 -W9_HTTP_PORT_SET='9001' -W9_TCP_PORT_SET='8443' -W9_UDP_PORT_SET='8443' -W9_RCODE='5zuDcsG3MVy3M' -W9_URL='appname.example.com' +W9_HTTP_PORT_SET=9001 +W9_TCP_PORT_SET=8443 +W9_UDP_PORT_SET=8443 +W9_DB_EXPOSE=postgresql +W9_DB_VERSION=14.0 +W9_RCODE=5zuDcsG3MVy3M +W9_URL=appname.example.com W9_URL_REPLACE=true -W9_DB_EXPOSE="postgresql" -W9_DB_VERSION="14.0" W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### -# -- below from official .env +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Mattermost image environment variables +# Docs: https://docs.mattermost.com/install/install-docker.html +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: MM_BLEVESETTINGS_INDEXDIR=/mattermost/bleve-indexes MM_SQLSETTINGS_DRIVERNAME=postgres MM_SQLSETTINGS_DATASOURCE=postgres://postgres:${W9_RCODE}@${W9_ID}-postgresql:5432/mattermost?sslmode=disable&connect_timeout=10 MM_SERVICESETTINGS_SITEURL=https://${W9_URL} + +# Not used by default; enable only when needed: +# MM_EMAILSETTINGS_SENDEMAILNOTIFICATIONS=true +# MM_EMAILSETTINGS_REPLYTOADDRESS= +# MM_EMAILSETTINGS_FEEDBACKEMAIL= +# MM_SERVICESETTINGS_ENABLEOPENSERVER=true +# MM_TEAMSETTINGS_SITENAME=Mattermost diff --git a/apps/mattermost/CHANGELOG.md b/apps/mattermost/CHANGELOG.md index 582cf46c5..e1de8fdc5 100644 --- a/apps/mattermost/CHANGELOG.md +++ b/apps/mattermost/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Update Mattermost team edition from `11.1` to `11.11` (latest stable upstream release; no major-version jump). +- Align `.env` with the current repository policy: template layout, image-env section banner, and removal of the unused `W9_POWER_PASSWORD`. +- Drop the deprecated compose `version` field and the `# docs:`/`# image:` source comments, and document each published port inline. +- Add `apps/mattermost/tests/cases.yml` with a dedicated `/api/v4/system/ping` reachability check. +- Regenerate `README.md` from `variables.json` and `docker-compose.yml`. diff --git a/apps/mattermost/Notes.md b/apps/mattermost/Notes.md deleted file mode 100644 index b15c9274e..000000000 --- a/apps/mattermost/Notes.md +++ /dev/null @@ -1,16 +0,0 @@ -## Mattermost - -Mattermost 分为团队版和企业版,其中团队版即开源版 -官方文档:https://docs.mattermost.com/install/install-docker.html - -tag master 是每日更新版本 - -### 注意 - -* 容器默认为 PostgreSQL 数据库,使用 MySQL 数据库需要非常完整的数据库连接 - -## FAQ - -#### Why Postgres not MySQL for Mattermost? - -The official compose use PostgreSQL \ No newline at end of file diff --git a/apps/mattermost/README.md b/apps/mattermost/README.md index 3c01b3896..35637a9c2 100644 --- a/apps/mattermost/README.md +++ b/apps/mattermost/README.md @@ -1,26 +1,85 @@ -# Mattermost on Docker +# Mattermost on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Mattermost: +## Quick Start +### Deploy Verification - - community: 10.9 +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Mattermost**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Mattermost admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://docs.mattermost.com/install/install-docker.html/): +### Change Password -* **RAM**: 2 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 8 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Mattermost by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Mattermost Docker image](https://hub.docker.com/r/mattermost/mattermost-team-edition) and makes some improvements below. -If you want use Mattermost with **Websoft9 Business Support** free, you can [subscribe Mattermost](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Mattermost Administrator Guide](https://support.websoft9.com/docs/mattermost) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 11.11. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Mattermost web UI and REST API | 8065 | + + +### Data Directory + + +- `mattermost_config` → `/mattermost/config:rw` +- `mattermost_data` → `/mattermost/data:rw` +- `mattermost_logs` → `/mattermost/logs:rw` +- `mattermost_plugins` → `/mattermost/plugins:rw` +- `mattermost_client_plugins` → `/mattermost/client/plugins:rw` +- `mattermost_bleve-indexes` → `/mattermost/bleve-indexes:rw` +- `postgres` → `/var/lib/postgresql/data` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Mattermost Administrator Guide](https://support.websoft9.com/docs/mattermost) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/mattermost/mattermost-team-edition) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/mattermost/docker-compose.yml b/apps/mattermost/docker-compose.yml index 333606914..26956d53b 100644 --- a/apps/mattermost/docker-compose.yml +++ b/apps/mattermost/docker-compose.yml @@ -1,8 +1,3 @@ -# docs: https://docs.mattermost.com/install/install-docker.html#deploy-mattermost-on-docker-for-production-use -# image: https://hub.docker.com/r/mattermost/mattermost-team-edition - -version: '3.8' - services: mattermost: image: ${W9_REPO}:${W9_VERSION} @@ -11,9 +6,9 @@ services: security_opt: - no-new-privileges:true ports: - - ${W9_HTTP_PORT_SET}:8065 - - ${W9_TCP_PORT_SET}:8443/tcp - - ${W9_UDP_PORT_SET}:8443/udp + - "${W9_HTTP_PORT_SET}:8065" # Mattermost web UI and REST API + - "${W9_TCP_PORT_SET}:8443/tcp" # Mattermost Calls (TCP) + - "${W9_UDP_PORT_SET}:8443/udp" # Mattermost Calls (UDP) volumes: - mattermost_config:/mattermost/config:rw - mattermost_data:/mattermost/data:rw diff --git a/apps/mattermost/src/READEME.md b/apps/mattermost/src/READEME.md new file mode 100644 index 000000000..ec4600406 --- /dev/null +++ b/apps/mattermost/src/READEME.md @@ -0,0 +1 @@ +# Readme \ No newline at end of file diff --git a/apps/mattermost/src/after_up.sh b/apps/mattermost/src/after_up.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/mattermost/src/after_up.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/mattermost/src/docker-compose.yml b/apps/mattermost/src/docker-compose.yml deleted file mode 100644 index 5bca4fed5..000000000 --- a/apps/mattermost/src/docker-compose.yml +++ /dev/null @@ -1,68 +0,0 @@ - -version: "3" - -services: - - db: - build: db - read_only: true - restart: unless-stopped - volumes: - - ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data - - /etc/localtime:/etc/localtime:ro - environment: - - POSTGRES_USER=mmuser - - POSTGRES_PASSWORD=mmuser_password - - POSTGRES_DB=mattermost - # uncomment the following to enable backup - # - AWS_ACCESS_KEY_ID=XXXX - # - AWS_SECRET_ACCESS_KEY=XXXX - # - WALE_S3_PREFIX=s3://BUCKET_NAME/PATH - # - AWS_REGION=us-east-1 - - app: - build: - context: app - # uncomment following lines for team edition or change UID/GID - # args: - # - edition=team - # - PUID=1000 - # - PGID=1000 - # - MM_VERSION=5.31 - restart: unless-stopped - volumes: - - ./volumes/app/mattermost/config:/mattermost/config:rw - - ./volumes/app/mattermost/data:/mattermost/data:rw - - ./volumes/app/mattermost/logs:/mattermost/logs:rw - - ./volumes/app/mattermost/plugins:/mattermost/plugins:rw - - ./volumes/app/mattermost/client-plugins:/mattermost/client/plugins:rw - - /etc/localtime:/etc/localtime:ro - # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine - # to avoid Token request failed: certificate signed by unknown authority (link: https://github.com/mattermost/mattermost-server/issues/13059) - # - /pki_chain.pem:/etc/ssl/certs/pki_chain.pem:ro - environment: - # set same as db credentials and dbname - - MM_USERNAME=mmuser - - MM_PASSWORD=mmuser_password - - MM_DBNAME=mattermost - - # use the credentials you've set above, in the format: - # MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 - - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 - - # in case your config is not in default location - #- MM_CONFIG=/mattermost/config/config.json - - web: - build: web - ports: - - "80:8080" - - "443:8443" - read_only: true - restart: unless-stopped - volumes: - # This directory must have cert files if you want to enable SSL - - ./volumes/web/cert:/cert:ro - - /etc/localtime:/etc/localtime:ro - cap_drop: - - ALL \ No newline at end of file diff --git a/apps/mattermost/src/filelist b/apps/mattermost/src/filelist deleted file mode 100644 index 412c25747..000000000 --- a/apps/mattermost/src/filelist +++ /dev/null @@ -1 +0,0 @@ -docker-compose.yml \ No newline at end of file diff --git a/apps/mattermost/src/get_version.sh b/apps/mattermost/src/get_version.sh deleted file mode 100644 index 4d9e17d8c..000000000 --- a/apps/mattermost/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ -sudo echo "Mattermost version:" $(sudo docker exec -i mattermost /mattermost/bin/mattermost version|grep -i "version" | cut -d ":" -f 2) |sudo tee -a /data/logs/install_version.txt diff --git a/apps/mattermost/tests/cases.yml b/apps/mattermost/tests/cases.yml new file mode 100644 index 000000000..24ef50c36 --- /dev/null +++ b/apps/mattermost/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: system-ping + type: web-access + path: /api/v4/system/ping + expect_status: 200 diff --git a/apps/mattermost/variables.json b/apps/mattermost/variables.json index 6584f0e0b..f69a02fe2 100644 --- a/apps/mattermost/variables.json +++ b/apps/mattermost/variables.json @@ -9,7 +9,7 @@ { "dist": "community", "version": [ - "11.1" + "11.11" ] } ], diff --git a/apps/mautic/variables.json b/apps/mautic/variables.json index 207ed64b4..b298b61de 100644 --- a/apps/mautic/variables.json +++ b/apps/mautic/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/meilisearch/variables.json b/apps/meilisearch/variables.json index e10e912cd..49f53b80c 100644 --- a/apps/meilisearch/variables.json +++ b/apps/meilisearch/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/getmeili/meilisearch" + }, + "access": { + "defaultScheme": "http", + "api": { + "port": 7700, + "path": "/" + } } } diff --git a/apps/metabase/.env b/apps/metabase/.env index 6d65f0492..76def0ded 100644 --- a/apps/metabase/.env +++ b/apps/metabase/.env @@ -1,24 +1,44 @@ W9_REPO=metabase/metabase -W9_VERSION='v0.57.5.3' -W9_POWER_PASSWORD='mbt3oi7!kWiEhO5k' +W9_DIST=community +W9_VERSION=v0.64.x + +# Optional password seed: enable only when the package actually controls a DB or built-in login. +# See docs/w9-env-spec.md for when W9_POWER_PASSWORD is appropriate. +W9_POWER_PASSWORD="mbt3oi7!kWiEhO5k" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='metabase' -W9_HTTP_PORT_SET='9001' -W9_HTTP_PORT=3000 -W9_URL='appname.example.com' -W9_DB_EXPOSE="postgresql" -W9_DB_VERSION="13" +W9_ID=metabase +W9_HTTP_PORT=3000 +W9_HTTP_PORT_SET=9001 +W9_DB_EXPOSE=postgresql +W9_DB_VERSION=14 +W9_URL=appname.example.com W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Metabase image environment variables +# Docs: https://www.metabase.com/docs/latest/installation-and-operation/running-metabase-on-docker +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: MB_DB_TYPE=postgres -MB_DB_DBNAME=$W9_ID +MB_DB_DBNAME=${W9_ID} MB_DB_PORT=5432 MB_DB_USER=postgres -MB_DB_PASS=$W9_POWER_PASSWORD -MB_DB_HOST=$W9_ID-postgresql +MB_DB_PASS=${W9_POWER_PASSWORD} +MB_DB_HOST=${W9_ID}-postgresql JAVA_TIMEZONE=America/Los_Angeles -W9_DIST='community' + +# Not used by default; enable only when needed: +# MB_PLUGINS_DIR=/plugins +# MB_JETTY_PORT=3000 diff --git a/apps/metabase/CHANGELOG.md b/apps/metabase/CHANGELOG.md index 582cf46c5..4f55e6cfc 100644 --- a/apps/metabase/CHANGELOG.md +++ b/apps/metabase/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-08 +- Updated Metabase from `v0.57.5.3` to `v0.64.x`. +- Updated bundled PostgreSQL from `13` to `14` for Metabase 0.64 compatibility. +- Normalized `.env` and `docker-compose.yml` to current repository policy requirements. +- Added app-specific validation coverage for the Metabase setup path. diff --git a/apps/metabase/Notes.md b/apps/metabase/Notes.md deleted file mode 100644 index f08d78f61..000000000 --- a/apps/metabase/Notes.md +++ /dev/null @@ -1,3 +0,0 @@ -## docker-compose - -如果提供的镜像是通过cmd来启动容器,则可以通过在cmd中增加命令来改变启动过程;但是enterpoint无法修改? diff --git a/apps/metabase/README.md b/apps/metabase/README.md index f4e5fe886..48bfef10a 100644 --- a/apps/metabase/README.md +++ b/apps/metabase/README.md @@ -1,26 +1,88 @@ -# Metabase on Docker +# Metabase on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Metabase: +## Quick Start +### Deploy Verification - - community: v0.54.2.4, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Metabase**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Metabase admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://www.metabase.com/docs/latest/operations-guide/running-metabase-on-docker.html): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Metabase by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Metabase Docker image](https://hub.docker.com/r/metabase/metabase) and makes some improvements below. -If you want use Metabase with **Websoft9 Business Support** free, you can [subscribe Metabase](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Metabase Administrator Guide](https://support.websoft9.com/docs/metabase) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: v0.64.x, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | + + +### Data Directory + + +- `metabase-data` → `/metabase-data` +- `metabase-plugins` → `/plugins` +- `postgres` → `/var/lib/postgresql/data` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Metabase Administrator Guide](https://support.websoft9.com/docs/metabase) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/metabase/metabase) + +- [Releases](https://github.com/metabase/metabase/releases) + +- [Official docs](https://www.metabase.com/docs/latest/installation-and-operation/running-metabase-on-docker) + +- [Official docs](https://www.metabase.com/docs/latest/operations-guide/upgrading-metabase) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/metabase/docker-compose.yml b/apps/metabase/docker-compose.yml index 326a74cc3..64a3fbf77 100644 --- a/apps/metabase/docker-compose.yml +++ b/apps/metabase/docker-compose.yml @@ -1,32 +1,28 @@ -# docs: https://www.metabase.com/docs/latest/operations-guide/running-metabase-on-docker.html -# image: https://hub.docker.com/r/metabase/metabase - -version: '3.8' services: metabase: - image: $W9_REPO:$W9_VERSION + image: ${W9_REPO}:${W9_VERSION} restart: unless-stopped - container_name: $W9_ID - hostname: $W9_ID - volumes: - - metabase-data:/metabase-data - - metabase-plugins:/plugins + container_name: ${W9_ID} + hostname: ${W9_ID} + volumes: + - metabase-data:/metabase-data + - metabase-plugins:/plugins ports: - - '$W9_HTTP_PORT_SET:$W9_HTTP_PORT' + - '${W9_HTTP_PORT_SET}:3000' # Web Console env_file: .env - depends_on: + depends_on: - postgres postgres: - container_name: $W9_ID-postgresql - image: postgres:$W9_DB_VERSION + container_name: ${W9_ID}-postgresql + image: postgres:${W9_DB_VERSION} restart: unless-stopped volumes: - postgres:/var/lib/postgresql/data environment: - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=$W9_POWER_PASSWORD - - POSTGRES_DB=$W9_ID + - POSTGRES_PASSWORD=${W9_POWER_PASSWORD} + - POSTGRES_DB=${W9_ID} volumes: postgres: diff --git a/apps/metabase/src/READEME.md b/apps/metabase/src/READEME.md new file mode 100644 index 000000000..ec4600406 --- /dev/null +++ b/apps/metabase/src/READEME.md @@ -0,0 +1 @@ +# Readme \ No newline at end of file diff --git a/apps/metabase/src/after_up.sh b/apps/metabase/src/after_up.sh deleted file mode 100644 index f1662e7af..000000000 --- a/apps/metabase/src/after_up.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo systemctl stop nginx -cd /opt -chmod +x create_users.sh -MB_HOSTNAME=localhost MB_PORT=9001 W9_POWER_PASSWORD=$W9_POWER_PASSWORD ./create_users.sh -sudo systemctl start nginx diff --git a/apps/metabase/src/create_user.sh b/apps/metabase/src/create_user.sh deleted file mode 100644 index 4dfffb69f..000000000 --- a/apps/metabase/src/create_user.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -# copy from: https://www.metabase.com/learn/administration/serialization#add-users-to-our-metabase-origin-environment - -ADMIN_EMAIL=${MB_ADMIN_EMAIL:-admin@metabase.local} -ADMIN_PASSWORD=${W9_POWER_PASSWORD:-Metapass123} - -METABASE_HOST=${MB_HOSTNAME} -METABASE_PORT=${MB_PORT:-3000} - -echo "⌚︎ Waiting for Metabase to start" -while (! curl -s -m 5 http://${METABASE_HOST}:${METABASE_PORT}/api/session/properties -o /dev/null); do sleep 5; done - -echo "😎 Creating admin user" - -SETUP_TOKEN=$(curl -s -m 5 -X GET \ - -H "Content-Type: application/json" \ - http://${METABASE_HOST}:${METABASE_PORT}/api/session/properties \ - | jq -r '.["setup-token"]' -) - -MB_TOKEN=$(curl -s -X POST \ - -H "Content-type: application/json" \ - http://${METABASE_HOST}:${METABASE_PORT}/api/setup \ - -d '{ - "token": "'${SETUP_TOKEN}'", - "user": { - "email": "'${ADMIN_EMAIL}'", - "first_name": "Metabase", - "last_name": "Admin", - "password": "'${ADMIN_PASSWORD}'" - }, - "prefs": { - "allow_tracking": false, - "site_name": "Metawhat" - } -}' | jq -r '.id') - - -echo -e "\n👥 Creating some basic users: " -curl -s "http://${METABASE_HOST}:${METABASE_PORT}/api/user" \ - -H 'Content-Type: application/json' \ - -H "X-Metabase-Session: ${MB_TOKEN}" \ - -d '{"first_name":"Basic","last_name":"User","email":"basic@somewhere.com","login_attributes":{"region_filter":"WA"},"password":"'${ADMIN_PASSWORD}'"}' - -curl -s "http://${METABASE_HOST}:${METABASE_PORT}/api/user" \ - -H 'Content-Type: application/json' \ - -H "X-Metabase-Session: ${MB_TOKEN}" \ - -d '{"first_name":"Basic 2","last_name":"User","email":"basic2@somewhere.com","login_attributes":{"region_filter":"CA"},"password":"'${ADMIN_PASSWORD}'"}' - -echo -e "\n👥 Basic users created!" diff --git a/apps/metabase/src/get_version.sh b/apps/metabase/src/get_version.sh deleted file mode 100644 index adf1657de..000000000 --- a/apps/metabase/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ -sudo echo "metabase version:" $(curl https://api.github.com/repos/metabase/metabase/releases/latest |jq -r .tag_name) |sudo tee -a /data/logs/install_version.txt diff --git a/apps/metabase/tests/cases.yml b/apps/metabase/tests/cases.yml new file mode 100644 index 000000000..86e78265f --- /dev/null +++ b/apps/metabase/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: setup-page + type: web-access + path: /setup + expect_status: 200 diff --git a/apps/metabase/variables.json b/apps/metabase/variables.json index 6d7716197..fc8245a1d 100644 --- a/apps/metabase/variables.json +++ b/apps/metabase/variables.json @@ -2,11 +2,19 @@ "name": "metabase", "trademark": "Metabase", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/metabase/metabase", + "releases": "https://github.com/metabase/metabase/releases", + "docs": [ + "https://www.metabase.com/docs/latest/installation-and-operation/running-metabase-on-docker", + "https://www.metabase.com/docs/latest/operations-guide/upgrading-metabase" + ] + }, "edition": [ { "dist": "community", "version": [ - "v0.57.5.3", + "v0.64.x", "latest" ] } @@ -23,7 +31,7 @@ "memory": "1", "disk": "1" }, - "upstream": { - "image": "https://hub.docker.com/r/metabase/metabase" + "help": { + "login": "First run: open the site and create the administrator account in the Metabase setup wizard, then sign in with those credentials." } } diff --git a/apps/milvus/variables.json b/apps/milvus/variables.json index 18813e7e3..b92c8058f 100644 --- a/apps/milvus/variables.json +++ b/apps/milvus/variables.json @@ -19,10 +19,6 @@ "web": { "port": 9091, "path": "/" - }, - "admin": { - "port": 9091, - "path": "/webui" } }, "requirements": { diff --git a/apps/miniflux/variables.json b/apps/miniflux/variables.json index fdb1d916c..cb1333975 100644 --- a/apps/miniflux/variables.json +++ b/apps/miniflux/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/minio/variables.json b/apps/minio/variables.json index b9b32a3f6..b99e958c0 100644 --- a/apps/minio/variables.json +++ b/apps/minio/variables.json @@ -11,6 +11,17 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 9001, + "path": "/" + }, + "api": { + "port": 9000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/mixpost/variables.json b/apps/mixpost/variables.json index feb392b7b..12e590856 100644 --- a/apps/mixpost/variables.json +++ b/apps/mixpost/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/mlflow/variables.json b/apps/mlflow/variables.json index e9a0d9545..16827dd65 100644 --- a/apps/mlflow/variables.json +++ b/apps/mlflow/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 5000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/mongocompass/variables.json b/apps/mongocompass/variables.json index b384c20c0..6952514c2 100644 --- a/apps/mongocompass/variables.json +++ b/apps/mongocompass/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "https", + "web": { + "port": 6901, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/mongodb/.env b/apps/mongodb/.env index 737ca01b7..2d4b47060 100644 --- a/apps/mongodb/.env +++ b/apps/mongodb/.env @@ -1,15 +1,34 @@ -# versions for you 4.4 -W9_POWER_PASSWORD='0ujq9yv!hHhHa9nk' -W9_VERSION='8.2.2' W9_REPO=mongo +W9_DIST=community +W9_VERSION=7.0 +W9_POWER_PASSWORD="0ujq9yv!hHhHa9nk" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='mongodb' -W9_DB_PORT=27017 -W9_DB_PORT_SET='27017' + +W9_ID=mongodb +W9_DB_PORT_SET=27017 W9_LOGIN_USER=root -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD -W9_COMMAND="--wiredTigerCacheSizeGB 2 --config /etc/mongod.conf" +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### -W9_DIST='community' + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# MongoDB image environment variables +# Docs: https://hub.docker.com/_/mongo +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +MONGO_INITDB_ROOT_USERNAME=${W9_LOGIN_USER} +MONGO_INITDB_ROOT_PASSWORD=${W9_LOGIN_PASSWORD} + +# Not used by default; enable only when needed: +# MONGO_INITDB_DATABASE= +# MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_root_username +# MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_root_password diff --git a/apps/mongodb/CHANGELOG.md b/apps/mongodb/CHANGELOG.md index 582cf46c5..b99ff106a 100644 --- a/apps/mongodb/CHANGELOG.md +++ b/apps/mongodb/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Prune MongoDB versions that are out of vendor maintenance, keeping only the maintained tracks `8.3`, `8.0`, and `7.0` (plus `latest`). +- Move the default image to `7.0`: the maintained `8.3` and `8.0` images still refuse to start on Linux kernel 6.19+/Ubuntu 26.04 (upstream fix pending in 8.3.14 / 8.0.35). +- Track MongoDB lifecycle facts in `metadata/db-lifecycle.json`. +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, inline `command`, and refreshed upstream metadata. +- Record first-startup-only credential variables and add a mongosh connectivity smoke test for deployment validation. diff --git a/apps/mongodb/Notes.md b/apps/mongodb/Notes.md deleted file mode 100644 index bf098a0f2..000000000 --- a/apps/mongodb/Notes.md +++ /dev/null @@ -1,15 +0,0 @@ -## MongoDB - -### MongoDB的认证 - -MongoDB认证与下列三处相关: -- 环境变量用户和密码的设置,如果设置用户和密码后,默认已经开启了认证 -- 通过挂载mongod.conf配置文件设置认证相关选项 -- 通过comman参数--noauth或--auth直接设置 - - > 优先度:环境变量>command参数>mongod.conf,并且如果环境变量设置了用户密码,comman参数设置成--noauth,无法启动容器 - - - #### How to get the mantaince version of MongoDB? - - refer to: https://www.mongodb.com/try/download/community diff --git a/apps/mongodb/README.md b/apps/mongodb/README.md index 2f18f826f..8662cc05b 100644 --- a/apps/mongodb/README.md +++ b/apps/mongodb/README.md @@ -1,26 +1,89 @@ -# MongoDB on Docker +# MongoDB on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for MongoDB: +## Quick Start +### Deploy Verification - - community: 8.0.3, 7.0.4, 6.0.12, 5.0.23, 4.4.26, 4.2.24-rc2, 4.2.24, 4.0.28, 3.6.23, 3.4.24, 3.2.21, 3.0.15, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **MongoDB**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the MongoDB admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://github.com/mongodb/docker#recommended-system-requirements): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this MongoDB by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [MongoDB Docker image](https://hub.docker.com/_/mongo) and makes some improvements below. -If you want use MongoDB with **Websoft9 Business Support** free, you can [subscribe MongoDB](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[MongoDB Administrator Guide](https://support.websoft9.com/docs/mongodb) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 8.3, 8.0, 7.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| MongoDB | 27017 | + + +### Data Directory + + +Data is persisted in the `mongo_data` volume, mounted at `/data/db`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `MONGO_INITDB_ROOT_USERNAME`, `MONGO_INITDB_ROOT_PASSWORD` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration is overridden by mounting `./src/mongod.conf` to `/etc/mongod.conf`. + + +## References + +- [MongoDB Administrator Guide](https://support.websoft9.com/docs/mongodb) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/mongo) + +- [GitHub docs](https://github.com/docker-library/mongo) + +- [Official docs](https://www.mongodb.com/docs/manual/installation/) + +- [Official docs](https://www.mongodb.com/docs/manual/reference/versioning/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/mongodb/docker-compose.yml b/apps/mongodb/docker-compose.yml index d0c0128e6..067b8db53 100644 --- a/apps/mongodb/docker-compose.yml +++ b/apps/mongodb/docker-compose.yml @@ -1,20 +1,12 @@ -# refer to: https://github.com/docker-library/docs/blob/master/mongo/stack.yml -# image: https://hub.docker.com/_/mongo - -version: '3.8' - services: mongo: image: ${W9_REPO}:${W9_VERSION} restart: unless-stopped container_name: ${W9_ID} ports: - - ${W9_DB_PORT_SET}:${W9_DB_PORT} + - "${W9_DB_PORT_SET}:27017" # MongoDB env_file: .env - environment: - MONGO_INITDB_ROOT_USERNAME: ${W9_LOGIN_USER} - MONGO_INITDB_ROOT_PASSWORD: ${W9_LOGIN_PASSWORD} - command: ${W9_COMMAND} + command: --wiredTigerCacheSizeGB 2 --config /etc/mongod.conf volumes: - mongo_data:/data/db - ./src/mongod.conf:/etc/mongod.conf @@ -23,6 +15,6 @@ networks: default: name: ${W9_NETWORK} external: true - + volumes: mongo_data: diff --git a/apps/mongodb/src/get_version.sh b/apps/mongodb/src/get_version.sh deleted file mode 100644 index 7a6d2c07b..000000000 --- a/apps/mongodb/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ -sudo echo "MongoDB version:" $(docker exec -i $1 mongod --version | grep db | cut -d " " -f 3) >> /data/logs/install_version.txt diff --git a/apps/mongodb/tests/cases.yml b/apps/mongodb/tests/cases.yml new file mode 100644 index 000000000..df8324f2e --- /dev/null +++ b/apps/mongodb/tests/cases.yml @@ -0,0 +1,7 @@ +# MongoDB has no HTTP surface, so the adaptive web-access check does not apply. +# Its core path is accepting authenticated client connections, so a custom +# script runs an authenticated mongosh ping inside the container. +custom: + - id: mongosh-ping + type: script + script: check.sh diff --git a/apps/mongodb/tests/check.sh b/apps/mongodb/tests/check.sh new file mode 100755 index 000000000..05f8beec2 --- /dev/null +++ b/apps/mongodb/tests/check.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +container="${W9_ID:?W9_ID is required}" +user="${W9_LOGIN_USER:?W9_LOGIN_USER is required}" +password="${W9_LOGIN_PASSWORD:?W9_LOGIN_PASSWORD is required}" + +deadline=$((SECONDS + 180)) +while [ "${SECONDS}" -lt "${deadline}" ]; do + result="$(docker exec "${container}" mongosh --quiet --username "${user}" --password "${password}" --authenticationDatabase admin --eval 'db.runCommand({ ping: 1 }).ok' 2>/dev/null || true)" + if [ "${result}" = "1" ]; then + echo "MongoDB accepted an authenticated local ping" + exit 0 + fi + sleep 5 +done + +echo "MongoDB did not accept an authenticated ping before timeout" >&2 +exit 1 diff --git a/apps/mongodb/variables.json b/apps/mongodb/variables.json index eb7ab0de5..b53f062b1 100644 --- a/apps/mongodb/variables.json +++ b/apps/mongodb/variables.json @@ -6,19 +6,9 @@ { "dist": "community", "version": [ - "8.2.2", - "8.0.3", - "7.0.4", - "6.0.12", - "5.0.23", - "4.4.26", - "4.2.24-rc2", - "4.2.24", - "4.0.28", - "3.6.23", - "3.4.24", - "3.2.21", - "3.0.15", + "8.3", + "8.0", + "7.0", "latest" ] } @@ -29,6 +19,17 @@ "disk": "1" }, "upstream": { - "image": "https://hub.docker.com/_/mongo" + "image": "https://hub.docker.com/_/mongo", + "docs": [ + "https://github.com/docker-library/mongo", + "https://www.mongodb.com/docs/manual/installation/", + "https://www.mongodb.com/docs/manual/reference/versioning/" + ] + }, + "env": { + "first_startup_only": [ + "MONGO_INITDB_ROOT_USERNAME", + "MONGO_INITDB_ROOT_PASSWORD" + ] } } diff --git a/apps/mongoexpress/variables.json b/apps/mongoexpress/variables.json index 823c4a3ee..1bd405118 100644 --- a/apps/mongoexpress/variables.json +++ b/apps/mongoexpress/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8081, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/monkeycode/variables.json b/apps/monkeycode/variables.json index 878430595..fb0783722 100644 --- a/apps/monkeycode/variables.json +++ b/apps/monkeycode/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/mqttx/variables.json b/apps/mqttx/variables.json index 6c14fdd52..2d7ab2d70 100644 --- a/apps/mqttx/variables.json +++ b/apps/mqttx/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/mysqlworkbench/variables.json b/apps/mysqlworkbench/variables.json index 58464c88f..4000e66ec 100644 --- a/apps/mysqlworkbench/variables.json +++ b/apps/mysqlworkbench/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/linuxserver/mysql-workbench" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 3000, + "path": "/" + } } } diff --git a/apps/navidrome/variables.json b/apps/navidrome/variables.json index 7c7c9c5c5..2fdb4f45b 100644 --- a/apps/navidrome/variables.json +++ b/apps/navidrome/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 4533, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/neko/variables.json b/apps/neko/variables.json index e613a53d2..801eec03d 100644 --- a/apps/neko/variables.json +++ b/apps/neko/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/neo4j/variables.json b/apps/neo4j/variables.json index 0a7d2d635..ee65591e8 100644 --- a/apps/neo4j/variables.json +++ b/apps/neo4j/variables.json @@ -13,6 +13,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 7474, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/netdata/variables.json b/apps/netdata/variables.json index 4f9e2aca2..29385830a 100644 --- a/apps/netdata/variables.json +++ b/apps/netdata/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 19999, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nextchat/variables.json b/apps/nextchat/variables.json index 5614ccaa8..9063b8d37 100644 --- a/apps/nextchat/variables.json +++ b/apps/nextchat/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nexterm/variables.json b/apps/nexterm/variables.json index f070a206f..d79598c7a 100644 --- a/apps/nexterm/variables.json +++ b/apps/nexterm/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 6989, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/nextterminal/variables.json b/apps/nextterminal/variables.json index 0d81f9414..eb28e0bb4 100644 --- a/apps/nextterminal/variables.json +++ b/apps/nextterminal/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8088, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nexus/variables.json b/apps/nexus/variables.json index 3df67721e..0fd91eb25 100644 --- a/apps/nexus/variables.json +++ b/apps/nexus/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8081, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/nginx/variables.json b/apps/nginx/variables.json index 5fb590234..bcdcfdee7 100644 --- a/apps/nginx/variables.json +++ b/apps/nginx/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nocobase/variables.json b/apps/nocobase/variables.json index f317c87b1..971373baf 100644 --- a/apps/nocobase/variables.json +++ b/apps/nocobase/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nocodb/variables.json b/apps/nocodb/variables.json index bcb4436b1..d78c0b0a0 100644 --- a/apps/nocodb/variables.json +++ b/apps/nocodb/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/nodejs/variables.json b/apps/nodejs/variables.json index 14066cfca..8edcdd001 100644 --- a/apps/nodejs/variables.json +++ b/apps/nodejs/variables.json @@ -38,5 +38,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/node" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/nodered/variables.json b/apps/nodered/variables.json index 535412c8b..f157f02da 100644 --- a/apps/nodered/variables.json +++ b/apps/nodered/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 1880, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/nomad/variables.json b/apps/nomad/variables.json index 1e4dfee16..a128459e1 100644 --- a/apps/nomad/variables.json +++ b/apps/nomad/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/hashicorp/nomad" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/nopcommerce/.env b/apps/nopcommerce/.env index 12040fa55..b907ed5b8 100644 --- a/apps/nopcommerce/.env +++ b/apps/nopcommerce/.env @@ -1,14 +1,46 @@ -W9_POWER_PASSWORD='G2lduAjN!7!OHrju' -W9_VERSION='4.90.2' -W9_DIST='community' W9_REPO=nopcommerceteam/nopcommerce +W9_DIST=community +W9_VERSION=4.90.8 + +# Optional password seed: enabled because this package controls the bundled MySQL credentials. +W9_POWER_PASSWORD='G2lduAjN!7!OHrju' + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='nopcommerce' + +W9_ID=nopcommerce W9_HTTP_PORT=80 -W9_HTTP_PORT_SET='9001' -W9_URL='appname.example.com' -W9_DB_EXPOSE="mysql" +W9_HTTP_PORT_SET=9001 +W9_DB_EXPOSE=mysql W9_DB_VERSION=8.0 +W9_URL=appname.example.com W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### + +#### ----------------------------------------------------------------------------------------- #### + +#W9_NAME="" +#W9_RCODE="" + +# ============================================================ +# NopCommerce image environment variables +# Docs: https://hub.docker.com/r/nopcommerceteam/nopcommerce +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +MYSQL_DATABASE=nopcommerce +MYSQL_USER=nopcommerce +MYSQL_PASSWORD=${W9_POWER_PASSWORD} +MYSQL_ROOT_PASSWORD=${W9_POWER_PASSWORD} + +# Not used by default; enable only when needed: +# APP_VAR_1= +# APP_VAR_2= +# APP_VAR_3= +# APP_VAR_4= +# APP_VAR_5= diff --git a/apps/nopcommerce/CHANGELOG.md b/apps/nopcommerce/CHANGELOG.md index 582cf46c5..38eed43f7 100644 --- a/apps/nopcommerce/CHANGELOG.md +++ b/apps/nopcommerce/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Updated NopCommerce from `4.90.2` to `4.90.8`. +- Normalized `.env` and `docker-compose.yml` to current repository policy, including braced variable references and inline port purpose comments. +- Added app-specific validation coverage with `tests/cases.yml`. diff --git a/apps/nopcommerce/README.md b/apps/nopcommerce/README.md index d882f6b2a..1e9d05041 100644 --- a/apps/nopcommerce/README.md +++ b/apps/nopcommerce/README.md @@ -1,26 +1,88 @@ -# NopCommerce on Docker +# NopCommerce on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for NopCommerce: +## Quick Start +### Deploy Verification - - community: 4.80.5, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **NopCommerce**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the NopCommerce admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://docs.nopcommerce.com/en/installation-and-upgrading/technology-and-system-requirements.html): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this NopCommerce by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [NopCommerce Docker image](https://hub.docker.com/r/nopcommerceteam/nopcommerce) and makes some improvements below. -If you want use NopCommerce with **Websoft9 Business Support** free, you can [subscribe NopCommerce](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[NopCommerce Administrator Guide](https://support.websoft9.com/docs/nopcommerce) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 4.90.8, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 80 | + + +### Data Directory + + +- `nopcommerce` → `/app` +- `mysql` → `/var/lib/mysql` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [NopCommerce Administrator Guide](https://support.websoft9.com/docs/nopcommerce) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/nopcommerceteam/nopcommerce) + +- [Releases](https://github.com/nopSolutions/nopCommerce/releases) + +- [GitHub docs](https://github.com/nopSolutions/nopCommerce/releases/tag/release-4.90.8) + +- [Official docs](https://www.nopcommerce.com/release-notes) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/nopcommerce/docker-compose.yml b/apps/nopcommerce/docker-compose.yml index eec269f8d..7860bb5af 100644 --- a/apps/nopcommerce/docker-compose.yml +++ b/apps/nopcommerce/docker-compose.yml @@ -1,36 +1,32 @@ -# compose: https://github.com/nopSolutions/nopCommerce/blob/develop/docker-compose.yml -# image: https://hub.docker.com/r/nopcommerceteam/nopcommerce/tags - -version: '3.8' - services: nopcommerce: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} ports: - - ${W9_HTTP_PORT_SET}:80 + - "${W9_HTTP_PORT_SET}:80" # Web Console volumes: - nopcommerce:/app - depends_on: + depends_on: - mysql restart: unless-stopped env_file: .env mysql: - image: mysql:$W9_DB_VERSION - container_name: $W9_ID-mysql + image: mysql:${W9_DB_VERSION} + container_name: ${W9_ID}-mysql restart: unless-stopped - command: - - --character-set-server=utf8mb4 + command: + - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --default-authentication-plugin=mysql_native_password volumes: - mysql:/var/lib/mysql + env_file: .env environment: - MYSQL_DATABASE: nopcommerce - MYSQL_USER: nopcommerce - MYSQL_PASSWORD: $W9_POWER_PASSWORD - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} networks: default: diff --git a/apps/nopcommerce/tests/cases.yml b/apps/nopcommerce/tests/cases.yml new file mode 100644 index 000000000..b4e0215fb --- /dev/null +++ b/apps/nopcommerce/tests/cases.yml @@ -0,0 +1,4 @@ +custom: + - id: install-page + type: script + script: smoke-install-page.sh diff --git a/apps/nopcommerce/tests/smoke-install-page.sh b/apps/nopcommerce/tests/smoke-install-page.sh new file mode 100755 index 000000000..3ed747236 --- /dev/null +++ b/apps/nopcommerce/tests/smoke-install-page.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +tmp_file="$(mktemp)" +trap 'rm -f "${tmp_file}"' EXIT + +curl -fsSL "${BASE_URL}" -o "${tmp_file}" +grep -qi "nopCommerce" "${tmp_file}" diff --git a/apps/nopcommerce/variables.json b/apps/nopcommerce/variables.json index 0151e1c6d..30a0f2880 100644 --- a/apps/nopcommerce/variables.json +++ b/apps/nopcommerce/variables.json @@ -6,17 +6,29 @@ { "dist": "community", "version": [ - "4.90.2", + "4.90.8", "latest" ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", "disk": "1" }, "upstream": { - "image": "https://hub.docker.com/r/nopcommerceteam/nopcommerce" + "image": "https://hub.docker.com/r/nopcommerceteam/nopcommerce", + "releases": "https://github.com/nopSolutions/nopCommerce/releases", + "docs": [ + "https://github.com/nopSolutions/nopCommerce/releases/tag/release-4.90.8", + "https://www.nopcommerce.com/release-notes" + ] } } diff --git a/apps/odoo/variables.json b/apps/odoo/variables.json index 010613f75..bd6dda660 100644 --- a/apps/odoo/variables.json +++ b/apps/odoo/variables.json @@ -28,10 +28,6 @@ "web": { "port": 8069, "path": "/" - }, - "admin": { - "port": 8069, - "path": "/web/login" } }, "requirements": { diff --git a/apps/ollama/.env b/apps/ollama/.env index b0b9ad316..6b5c556ef 100644 --- a/apps/ollama/.env +++ b/apps/ollama/.env @@ -1,15 +1,33 @@ W9_REPO=ollama/ollama -W9_DIST='community' -W9_VERSION='0.13.1' -W9_POWER_PASSWORD='3!1ImmOey5YJjKMy' -W9_HTTP_PORT_SET='9001' -W9_ID='ollama' +W9_DIST=community +W9_VERSION=0.40.2 + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=ollama +W9_HTTP_PORT_SET=9001 W9_HTTP_PORT=11434 -W9_URL='example.youdomain.com' -W9_URL_REPLACE=true +W9_URL=example.youdomain.com W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### +# ============================================================ +# Ollama image environment variables +# Docs: https://hub.docker.com/r/ollama/ollama +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: -# Below environment is created by app: https://github.com/ollama/ollama/blob/main/docs/docker.md +# Not used by default; enable only when needed: +# OLLAMA_HOST=0.0.0.0:11434 +# OLLAMA_KEEP_ALIVE=5m +# OLLAMA_MAX_LOADED_MODELS=1 +# OLLAMA_NUM_PARALLEL=1 +# CUDA_VISIBLE_DEVICES=0 diff --git a/apps/ollama/CHANGELOG.md b/apps/ollama/CHANGELOG.md index 582cf46c5..35e395c22 100644 --- a/apps/ollama/CHANGELOG.md +++ b/apps/ollama/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG -## Release -### Fixes and Enhancements - +## 2026-10-09 +- update Ollama from 0.13.1 to 0.40.2 +- align `.env`, `docker-compose.yml`, and upstream metadata with current repository policy +- add a basic API smoke test for `/api/tags` diff --git a/apps/ollama/README.md b/apps/ollama/README.md index 4371069c2..23afac622 100644 --- a/apps/ollama/README.md +++ b/apps/ollama/README.md @@ -1,26 +1,85 @@ -# Ollama on Docker +# Ollama on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Ollama: +## Quick Start +### Deploy Verification - - community: 0.9.1, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Ollama**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Ollama admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://ollama.com): +### Change Password -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 10 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Ollama by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Ollama Docker image](https://hub.docker.com/r/ollama/ollama) and makes some improvements below. -If you want use Ollama with **Websoft9 Business Support** free, you can [subscribe Ollama](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Ollama Administrator Guide](https://support.websoft9.com/docs/ollama) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 0.40.2, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| API | 11434 | +| API | 11434 | + + +### Data Directory + + +Data is persisted in the `ollama` volume, mounted at `/root/.ollama`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Ollama Administrator Guide](https://support.websoft9.com/docs/ollama) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/ollama/ollama) + +- [Releases](https://github.com/ollama/ollama/releases) + +- [GitHub docs](https://github.com/ollama/ollama/blob/main/docs/docker.md) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/ollama/docker-compose.yml b/apps/ollama/docker-compose.yml index becf0cd45..c930796c9 100644 --- a/apps/ollama/docker-compose.yml +++ b/apps/ollama/docker-compose.yml @@ -1,22 +1,18 @@ -# image and docs: https://hub.docker.com/r/ollama/ollama -# docs: https://github.com/ollama/ollama/blob/main/docs/docker.md - services: - app-nogpu: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:11434 - env_file: + - "${W9_HTTP_PORT_SET}:11434" # API + env_file: - .env volumes: - ollama:/root/.ollama app-nvidia: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped deploy: resources: @@ -27,8 +23,8 @@ services: capabilities: [gpu] runtime: nvidia ports: - - $W9_HTTP_PORT_SET:11434 - env_file: + - "${W9_HTTP_PORT_SET}:11434" # API + env_file: - .env volumes: - ollama:/root/.ollama @@ -40,5 +36,5 @@ volumes: networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true diff --git a/apps/ollama/tests/cases.yml b/apps/ollama/tests/cases.yml new file mode 100644 index 000000000..845e2eb80 --- /dev/null +++ b/apps/ollama/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: api-tags + type: web-access + path: /api/tags + expect_status: 200 diff --git a/apps/ollama/variables.json b/apps/ollama/variables.json index 4a4df94ae..7a45f883d 100644 --- a/apps/ollama/variables.json +++ b/apps/ollama/variables.json @@ -2,11 +2,18 @@ "name": "ollama", "trademark": "Ollama", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/ollama/ollama", + "releases": "https://github.com/ollama/ollama/releases", + "docs": [ + "https://github.com/ollama/ollama/blob/main/docs/docker.md" + ] + }, "edition": [ { "dist": "community", "version": [ - "0.13.1", + "0.40.2", "latest" ] } @@ -16,7 +23,11 @@ "memory": "4", "disk": "10" }, - "upstream": { - "image": "https://hub.docker.com/r/ollama/ollama" + "access": { + "defaultScheme": "http", + "api": { + "port": 11434, + "path": "/" + } } } diff --git a/apps/onlyofficedocs/variables.json b/apps/onlyofficedocs/variables.json index 98f78c943..0e31aa1c1 100644 --- a/apps/onlyofficedocs/variables.json +++ b/apps/onlyofficedocs/variables.json @@ -27,5 +27,12 @@ "https://api.onlyoffice.com/docs/docs-api/get-started/basic-concepts/", "https://github.com/ONLYOFFICE/Docker-DocumentServer" ] + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/openhands/.env b/apps/openhands/.env index 2fbe79cf8..26c56bb11 100644 --- a/apps/openhands/.env +++ b/apps/openhands/.env @@ -1,18 +1,41 @@ -W9_REPO="docker.all-hands.dev/all-hands-ai/openhands" -W9_DIST='community' -W9_VERSION='0.28' +W9_REPO=ghcr.io/openhands/agent-canvas +W9_DIST=community +W9_VERSION=1.26.0 -W9_HTTP_PORT_SET='9001' -W9_ID='openhands' -W9_HTTP_PORT=3000 -W9_URL='example.youdomain.com' -W9_URL_REPLACE=true +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=openhands +W9_HTTP_PORT_SET=9001 +W9_HTTP_PORT=8000 +W9_URL=example.youdomain.com W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### +# ============================================================ +# OpenHands image environment variables +# Docs: https://docs.openhands.dev/openhands/usage/agent-canvas/backend-setup/docker +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ -# Below environment is created by this app: +# Used by docker-compose.yml: +PORT=${W9_HTTP_PORT} +# Declared in variables.json `env.secrets`. The value below is a plain-text shape default; +# the platform may regenerate a same-shaped value and overwrite it on this instance. +# Backend API key the Canvas UI asks for on the login screen. +LOCAL_BACKEND_API_KEY=Kx7Qm2TpR9wZb4HnV1sLc6Dg0Fj3YaQd +# Encryption key for stored settings and secrets; keep it stable so saved secrets stay decryptable. +OH_SECRET_KEY=Pv5Rt8Wy2Nk7Mc4Xb1Lz6Df0Gh3Jq9Ue +AGENT_CANVAS_DISABLE_TELEMETRY=true -SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik -LOG_ALL_EVENTS=true +# Not used by default; enable only when needed: +# AGENT_CANVAS_ALLOW_LAN_SESSION_KEY=true +# OH_BIND_HOST=0.0.0.0 +# OH_CONVERSATION_RUNTIME=docker +# OH_DISABLE_AUTOMATIONS=false +# LOG_LEVEL=info diff --git a/apps/openhands/CHANGELOG.md b/apps/openhands/CHANGELOG.md index 582cf46c5..ac7dcf511 100644 --- a/apps/openhands/CHANGELOG.md +++ b/apps/openhands/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG -## Release -### Fixes and Enhancements - +## 2026-10-09 +- migrate the package from legacy OpenHands 0.28 to Agent Canvas 1.26.0 +- switch to the official `ghcr.io/openhands/agent-canvas` image and current Docker persistence layout +- add metadata for the generated API key and a `/canvas` smoke test +- set `LOCAL_BACKEND_API_KEY` and `OH_SECRET_KEY` from `W9_POWER_PASSWORD` so the UI API-key login and stored-secret encryption are fixed and known +- expose the login token as `LOCAL_BACKEND_API_KEY` and fix the credential source (was pointing at a non-existent state file path) +- provide plain-text `.env` defaults for `LOCAL_BACKEND_API_KEY` and `OH_SECRET_KEY` and declare them in `variables.json` `env.secrets` so the platform can regenerate same-shaped values diff --git a/apps/openhands/README.md b/apps/openhands/README.md index fc7e7cd3e..518dbc379 100644 --- a/apps/openhands/README.md +++ b/apps/openhands/README.md @@ -1,26 +1,89 @@ -# OpenHands on Docker +# OpenHands on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for OpenHands: +## Quick Start +### Deploy Verification - - community: 0.28 +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **OpenHands**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the OpenHands admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://www.all-hands.dev): +### Change Password -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 10 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this OpenHands by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [OpenHands Docker image](https://ghcr.io/openhands/agent-canvas) and makes some improvements below. -If you want use OpenHands with **Websoft9 Business Support** free, you can [subscribe OpenHands](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[OpenHands Administrator Guide](https://support.websoft9.com/docs/openhands) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 1.26.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 8000 | + + +### Data Directory + + +- `/var/run/docker.sock` → `/var/run/docker.sock` +- `openhands-home` → `/home/openhands/.openhands` +- `openhands-projects` → `/projects` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [OpenHands Administrator Guide](https://support.websoft9.com/docs/openhands) by Websoft9 + +- [GHCR image](https://ghcr.io/openhands/agent-canvas) + +- [Releases](https://github.com/OpenHands/OpenHands/releases) + +- [Official docs](https://docs.openhands.dev/openhands/usage/agent-canvas/backend-setup/docker) + +- [Official docs](https://docs.openhands.dev/openhands/usage/agent-canvas/setup) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/openhands/docker-compose.yml b/apps/openhands/docker-compose.yml index af07a737a..33dba6c00 100644 --- a/apps/openhands/docker-compose.yml +++ b/apps/openhands/docker-compose.yml @@ -1,33 +1,25 @@ -# image,docs: https://docs.all-hands.dev/modules/usage/installation - services: - app: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} extra_hosts: host.docker.internal: host-gateway restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:3000 - depends_on: - - runtime - env_file: + - "${W9_HTTP_PORT_SET}:8000" # Web Console + env_file: - .env volumes: - /var/run/docker.sock:/var/run/docker.sock - - openhands-state:/.openhands-state - - runtime: - image: docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik - container_name: $W9_ID-runtime - restart: "no" + - openhands-home:/home/openhands/.openhands + - openhands-projects:/projects volumes: - openhands-state: + openhands-home: + openhands-projects: networks: default: - name: $W9_NETWORK - external: true \ No newline at end of file + name: ${W9_NETWORK} + external: true diff --git a/apps/openhands/tests/cases.yml b/apps/openhands/tests/cases.yml new file mode 100644 index 000000000..c7763bc8e --- /dev/null +++ b/apps/openhands/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: canvas-ui + type: web-access + path: /canvas + expect_status: 200 diff --git a/apps/openhands/variables.json b/apps/openhands/variables.json index 24492123e..24367f267 100644 --- a/apps/openhands/variables.json +++ b/apps/openhands/variables.json @@ -2,20 +2,48 @@ "name": "openhands", "trademark": "OpenHands", "release": true, + "upstream": { + "image": "ghcr.io/openhands/agent-canvas", + "releases": "https://github.com/OpenHands/OpenHands/releases", + "docs": [ + "https://docs.openhands.dev/openhands/usage/agent-canvas/backend-setup/docker", + "https://docs.openhands.dev/openhands/usage/agent-canvas/setup" + ] + }, "edition": [ { "dist": "community", "version": [ - "0.28" + "1.26.0", + "latest" ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/canvas" + } + }, "requirements": { "cpu": "2", "memory": "4", "disk": "10" }, - "upstream": { - "image": "https://github.com/All-Hands-AI/OpenHands/pkgs/container/openhands" + "env": { + "secrets": [ + "LOCAL_BACKEND_API_KEY", + "OH_SECRET_KEY" + ] + }, + "credentials": { + "token": { + "source": "container-env", + "name": "LOCAL_BACKEND_API_KEY" + } + }, + "help": { + "login": "Open the site and enter the access token on the API key login screen. The token is the `LOCAL_BACKEND_API_KEY` value." } } diff --git a/apps/opensearch/.env b/apps/opensearch/.env index fc8459ee6..9c99eb096 100644 --- a/apps/opensearch/.env +++ b/apps/opensearch/.env @@ -3,19 +3,38 @@ # otherwise opensearch can't running W9_REPO=opensearchproject/opensearch -W9_VERSION='3' -W9_DIST='community' +W9_VERSION=3.9.0 +W9_DIST=community W9_POWER_PASSWORD='6DSJl2!PckWnROAZ' #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='opensearch' -W9_RCODE='i9Vascu8LVWJX' -W9_HTTPS_PORT_SET='9001' +W9_ID=opensearch +W9_RCODE=i9Vascu8LVWJX +W9_HTTPS_PORT_SET=9001 W9_HTTPS_PORT=9200 -W9_DASHBOARD_PORT_SET='9002' +W9_DASHBOARD_PORT_SET=9002 # two user: admin and kibanaserver were useful W9_LOGIN_USER=admin -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD -W9_URL='appname.example.com' +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} +W9_URL=appname.example.com W9_NETWORK=websoft9 + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# OpenSearch image environment variables +# Docs: https://docs.opensearch.org/latest/install-and-configure/install-opensearch/docker/ +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +# Not used by default; enable only when needed: +# OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m +# DISABLE_SECURITY_PLUGIN=true +# DISABLE_INSTALL_DEMO_CONFIG=true +# plugins.security.ssl.http.enabled=false +# plugins.security.disabled=true diff --git a/apps/opensearch/CHANGELOG.md b/apps/opensearch/CHANGELOG.md index 582cf46c5..84d01d916 100644 --- a/apps/opensearch/CHANGELOG.md +++ b/apps/opensearch/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG -## Release -### Fixes and Enhancements - +## 2026-10-09 +- update OpenSearch from 3 to 3.9.0 and add first-start-only password metadata +- align compose variable references, published port comments, and health check wiring with current policy +- add a smoke test for OpenSearch Dashboards and document the `vm.max_map_count` prerequisite diff --git a/apps/opensearch/README.md b/apps/opensearch/README.md index 6ef24d9ca..8e9e002f3 100644 --- a/apps/opensearch/README.md +++ b/apps/opensearch/README.md @@ -1,26 +1,90 @@ -# OpenSearch on Docker +# OpenSearch on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for OpenSearch: +## Quick Start +### Deploy Verification - - community: 3, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **OpenSearch**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the OpenSearch admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://github.com/onlyoffice/docker#recommended-system-requirements): +### Change Password -* **RAM**: 8 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 8 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this OpenSearch by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [OpenSearch Docker image](https://hub.docker.com/r/opensearchproject/opensearch) and makes some improvements below. -If you want use OpenSearch with **Websoft9 Business Support** free, you can [subscribe OpenSearch](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[OpenSearch Administrator Guide](https://support.websoft9.com/docs/opensearch) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 3.9.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| HTTPS API | 9200 | +| Dashboards | 5601 | + + +### Data Directory + + +Data is persisted in the `opensearch-data` volume, mounted at `/usr/share/opensearch/data`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `OPENSEARCH_INITIAL_ADMIN_PASSWORD` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [OpenSearch Administrator Guide](https://support.websoft9.com/docs/opensearch) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/opensearchproject/opensearch) + +- [Official docs](https://docs.opensearch.org/latest/install-and-configure/install-opensearch/docker/) + +- [Official docs](https://docs.opensearch.org/latest/install-and-configure/install-dashboards/docker/) + +- [Official docs](https://opensearch.org/releases/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/opensearch/docker-compose.yml b/apps/opensearch/docker-compose.yml index f78744dd3..28e2223ca 100644 --- a/apps/opensearch/docker-compose.yml +++ b/apps/opensearch/docker-compose.yml @@ -1,14 +1,8 @@ -# image: https://hub.docker.com/r/opensearchproject/opensearch -# image: https://hub.docker.com/r/opensearchproject/opensearch-dashboards -# doc : https://opensearch.org/downloads.html - -version: '3.8' - services: opensearch: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID - hostname: $W9_RCODE + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} + hostname: ${W9_RCODE} env_file: .env environment: - discovery.type=single-node @@ -25,17 +19,26 @@ services: volumes: - opensearch-data:/usr/share/opensearch/data ports: - - $W9_HTTPS_PORT_SET:9200 + - "${W9_HTTPS_PORT_SET}:9200" # HTTPS API + healthcheck: + test: ["CMD-SHELL", "curl -skf https://127.0.0.1:9200 >/dev/null || exit 1"] + interval: 30s + timeout: 10s + retries: 10 opensearch-dashboards: - image: $W9_REPO-dashboards:$W9_VERSION - container_name: $W9_ID-dashboards + image: ${W9_REPO}-dashboards:${W9_VERSION} + container_name: ${W9_ID}-dashboards + restart: unless-stopped + depends_on: + - opensearch ports: - - $W9_DASHBOARD_PORT_SET:5601 + - "${W9_DASHBOARD_PORT_SET}:5601" # Dashboards expose: - '5601' environment: - OPENSEARCH_HOSTS: '["https://$W9_RCODE:9200"]' + OPENSEARCH_HOSTS: '["https://${W9_RCODE}:9200"]' + env_file: .env busybox: image: busybox @@ -48,4 +51,4 @@ volumes: networks: default: name: ${W9_NETWORK} - external: true \ No newline at end of file + external: true diff --git a/apps/opensearch/tests/cases.yml b/apps/opensearch/tests/cases.yml new file mode 100644 index 000000000..3735b8b59 --- /dev/null +++ b/apps/opensearch/tests/cases.yml @@ -0,0 +1,7 @@ +skip: + - id: web-access + +optional: + - id: dashboards-ui + type: script + script: check.sh diff --git a/apps/opensearch/tests/check.sh b/apps/opensearch/tests/check.sh new file mode 100644 index 000000000..9b7f79907 --- /dev/null +++ b/apps/opensearch/tests/check.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -uo pipefail + +port="${W9_DASHBOARD_PORT_SET:-9002}" +base="${BASE_URL:-http://localhost:${port}}" +deadline=$((SECONDS + 300)) +code="000" + +while [ "$SECONDS" -lt "$deadline" ]; do + code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "${base}/app/home" || true) + case "$code" in + 200|301|302) + break + ;; + esac + sleep 5 +done + +case "$code" in + 200|301|302) + echo "opensearch dashboards ${base}/app/home -> ${code}" + ;; + *) + echo "opensearch dashboards ${base}/app/home -> ${code} (timeout)" + exit 1 + ;; +esac diff --git a/apps/opensearch/variables.json b/apps/opensearch/variables.json index 60d8c9a73..e1898dcc8 100644 --- a/apps/opensearch/variables.json +++ b/apps/opensearch/variables.json @@ -2,11 +2,19 @@ "name": "opensearch", "trademark": "OpenSearch", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/opensearchproject/opensearch", + "docs": [ + "https://docs.opensearch.org/latest/install-and-configure/install-opensearch/docker/", + "https://docs.opensearch.org/latest/install-and-configure/install-dashboards/docker/", + "https://opensearch.org/releases/" + ] + }, "edition": [ { "dist": "community", "version": [ - "3", + "3.9.0", "latest" ] } @@ -23,7 +31,13 @@ "memory": "8", "disk": "8" }, - "upstream": { - "image": "https://hub.docker.com/r/opensearchproject/opensearch" + "env": { + "first_startup_only": [ + "OPENSEARCH_INITIAL_ADMIN_PASSWORD" + ] + }, + "help": { + "login": "The initial `admin` password comes from `W9_POWER_PASSWORD` via `OPENSEARCH_INITIAL_ADMIN_PASSWORD` and is only applied when the data volume is empty.", + "db": "OpenSearch still requires the host kernel setting `vm.max_map_count=262144` before deployment." } } diff --git a/apps/owncloud/.env b/apps/owncloud/.env index 526bd328e..129f30675 100644 --- a/apps/owncloud/.env +++ b/apps/owncloud/.env @@ -1,32 +1,42 @@ -W9_REPO=owncloud/server -W9_DIST='community' -W9_VERSION='10.16' +W9_REPO=owncloud/ocis +W9_DIST=community +W9_VERSION=8.2 W9_POWER_PASSWORD='yJ!E1w04pxHnJ!PT' + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='owncloud' -# Environments which for user settings when create application -W9_HTTP_PORT_SET='9001' -W9_HTTP_PORT=8080 -W9_URL='example.youdomain.com' -# This is used for OWNCLOUD_TRUSTED_DOMAINS and OWNCLOUD_DOMAIN +W9_ID=owncloud +W9_HTTPS_PORT_SET=9001 +W9_HTTPS_PORT=9200 +W9_URL=example.youdomain.com W9_URL_REPLACE=true W9_LOGIN_USER=admin -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD -W9_DB_EXPOSE="mysql" -W9_DB_VERSION=5.7 +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} W9_NETWORK=websoft9 + #### ----------------------------------------------------------------------------------------- #### -#----------------- OWNCLOUD environment if you need ---------------------# -OWNCLOUD_DOMAIN=$W9_URL -OWNCLOUD_TRUSTED_DOMAINS=$W9_URL -OWNCLOUD_DB_TYPE=mysql -OWNCLOUD_DB_NAME=$W9_ID -OWNCLOUD_DB_USERNAME=$W9_ID -OWNCLOUD_DB_PASSWORD=$W9_POWER_PASSWORD -OWNCLOUD_DB_HOST=$W9_ID-mysql -OWNCLOUD_ADMIN_USERNAME=$W9_LOGIN_USER -OWNCLOUD_ADMIN_PASSWORD=$W9_POWER_PASSWORD -OWNCLOUD_MYSQL_UTF8MB4=true -OWNCLOUD_REDIS_ENABLED=true -OWNCLOUD_REDIS_HOST=$W9_ID-redis +# ============================================================ +# ownCloud Infinite Scale image environment variables +# Docs: https://github.com/owncloud/ocis/tree/master/deployments/examples/ocis_full +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +OCIS_URL=https://${W9_URL}:${W9_HTTPS_PORT_SET} +PROXY_HTTP_ADDR=0.0.0.0:${W9_HTTPS_PORT} +PROXY_TLS=true +OCIS_INSECURE=true +IDM_ADMIN_PASSWORD=${W9_LOGIN_PASSWORD} + +# Not used by default; enable only when needed: +# OCIS_LOG_LEVEL=info +# OCIS_LOG_PRETTY=true +# OCIS_EXCLUDE_RUN_SERVICES=idm +# IDM_CREATE_DEMO_USERS=false +# OCIS_CORS_ALLOW_ORIGINS=https://${W9_URL}:${W9_HTTPS_PORT_SET} +# OCIS_JWT_SECRET= diff --git a/apps/owncloud/CHANGELOG.md b/apps/owncloud/CHANGELOG.md index 582cf46c5..739cfae39 100644 --- a/apps/owncloud/CHANGELOG.md +++ b/apps/owncloud/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## Release -### Fixes and Enhancements - +## 2026-10-09 +- replace the legacy ownCloud Server package with ownCloud Infinite Scale 8.2.1 +- simplify the deployment from `server + mysql + redis` to the official single-container `owncloud/ocis` topology +- add a one-shot `ocis-init` service that runs the official `ocis init` once to generate `ocis.yaml` +- keep the main container on the official default `ocis server` command (no entrypoint override) +- add HTTPS smoke testing and record first-start-only admin password behavior diff --git a/apps/owncloud/Notes.md b/apps/owncloud/Notes.md index ffdfcbbc4..fa64804ab 100644 --- a/apps/owncloud/Notes.md +++ b/apps/owncloud/Notes.md @@ -1,20 +1,22 @@ -# Owncloud +# ownCloud -OWNCLOUD_DOMAIN 和 OWNCLOUD_TRUSTED_DOMAINS 必须通过环境[变量设置](https://doc.owncloud.com/server/10.13/admin_manual/configuration/server/config_sample_php_parameters.html#define-list-of-trusted-domains-that-users-can-log-into),config.php 设置它们是无效的。 +当前软件包已切换为 ownCloud Infinite Scale (`owncloud/ocis`),不再使用旧版 `owncloud/server` + MySQL + Redis 拓扑。 ## FAQ -#### 初始化提示 You are accessing the server from an untrusted domain? +#### 默认使用 HTTP 还是 HTTPS? -- OWNCLOUD_DOMAIN=${W9_URL} -- OWNCLOUD_TRUSTED_DOMAINS=${W9_URL} +- 当前包按 oCIS 官方默认行为启用 HTTPS。 +- 因为启用了 `OCIS_INSECURE=true`,首次部署会使用自签名证书。 +- 浏览器首次访问时如果提示证书风险,继续访问即可。 -以上两个环境变量都需要设置。OWNCLOUD_TRUSTED_DOMAINS 可以设置多个(以,作为分隔符),OWNCLOUD_TRUSTED_DOMAINS 与 OWNCLOUD_DOMAIN 不一样也不影响访问。 +#### 管理员账号如何初始化? -#### 域名发生变化后如何更换 URL ? +- 用户名固定为 `admin` +- 密码来自 `W9_LOGIN_PASSWORD` +- `IDM_ADMIN_PASSWORD` 只会在首次启动、数据卷为空时生效 -原理是上是通过更换 OWNCLOUD_DOMAIN 和 OWNCLOUD_TRUSTED_DOMAINS 后重建应用生效。 当前已经通过 W9_URL_REPLACE=true 实现自动适应。 +#### 域名变化后如何处理? -#### W9_URL 需要带端口吗? - -带或不带都可以,故建议不带 \ No newline at end of file +- `OCIS_URL=https://${W9_URL}:${W9_HTTPS_PORT_SET}` 由包内环境变量生成。 +- 修改 `W9_URL` 后需要重建应用,使新 URL 重新注入运行配置。 diff --git a/apps/owncloud/README.md b/apps/owncloud/README.md index 3ea52e60d..09b2f67e7 100644 --- a/apps/owncloud/README.md +++ b/apps/owncloud/README.md @@ -1,26 +1,89 @@ -# Owncloud on Docker +# ownCloud on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Owncloud: +## Quick Start +### Deploy Verification - - community: 10.15, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **ownCloud**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the ownCloud admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://doc.owncloud.com/server/10.8/admin_manual/installation/docker/): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Owncloud by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [ownCloud Docker image](https://hub.docker.com/r/owncloud/ocis) and makes some improvements below. -If you want use Owncloud with **Websoft9 Business Support** free, you can [subscribe Owncloud](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Owncloud Administrator Guide](https://support.websoft9.com/docs/owncloud) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 8.2, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| HTTPS Web Console | 9200 | + + +### Data Directory + + +- `owncloud-config` → `/etc/ocis` +- `owncloud-data` → `/var/lib/ocis` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `IDM_ADMIN_PASSWORD` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [ownCloud Administrator Guide](https://support.websoft9.com/docs/owncloud) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/owncloud/ocis) + +- [Releases](https://github.com/owncloud/ocis/releases) + +- [GitHub docs](https://github.com/owncloud/ocis/tree/master/deployments/examples/ocis_full) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/owncloud/docker-compose.yml b/apps/owncloud/docker-compose.yml index 697677806..50ba8ef7a 100644 --- a/apps/owncloud/docker-compose.yml +++ b/apps/owncloud/docker-compose.yml @@ -1,65 +1,45 @@ -# docs: https://doc.owncloud.com/server/10.8/admin_manual/installation/docker/ -# image: https://hub.docker.com/r/owncloud/server - -version: '3.8' - services: + ocis-init: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID}-init + restart: "no" + env_file: .env + entrypoint: ["/bin/sh", "-c"] + command: + - | + if [ -f /etc/ocis/ocis.yaml ]; then + echo "[ocis-init] config already exists, skipping" + else + echo "[ocis-init] generating ocis.yaml" + ocis init --insecure true + fi + volumes: + - owncloud-config:/etc/ocis + owncloud: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} + restart: unless-stopped + depends_on: + ocis-init: + condition: service_completed_successfully ports: - - $W9_HTTP_PORT_SET:8080 + - "${W9_HTTPS_PORT_SET}:9200" # HTTPS Web Console volumes: - - owncloud:/mnt/data + - owncloud-config:/etc/ocis + - owncloud-data:/var/lib/ocis env_file: .env healthcheck: - test: ["CMD", "/usr/bin/healthcheck"] + test: ["CMD-SHELL", "curl -skf https://127.0.0.1:9200/ >/dev/null || exit 1"] interval: 30s timeout: 10s - retries: 5 - depends_on: - - mysql - - redis - restart: unless-stopped - - mysql: - image: mysql:$W9_DB_VERSION - container_name: $W9_ID-mysql - restart: unless-stopped - command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"] - volumes: - - mysql:/var/lib/mysql - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=$W9_POWER_PASSWORD"] - interval: 10s - timeout: 5s - retries: 5 - environment: - MYSQL_DATABASE: $W9_ID - MYSQL_USER: $W9_ID - MYSQL_PASSWORD: $W9_POWER_PASSWORD - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD - - redis: - image: redis:6 - env_file: .env - container_name: $W9_ID-redis - restart: unless-stopped - command: ["--databases", "1"] - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - volumes: - - redis:/data + retries: 10 volumes: - owncloud: - redis: - mysql: - + owncloud-config: + owncloud-data: + networks: default: name: ${W9_NETWORK} - external: true \ No newline at end of file + external: true diff --git a/apps/owncloud/src/after_up.sh b/apps/owncloud/src/after_up.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/owncloud/src/after_up.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/owncloud/src/filelist b/apps/owncloud/src/filelist deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/owncloud/src/get_version.sh b/apps/owncloud/src/get_version.sh deleted file mode 100644 index 22abd4bfa..000000000 --- a/apps/owncloud/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ -sudo echo "$(docker exec -i $1 occ -Version)" |sudo tee -a /data/logs/install_version.txt diff --git a/apps/owncloud/tests/cases.yml b/apps/owncloud/tests/cases.yml new file mode 100644 index 000000000..c190b2333 --- /dev/null +++ b/apps/owncloud/tests/cases.yml @@ -0,0 +1,7 @@ +skip: + - id: web-access + +optional: + - id: ocis-https + type: script + script: check.sh diff --git a/apps/owncloud/tests/check.sh b/apps/owncloud/tests/check.sh new file mode 100644 index 000000000..98488dc48 --- /dev/null +++ b/apps/owncloud/tests/check.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -uo pipefail + +port="${W9_HTTPS_PORT_SET:-9001}" +base="${BASE_URL:-https://localhost:${port}}" +deadline=$((SECONDS + 300)) +code="000" + +while [ "$SECONDS" -lt "$deadline" ]; do + code=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 15 "${base}/" || true) + case "$code" in + 200|301|302|303) + break + ;; + esac + sleep 5 +done + +case "$code" in + 200|301|302|303) + echo "ocis root ${base}/ -> ${code}" + ;; + *) + echo "ocis root ${base}/ -> ${code} (timeout)" + exit 1 + ;; +esac diff --git a/apps/owncloud/variables.json b/apps/owncloud/variables.json index a33894efa..802d9cd93 100644 --- a/apps/owncloud/variables.json +++ b/apps/owncloud/variables.json @@ -1,22 +1,52 @@ { "name": "owncloud", - "trademark": "Owncloud", + "trademark": "ownCloud", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/owncloud/ocis", + "releases": "https://github.com/owncloud/ocis/releases", + "docs": [ + "https://github.com/owncloud/ocis/tree/master/deployments/examples/ocis_full" + ] + }, "edition": [ { "dist": "community", "version": [ - "10.16", + "8.2", "latest" ] } ], + "access": { + "defaultScheme": "https", + "web": { + "port": 9200, + "path": "/" + } + }, "requirements": { "cpu": "1", - "memory": "1", - "disk": "1" + "memory": "2", + "disk": "2" }, - "upstream": { - "image": "https://hub.docker.com/r/owncloud/server" + "credentials": { + "username": { + "source": "inline", + "value": "admin" + }, + "password": { + "source": "container-env", + "name": "W9_LOGIN_PASSWORD" + } + }, + "env": { + "first_startup_only": [ + "IDM_ADMIN_PASSWORD" + ] + }, + "help": { + "login": "This package now deploys ownCloud Infinite Scale (oCIS). The built-in `admin` account password comes from `W9_LOGIN_PASSWORD` and is only applied on first startup.", + "db": "This package no longer bundles MySQL or Redis because ownCloud Infinite Scale uses its own integrated single-node services in the default deployment profile." } } diff --git a/apps/paperlessngx/src/after_up.sh b/apps/paperlessngx/src/after_up.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/paperlessngx/src/after_up.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/paperlessngx/src/encrypt.sh b/apps/paperlessngx/src/encrypt.sh deleted file mode 100644 index 2939685f7..000000000 --- a/apps/paperlessngx/src/encrypt.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin -clear - - - -# Add encrypt script below if use W9_ENCRYPT_PASSWORD at .env file -# ------------- start ------------------------- - - - -# ------------- end --------------------------- diff --git a/apps/pgadmin/.env b/apps/pgadmin/.env index cd9b7877f..c9496979f 100644 --- a/apps/pgadmin/.env +++ b/apps/pgadmin/.env @@ -1,22 +1,40 @@ W9_REPO=dpage/pgadmin4 -W9_DIST='community' -W9_VERSION='9.8' -W9_POWER_PASSWORD='fzSiIb6!yS5W3ROd' +W9_DIST=community +W9_VERSION=9.18 +W9_POWER_PASSWORD="fzSiIb6!yS5W3ROd" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='pgadmin' -# Environments which for user settings when create application -W9_HTTP_PORT_SET='9090' -# W9_HTTP_PORT or W9_HTTPS_PORT is need at leaset and used for proxy for web application + +W9_ID=pgadmin W9_HTTP_PORT=80 -W9_URL='example.youdomain.com' -# default pgadmin user user@domain.com ,passwd SuperSecret if not set +W9_HTTP_PORT_SET=9090 W9_LOGIN_USER=user@domain.com -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} +W9_URL=pgadmin.example.com W9_NETWORK=websoft9 + #### ----------------------------------------------------------------------------------------- #### -#----------------- pgAdmin environment if you need ---------------------# -PGADMIN_DEFAULT_EMAIL=$W9_LOGIN_USER -PGADMIN_DEFAULT_PASSWORD=$W9_LOGIN_PASSWORD +# ============================================================ +# pgAdmin image environment variables +# Docs: https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +PGADMIN_DEFAULT_EMAIL=${W9_LOGIN_USER} +PGADMIN_DEFAULT_PASSWORD=${W9_LOGIN_PASSWORD} PGADMIN_LISTEN_ADDRESS=0.0.0.0 +PGADMIN_DISABLE_POSTFIX=1 + +# Not used by default; enable only when needed: +# PGADMIN_LISTEN_PORT=80 +# PGADMIN_ENABLE_TLS=True +# PGADMIN_DEFAULT_PASSWORD_FILE=/run/secrets/pgadmin_password +# PGADMIN_SERVER_JSON_FILE=/pgadmin4/servers.json +# PGADMIN_REPLACE_SERVERS_ON_STARTUP=True diff --git a/apps/pgadmin/CHANGELOG.md b/apps/pgadmin/CHANGELOG.md index 582cf46c5..6352dea51 100644 --- a/apps/pgadmin/CHANGELOG.md +++ b/apps/pgadmin/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-09 +- Updated pgAdmin from `9.8` to `9.18`. +- Refreshed `.env`, `docker-compose.yml`, metadata, and test coverage to current repository conventions. diff --git a/apps/pgadmin/Notes.md b/apps/pgadmin/Notes.md deleted file mode 100644 index 6ad6aca57..000000000 --- a/apps/pgadmin/Notes.md +++ /dev/null @@ -1,3 +0,0 @@ -# pgAdmin - -Add Postges for testing \ No newline at end of file diff --git a/apps/pgadmin/README.md b/apps/pgadmin/README.md index 7271aba09..7f6f0a1c6 100644 --- a/apps/pgadmin/README.md +++ b/apps/pgadmin/README.md @@ -1,26 +1,87 @@ -# pgAdmin on Docker +# pgAdmin on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for pgAdmin: +## Quick Start +### Deploy Verification - - community: 9.4.0, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **pgAdmin**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the pgAdmin admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://github.com/postgres/pgadmin4/blob/master/requirements.txt): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 2 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this pgAdmin by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [pgAdmin Docker image](https://hub.docker.com/r/dpage/pgadmin4) and makes some improvements below. -If you want use pgAdmin with **Websoft9 Business Support** free, you can [subscribe pgAdmin](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[pgAdmin Administrator Guide](https://support.websoft9.com/docs/pgadmin) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 9.18, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 80 | + + +### Data Directory + + +Data is persisted in the `pgadmin` volume, mounted at `/var/lib/pgadmin`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `PGADMIN_DEFAULT_EMAIL`, `PGADMIN_DEFAULT_PASSWORD` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [pgAdmin Administrator Guide](https://support.websoft9.com/docs/pgadmin) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/dpage/pgadmin4) + +- [Official docs](https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html) + +- [Official docs](https://www.pgadmin.org/docs/pgadmin4/9.18/release_notes.html) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/pgadmin/docker-compose.yml b/apps/pgadmin/docker-compose.yml index 5a00dcacb..0db8bfa2f 100644 --- a/apps/pgadmin/docker-compose.yml +++ b/apps/pgadmin/docker-compose.yml @@ -1,17 +1,12 @@ -# image: https://hub.docker.com/r/dpage/pgadmin4 -# docs: https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html -# postgres only for test - -version: "3.8" services: pgadmin: - image: $W9_REPO:$W9_VERSION + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped - container_name: $W9_ID volumes: - pgadmin:/var/lib/pgadmin ports: - - "${W9_HTTP_PORT_SET}:80" + - "${W9_HTTP_PORT_SET}:80" # Web Console env_file: .env networks: @@ -20,4 +15,4 @@ networks: external: true volumes: - pgadmin: \ No newline at end of file + pgadmin: diff --git a/apps/pgadmin/src/after_up.sh b/apps/pgadmin/src/after_up.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/pgadmin/src/after_up.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/pgadmin/src/filelist b/apps/pgadmin/src/filelist deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/pgadmin/src/get_version.sh b/apps/pgadmin/src/get_version.sh deleted file mode 100644 index 15323a54e..000000000 --- a/apps/pgadmin/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ -sudo echo "pgadmin version $(docker exec -i $1 sh -c 'cat docs/release_notes.html |grep -i version |tail -1 |cut -d= -f4')" 1>> /data/logs/install_version.txt diff --git a/apps/pgadmin/tests/cases.yml b/apps/pgadmin/tests/cases.yml new file mode 100644 index 000000000..e24b793ac --- /dev/null +++ b/apps/pgadmin/tests/cases.yml @@ -0,0 +1,2 @@ +skip: + - id: web-access diff --git a/apps/pgadmin/variables.json b/apps/pgadmin/variables.json index 2ee3a04ae..bc7062cd2 100644 --- a/apps/pgadmin/variables.json +++ b/apps/pgadmin/variables.json @@ -6,7 +6,7 @@ { "dist": "community", "version": [ - "9.8", + "9.18", "latest" ] } @@ -24,6 +24,26 @@ "disk": "2" }, "upstream": { - "image": "https://hub.docker.com/r/dpage/pgadmin4" + "image": "https://hub.docker.com/r/dpage/pgadmin4", + "docs": [ + "https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html", + "https://www.pgadmin.org/docs/pgadmin4/9.18/release_notes.html" + ] + }, + "credentials": { + "username": { + "source": "inline", + "value": "user@domain.com" + }, + "password": { + "source": "container-env", + "name": "W9_LOGIN_PASSWORD" + } + }, + "env": { + "first_startup_only": [ + "PGADMIN_DEFAULT_EMAIL", + "PGADMIN_DEFAULT_PASSWORD" + ] } } diff --git a/apps/php/variables.json b/apps/php/variables.json index 12b678412..9d246b57b 100644 --- a/apps/php/variables.json +++ b/apps/php/variables.json @@ -19,6 +19,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/phpmyadmin/variables.json b/apps/phpmyadmin/variables.json index 28c70eb64..bbf1782b6 100644 --- a/apps/phpmyadmin/variables.json +++ b/apps/phpmyadmin/variables.json @@ -15,10 +15,6 @@ "web": { "port": 80, "path": "/" - }, - "admin": { - "port": 80, - "path": "/phpmyadmin/" } }, "requirements": { diff --git a/apps/pimcore/.env b/apps/pimcore/.env index 4c5536c7d..ae669dc69 100644 --- a/apps/pimcore/.env +++ b/apps/pimcore/.env @@ -1,17 +1,43 @@ -W9_POWER_PASSWORD=uQ8E1wVTzG8SOk3! - -W9_NAME=pimcore W9_REPO=pimcore/pimcore +W9_DIST=community +W9_VERSION=php8.5-v5 +W9_POWER_PASSWORD="uQ8E1wVTzG8SOk3!" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### -# version refer to: https://github.com/pimcore/docker#image-flavors -W9_VERSION=php8.2-latest +W9_ID=pimcore +W9_HTTP_PORT=80 +W9_HTTP_PORT_SET=9001 +W9_DB_VERSION=10.11 +W9_DB_EXPOSE=mariadb +W9_URL=pimcore.example.com W9_NETWORK=websoft9 -W9_HTTP_PORT=9001 +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Pimcore image environment variables +# Docs: https://github.com/pimcore/docker/blob/5.x/README.md +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +PIMCORE_SKELETON_VERSION=v2026.3.0 +PIMCORE_DB_HOST=${W9_ID}-mariadb +PIMCORE_DB_PORT=3306 +PIMCORE_DB_NAME=pimcore +PIMCORE_DB_USER=pimcore +PIMCORE_DB_PASSWORD=${W9_POWER_PASSWORD} +PIMCORE_APP_ENV=prod -W9_DB_PORT=3306 -W9_DB_MYSQL_VERSION=5.7 -W9_DB_MYSQL_PORT=3306 -W9_DB_MYSQL_PASSWORD=$W9_POWER_PASSWORD -W9_DB_MYSQL_NAME=$W9_NAME -W9_DB_MYSQL_USER=$W9_NAME \ No newline at end of file +# Not used by default; enable only when needed: +# PIMCORE_INSTALL_ADMIN_USERNAME=admin +# PIMCORE_INSTALL_ADMIN_PASSWORD=${W9_POWER_PASSWORD} +# PIMCORE_INSTALL_PROFILE=App\Installer\SkeletonProfile +# PIMCORE_TRUSTED_PROXIES= +# PIMCORE_CORS_ALLOW_ORIGIN= diff --git a/apps/pimcore/CHANGELOG.md b/apps/pimcore/CHANGELOG.md index 582cf46c5..e5c1c72a4 100644 --- a/apps/pimcore/CHANGELOG.md +++ b/apps/pimcore/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-09 +- Updated Pimcore packaging to the current `pimcore/pimcore:php8.5-v5` runtime line. +- Reworked the package into a deployable minimal topology with nginx, PHP, MariaDB, and Redis. +- Added first-start skeleton bootstrap logic so the package reaches the upstream installer instead of failing with missing application code. diff --git a/apps/pimcore/Notes.md b/apps/pimcore/Notes.md index 96927c076..2b9e81904 100644 --- a/apps/pimcore/Notes.md +++ b/apps/pimcore/Notes.md @@ -1,3 +1,4 @@ # Pimcore -Can not used, need improve \ No newline at end of file +- The package now bootstraps an official Pimcore skeleton project on first start. +- Installation still requires completing the browser installer and providing a Pimcore product key, per current upstream requirements. diff --git a/apps/pimcore/README.md b/apps/pimcore/README.md index 4f8466523..d174bb9a6 100644 --- a/apps/pimcore/README.md +++ b/apps/pimcore/README.md @@ -1,26 +1,93 @@ -# Pimcore on Docker +# Pimcore on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Pimcore : +## Quick Start +### Deploy Verification - - community: php8.2-latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Pimcore**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Pimcore admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://github.com/pimcore/docker#recommended-system-requirements): +### Change Password -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Pimcore by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Pimcore Docker image](https://hub.docker.com/r/pimcore/pimcore) and makes some improvements below. -If you want use Pimcore with **Websoft9 Business Support** free, you can [subscribe Pimcore ](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Pimcore Administrator Guide](https://support.websoft9.com/docs/pimcore) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: php8.5-v5. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 80 | + + +### Data Directory + + +- `pimcore` → `/var/www/html` +- `mariadb` → `/var/lib/mysql` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +- `./src/nginx.conf` → `/etc/nginx/conf.d/default.conf` +- `./src/bootstrap.sh` → `/usr/local/bin/bootstrap.sh` +- `./src/messenger.yaml` → `/websoft9-src/messenger.yaml` + + + +## References + +- [Pimcore Administrator Guide](https://support.websoft9.com/docs/pimcore) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/pimcore/pimcore) + +- [Releases](https://github.com/pimcore/pimcore/releases) + +- [Official compose](https://github.com/pimcore/skeleton/blob/2024.x/docker-compose.yaml) + +- [GitHub docs](https://github.com/pimcore/docker/blob/5.x/README.md) + +- [Official docs](https://packagist.org/packages/pimcore/skeleton) + +- [Official docs](https://packagist.org/packages/pimcore/pimcore) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/pimcore/docker-compose.yml b/apps/pimcore/docker-compose.yml index 0f744e155..5ac36d530 100644 --- a/apps/pimcore/docker-compose.yml +++ b/apps/pimcore/docker-compose.yml @@ -1,79 +1,71 @@ -# docs1: https://pimcore.com/docs/platform/Pimcore/Getting_Started/Installation/Docker_Based_Installation/ -# docs2: https://github.com/pimcore/docker - -version: '3.8' -services: - pimcore: - image: $W9_REPO:$W9_VERSION - container_name: $W9_NAME +services: + nginx: + image: nginx:stable-alpine + container_name: ${W9_ID} restart: unless-stopped - env_file: .env ports: - - $W9_HTTP_PORT:80 - logging: - driver: "json-file" - options: - max-file: "5" - max-size: 10m + - "${W9_HTTP_PORT_SET}:80" # Web Console volumes: - - pimcore:/var/www/html - environment: - PIMCORE_ENVIRONMENT: dev - MYSQL_HOST: $W9_NAME-db - MYSQL_DATABASE: $W9_DB_MYSQL_NAME - MYSQL_USER: $W9_DB_MYSQL_USER - MYSQL_PASSWORD: $W9_DB_MYSQL_PASSWORD - - supervisord: - #user: '1000:1000' # set to your uid:gid - image: pimcore/pimcore:php8.2-supervisord-latest - container_name: $W9_NAME-supervisord + - pimcore:/var/www/html:ro + - ./src/nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - db: - condition: service_healthy - volumes: - - .:/var/www/html - - ./src/supervisord.conf:/etc/supervisor/conf.d/pimcore.conf:ro + php: + condition: service_started + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 -O - http://127.0.0.1/ >/dev/null || exit 1"] + interval: 30s + timeout: 10s + retries: 20 + start_period: 180s - nginx: - image: nginx:stable-alpine - ports: - - "$W9_HTTP_PORT:80" + php: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID}-php + restart: unless-stopped + env_file: .env + environment: + COMPOSER_MEMORY_LIMIT: -1 + command: sh -c "/usr/local/bin/bootstrap.sh && exec php-fpm" volumes: - - .:/var/www/html:ro - - ./src/nginx.conf:/etc/nginx/conf.d/default.conf:ro + - pimcore:/var/www/html + - ./src/bootstrap.sh:/usr/local/bin/bootstrap.sh:ro + - ./src/messenger.yaml:/websoft9-src/messenger.yaml:ro depends_on: - - php + mariadb: + condition: service_healthy + redis: + condition: service_started - mysql: - image: mysql:$W9_DB_MYSQL_VERSION - container_name: $W9_NAME-db + mariadb: + image: mariadb:${W9_DB_VERSION} + container_name: ${W9_ID}-mariadb restart: unless-stopped - ports: - - ${W9_DB_MYSQL_PORT}:3306 - command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb_log_buffer_size=30M + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --innodb-file-per-table=1 volumes: - - mysql_data:/var/lib/mysql + - mariadb:/var/lib/mysql environment: - MYSQL_DATABASE: $W9_DB_MYSQL_NAME - MYSQL_USER: $W9_DB_MYSQL_USER - MYSQL_PASSWORD: $W9_DB_MYSQL_PASSWORD - MYSQL_ROOT_PASSWORD: $W9_DB_MYSQL_PASSWORD + MYSQL_ROOT_PASSWORD: ${W9_POWER_PASSWORD} + MYSQL_DATABASE: ${PIMCORE_DB_NAME} + MYSQL_USER: ${PIMCORE_DB_USER} + MYSQL_PASSWORD: ${PIMCORE_DB_PASSWORD} + healthcheck: + test: ["CMD-SHELL", "mariadb -h 127.0.0.1 -u${PIMCORE_DB_USER} -p${PIMCORE_DB_PASSWORD} ${PIMCORE_DB_NAME} -e 'SELECT 1' >/dev/null 2>&1"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 60s redis: - image: redis:alpine - container_name: $W9_NAME-redis - command: [ redis-server, --maxmemory 128mb, --maxmemory-policy volatile-lru, --save "" ] + image: redis:7.4-alpine + container_name: ${W9_ID}-redis + restart: unless-stopped + command: ["redis-server", "--maxmemory", "128mb", "--maxmemory-policy", "volatile-lru", "--save", ""] - +volumes: + pimcore: + mariadb: networks: default: - name: ${W9_NETWORK} - external: true - -volumes: - pimcore: - driver: local - mysql_data: - driver: local \ No newline at end of file + name: ${W9_NETWORK} + external: true diff --git a/apps/pimcore/src/bootstrap.sh b/apps/pimcore/src/bootstrap.sh new file mode 100755 index 000000000..6193db7bd --- /dev/null +++ b/apps/pimcore/src/bootstrap.sh @@ -0,0 +1,44 @@ +#!/bin/sh +set -eu + +APP_DIR=/var/www/html + +wait_for_mariadb() { + until mariadb-admin ping -h"${PIMCORE_DB_HOST}" -u"${PIMCORE_DB_USER}" -p"${PIMCORE_DB_PASSWORD}" --silent >/dev/null 2>&1; do + sleep 3 + done +} + +bootstrap_project() { + if [ -f "${APP_DIR}/composer.json" ] && [ -f "${APP_DIR}/vendor/bin/pimcore-install" ]; then + return + fi + + tmp_dir="$(mktemp -d)" + COMPOSER_MEMORY_LIMIT=-1 composer create-project --no-interaction --prefer-dist --no-scripts pimcore/skeleton "${tmp_dir}" "${PIMCORE_SKELETON_VERSION}" + cp -a "${tmp_dir}/." "${APP_DIR}/" + rm -rf "${tmp_dir}" +} + +configure_project() { + mkdir -p "${APP_DIR}/config/packages" + + cat >"${APP_DIR}/.env.local" <&2; exit 1 ;; \ + esac; \ + wget -O /tmp/pocketbase.zip "https://github.com/pocketbase/pocketbase/releases/download/${POCKETBASE_VERSION}/pocketbase_${version}_linux_${pb_arch}.zip"; \ + unzip /tmp/pocketbase.zip -d /usr/local/bin; \ + chmod +x /usr/local/bin/pocketbase; \ + rm -f /tmp/pocketbase.zip; \ + mkdir -p /pb_data + +COPY src/entrypoint.sh /usr/local/bin/entrypoint.sh + +RUN chmod +x /usr/local/bin/entrypoint.sh + +EXPOSE 8090 + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/apps/pocketbase/README.md b/apps/pocketbase/README.md index 99e35bb23..300074e1e 100644 --- a/apps/pocketbase/README.md +++ b/apps/pocketbase/README.md @@ -1,26 +1,91 @@ -# PocketBase on Docker +# PocketBase on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for PocketBase: +## Quick Start +### Deploy Verification - - community: latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **PocketBase**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the PocketBase admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://pocketbase.io/docs/): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this PocketBase by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [PocketBase Docker image](https://github.com/pocketbase/pocketbase/releases) and makes some improvements below. -If you want use PocketBase with **Websoft9 Business Support** free, you can [subscribe PocketBase](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[PocketBase Administrator Guide](https://support.websoft9.com/docs/pocketbase) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: v0.40.5, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console and API | 8090 | + + +### Data Directory + + +Data is kept inside the container; a named volume is recommended for persistence. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `W9_LOGIN_USER`, `W9_LOGIN_PASSWORD` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [PocketBase Administrator Guide](https://support.websoft9.com/docs/pocketbase) by Websoft9 + +- [Docker Hub image](https://github.com/pocketbase/pocketbase/releases) + +- [Releases](https://github.com/pocketbase/pocketbase/releases) + +- [Official docs](https://pocketbase.io/docs/) + +- [GitHub docs](https://github.com/pocketbase/pocketbase) + +- [GitHub docs](https://github.com/pocketbase/pocketbase/blob/master/CHANGELOG.md) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/pocketbase/docker-compose.yml b/apps/pocketbase/docker-compose.yml index dab3ce6ab..f66d5781c 100644 --- a/apps/pocketbase/docker-compose.yml +++ b/apps/pocketbase/docker-compose.yml @@ -1,21 +1,30 @@ -# image: https://hub.docker.com/r/elestio/pocketbase - services: pocketbase: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + build: + context: . + dockerfile: Dockerfile + args: + POCKETBASE_VERSION: ${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:8090 - env_file: + - "${W9_HTTP_PORT_SET}:8090" # Web Console and API + env_file: - .env volumes: - - pb_data:/pb_data + - pb_data:${POCKETBASE_DIR} + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 -O - http://127.0.0.1:8090/api/health >/dev/null || exit 1"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 60s volumes: pb_data: - + networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true diff --git a/apps/pocketbase/src/entrypoint.sh b/apps/pocketbase/src/entrypoint.sh new file mode 100755 index 000000000..266d768da --- /dev/null +++ b/apps/pocketbase/src/entrypoint.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -eu + +data_dir="${POCKETBASE_DIR:-/pb_data}" +http_port="${W9_HTTP_PORT:-8090}" + +mkdir -p "${data_dir}" + +if [ ! -f "${data_dir}/data.db" ] && [ -n "${W9_LOGIN_USER:-}" ] && [ -n "${W9_LOGIN_PASSWORD:-}" ]; then + /usr/local/bin/pocketbase superuser create "${W9_LOGIN_USER}" "${W9_LOGIN_PASSWORD}" --dir="${data_dir}" || true +fi + +exec /usr/local/bin/pocketbase serve --http="0.0.0.0:${http_port}" --dir="${data_dir}" diff --git a/apps/pocketbase/tests/cases.yml b/apps/pocketbase/tests/cases.yml new file mode 100644 index 000000000..6cf572714 --- /dev/null +++ b/apps/pocketbase/tests/cases.yml @@ -0,0 +1,8 @@ +skip: + - id: web-access + +optional: + - id: admin-console + type: web-access + path: /_/ + expect_status: 200 diff --git a/apps/pocketbase/variables.json b/apps/pocketbase/variables.json index cea5d6be7..19fb136a5 100644 --- a/apps/pocketbase/variables.json +++ b/apps/pocketbase/variables.json @@ -3,13 +3,19 @@ "trademark": "PocketBase", "release": true, "upstream": { - "image": "https://hub.docker.com/r/spectado/pocketbase" + "image": "https://github.com/pocketbase/pocketbase/releases", + "releases": "https://github.com/pocketbase/pocketbase/releases", + "docs": [ + "https://pocketbase.io/docs/", + "https://github.com/pocketbase/pocketbase", + "https://github.com/pocketbase/pocketbase/blob/master/CHANGELOG.md" + ] }, "edition": [ { "dist": "community", "version": [ - "v0.29.1", + "v0.40.5", "latest" ] } @@ -40,5 +46,14 @@ "name": "W9_LOGIN_PASSWORD", "format": "text" } + }, + "env": { + "first_startup_only": [ + "W9_LOGIN_USER", + "W9_LOGIN_PASSWORD" + ] + }, + "help": { + "login": "PocketBase is pre-1.0 and may require manual migration review on upgrades. The first startup creates the configured superuser inside the empty pb_data directory." } } diff --git a/apps/portainer/.env b/apps/portainer/.env index be20703f3..5cc57a53f 100644 --- a/apps/portainer/.env +++ b/apps/portainer/.env @@ -1,11 +1,41 @@ -W9_DIST='community' -W9_VERSION='2.34.0' W9_REPO=portainer/portainer-ce +W9_DIST=community +W9_VERSION=2.45.1 + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='portainer' -W9_HTTP_PORT_SET='9001' + +W9_ID=portainer + +# Web/internal ports: uncomment the ones the package actually uses. W9_HTTP_PORT=9000 -W9_URL='appname.example.com' +W9_HTTP_PORT_SET=9001 + +# Built-in login and URL helpers: keep these in the protected block because the appstore parser +# reads them from the app package metadata surface. +# Portainer creates the first administrator account interactively in the browser on first run, +# so no login pair is seeded. +W9_URL=appname.example.com + W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Portainer image environment variables +# Docs: https://docs.portainer.io/advanced/cli +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +# Not used by default; enable only when needed: +# CSP=true +# COMPACT_DB=false +# TRUSTED_ORIGINS= +# EDGE_COMPUTE=false +# EDGE_PORTAINER_URL= diff --git a/apps/portainer/CHANGELOG.md b/apps/portainer/CHANGELOG.md index 582cf46c5..36653916a 100644 --- a/apps/portainer/CHANGELOG.md +++ b/apps/portainer/CHANGELOG.md @@ -1,5 +1,16 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Update Portainer CE from `2.34.0` to `2.45.1` (latest stable upstream release; Portainer publishes no `x.x` tag, so exact `x.x.x` pinning is required). +- Align `.env` with the current repository policy: template layout and image-env section banner. +- Drop the deprecated compose `version` field and the `# image:`/`# docs:` source comments, and document the published port inline. +- Declare the Portainer first-run setup token as a `variables.json` `credentials.token` source (`container-log`) with a short `help.login` note. +- Add `apps/portainer/tests/cases.yml` with a dedicated `/api/system/status` reachability check. +- Regenerate `README.md` from `variables.json` and `docker-compose.yml`. + +## 2026-10-10 + +- Replace the fragile setup-token `credentials.container-log` regex model with structured `setup.steps`. +- Model the Portainer bootstrap flow as two login-prep steps: read the setup token from logs, then open the web setup screen. +- Keep `help.login` focused on the final administrator sign-in after the wizard completes. diff --git a/apps/portainer/Notes.md b/apps/portainer/Notes.md deleted file mode 100644 index a59ce071f..000000000 --- a/apps/portainer/Notes.md +++ /dev/null @@ -1 +0,0 @@ -## About diff --git a/apps/portainer/README.md b/apps/portainer/README.md index b9af031df..3eef8691d 100644 --- a/apps/portainer/README.md +++ b/apps/portainer/README.md @@ -1,26 +1,82 @@ -# Portainer on Docker +# Portainer on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Portainer: +## Quick Start +### Deploy Verification - - community: 2.31.0, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Portainer**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Portainer admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://documentation.portainer.io/v2.0-be/deploy/requirements/): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 4 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Portainer by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Portainer Docker image](https://hub.docker.com/r/portainer/portainer-ce) and makes some improvements below. -If you want use Portainer with **Websoft9 Business Support** free, you can [subscribe Portainer](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Portainer Administrator Guide](https://support.websoft9.com/docs/portainer) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 2.45.1, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Portainer web UI and REST API | 9000 | + + +### Data Directory + + +- `portainer` → `/data` +- `/var/run/docker.sock` → `/var/run/docker.sock` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Portainer Administrator Guide](https://support.websoft9.com/docs/portainer) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/portainer/portainer-ce) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/portainer/docker-compose.yml b/apps/portainer/docker-compose.yml index 5d10e2e75..6115314a4 100644 --- a/apps/portainer/docker-compose.yml +++ b/apps/portainer/docker-compose.yml @@ -1,16 +1,11 @@ -# image: https://hub.docker.com/r/portainer/portainer-ce -# docs: https://docs.portainer.io/ - -version: '3.8' - services: portainer: image: ${W9_REPO}:${W9_VERSION} container_name: ${W9_ID} restart: unless-stopped - env_file: .env ports: - - ${W9_HTTP_PORT_SET}:9000 + - "${W9_HTTP_PORT_SET}:9000" # Portainer web UI and REST API + env_file: .env volumes: - portainer:/data - /var/run/docker.sock:/var/run/docker.sock diff --git a/apps/portainer/tests/cases.yml b/apps/portainer/tests/cases.yml new file mode 100644 index 000000000..b1a8b98da --- /dev/null +++ b/apps/portainer/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: system-status + type: web-access + path: /api/system/status + expect_status: 200 diff --git a/apps/portainer/variables.json b/apps/portainer/variables.json index a8b0d1c6c..4ae4a0373 100644 --- a/apps/portainer/variables.json +++ b/apps/portainer/variables.json @@ -9,7 +9,7 @@ { "dist": "community", "version": [ - "2.34.0", + "2.45.1", "latest" ] } @@ -25,5 +25,29 @@ "cpu": "1", "memory": "1", "disk": "4" + }, + "setup": { + "steps": [ + { + "id": "setup-token", + "text": "View the container logs and copy the one-time setup token printed by Portainer.", + "action": { + "type": "show-log", + "service": "portainer", + "tail": 50 + } + }, + { + "id": "setup-wizard", + "text": "Open Portainer and paste the setup token to create the first administrator account.", + "action": { + "type": "open", + "access": "web" + } + } + ] + }, + "help": { + "login": "After the setup wizard finishes, sign in with the administrator account and password you created there." } } diff --git a/apps/posthog/.env b/apps/posthog/.env index ffbc582cb..fe0c2ba29 100644 --- a/apps/posthog/.env +++ b/apps/posthog/.env @@ -1,47 +1,75 @@ -W9_REPO=wordpress +W9_REPO=posthog/posthog W9_DIST=community W9_VERSION=latest W9_POWER_PASSWORD=1PrMxExC45LsCT -# Environments which for user settings when create application -# Named expression: W9_xxx_xxx_SET, xxx refer to file fields -W9_HTTP_PORT_SET=9001 -# W9_HTTPS_PORT_SET=9002 -# W9_DB_PORT_SET=3306 -# W9_SSH_PORT_SET=23 -W9_KEY_SET="dfsjdkjf77xjxcjcj" +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. #### -- Not allowed to edit below environments when recreate app based on existing data -- #### W9_ID=posthog - -# W9_HTTP_PORT or W9_HTTPS_PORT is need at leaset and used for proxy for web application -# Some container (e.g teleport) need HTTPS access, then need to set this pra W9_HTTP_PORT=80 -W9_HTTPS_PORT=81 - -W9_LOGIN_USER=admin -# use https://1password.com/zh-cn/password-generator/ to genarate 14 bit password -# this password can also use password file -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD -W9_ADMIN_PATH="/wp-login" - -# Container name's suffix must use one of the value -W9_DB_EXPOSE="mysql,postgresql,mariadb,mongodb,redis" - -# It is used when the application APP needs to set an external URL, which can be IP(or domain), IP:PORT -# If have protocols, should be set it in the APP's ENV +W9_HTTP_PORT_SET=9019 +W9_DB_EXPOSE=postgresql +W9_DB_VERSION=15-alpine W9_URL=example.youdomain.com -# modifies W9_URL on init when it is true W9_URL_REPLACE=true - W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### +# ============================================================ +# PostHog image environment variables +# Docs: https://posthog.com/docs/self-host +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# ============================================================ + +# Used by docker-compose.yml: +POSTHOG_NODE_TAG=latest +REDIS_VERSION=7.2-alpine +VALKEY_VERSION=8.1-alpine +CLICKHOUSE_VERSION=26.6 +KAFKA_VERSION=v25.1.9 +OBJECTSTORAGE_VERSION=4.29 + +POSTHOG_DB_NAME=posthog +POSTHOG_DB_USER=posthog +POSTHOG_DB_PASSWORD=${W9_POWER_PASSWORD} +POSTHOG_SECRET=change-this-posthog-secret +ENCRYPTION_SALT_KEYS=change-this-salt-key + +DATABASE_URL=postgres://${POSTHOG_DB_USER}:${POSTHOG_DB_PASSWORD}@db:5432/${POSTHOG_DB_NAME} +REDIS_URL=redis://redis7:6379/ +KAFKA_HOSTS=kafka:9092 + +CLICKHOUSE_HOST=clickhouse +CLICKHOUSE_DATABASE=posthog +CLICKHOUSE_SECURE=false +CLICKHOUSE_VERIFY=false + +OBJECT_STORAGE_ENABLED=true +OBJECT_STORAGE_ENDPOINT=http://objectstorage:19000 +OBJECT_STORAGE_PUBLIC_ENDPOINT=https://${W9_URL} +OBJECT_STORAGE_ACCESS_KEY_ID=object_storage_root_user +OBJECT_STORAGE_SECRET_ACCESS_KEY=${W9_POWER_PASSWORD} +OBJECT_STORAGE_FORCE_PATH_STYLE=true + +SESSION_RECORDING_V2_S3_ENDPOINT=${OBJECT_STORAGE_ENDPOINT} +SESSION_RECORDING_V2_S3_ACCESS_KEY_ID=${OBJECT_STORAGE_ACCESS_KEY_ID} +SESSION_RECORDING_V2_S3_SECRET_ACCESS_KEY=${OBJECT_STORAGE_SECRET_ACCESS_KEY} + +SITE_URL=https://${W9_URL} +IS_BEHIND_PROXY=true +DISABLE_SECURE_SSL_REDIRECT=true -# Below environment is created by apphub +# Not used by default; enable only when needed: +# ANTHROPIC_API_KEY= +# OPENAI_API_KEY= +# OPENAI_BASE_URL=https://api.openai.com/v1 +# OPENAI_MODEL=gpt-4.1-mini +# OPT_OUT_CAPTURE=false #W9_NAME="" -#W9_RCODE="" \ No newline at end of file +#W9_RCODE="" diff --git a/apps/posthog/CHANGELOG.md b/apps/posthog/CHANGELOG.md index 582cf46c5..411672483 100644 --- a/apps/posthog/CHANGELOG.md +++ b/apps/posthog/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-09 +- Replaced the placeholder WordPress/Discuz files with a real PostHog self-hosted Compose package. +- Added PostHog upstream metadata, runtime environment wiring, and access metadata. +- Added compose helper scripts for PostHog startup and migration flow. diff --git a/apps/posthog/Dockerfile b/apps/posthog/Dockerfile deleted file mode 100644 index 4364b46fb..000000000 --- a/apps/posthog/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -# image: https://hub.docker.com/r/websoft9dev/discuzq - -FROM ccr.ccs.tencentyun.com/discuzq/dzq:latest - -LABEL org.opencontainers.image.authors="https://www.websoft9.com" \ - org.opencontainers.image.description="Application packaged by Websoft9" \ - org.opencontainers.image.source="https://github.com/Websoft9/docker-library/tree/main/apps/opencart" \ - org.opencontainers.image.title="OpenCart" \ - org.opencontainers.image.vendor="Websoft9 Inc." \ - org.opencontainers.image.version="4.0.1.1" - -ENV DISCUZQ_MYSQL_HOST=mysql -ENV DISCUZQ_MYSQL_USER=discuzq -ENV DISCUZQ_MYSQL_PASSWORD=discuzq -ENV DISCUZQ_MYSQL_DATABASE=discuzq -ENV DISCUZQ_SITENAME=DiscuzQ - -COPY cmd.sh /tmp -RUN chmod +x /tmp/cmd.sh - -CMD ["/tmp/cmd.sh"] diff --git a/apps/posthog/Notes.md b/apps/posthog/Notes.md index 1fdbbb29d..aa70045ea 100644 --- a/apps/posthog/Notes.md +++ b/apps/posthog/Notes.md @@ -1,2 +1,8 @@ -# Appname -## FAQ +# PostHog + +## Maintenance Notes + +- This app was rebuilt from an accidental placeholder/template package. +- Upstream self-hosting is compose-based and tracks floating images rather than stable semver releases. +- `W9_VERSION` intentionally remains `latest` unless Websoft9 decides to pin a known-good tag later. +- The package keeps the app-local topology smaller than upstream hobby by using published images instead of upstream local builds. diff --git a/apps/posthog/README.md b/apps/posthog/README.md index ab3d1d6cd..47f1645d1 100644 --- a/apps/posthog/README.md +++ b/apps/posthog/README.md @@ -1,26 +1,29 @@ -# PostHog on Docker +# PostHog on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for PostHog: +This app package deploys the official self-hosted PostHog stack on Websoft9 with Docker Compose. +- community: latest - - community: latest +## Requirements +PostHog recommends a VM roughly equivalent to: -## System Requirements +- 4 vCPU +- 16 GB RAM +- 30 GB available disk -The following are the minimal [recommended requirements](https://posthog.com): +## Notes -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 10 GB of free space -* **bandwidth**: more fluent experience over 100M +- PostHog does not publish stable self-hosted releases in the usual `x.y.z` form. +- The upstream project recommends running the latest Docker image for self-hosted deployments. +- This package exposes the PostHog web entrypoint through the internal Caddy proxy on port `80`. ## Install -You can install this PostHog by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Use the standard `docker-library` workflow for apps under `apps/posthog`. -If you want use PostHog with **Websoft9 Business Support** free, you can [subscribe PostHog](https://www.websoft9.com/apps) on Cloud platform +## Upstream -## Documentation - -[PostHog Administrator Guide](https://support.websoft9.com/docs/posthog) powered by Websoft9 \ No newline at end of file +- Docs: https://posthog.com/docs/self-host +- Source: https://github.com/PostHog/posthog +- Image: https://hub.docker.com/r/posthog/posthog diff --git a/apps/posthog/docker-compose.yml b/apps/posthog/docker-compose.yml index b501aed86..a09035ec5 100644 --- a/apps/posthog/docker-compose.yml +++ b/apps/posthog/docker-compose.yml @@ -1,50 +1,543 @@ -# image,docs: https://hub.docker.com/_/wordpress/ +# docs: https://posthog.com/docs/self-host -services: +x-logging: &default-logging + driver: "json-file" + options: + max-file: "5" + max-size: 10m - wordpress: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID - restart: unless-stopped - #This is for access host from container - # extra_hosts: ["host.docker.internal:host-gateway"] - # command: | - # /bin/bash -c "ping -c 3 host.docker.internal" - logging: - driver: "json-file" - options: - max-file: "5" - max-size: 10m - deploy: - resources: - limits: - memory: 5g - cpus: '0.7' +services: + proxy: + image: caddy:2 + container_name: ${W9_ID} + restart: unless-stopped + logging: *default-logging ports: - - $W9_HTTP_PORT_SET:80 - env_file: .env + - "${W9_HTTP_PORT_SET}:80" # Web Console + command: + - sh + - -c + - | + printf '%s\n' "$${CADDYFILE}" > /etc/caddy/Caddyfile + exec caddy run -c /etc/caddy/Caddyfile + environment: + CADDYFILE: | + :80 { + @replay_capture { + path /s + path /s/ + path /s/* + } + + @capture { + path /e + path /e/ + path /e/* + path /i/v0 + path /i/v0/ + path /i/v0/* + path /i/v1/analytics/events + path /i/v1/analytics/events/ + path /batch + path /batch/ + path /batch/* + path /capture + path /capture/ + path /capture/* + } + + @flags { + path /flags + path /flags/ + path /flags/* + path /api/feature_flag/local_evaluation + path /api/feature_flag/local_evaluation/ + path /api/feature_flag/local_evaluation/* + } + + @webhooks { + path /public/webhooks + path /public/webhooks/ + path /public/webhooks/* + path /public/m/ + path /public/m/* + } + + @objectstorage { + path /posthog + path /posthog/ + path /posthog/* + } + + handle @replay_capture { + reverse_proxy replay-capture:3000 + } + + handle @capture { + reverse_proxy capture:3000 + } + + handle @flags { + reverse_proxy feature-flags:3001 + } + + handle @webhooks { + reverse_proxy plugins:6738 + } + + handle @objectstorage { + reverse_proxy objectstorage:19000 + } + + handle { + reverse_proxy web:8000 + } + } + depends_on: + web: + condition: service_started + + db: + image: postgres:${W9_DB_VERSION} + container_name: ${W9_ID}-postgresql + restart: unless-stopped + logging: *default-logging + environment: + POSTGRES_USER: ${POSTHOG_DB_USER} + POSTGRES_DB: ${POSTHOG_DB_NAME} + POSTGRES_PASSWORD: ${POSTHOG_DB_PASSWORD} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTHOG_DB_USER}"] + interval: 5s + timeout: 30s + retries: 30 + start_period: 10s volumes: - - wordpress:/var/www/html - - ./src/php_exra.ini:/usr/local/etc/php/conf.d/php_exra.ini + - postgres-data:/var/lib/postgresql/data - mariadb: - image: mariadb:10.4 - container_name: $W9_ID-mariadb + redis7: + image: redis:${REDIS_VERSION} + container_name: ${W9_ID}-redis restart: unless-stopped - command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb_log_buffer_size=30M + logging: *default-logging + command: redis-server --maxmemory-policy allkeys-lru --maxmemory 200mb + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 3s + timeout: 10s + retries: 10 volumes: - - mysql_data:/var/lib/mysql + - redis-data:/data + + valkey: + image: valkey/valkey:${VALKEY_VERSION} + container_name: ${W9_ID}-valkey + restart: unless-stopped + logging: *default-logging + command: valkey-server --maxmemory-policy allkeys-lru --maxmemory 200mb + healthcheck: + test: ["CMD", "valkey-cli", "ping"] + interval: 3s + timeout: 10s + retries: 10 + + clickhouse: + image: clickhouse/clickhouse-server:${CLICKHOUSE_VERSION} + container_name: ${W9_ID}-clickhouse + restart: unless-stopped + logging: *default-logging environment: - MYSQL_DATABASE: $W9_ID - MYSQL_USER: $W9_ID - MYSQL_PASSWORD: $W9_POWER_PASSWORD - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD + CLICKHOUSE_SKIP_USER_SETUP: "1" + KAFKA_HOSTS: kafka:9092 + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"] + interval: 3s + timeout: 10s + retries: 10 + volumes: + - clickhouse-data:/var/lib/clickhouse + + kafka: + image: docker.io/redpandadata/redpanda:${KAFKA_VERSION} + container_name: ${W9_ID}-kafka + restart: unless-stopped + logging: *default-logging + command: + - redpanda + - start + - --kafka-addr + - internal://0.0.0.0:9092,external://0.0.0.0:19092 + - --advertise-kafka-addr + - internal://kafka:9092,external://localhost:19092 + - --pandaproxy-addr + - internal://0.0.0.0:8082,external://0.0.0.0:18082 + - --advertise-pandaproxy-addr + - internal://kafka:8082,external://localhost:18082 + - --schema-registry-addr + - internal://0.0.0.0:8081,external://0.0.0.0:18081 + - --rpc-addr + - kafka:33145 + - --advertise-rpc-addr + - kafka:33145 + - --mode + - dev-container + - --smp + - "2" + - --memory + - 3G + - --reserve-memory + - 500M + - --overprovisioned + - --set + - redpanda.empty_seed_starts_cluster=false + - --seeds + - kafka:33145 + - --set + - redpanda.auto_create_topics_enabled=true + environment: + ALLOW_PLAINTEXT_LISTENER: "true" + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:9644/v1/status/ready || exit 1"] + interval: 3s + timeout: 10s + retries: 10 + volumes: + - kafka-data:/var/lib/redpanda/data + + objectstorage: + image: chrislusf/seaweedfs:${OBJECTSTORAGE_VERSION} + container_name: ${W9_ID}-objectstorage + restart: unless-stopped + logging: *default-logging + entrypoint: + - /bin/sh + - -c + - | + ( + while true; do + printf 's3.configure -access_key=%s -secret_key=%s -user=posthog -actions=Admin -apply\ns3.bucket.create -name posthog\ns3.bucket.create -name ai-blobs\n' "${OBJECT_STORAGE_ACCESS_KEY_ID}" "${OBJECT_STORAGE_SECRET_ACCESS_KEY}" | /usr/bin/weed shell -master=localhost:19001 >/dev/null 2>&1 || true + if echo 's3.bucket.list' | /usr/bin/weed shell -master=localhost:19001 2>/dev/null | grep -q ai-blobs && echo 's3.configure' | /usr/bin/weed shell -master=localhost:19001 2>/dev/null | grep -q "${OBJECT_STORAGE_ACCESS_KEY_ID}"; then + touch /tmp/objectstorage-ready + break + fi + sleep 1 + done + ) & + exec /usr/bin/weed "$$@" + - -- + command: + - server + - -master.port=19001 + - -s3 + - -s3.port=19000 + - -dir=/data + - -volume.max=1000 + - -master.volumePreallocate=false + healthcheck: + test: ["CMD", "test", "-f", "/tmp/objectstorage-ready"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 10s + volumes: + - objectstorage-data:/data + + geoip: + image: alpine:3.20 + container_name: ${W9_ID}-geoip + restart: "no" + logging: *default-logging + command: + - /bin/sh + - -ec + - | + apk add --no-cache brotli curl >/dev/null + mkdir -p /share + if [ ! -s /share/GeoLite2-City.mmdb ]; then + curl -fsSL https://mmdbcdn.posthog.net/ | brotli -d > /share/GeoLite2-City.mmdb + fi + volumes: + - share-data:/share + + web: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID}-web + restart: unless-stopped + logging: *default-logging + command: /compose/start + env_file: + - .env + volumes: + - ./src/compose:/compose:ro + environment: + SECRET_KEY: ${POSTHOG_SECRET} + SITE_URL: ${SITE_URL} + DEPLOYMENT: hobby + FEATURE_FLAGS_SERVICE_URL: http://feature-flags:3001 + OBJECT_STORAGE_ENABLED: "true" + INTERNAL_API_SECRET: ${POSTHOG_SECRET} + RECORDING_API_URL: http://recording-api:6738 + OTEL_SDK_DISABLED: "true" + PERSONHOG_ENABLED: "false" + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + clickhouse: + condition: service_healthy + kafka: + condition: service_healthy + objectstorage: + condition: service_healthy + feature-flags: + condition: service_started + + worker: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID}-worker + restart: unless-stopped + logging: *default-logging + command: ./bin/docker-worker-celery --with-scheduler + env_file: + - .env + environment: + SECRET_KEY: ${POSTHOG_SECRET} + SITE_URL: ${SITE_URL} + DEPLOYMENT: hobby + FEATURE_FLAGS_SERVICE_URL: http://feature-flags:3001 + OBJECT_STORAGE_ENABLED: "true" + INTERNAL_API_SECRET: ${POSTHOG_SECRET} + RECORDING_API_URL: http://recording-api:6738 + POSTHOG_SKIP_MIGRATION_CHECKS: "1" + OTEL_SDK_DISABLED: "true" + PERSONHOG_ENABLED: "false" + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + clickhouse: + condition: service_healthy + kafka: + condition: service_healthy + objectstorage: + condition: service_healthy + web: + condition: service_started + + plugins: + image: posthog/posthog-node:${POSTHOG_NODE_TAG} + container_name: ${W9_ID}-plugins + restart: unless-stopped + logging: *default-logging + command: node nodejs/dist/index.js + env_file: + - .env + environment: + SECRET_KEY: ${POSTHOG_SECRET} + SITE_URL: ${SITE_URL} + PERSONS_DATABASE_URL: ${DATABASE_URL} + BEHAVIORAL_COHORTS_DATABASE_URL: ${DATABASE_URL} + CDP_REDIS_HOST: redis7 + CDP_REDIS_PORT: "6379" + CDP_VALKEY_HOST: valkey + CDP_VALKEY_PORT: "6379" + LOGS_REDIS_HOST: redis7 + LOGS_REDIS_PORT: "6379" + LOGS_REDIS_TLS: "false" + TRACES_REDIS_HOST: redis7 + TRACES_REDIS_PORT: "6379" + TRACES_REDIS_TLS: "false" + ENCRYPTION_SALT_KEYS: ${ENCRYPTION_SALT_KEYS} + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + valkey: + condition: service_healthy + clickhouse: + condition: service_healthy + kafka: + condition: service_healthy + objectstorage: + condition: service_healthy + + ingestion-general: + image: posthog/posthog-node:${POSTHOG_NODE_TAG} + container_name: ${W9_ID}-ingestion + restart: unless-stopped + logging: *default-logging + command: node nodejs/dist/index.js + env_file: + - .env + environment: + PLUGIN_SERVER_MODE: ingestion-v2-combined + SECRET_KEY: ${POSTHOG_SECRET} + PERSONS_DATABASE_URL: ${DATABASE_URL} + BEHAVIORAL_COHORTS_DATABASE_URL: ${DATABASE_URL} + COOKIELESS_REDIS_HOST: redis7 + COOKIELESS_REDIS_PORT: "6379" + CDP_REDIS_HOST: redis7 + ENCRYPTION_SALT_KEYS: ${ENCRYPTION_SALT_KEYS} + AI_BLOB_S3_BUCKET: ai-blobs + AI_BLOB_S3_PREFIX: aio/ + AI_BLOB_S3_ENDPOINT: ${OBJECT_STORAGE_ENDPOINT} + AI_BLOB_S3_REGION: us-east-1 + AI_BLOB_S3_ACCESS_KEY_ID: ${OBJECT_STORAGE_ACCESS_KEY_ID} + AI_BLOB_S3_SECRET_ACCESS_KEY: ${OBJECT_STORAGE_SECRET_ACCESS_KEY} + AI_BLOB_OFFLOAD_TEAMS: "*" + PERSONHOG_ENABLED: "false" + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + clickhouse: + condition: service_healthy + kafka: + condition: service_healthy + objectstorage: + condition: service_healthy + + ingestion-sessionreplay: + image: posthog/posthog-node:${POSTHOG_NODE_TAG} + container_name: ${W9_ID}-sessionreplay + restart: unless-stopped + logging: *default-logging + command: node nodejs/dist/index.js + env_file: + - .env + environment: + PLUGIN_SERVER_MODE: recordings-blob-ingestion-v2 + SESSION_RECORDING_V2_S3_TIMEOUT_MS: "120000" + ENCRYPTION_SALT_KEYS: ${ENCRYPTION_SALT_KEYS} + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + kafka: + condition: service_healthy + objectstorage: + condition: service_healthy + + recording-api: + image: posthog/posthog-node:${POSTHOG_NODE_TAG} + container_name: ${W9_ID}-recording-api + restart: unless-stopped + logging: *default-logging + command: node nodejs/dist/index.js + env_file: + - .env + environment: + PLUGIN_SERVER_MODE: recording-api + SESSION_RECORDING_API_REDIS_HOST: redis7 + SESSION_RECORDING_API_REDIS_PORT: "6379" + ENCRYPTION_SALT_KEYS: ${ENCRYPTION_SALT_KEYS} + INTERNAL_API_SECRET: ${POSTHOG_SECRET} + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + clickhouse: + condition: service_healthy + objectstorage: + condition: service_healthy + + capture: + image: ghcr.io/posthog/posthog/capture:master + container_name: ${W9_ID}-capture + restart: unless-stopped + logging: *default-logging + env_file: + - .env + environment: + ADDRESS: 0.0.0.0:3000 + KAFKA_TOPIC: events_plugin_ingestion + CAPTURE_OUTPUT_ANALYTICS_MAIN_TOPIC: events_plugin_ingestion + KAFKA_ERROR_TRACKING_TOPIC: ingestion-errortracking-main + CAPTURE_OUTPUT_ERROR_TRACKING_TOPIC: ingestion-errortracking-main + KAFKA_INGESTION_PRODUCER_METADATA_BROKER_LIST: kafka:9092 + CAPTURE_MODE: events + RUST_LOG: info,rdkafka=warn + CAPTURE_V1_SINKS: msk + CAPTURE_V1_SINK_MSK_KAFKA_HOSTS: kafka:9092 + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_MAIN: events_plugin_ingestion + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_HISTORICAL: events_plugin_ingestion_historical + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_OVERFLOW: events_plugin_ingestion_overflow + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_DLQ: events_plugin_ingestion_dlq + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_EXCEPTION: ingestion-errortracking-main + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_HEATMAP: heatmaps_ingestion + CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_CLIENT_INGESTION_WARNING: ingestion-clientwarnings-main-1 + depends_on: + kafka: + condition: service_healthy + redis7: + condition: service_healthy + + replay-capture: + image: ghcr.io/posthog/posthog/capture:master + container_name: ${W9_ID}-replay-capture + restart: unless-stopped + logging: *default-logging + env_file: + - .env + environment: + ADDRESS: 0.0.0.0:3000 + KAFKA_TOPIC: session_recording_snapshot_item_events + CAPTURE_OUTPUT_SESSION_REPLAY_MAIN_TOPIC: session_recording_snapshot_item_events + KAFKA_INGESTION_PRODUCER_METADATA_BROKER_LIST: kafka:9092 + CAPTURE_MODE: recordings + depends_on: + kafka: + condition: service_healthy + redis7: + condition: service_healthy + + feature-flags: + image: ghcr.io/posthog/posthog/feature-flags:master + container_name: ${W9_ID}-feature-flags + restart: unless-stopped + logging: *default-logging + env_file: + - .env + volumes: + - share-data:/share + environment: + WRITE_DATABASE_URL: ${DATABASE_URL} + READ_DATABASE_URL: ${DATABASE_URL} + PERSONS_WRITE_DATABASE_URL: ${DATABASE_URL} + PERSONS_READ_DATABASE_URL: ${DATABASE_URL} + ADDRESS: 0.0.0.0:3001 + COOKIELESS_REDIS_HOST: redis7 + COOKIELESS_REDIS_PORT: "6379" + RUST_LOG: info + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3001/_readiness"] + interval: 5s + timeout: 5s + retries: 12 + start_period: 10s + depends_on: + db: + condition: service_healthy + redis7: + condition: service_healthy + geoip: + condition: service_completed_successfully volumes: - wordpress: - mysql_data: - + postgres-data: + redis-data: + clickhouse-data: + kafka-data: + objectstorage-data: + share-data: + networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true diff --git a/apps/posthog/src/after_up.sh b/apps/posthog/src/after_up.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/posthog/src/after_up.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/posthog/src/compose/start b/apps/posthog/src/compose/start new file mode 100755 index 000000000..9d80224f9 --- /dev/null +++ b/apps/posthog/src/compose/start @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +/compose/wait +./bin/migrate +exec ./bin/docker-server diff --git a/apps/posthog/src/compose/wait b/apps/posthog/src/compose/wait new file mode 100755 index 000000000..f0fd152df --- /dev/null +++ b/apps/posthog/src/compose/wait @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +import socket +import time + + +def wait_for(name: str, host: str, port: int) -> None: + while True: + try: + with socket.create_connection((host, port), timeout=5): + return + except OSError: + print(f"waiting for {name} on {host}:{port}") + time.sleep(5) + + +wait_for("ClickHouse", "clickhouse", 9000) +wait_for("PostgreSQL", "db", 5432) diff --git a/apps/posthog/src/encrypt.sh b/apps/posthog/src/encrypt.sh deleted file mode 100644 index 2939685f7..000000000 --- a/apps/posthog/src/encrypt.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin -clear - - - -# Add encrypt script below if use W9_ENCRYPT_PASSWORD at .env file -# ------------- start ------------------------- - - - -# ------------- end --------------------------- diff --git a/apps/posthog/src/filelist b/apps/posthog/src/filelist deleted file mode 100644 index 341240aed..000000000 --- a/apps/posthog/src/filelist +++ /dev/null @@ -1,3 +0,0 @@ -docker-compose.yml -script/test.sh -docker \ No newline at end of file diff --git a/apps/posthog/src/get_version.sh b/apps/posthog/src/get_version.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/posthog/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/posthog/src/nginx-proxy.conf.template b/apps/posthog/src/nginx-proxy.conf.template deleted file mode 100644 index 951364ffe..000000000 --- a/apps/posthog/src/nginx-proxy.conf.template +++ /dev/null @@ -1,57 +0,0 @@ -proxy_busy_buffers_size 512k; -proxy_buffers 4 512k; -proxy_buffer_size 256k; -client_max_body_size 50m; -# override default location / -location / { - add_header X-Served-By $host; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Scheme $scheme; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_pass $forward_scheme://$server:$port$request_uri; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection upgrade; - } - -location /console { - proxy_pass http://$server:8080; - proxy_http_version 1.1; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; -} - -# for echo some useful information -location / { - default_type text/plain; - return 200 'Hello World'; -} - -location /oida/ { -# this is the address and port of the ORDS installation -proxy_pass http://127.0.0.1:8080/ords/; - -# set Origin to blank to avoid Chrome problems with CORS -proxy_set_header Origin "" ; - -# pass along some header variables with the public host name/port/and so on -proxy_set_header Host $host; -proxy_set_header X-Forwarded-Host $host:$server_port; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; - -# this reverse proxies any "location" headers being passed in the response -proxy_redirect http://$host/ords/ https://$host/oida/; - -# also tell cookies their public path -proxy_cookie_path /ords/ /oida/; - -# reverse proxy links included in response (ie from ORDS webservice) -sub_filter_types application/json ; -sub_filter http://$host/ords/ https://$host/oida/; -sub_filter_once off; -} diff --git a/apps/posthog/src/php_exra.ini b/apps/posthog/src/php_exra.ini deleted file mode 100644 index b253d5718..000000000 --- a/apps/posthog/src/php_exra.ini +++ /dev/null @@ -1,8 +0,0 @@ -file_uploads = On -max_input_time = 800 -max_execution_time = 300 -memory_limit = 600M -upload_max_filesize = 900M -post_max_size = 900M -max_file_uploads = 200 -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT \ No newline at end of file diff --git a/apps/posthog/src/replace_url.sh b/apps/posthog/src/replace_url.sh deleted file mode 100644 index f737258b3..000000000 --- a/apps/posthog/src/replace_url.sh +++ /dev/null @@ -1 +0,0 @@ -# some application have write url to database or config file, once replaced url at .env, it should replace it at config file or database \ No newline at end of file diff --git a/apps/posthog/variables.json b/apps/posthog/variables.json index fa4a41f78..099b1af2c 100644 --- a/apps/posthog/variables.json +++ b/apps/posthog/variables.json @@ -10,9 +10,23 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { - "cpu": "2", - "memory": "4", - "disk": "10" + "cpu": "4", + "memory": "16", + "disk": "30" + }, + "upstream": { + "image": "https://hub.docker.com/r/posthog/posthog", + "docs": [ + "https://posthog.com/docs/self-host", + "https://github.com/PostHog/posthog" + ] } } diff --git a/apps/pydio/src/get_version.sh b/apps/pydio/src/get_version.sh deleted file mode 100644 index 8b1378917..000000000 --- a/apps/pydio/src/get_version.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/python/variables.json b/apps/python/variables.json index 5bc34ca75..f49f91a98 100644 --- a/apps/python/variables.json +++ b/apps/python/variables.json @@ -25,5 +25,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/python" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/qdrant/.env b/apps/qdrant/.env new file mode 100644 index 000000000..b4e7a58bd --- /dev/null +++ b/apps/qdrant/.env @@ -0,0 +1,45 @@ +W9_REPO=qdrant/qdrant +W9_DIST=community +W9_VERSION=v1.19 + +# Optional password seed: enable only when the package actually controls a DB or built-in login. +# See docs/w9-env-spec.md for when W9_POWER_PASSWORD is appropriate. +# W9_POWER_PASSWORD="{power_password}" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=qdrant +W9_HTTP_PORT=6333 +W9_HTTP_PORT_SET=6333 +W9_GRPC_PORT_SET=6334 +W9_ADMIN_PATH="/dashboard" +W9_URL=qdrant.example.com + +W9_NETWORK=websoft9 + +#### ----------------------------------------------------------------------------------------- #### + +#W9_NAME="" +#W9_RCODE="" + +# ============================================================ +# Qdrant image environment variables +# Docs: https://hub.docker.com/r/qdrant/qdrant +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +QDRANT__SERVICE__HTTP_PORT=${W9_HTTP_PORT} +QDRANT__SERVICE__GRPC_PORT=6334 + +# Not used by default; enable only when needed: +# QDRANT__LOG_LEVEL=INFO +# QDRANT__SERVICE__API_KEY= +# QDRANT__SERVICE__READ_ONLY_API_KEY= +# QDRANT__STORAGE__SNAPSHOTS_PATH=/qdrant/snapshots +# QDRANT__TELEMETRY_DISABLED=true diff --git a/apps/qdrant/CHANGELOG.md b/apps/qdrant/CHANGELOG.md new file mode 100644 index 000000000..9ee861592 --- /dev/null +++ b/apps/qdrant/CHANGELOG.md @@ -0,0 +1,5 @@ +# CHANGELOG + +## 2026-10-09 +- Initial Websoft9 package for Qdrant using the official `qdrant/qdrant:v1.19.2` image. +- Added persistent single-node deployment, healthcheck, metadata, and validation tests. diff --git a/apps/qdrant/README.md b/apps/qdrant/README.md new file mode 100644 index 000000000..888e30bf8 --- /dev/null +++ b/apps/qdrant/README.md @@ -0,0 +1,89 @@ +# Qdrant on Docker + +## Quick Start + +### Deploy Verification + +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Qdrant**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + + +### Usage + +1. Make sure you are signed in to the Qdrant admin console. +2. Try a core feature. + +### Change Password + +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + + +## Configuration Reference + +Websoft9 packages this app from the official [Qdrant Docker image](https://hub.docker.com/r/qdrant/qdrant) and makes some improvements below. + + + + + +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: v1.19.2, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| HTTP API and Web UI | 6333 | +| gRPC API | 6334 | + + +### Data Directory + + +Data is persisted in the `qdrant` volume, mounted at `/qdrant/storage`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Qdrant Administrator Guide](https://support.websoft9.com/docs/qdrant) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/qdrant/qdrant) + +- [Releases](https://github.com/qdrant/qdrant/releases) + +- [GitHub docs](https://github.com/qdrant/qdrant) + +- [Official docs](https://qdrant.tech/documentation/quickstart/) + +- [Official docs](https://api.qdrant.tech/api-reference/service/healthz) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/qdrant/docker-compose.yml b/apps/qdrant/docker-compose.yml new file mode 100644 index 000000000..dd6b95078 --- /dev/null +++ b/apps/qdrant/docker-compose.yml @@ -0,0 +1,25 @@ +services: + qdrant: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} + restart: unless-stopped + ports: + - "${W9_HTTP_PORT_SET}:6333" # HTTP API and Web UI + - "${W9_GRPC_PORT_SET}:6334" # gRPC API + volumes: + - qdrant:/qdrant/storage + env_file: .env + healthcheck: + test: ["CMD-SHELL", "bash -lc 'exec 3<>/dev/tcp/127.0.0.1/6333 && printf \"GET /healthz HTTP/1.1\\r\\nHost: 127.0.0.1\\r\\nConnection: close\\r\\n\\r\\n\" >&3 && cat <&3 | grep -q \"healthz check passed\"'"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 20s + +volumes: + qdrant: + +networks: + default: + name: ${W9_NETWORK} + external: true diff --git a/apps/graylog/src/filelist b/apps/qdrant/src/.gitkeep similarity index 100% rename from apps/graylog/src/filelist rename to apps/qdrant/src/.gitkeep diff --git a/apps/qdrant/tests/cases.yml b/apps/qdrant/tests/cases.yml new file mode 100644 index 000000000..949c96248 --- /dev/null +++ b/apps/qdrant/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: healthz + type: web-access + path: /healthz + expect_status: 200 diff --git a/apps/qdrant/variables.json b/apps/qdrant/variables.json new file mode 100644 index 000000000..345c3b292 --- /dev/null +++ b/apps/qdrant/variables.json @@ -0,0 +1,51 @@ +{ + "name": "qdrant", + "trademark": "Qdrant", + "release": true, + "upstream": { + "image": "https://hub.docker.com/r/qdrant/qdrant", + "releases": "https://github.com/qdrant/qdrant/releases", + "docs": [ + "https://github.com/qdrant/qdrant", + "https://qdrant.tech/documentation/quickstart/", + "https://api.qdrant.tech/api-reference/service/healthz" + ] + }, + "edition": [ + { + "dist": "community", + "version": [ + "v1.19", + "latest" + ] + } + ], + "access": { + "defaultScheme": "http", + "api": { + "port": 6333, + "path": "/" + }, + "web": { + "port": 6333, + "path": "/dashboard" + }, + "grpc": { + "port": 6334, + "scheme": "grpc", + "path": "/" + } + }, + "requirements": { + "cpu": "1", + "memory": "2", + "disk": "1" + }, + "credentials": {}, + "env": { + "first_startup_only": [] + }, + "help": { + "db": "Qdrant starts without authentication by default. Secure the instance before internet exposure by enabling API keys in the image environment variables section." + } +} diff --git a/apps/rabbitmq/variables.json b/apps/rabbitmq/variables.json index 1d63c1201..461060fed 100644 --- a/apps/rabbitmq/variables.json +++ b/apps/rabbitmq/variables.json @@ -14,7 +14,9 @@ "edition": [ { "dist": "community", - "version": ["4.3-management"] + "version": [ + "4.3-management" + ] } ], "requirements": { @@ -27,5 +29,12 @@ "RABBITMQ_DEFAULT_USER", "RABBITMQ_DEFAULT_PASS" ] + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 15672, + "path": "/" + } } } diff --git a/apps/rancher/.env b/apps/rancher/.env index 1ff340c21..bf0139944 100644 --- a/apps/rancher/.env +++ b/apps/rancher/.env @@ -1,11 +1,35 @@ -W9_DIST='community' -W9_VERSION='latest' W9_REPO=rancher/rancher -W9_ID='rancher' -W9_HTTP_PORT_SET='9001' +W9_DIST=community +W9_VERSION=v2.15.2 + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=rancher W9_HTTPS_PORT=443 -W9_URL='appname.example.com' +W9_HTTPS_PORT_SET=9004 + +W9_URL=appname.example.com + W9_NETWORK=websoft9 -# more environments from this app: https://ranchermanager.docs.rancher.com/v2.8/reference-guides/single-node-rancher-in-docker/advanced-options +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Rancher image environment variables +# Docs: https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/other-installation-methods/rancher-on-a-single-node-with-docker +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +# Not used by default; enable only when needed: +# CATTLE_SYSTEM_DEFAULT_REGISTRY= +# CATTLE_TLS_MIN_VERSION=1.2 +# CATTLE_SERVER_URL=https://${W9_URL} +# CATTLE_TELEMETRY_OPT_OUT=true +# CATTLE_BOOTSTRAP_PASSWORD= diff --git a/apps/rancher/CHANGELOG.md b/apps/rancher/CHANGELOG.md index 3f2d7b08c..c180b2ef5 100644 --- a/apps/rancher/CHANGELOG.md +++ b/apps/rancher/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## 2026-09-12 -- Replaced the legacy `W9_LOGIN_GET_PASSWORD` command with declarative `variables.json.credentials.password` metadata using the Rancher bootstrap password log pattern. -- Regenerated the README. +## 2026-09-30 + +- Pin Rancher community from the floating `latest` alias to `v2.15.2`. +- Model the console as an HTTPS port (`W9_HTTPS_PORT_SET`) instead of `W9_HTTP_PORT_SET`. +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, and the current `.env` layout. +- Add a self-signed HTTPS reachability check in `tests/cases.yml`. diff --git a/apps/rancher/Notes.md b/apps/rancher/Notes.md deleted file mode 100644 index f532e7ef5..000000000 --- a/apps/rancher/Notes.md +++ /dev/null @@ -1,4 +0,0 @@ -## Rancher - -- Ranker need Set https at Websoft9 Gateway, otherwise it can't login -- User should get command to retrieve the setup password from Websoft9 console diff --git a/apps/rancher/README.md b/apps/rancher/README.md index e7a7ea793..6baa1dfc1 100644 --- a/apps/rancher/README.md +++ b/apps/rancher/README.md @@ -33,7 +33,7 @@ Apps run as containers; rebuild after any configuration change. ### Version Support -Supported versions: latest. +Supported versions: v2.15.2, latest. The `latest` tag is not guaranteed to remain valid; pin a specific version for production. @@ -42,7 +42,7 @@ The `latest` tag is not guaranteed to remain valid; pin a specific version for p | Purpose | Port | | --- | --- | -| W9_HTTP_PORT_SET | 443 | +| Rancher web console (HTTPS) | 443 | ### Data Directory @@ -68,6 +68,10 @@ Configuration files live inside the image; mount a single file read-only to over - [Docker Hub image](https://hub.docker.com/r/rancher/rancher) +- [Releases](https://github.com/rancher/rancher/releases) + +- [Official docs](https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/other-installation-methods/rancher-on-a-single-node-with-docker) + ## Troubleshooting diff --git a/apps/rancher/docker-compose.yml b/apps/rancher/docker-compose.yml index 85931a996..ff77f5a7b 100644 --- a/apps/rancher/docker-compose.yml +++ b/apps/rancher/docker-compose.yml @@ -1,6 +1,3 @@ -# docs:https://ranchermanager.docs.rancher.com/v2.8/getting-started/installation-and-upgrade/other-installation-methods/rancher-on-a-single-node-with-docker -# image: https://hub.docker.com/r/rancher/rancher/tags - version: '3.8' services: @@ -8,10 +5,10 @@ services: image: ${W9_REPO}:${W9_VERSION} container_name: ${W9_ID} privileged: true - env_file: + env_file: - .env ports: - - ${W9_HTTP_PORT_SET}:443 + - "${W9_HTTPS_PORT_SET}:443" # Rancher web console (HTTPS) restart: unless-stopped volumes: - rancher:/var/lib/rancher diff --git a/apps/rancher/tests/cases.yml b/apps/rancher/tests/cases.yml new file mode 100644 index 000000000..2b69b4d73 --- /dev/null +++ b/apps/rancher/tests/cases.yml @@ -0,0 +1,9 @@ +# Rancher serves the console over HTTPS with a self-signed certificate, so the +# adaptive HTTP web-access check does not apply. +skip: + - id: web-access + +optional: + - id: rancher-https + type: script + script: check.sh diff --git a/apps/rancher/tests/check.sh b/apps/rancher/tests/check.sh new file mode 100755 index 000000000..e57bfe835 --- /dev/null +++ b/apps/rancher/tests/check.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -uo pipefail + +port="${W9_HTTPS_PORT_SET:-9004}" +base="https://localhost:${port}" +deadline=$((SECONDS + 300)) +code="000" + +while [ "${SECONDS}" -lt "${deadline}" ]; do + code=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 20 "${base}/" || true) + case "${code}" in + 200|301|302|303) break ;; + esac + sleep 5 +done + +if [ "${code}" != "200" ] && [ "${code}" != "301" ] && [ "${code}" != "302" ] && [ "${code}" != "303" ]; then + echo "rancher ${base}/ -> ${code} (timeout)" + exit 1 +fi +echo "rancher ${base}/ -> ${code}" diff --git a/apps/rancher/variables.json b/apps/rancher/variables.json index cce850643..932a8d8d1 100644 --- a/apps/rancher/variables.json +++ b/apps/rancher/variables.json @@ -3,12 +3,17 @@ "trademark": "Rancher", "release": true, "upstream": { - "image": "https://hub.docker.com/r/rancher/rancher" + "image": "https://hub.docker.com/r/rancher/rancher", + "releases": "https://github.com/rancher/rancher/releases", + "docs": [ + "https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/other-installation-methods/rancher-on-a-single-node-with-docker" + ] }, "edition": [ { "dist": "community", "version": [ + "v2.15.2", "latest" ] } @@ -25,12 +30,8 @@ "memory": "2", "disk": "1" }, - "credentials": { - "password": { - "source": "container-log", - "match": "regex", - "pattern": "Bootstrap Password:\\s*(.+)", - "group": 1 - } + "credentials": {}, + "help": { + "login": "Rancher prints the bootstrap password only after the container starts. Retrieve it manually with the official command `docker exec -it ${W9_ID} reset-password`, then use the printed password on the first login screen. The value is not available declaratively before runtime, so it is documented here instead of being modeled as machine-readable credentials." } } diff --git a/apps/redis/.env b/apps/redis/.env index d6f712dde..b66f6b5d2 100644 --- a/apps/redis/.env +++ b/apps/redis/.env @@ -1,13 +1,38 @@ -W9_DIST='community' W9_REPO=redis -W9_VERSION='8.0' -W9_POWER_PASSWORD='o!WO1fez4uYGVB6!' +W9_DIST=community +W9_VERSION=8.10 +W9_POWER_PASSWORD="o!WO1fez4uYGVB6!" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='redis' -W9_LOGIN_PASSWORD=$W9_POWER_PASSWORD + +W9_ID=redis W9_DB_PORT=6379 -W9_DB_PORT_SET='6379' +W9_DB_PORT_SET=6379 + +# Redis authenticates with the ACL `default` user; the password is seeded here. +W9_LOGIN_USER=default +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} + W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### -REDIS_PASSWORD=$W9_POWER_PASSWORD +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Redis image environment variables +# Docs: https://hub.docker.com/_/redis +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +# Not used by default; enable only when needed: +# REDIS_ARGS=--appendonly yes +# REDIS_MAXMEMORY=256mb +# REDIS_MAXMEMORY_POLICY=allkeys-lru +# REDIS_SAVE=3600 1 +# REDIS_APPENDONLY=yes diff --git a/apps/redis/CHANGELOG.md b/apps/redis/CHANGELOG.md index 582cf46c5..7e3d6d8c2 100644 --- a/apps/redis/CHANGELOG.md +++ b/apps/redis/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Upgrade Redis community to 8.10. +- Fix `upstream.image` to point at the official Redis image (`hub.docker.com/_/redis`). +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, and the current `.env` layout. +- Model the ACL `default` credentials through the `W9_LOGIN_*` pair and add an app-specific ping check in `tests/cases.yml`. diff --git a/apps/redis/Notes.md b/apps/redis/Notes.md deleted file mode 100644 index ecbb7bda0..000000000 --- a/apps/redis/Notes.md +++ /dev/null @@ -1,6 +0,0 @@ -## Redis - -You can set redis by one method of below: - -- command: redis-server --requirepass ${REDIS_PASSWORD} --bind 0.0.0.0 --loglevel verbose -- entrypoint: ["redis-server", "/etc/redis.conf"] \ No newline at end of file diff --git a/apps/redis/README.md b/apps/redis/README.md index 2df06a050..2075966de 100644 --- a/apps/redis/README.md +++ b/apps/redis/README.md @@ -1,26 +1,86 @@ -# Redis on Docker +# Redis on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Redis: +## Quick Start +### Deploy Verification - - community: 7.4, 7.2, 7.0, 6.0, 5.0, 4.0, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Redis**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Redis admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://redis.io/topics/config): +### Change Password -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Redis by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Redis Docker image](https://hub.docker.com/_/redis) and makes some improvements below. -If you want use Redis with **Websoft9 Business Support** free, you can [subscribe Redis](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Redis Administrator Guide](https://support.websoft9.com/docs/redis) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 8.10, 8.0, 7.4, 7.2, 7.0, 6.0, 5.0, 4.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Redis | 6379 | + + +### Data Directory + + +Data is persisted in the `redis_data` volume, mounted at `/data`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Redis Administrator Guide](https://support.websoft9.com/docs/redis) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/redis) + +- [Releases](https://github.com/redis/redis/releases) + +- [GitHub docs](https://github.com/docker-library/docs/blob/master/redis/README.md) + +- [Official docs](https://redis.io/docs/latest/operate/oss_and_stack/management/config/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/redis/docker-compose.yml b/apps/redis/docker-compose.yml index 3c741979a..092ff0d60 100644 --- a/apps/redis/docker-compose.yml +++ b/apps/redis/docker-compose.yml @@ -1,18 +1,16 @@ -# image: https://hub.docker.com/_/redis - version: '3.8' services: redis: - image: $W9_REPO:${W9_VERSION} + image: ${W9_REPO}:${W9_VERSION} container_name: ${W9_ID} restart: unless-stopped - ports: - - ${W9_DB_PORT_SET}:6379 + ports: + - "${W9_DB_PORT_SET}:6379" # Redis env_file: .env volumes: - redis_data:/data - command: redis-server --requirepass ${REDIS_PASSWORD} --bind 0.0.0.0 --loglevel verbose + command: redis-server --requirepass ${W9_LOGIN_PASSWORD} --bind 0.0.0.0 --loglevel verbose networks: default: diff --git a/apps/redis/tests/cases.yml b/apps/redis/tests/cases.yml new file mode 100644 index 000000000..926be700b --- /dev/null +++ b/apps/redis/tests/cases.yml @@ -0,0 +1,7 @@ +# Redis has no HTTP surface, so the adaptive web-access check does not apply. +# Its core path is accepting authenticated client connections, so a custom +# script runs an authenticated redis-cli ping inside the container. +custom: + - id: redis-ping + type: script + script: check.sh diff --git a/apps/redis/tests/check.sh b/apps/redis/tests/check.sh new file mode 100755 index 000000000..56f57e050 --- /dev/null +++ b/apps/redis/tests/check.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +container="${W9_ID:?W9_ID is required}" +password="${W9_LOGIN_PASSWORD:?W9_LOGIN_PASSWORD is required}" + +deadline=$((SECONDS + 180)) +while [ "${SECONDS}" -lt "${deadline}" ]; do + result="$(docker exec "${container}" redis-cli --no-auth-warning -a "${password}" ping 2>/dev/null || true)" + if [ "${result}" = "PONG" ]; then + echo "Redis accepted an authenticated local ping" + exit 0 + fi + sleep 5 +done + +echo "Redis did not accept an authenticated ping before timeout" >&2 +exit 1 diff --git a/apps/redis/variables.json b/apps/redis/variables.json index bcf95b3b6..9f0464bc7 100644 --- a/apps/redis/variables.json +++ b/apps/redis/variables.json @@ -6,6 +6,7 @@ { "dist": "community", "version": [ + "8.10", "8.0", "7.4", "7.2", @@ -23,6 +24,11 @@ "disk": "1" }, "upstream": { - "image": "https://hub.docker.com/r/redis/redisinsight" + "image": "https://hub.docker.com/_/redis", + "releases": "https://github.com/redis/redis/releases", + "docs": [ + "https://github.com/docker-library/docs/blob/master/redis/README.md", + "https://redis.io/docs/latest/operate/oss_and_stack/management/config/" + ] } } diff --git a/apps/redisinsight/.env b/apps/redisinsight/.env index cc97eb306..df917cf82 100644 --- a/apps/redisinsight/.env +++ b/apps/redisinsight/.env @@ -1,10 +1,33 @@ -W9_VERSION='2.70' -W9_DIST='community' W9_REPO=redis/redisinsight +W9_DIST=community +W9_VERSION=3.8 + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='redisinsight' + +W9_ID=redisinsight W9_HTTP_PORT=5540 -W9_HTTP_PORT_SET='9091' +W9_HTTP_PORT_SET=9091 + +W9_URL=appname.example.com + W9_NETWORK=websoft9 -W9_URL='appname.example.com' -#### --------------------------------------------------------------------------------------- #### + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# RedisInsight image environment variables +# Docs: https://redis.io/docs/latest/operate/redisinsight/install/install-on-docker/ +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: + +# Not used by default; enable only when needed: +# RI_APP_PORT=5540 +# RI_ENABLE_ALERTING=true +# RI_LOG_LEVEL=info diff --git a/apps/redisinsight/CHANGELOG.md b/apps/redisinsight/CHANGELOG.md index 582cf46c5..a9947d268 100644 --- a/apps/redisinsight/CHANGELOG.md +++ b/apps/redisinsight/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Upgrade RedisInsight community to 3.8. +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, and the current `.env` layout. +- Add a dedicated health-endpoint check in `tests/cases.yml`. diff --git a/apps/redisinsight/Notes.md b/apps/redisinsight/Notes.md deleted file mode 100644 index bf795707c..000000000 --- a/apps/redisinsight/Notes.md +++ /dev/null @@ -1,3 +0,0 @@ -## RedisInsight - -默认即可远程访问 \ No newline at end of file diff --git a/apps/redisinsight/README.md b/apps/redisinsight/README.md index 4c4da7d40..2372530cd 100644 --- a/apps/redisinsight/README.md +++ b/apps/redisinsight/README.md @@ -1,26 +1,84 @@ -# RedisInsight on Docker +# RedisInsight on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for RedisInsight: +## Quick Start +### Deploy Verification - - community: 2.70, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **RedisInsight**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the RedisInsight admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://hub.docker.com/r/redis/redisinsight): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 4 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this RedisInsight by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [RedisInsight Docker image](https://hub.docker.com/r/redis/redisinsight) and makes some improvements below. -If you want use RedisInsight with **Websoft9 Business Support** free, you can [subscribe RedisInsight](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[RedisInsight Administrator Guide](https://support.websoft9.com/docs/redisinsight) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 3.8, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| RedisInsight web console | 5540 | + + +### Data Directory + + +Data is persisted in the `redisinsight` volume, mounted at `/data`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [RedisInsight Administrator Guide](https://support.websoft9.com/docs/redisinsight) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/redis/redisinsight) + +- [Releases](https://github.com/RedisInsight/RedisInsight/releases) + +- [Official docs](https://redis.io/docs/latest/operate/redisinsight/install/install-on-docker/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/redisinsight/docker-compose.yml b/apps/redisinsight/docker-compose.yml index 13caa3eed..6c33674cb 100644 --- a/apps/redisinsight/docker-compose.yml +++ b/apps/redisinsight/docker-compose.yml @@ -1,24 +1,20 @@ -# image: https://hub.docker.com/r/redis/redisinsight -# docs: https://docs.redis.com/latest/ri/installing/install-docker/ - - version: '3.8' services: redisinsight: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} env_file: - .env ports: - - $W9_HTTP_PORT_SET:5540 + - "${W9_HTTP_PORT_SET}:5540" # RedisInsight web console volumes: - redisinsight:/data restart: unless-stopped networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true volumes: diff --git a/apps/redisinsight/tests/cases.yml b/apps/redisinsight/tests/cases.yml new file mode 100644 index 000000000..2624c05c5 --- /dev/null +++ b/apps/redisinsight/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: health-endpoint + type: web-access + path: /api/health/ + expect_status: 200 diff --git a/apps/redisinsight/variables.json b/apps/redisinsight/variables.json index 910c347df..8ae33bcc6 100644 --- a/apps/redisinsight/variables.json +++ b/apps/redisinsight/variables.json @@ -6,7 +6,7 @@ { "dist": "community", "version": [ - "2.70", + "3.8", "latest" ] } @@ -24,6 +24,10 @@ "disk": "4" }, "upstream": { - "image": "https://hub.docker.com/r/redis/redisinsight" + "image": "https://hub.docker.com/r/redis/redisinsight", + "releases": "https://github.com/RedisInsight/RedisInsight/releases", + "docs": [ + "https://redis.io/docs/latest/operate/redisinsight/install/install-on-docker/" + ] } } diff --git a/apps/redmine/.env b/apps/redmine/.env index 1025f397c..c5fbc62f1 100644 --- a/apps/redmine/.env +++ b/apps/redmine/.env @@ -1,15 +1,48 @@ -W9_DIST='community' -W9_VERSION='6.1' W9_REPO=redmine -W9_POWER_PASSWORD='LFQr2zktxC!0q4cV' +W9_DIST=community +W9_VERSION=7.0 +W9_POWER_PASSWORD="LFQr2zktxC!0q4cV" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='redmine' + +W9_ID=redmine W9_HTTP_PORT=3000 -W9_HTTP_PORT_SET='9001' +W9_HTTP_PORT_SET=9003 + W9_LOGIN_USER=admin W9_LOGIN_PASSWORD=admin -W9_URL='appname.example.com' -W9_DB_EXPOSE="mysql" -W9_DB_VERSION=5.7 + +W9_URL=appname.example.com + +W9_DB_EXPOSE=mysql +W9_DB_VERSION=8.0 + W9_NETWORK=websoft9 -#### --------------------------------------------------------------------------------------- #### + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Redmine image environment variables +# Docs: https://github.com/docker-library/docs/blob/master/redmine/README.md +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +REDMINE_DB_MYSQL=${W9_ID}-mysql +REDMINE_DB_USERNAME=${W9_ID} +REDMINE_DB_DATABASE=${W9_ID} +REDMINE_DB_PASSWORD=${W9_POWER_PASSWORD} +REDMINE_PLUGINS_MIGRATE=1 +SECRET_KEY_BASE=${W9_POWER_PASSWORD} + +# Not used by default; enable only when needed: +# REDMINE_DB_PORT=3306 +# REDMINE_DB_POSTGRES= +# REDMINE_DB_SQLSERVER= +# REDMINE_HTTPS=true +# REDMINE_NO_DB_MIGRATE=true diff --git a/apps/redmine/CHANGELOG.md b/apps/redmine/CHANGELOG.md index 582cf46c5..6e7989862 100644 --- a/apps/redmine/CHANGELOG.md +++ b/apps/redmine/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Upgrade Redmine community to 7.0. +- Bump the bundled MySQL dependency from 5.7 to 8.0 (Redmine 7.0 supports MySQL 8.0-8.4). +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, upstream env vars moved to `.env`, and a sourced `SECRET_KEY_BASE`. +- Add an authenticated admin-login check in `tests/cases.yml`. diff --git a/apps/redmine/Notes.md b/apps/redmine/Notes.md deleted file mode 100644 index 2c7ae591d..000000000 --- a/apps/redmine/Notes.md +++ /dev/null @@ -1 +0,0 @@ -## Redmine \ No newline at end of file diff --git a/apps/redmine/README.md b/apps/redmine/README.md index 3c45e34c8..9fbe228bd 100644 --- a/apps/redmine/README.md +++ b/apps/redmine/README.md @@ -1,26 +1,88 @@ -# Redmine on Docker +# Redmine on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Redmine: +## Quick Start +### Deploy Verification - - community: 6.0, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Redmine**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Redmine admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Requirements): +### Change Password -* **RAM**: 1 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Redmine by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Redmine Docker image](https://hub.docker.com/_/redmine) and makes some improvements below. -If you want use Redmine with **Websoft9 Business Support** free, you can [subscribe Redmine](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Redmine Administrator Guide](https://support.websoft9.com/docs/redmine) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 7.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Redmine web console | 3000 | + + +### Data Directory + + +- `redmine_files` → `/usr/src/redmine/files` +- `mysql` → `/var/lib/mysql` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration is overridden by mounting `./src/configuration.yml` to `/usr/src/redmine/config/configuration.yml`. + + +## References + +- [Redmine Administrator Guide](https://support.websoft9.com/docs/redmine) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/redmine) + +- [Releases](https://www.redmine.org/projects/redmine/wiki/Download) + +- [GitHub docs](https://github.com/docker-library/docs/blob/master/redmine/README.md) + +- [Official docs](https://www.redmine.org/projects/redmine/wiki/RedmineInstall) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/redmine/docker-compose.yml b/apps/redmine/docker-compose.yml index 331074c6a..9ba8faccc 100644 --- a/apps/redmine/docker-compose.yml +++ b/apps/redmine/docker-compose.yml @@ -1,49 +1,43 @@ -# image: https://hub.docker.com/_/redmine -# docs: https://github.com/docker-library/redmine -# /usr/src/redmine/plugins is not a volume of image, but you can mount it, and when update Redmine it need backup and delete first - version: '3.8' -services: +services: redmine: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:3000 - volumes: - - redmine_files:/usr/src/redmine/files - - ./src/configuration.yml:/usr/src/redmine/config/configuration.yml - #- redmine_plugins:/usr/src/redmine/plugins + - "${W9_HTTP_PORT_SET}:3000" # Redmine web console + volumes: + - redmine_files:/usr/src/redmine/files + - ./src/configuration.yml:/usr/src/redmine/config/configuration.yml env_file: .env environment: - REDMINE_DB_MYSQL: $W9_ID-mysql - REDMINE_DB_USERNAME: $W9_ID - REDMINE_DB_DATABASE: $W9_ID - REDMINE_DB_PASSWORD: $W9_POWER_PASSWORD - REDMINE_PLUGINS_MIGRATE: 1 - SECRET_KEY_BASE: supersecretkey + REDMINE_DB_MYSQL: ${REDMINE_DB_MYSQL} + REDMINE_DB_USERNAME: ${REDMINE_DB_USERNAME} + REDMINE_DB_DATABASE: ${REDMINE_DB_DATABASE} + REDMINE_DB_PASSWORD: ${REDMINE_DB_PASSWORD} + REDMINE_PLUGINS_MIGRATE: ${REDMINE_PLUGINS_MIGRATE} + SECRET_KEY_BASE: ${SECRET_KEY_BASE} depends_on: - mysql mysql: - image: mysql:$W9_DB_VERSION - container_name: $W9_ID-mysql + image: mysql:${W9_DB_VERSION} + container_name: ${W9_ID}-mysql restart: unless-stopped command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - - mysql:/var/lib/mysql + - mysql:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD: $W9_POWER_PASSWORD - MYSQL_DATABASE: $W9_ID - MYSQL_USER: $W9_ID - MYSQL_PASSWORD: $W9_POWER_PASSWORD - + MYSQL_ROOT_PASSWORD: ${W9_POWER_PASSWORD} + MYSQL_DATABASE: ${W9_ID} + MYSQL_USER: ${W9_ID} + MYSQL_PASSWORD: ${W9_POWER_PASSWORD} + volumes: mysql: redmine_files: - redmine_plugins: - + networks: default: name: ${W9_NETWORK} diff --git a/apps/redmine/tests/cases.yml b/apps/redmine/tests/cases.yml new file mode 100644 index 000000000..53779ffc9 --- /dev/null +++ b/apps/redmine/tests/cases.yml @@ -0,0 +1,6 @@ +# The adaptive web-access check covers reachability of the Redmine root. +# This exercises the core authenticated path with the built-in admin account. +custom: + - id: admin-login + type: script + script: check.sh diff --git a/apps/redmine/tests/check.sh b/apps/redmine/tests/check.sh new file mode 100755 index 000000000..c5b9204d7 --- /dev/null +++ b/apps/redmine/tests/check.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +base="${BASE_URL:-http://localhost:${W9_HTTP_PORT_SET:-3000}}" +user="${W9_LOGIN_USER:-admin}" +password="${W9_LOGIN_PASSWORD:-admin}" +jar="$(mktemp)" +trap 'rm -f "$jar"' EXIT + +deadline=$((SECONDS + 300)) +while [ "${SECONDS}" -lt "${deadline}" ]; do + page="$(curl -s -c "$jar" --max-time 15 "${base}/login" || true)" + token="$(printf '%s' "$page" | grep -oE 'name="authenticity_token" value="[^"]+"' | head -1 | sed -E 's/.*value="([^"]+)".*/\1/')" + if [ -n "${token}" ]; then + body="$(curl -s -b "$jar" -c "$jar" -L --max-time 15 \ + --data-urlencode "username=${user}" \ + --data-urlencode "password=${password}" \ + --data-urlencode "authenticity_token=${token}" \ + --data-urlencode "login=Login" \ + "${base}/login" || true)" + if printf '%s' "$body" | grep -q '/logout'; then + echo "Redmine admin login succeeded" + exit 0 + fi + fi + sleep 5 +done + +echo "Redmine admin login did not succeed before timeout" >&2 +exit 1 diff --git a/apps/redmine/variables.json b/apps/redmine/variables.json index 6127393e0..3ac6598eb 100644 --- a/apps/redmine/variables.json +++ b/apps/redmine/variables.json @@ -3,13 +3,18 @@ "trademark": "Redmine", "release": true, "upstream": { - "image": "https://hub.docker.com/_/redmine" + "image": "https://hub.docker.com/_/redmine", + "releases": "https://www.redmine.org/projects/redmine/wiki/Download", + "docs": [ + "https://github.com/docker-library/docs/blob/master/redmine/README.md", + "https://www.redmine.org/projects/redmine/wiki/RedmineInstall" + ] }, "edition": [ { "dist": "community", "version": [ - "6.1", + "7.0", "latest" ] } diff --git a/apps/registry/.env b/apps/registry/.env index cfeda051c..ea9508736 100644 --- a/apps/registry/.env +++ b/apps/registry/.env @@ -1,21 +1,38 @@ W9_REPO=registry -W9_DIST='community' -W9_VERSION='3.0' +W9_DIST=community +W9_VERSION=3.1 + +# Optional password seed: enable only when the package actually controls a DB or built-in login. +# See docs/w9-env-spec.md for when W9_POWER_PASSWORD is appropriate. +# W9_POWER_PASSWORD="{power_password}" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. -# Environments which for user settings when create application -W9_HTTP_PORT_SET='5000' #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='mycrm' + +W9_ID=registry W9_HTTP_PORT=5000 -W9_URL='example.youdomain.com' +W9_HTTP_PORT_SET=5000 +W9_URL=example.youdomain.com + W9_NETWORK=websoft9 + #### ----------------------------------------------------------------------------------------- #### -# Below is environments of Registry -# env docs: https://distribution.github.io/distribution/about/configuration/ -# config_file:/etc/docker/registry/config.yml +# ============================================================ +# Docker Registry image environment variables +# Docs: https://distribution.github.io/distribution/about/configuration/ +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ +# Used by docker-compose.yml: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io -#REGISTRY_PROXY_USERNAME=admin -#REGISTRY_PROXY_PASSWORD=yourpassword + +# Not used by default; enable only when needed: +# REGISTRY_HTTP_ADDR=0.0.0.0:5000 +# REGISTRY_PROXY_USERNAME=admin +# REGISTRY_PROXY_PASSWORD=yourpassword diff --git a/apps/registry/CHANGELOG.md b/apps/registry/CHANGELOG.md index 582cf46c5..7d704f465 100644 --- a/apps/registry/CHANGELOG.md +++ b/apps/registry/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-08 +- Updated Docker Registry from `3.0` to `3.1`. +- Normalized `.env` and `docker-compose.yml` to current repository policy requirements. +- Added app-specific validation coverage for the Registry v2 API path. +- Clarified that `src/` currently contains reference-only files and is not mounted by default. diff --git a/apps/registry/Notes.md b/apps/registry/Notes.md deleted file mode 100644 index af16015db..000000000 --- a/apps/registry/Notes.md +++ /dev/null @@ -1 +0,0 @@ -# Registry diff --git a/apps/registry/README.md b/apps/registry/README.md index c1db42d7d..8a76451aa 100644 --- a/apps/registry/README.md +++ b/apps/registry/README.md @@ -1,26 +1,86 @@ -# Docker Registry on Docker +# Docker Registry on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Docker Registry: +## Quick Start +### Deploy Verification - - community: 2.8, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Docker Registry**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Docker Registry admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://distribution.github.io/distribution/): +### Change Password -* **RAM**: 4 GB or more -* **CPU**: 2 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Docker Registry by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Docker Registry Docker image](https://hub.docker.com/_/registry) and makes some improvements below. -If you want use Docker Registry with **Websoft9 Business Support** free, you can [subscribe Docker Registry](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Docker Registry Administrator Guide](https://support.websoft9.com/docs/registry) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 3.1, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Registry HTTP API | 5000 | + + +### Data Directory + + +Data is persisted in the `data` volume, mounted at `/var/lib/registry`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Docker Registry Administrator Guide](https://support.websoft9.com/docs/registry) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/_/registry) + +- [Releases](https://github.com/distribution/distribution/releases) + +- [Official docs](https://distribution.github.io/distribution/about/configuration/) + +- [Official docs](https://distribution.github.io/distribution/about/deploying/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/registry/docker-compose.yml b/apps/registry/docker-compose.yml index 51839966a..2185140af 100644 --- a/apps/registry/docker-compose.yml +++ b/apps/registry/docker-compose.yml @@ -1,9 +1,3 @@ -# image: https://hub.docker.com/_/registry -# github: https://github.com/distribution/distribution-library-image -# docs: https://distribution.github.io/distribution/ - -version: '3.8' - services: registry: image: ${W9_REPO}:${W9_VERSION} @@ -11,14 +5,14 @@ services: restart: unless-stopped env_file: .env ports: - - $W9_HTTP_PORT_SET:5000 + - ${W9_HTTP_PORT_SET}:5000 # Registry HTTP API volumes: - data:/var/lib/registry - + volumes: data: - + networks: default: name: ${W9_NETWORK} - external: true \ No newline at end of file + external: true diff --git a/apps/registry/src/README.md b/apps/registry/src/README.md index cdbd7a0b9..39fb52f5f 100644 --- a/apps/registry/src/README.md +++ b/apps/registry/src/README.md @@ -1,3 +1,7 @@ # About -This folder includes files mount to container and used by Websoft9 +This folder contains optional reference files for Docker Registry packaging. + +- Files under `src/` are not mounted by default in the current package. +- `config.yml.example` is a reference-only upstream-style configuration example. +- If the package later mounts a custom config from `src/`, the compose file must reference it explicitly. diff --git a/apps/registry/src/config.yml.exmaple b/apps/registry/src/config.yml.example similarity index 99% rename from apps/registry/src/config.yml.exmaple rename to apps/registry/src/config.yml.example index 70d5c9400..dca81b389 100644 --- a/apps/registry/src/config.yml.exmaple +++ b/apps/registry/src/config.yml.example @@ -228,4 +228,4 @@ validation: platforms: List platformlist: - architecture: amd64 - os: linux \ No newline at end of file + os: linux diff --git a/apps/registry/tests/cases.yml b/apps/registry/tests/cases.yml new file mode 100644 index 000000000..648a4e0fb --- /dev/null +++ b/apps/registry/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: v2-api + type: web-access + path: /v2/ + expect_status: 200 diff --git a/apps/registry/variables.json b/apps/registry/variables.json index a3c144a26..593da0ecb 100644 --- a/apps/registry/variables.json +++ b/apps/registry/variables.json @@ -2,11 +2,19 @@ "name": "registry", "trademark": "Docker Registry", "release": true, + "upstream": { + "image": "https://hub.docker.com/_/registry", + "releases": "https://github.com/distribution/distribution/releases", + "docs": [ + "https://distribution.github.io/distribution/about/configuration/", + "https://distribution.github.io/distribution/about/deploying/" + ] + }, "edition": [ { "dist": "community", "version": [ - "3.0", + "3.1", "latest" ] } @@ -16,7 +24,11 @@ "memory": "4", "disk": "1" }, - "upstream": { - "image": "https://hub.docker.com/_/registry" + "access": { + "defaultScheme": "http", + "api": { + "port": 5000, + "path": "/v2/" + } } } diff --git a/apps/ruby/CHANGELOG.md b/apps/ruby/CHANGELOG.md deleted file mode 100644 index 582cf46c5..000000000 --- a/apps/ruby/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# CHANGELOG - -## Release -### Fixes and Enhancements - diff --git a/apps/ruby/src/README.md b/apps/ruby/src/README.md deleted file mode 100644 index cdbd7a0b9..000000000 --- a/apps/ruby/src/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# About - -This folder includes files mount to container and used by Websoft9 diff --git a/apps/rundeck/.env b/apps/rundeck/.env index b07c96509..557d772d7 100644 --- a/apps/rundeck/.env +++ b/apps/rundeck/.env @@ -1,22 +1,39 @@ W9_REPO=rundeck/rundeck -W9_DIST='community' -W9_VERSION='5.17.0' -W9_POWER_PASSWORD='za!kKvWT29ki5clP' -W9_HTTP_PORT_SET='9001' +W9_DIST=community +W9_VERSION=6.2.1 + +# Optional password seed: enable only when the package actually controls a DB or built-in login. +# See docs/w9-env-spec.md for when W9_POWER_PASSWORD is appropriate. +W9_POWER_PASSWORD="za!kKvWT29ki5clP" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + #### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_ID='rundeck' -W9_HTTP_PORT=4440 -# This user and password is stable vaule +W9_ID=rundeck +W9_HTTP_PORT=4440 +W9_HTTP_PORT_SET=9001 W9_LOGIN_USER=admin W9_LOGIN_PASSWORD=admin -W9_URL='example.com' +W9_URL=example.youdomain.com W9_URL_REPLACE=true W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### -# rundesk environment: https://docs.rundeck.com/docs/administration/configuration/docker.html -# If URL not domain, it should http://$W9_URL:$W9_HTTP_PORT_SET -RUNDECK_GRAILS_URL=http://$W9_URL +# ============================================================ +# Rundeck image environment variables +# Docs: https://docs.rundeck.com/docs/administration/configuration/docker.html +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +RUNDECK_GRAILS_URL=http://${W9_URL} + +# Not used by default; enable only when needed: +# RUNDECK_SERVER_FORWARDED=true +# RUNDECK_TOKENS_FILE=/home/rundeck/server/config/tokens.properties diff --git a/apps/rundeck/CHANGELOG.md b/apps/rundeck/CHANGELOG.md index 582cf46c5..1acaeb8f3 100644 --- a/apps/rundeck/CHANGELOG.md +++ b/apps/rundeck/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-10-08 +- Updated Rundeck from `5.17.0` to `6.2.1`. +- Normalized `.env` and `docker-compose.yml` to current repository policy requirements. +- Added app-specific validation coverage for the Rundeck login page. diff --git a/apps/rundeck/Notes.md b/apps/rundeck/Notes.md deleted file mode 100644 index a200b02d3..000000000 --- a/apps/rundeck/Notes.md +++ /dev/null @@ -1,4 +0,0 @@ -# Rundesk - -- username and password environment? -- RUNDECK_GRAILS_URL is need port \ No newline at end of file diff --git a/apps/rundeck/README.md b/apps/rundeck/README.md index 79a3ac0b2..ece5764f2 100644 --- a/apps/rundeck/README.md +++ b/apps/rundeck/README.md @@ -1,26 +1,86 @@ -# Rundeck on Docker +# Rundeck on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for Rundeck: +## Quick Start +### Deploy Verification - - community: 5.12.0 +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Rundeck**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Rundeck admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://docs.rundeck.com/docs/administration/install/system-requirements.html): +### Change Password -* **RAM**: 2 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 4 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this Rundeck by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Rundeck Docker image](https://hub.docker.com/r/rundeck/rundeck) and makes some improvements below. -If you want use Rundeck with **Websoft9 Business Support** free, you can [subscribe Rundeck](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[Rundeck Administrator Guide](https://support.websoft9.com/docs/rundeck) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 6.2.1, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 4440 | + + +### Data Directory + + +Data is persisted in the `rundeck` volume, mounted at `/home/rundeck/server/data`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Rundeck Administrator Guide](https://support.websoft9.com/docs/rundeck) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/rundeck/rundeck) + +- [Releases](https://github.com/rundeck/rundeck/releases) + +- [Official docs](https://docs.rundeck.com/docs/administration/install/docker.html) + +- [Official docs](https://docs.rundeck.com/docs/administration/configuration/docker.html) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/rundeck/docker-compose.yml b/apps/rundeck/docker-compose.yml index 925c20a0f..9767863bd 100644 --- a/apps/rundeck/docker-compose.yml +++ b/apps/rundeck/docker-compose.yml @@ -1,16 +1,11 @@ -# docs: https://docs.rundeck.com/docs/administration/install/docker.html -# image: https://hub.docker.com/r/rundeck/rundeck - -version: '3.8' - services: rundeck: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped ports: - - $W9_HTTP_PORT_SET:4440 + - ${W9_HTTP_PORT_SET}:4440 # Web Console env_file: .env volumes: - rundeck:/home/rundeck/server/data @@ -20,5 +15,5 @@ volumes: networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true diff --git a/apps/rundeck/tests/cases.yml b/apps/rundeck/tests/cases.yml new file mode 100644 index 000000000..68247bea8 --- /dev/null +++ b/apps/rundeck/tests/cases.yml @@ -0,0 +1,5 @@ +optional: + - id: login-page + type: web-access + path: /user/login + expect_status: 200 diff --git a/apps/rundeck/variables.json b/apps/rundeck/variables.json index 357ac6db2..f0148a49a 100644 --- a/apps/rundeck/variables.json +++ b/apps/rundeck/variables.json @@ -2,20 +2,43 @@ "name": "rundeck", "trademark": "Rundeck", "release": true, + "upstream": { + "image": "https://hub.docker.com/r/rundeck/rundeck", + "releases": "https://github.com/rundeck/rundeck/releases", + "docs": [ + "https://docs.rundeck.com/docs/administration/install/docker.html", + "https://docs.rundeck.com/docs/administration/configuration/docker.html" + ] + }, "edition": [ { "dist": "community", "version": [ - "5.17.0" + "6.2.1", + "latest" ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 4440, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", "disk": "4" }, - "upstream": { - "image": "https://hub.docker.com/r/rundeck/rundeck" + "credentials": { + "username": { + "source": "inline", + "value": "admin" + }, + "password": { + "source": "container-env", + "name": "W9_LOGIN_PASSWORD" + } } } diff --git a/apps/seafile/variables.json b/apps/seafile/variables.json index e0b6a6283..63cd988cc 100644 --- a/apps/seafile/variables.json +++ b/apps/seafile/variables.json @@ -14,10 +14,6 @@ "web": { "port": 80, "path": "/" - }, - "admin": { - "port": 80, - "path": "/accounts/login/" } }, "requirements": { diff --git a/apps/selenium/.env b/apps/selenium/.env index ff46b723f..b533cf7ce 100644 --- a/apps/selenium/.env +++ b/apps/selenium/.env @@ -1,19 +1,38 @@ -W9_REPO="selenium/standalone-chrome" -W9_DIST='community' -W9_VERSION='137.0-20250727' +W9_REPO=selenium/standalone-chrome +W9_DIST=community +W9_VERSION=153.0 +W9_POWER_PASSWORD="VZRhqgHzsITR@" -W9_HTTP_PORT=4444 -W9_HTTP_PORT_SET='9001' -W9_HTTP_VNC_SET='7900' -W9_ID='selenium' +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### -W9_LOGIN_PASSWORD=secret -W9_ADMIN_PATH=":$W9_HTTP_VNC_SET" -W9_URL='example.youdomain.com' +W9_ID=selenium +W9_HTTP_PORT=4444 +W9_HTTP_PORT_SET=9001 +W9_ADMIN_PORT_SET=7900 +W9_LOGIN_USER=admin +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} +W9_ADMIN_PATH="/?autoconnect=1&resize=scale" W9_NETWORK=websoft9 #### ----------------------------------------------------------------------------------------- #### +# ============================================================ +# Selenium Standalone Chrome image environment variables +# Docs: https://github.com/SeleniumHQ/docker-selenium +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +SE_VNC_PASSWORD=${W9_LOGIN_PASSWORD} -# Below environment is created by this app: https://github.com/SeleniumHQ/docker-selenium +# Not used by default; enable only when needed: +# SE_VNC_NO_PASSWORD=true +# SE_VNC_VIEW_ONLY=true +# SE_START_VNC=false +# SE_NODE_MAX_SESSIONS=1 +# SE_NODE_OVERRIDE_MAX_SESSIONS=true diff --git a/apps/selenium/CHANGELOG.md b/apps/selenium/CHANGELOG.md index 582cf46c5..a0c1a818a 100644 --- a/apps/selenium/CHANGELOG.md +++ b/apps/selenium/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG -## Release -### Fixes and Enhancements +## 2026-09-30 +- Update Selenium Standalone Chrome to `153.0`. +- Declare the WebDriver API (`4444`) as the `web` surface and the noVNC console (`7900`) as the `admin` surface, with `access.admin.path` set to `/?autoconnect=1&resize=scale`. +- Add `W9_ADMIN_PATH` and `W9_LOGIN_USER` / `W9_LOGIN_PASSWORD` compatibility fields so Websoft9 can render the admin URL and the password. +- Enable the noVNC admin password from the package password through `SE_VNC_PASSWORD`. +- Normalize the package to current conventions: braced `${VAR}` references, documented port purpose, and refreshed upstream metadata. +- Add functional checks for the WebDriver `/status` endpoint and the password-protected noVNC console. +- Document that the noVNC view is black until a WebDriver session starts, and remove stale `src/` files that were never mounted. diff --git a/apps/selenium/Notes.md b/apps/selenium/Notes.md index 156c3d54d..0d283a885 100644 --- a/apps/selenium/Notes.md +++ b/apps/selenium/Notes.md @@ -1,3 +1,24 @@ # selenium ## FAQ + +### 访问方式 + +- WebDriver API(web):`http://:${W9_HTTP_PORT_SET}`,健康检查 `http://:${W9_HTTP_PORT_SET}/status` +- noVNC 管理界面(admin):`http://:${W9_ADMIN_PORT_SET}/?autoconnect=1&resize=scale`,密码为 `.env` 中的 `W9_LOGIN_PASSWORD`(即 `W9_POWER_PASSWORD`) + +### 修改 noVNC 密码 + +`SE_VNC_PASSWORD` 在容器启动时读取。修改 `.env` 中的 `W9_POWER_PASSWORD` 后,重建容器使其生效。 + +### noVNC 显示黑屏? + +Selenium 只在创建 WebDriver 会话时才启动 Chrome;没有活动会话时虚拟桌面为空,因此 noVNC 显示黑屏。这是正常行为,不是故障。先创建一个会话即可在 noVNC 中看到浏览器: + +```bash +curl -s -X POST "http://:${W9_HTTP_PORT_SET}/session" \ + -H 'Content-Type: application/json' \ + -d '{"capabilities":{"alwaysMatch":{"browserName":"chrome"}}}' +``` + +会话结束后浏览器会自动关闭,noVNC 重新变为黑屏。 diff --git a/apps/selenium/README.md b/apps/selenium/README.md index 4e7fa5b4c..90bc061a7 100644 --- a/apps/selenium/README.md +++ b/apps/selenium/README.md @@ -1,26 +1,83 @@ -# selenium on Docker +# Selenium on Docker -This is an **[Docker Compose template](https://github.com/Websoft9/docker-library)** powered by [Websoft9](https://www.websoft9.com) based on Docker for selenium: +## Quick Start +### Deploy Verification - - community: 124.0-20250414, latest +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Selenium**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + +### Usage -## System Requirements +1. Make sure you are signed in to the Selenium admin console. +2. Try a core feature. -The following are the minimal [recommended requirements](https://www.selenium.dev): +### Change Password -* **RAM**: 2 GB or more -* **CPU**: 1 cores or higher -* **Disk**: at least 1 GB of free space -* **bandwidth**: more fluent experience over 100M +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + -## Install +## Configuration Reference -You can install this selenium by [How to use it?](https://github.com/Websoft9/docker-library#how-to-use-it). +Websoft9 packages this app from the official [Selenium Docker image](https://hub.docker.com/r/selenium/standalone-chrome) and makes some improvements below. -If you want use selenium with **Websoft9 Business Support** free, you can [subscribe selenium](https://www.websoft9.com/apps) on Cloud platform + -## Documentation + -[selenium Administrator Guide](https://support.websoft9.com/docs/selenium) powered by Websoft9 \ No newline at end of file +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: 153.0, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Selenium WebDriver API | 4444 | +| noVNC admin console | 7900 | + + +### Data Directory + + +Data is kept inside the container; a named volume is recommended for persistence. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Selenium Administrator Guide](https://support.websoft9.com/docs/selenium) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/selenium/standalone-chrome) + +- [GitHub docs](https://github.com/SeleniumHQ/docker-selenium) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/selenium/docker-compose.yml b/apps/selenium/docker-compose.yml index 25151e230..e89348d58 100644 --- a/apps/selenium/docker-compose.yml +++ b/apps/selenium/docker-compose.yml @@ -1,18 +1,15 @@ -# image,docs: https://hub.docker.com/r/selenium/standalone-chrome - services: app: - image: $W9_REPO:$W9_VERSION - container_name: $W9_ID + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} restart: unless-stopped shm_size: "2g" ports: - - $W9_HTTP_PORT_SET:4444 #WebDriver - - $W9_HTTP_VNC_SET:7900 #monitor - env_file: - - .env - + - "${W9_HTTP_PORT_SET}:4444" # Selenium WebDriver API + - "${W9_ADMIN_PORT_SET}:7900" # noVNC admin console + env_file: .env + networks: default: - name: $W9_NETWORK + name: ${W9_NETWORK} external: true diff --git a/apps/selenium/src/README.md b/apps/selenium/src/README.md deleted file mode 100644 index cdbd7a0b9..000000000 --- a/apps/selenium/src/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# About - -This folder includes files mount to container and used by Websoft9 diff --git a/apps/selenium/src/nginx-proxy.conf.template b/apps/selenium/src/nginx-proxy.conf.template deleted file mode 100644 index 951364ffe..000000000 --- a/apps/selenium/src/nginx-proxy.conf.template +++ /dev/null @@ -1,57 +0,0 @@ -proxy_busy_buffers_size 512k; -proxy_buffers 4 512k; -proxy_buffer_size 256k; -client_max_body_size 50m; -# override default location / -location / { - add_header X-Served-By $host; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Scheme $scheme; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_pass $forward_scheme://$server:$port$request_uri; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection upgrade; - } - -location /console { - proxy_pass http://$server:8080; - proxy_http_version 1.1; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; -} - -# for echo some useful information -location / { - default_type text/plain; - return 200 'Hello World'; -} - -location /oida/ { -# this is the address and port of the ORDS installation -proxy_pass http://127.0.0.1:8080/ords/; - -# set Origin to blank to avoid Chrome problems with CORS -proxy_set_header Origin "" ; - -# pass along some header variables with the public host name/port/and so on -proxy_set_header Host $host; -proxy_set_header X-Forwarded-Host $host:$server_port; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; - -# this reverse proxies any "location" headers being passed in the response -proxy_redirect http://$host/ords/ https://$host/oida/; - -# also tell cookies their public path -proxy_cookie_path /ords/ /oida/; - -# reverse proxy links included in response (ie from ORDS webservice) -sub_filter_types application/json ; -sub_filter http://$host/ords/ https://$host/oida/; -sub_filter_once off; -} diff --git a/apps/selenium/src/php_exra.ini b/apps/selenium/src/php_exra.ini deleted file mode 100644 index b253d5718..000000000 --- a/apps/selenium/src/php_exra.ini +++ /dev/null @@ -1,8 +0,0 @@ -file_uploads = On -max_input_time = 800 -max_execution_time = 300 -memory_limit = 600M -upload_max_filesize = 900M -post_max_size = 900M -max_file_uploads = 200 -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT \ No newline at end of file diff --git a/apps/selenium/tests/cases.yml b/apps/selenium/tests/cases.yml new file mode 100644 index 000000000..b3700cd89 --- /dev/null +++ b/apps/selenium/tests/cases.yml @@ -0,0 +1,13 @@ +# The adaptive checks cover compose config, container state and the WebDriver +# entry point. Selenium's core path is a ready WebDriver API plus the +# password-protected noVNC admin console, so both are exercised explicitly. +optional: + - id: webdriver-status + type: web-access + path: /status + expect_status: 200 + +custom: + - id: novnc-admin-password + type: script + script: check.sh diff --git a/apps/selenium/tests/check.sh b/apps/selenium/tests/check.sh new file mode 100755 index 000000000..6be7fd04d --- /dev/null +++ b/apps/selenium/tests/check.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +container="${W9_ID:?W9_ID is required}" +password="${W9_POWER_PASSWORD:?W9_POWER_PASSWORD is required}" +admin_port="${W9_ADMIN_PORT_SET:?W9_ADMIN_PORT_SET is required}" + +code="$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "http://localhost:${admin_port}/" || true)" +if [ "${code}" != "200" ]; then + echo "noVNC admin console returned HTTP ${code}" >&2 + exit 1 +fi + +actual="$(docker exec "${container}" printenv SE_VNC_PASSWORD 2>/dev/null || true)" +if [ -z "${actual}" ]; then + echo "SE_VNC_PASSWORD is not set; the admin console is unprotected" >&2 + exit 1 +fi +if [ "${actual}" != "${password}" ]; then + echo "SE_VNC_PASSWORD does not match the package password" >&2 + exit 1 +fi + +echo "noVNC admin console reachable and password-protected" diff --git a/apps/selenium/variables.json b/apps/selenium/variables.json index df7097304..75b4d8d59 100644 --- a/apps/selenium/variables.json +++ b/apps/selenium/variables.json @@ -1,15 +1,18 @@ { "name": "selenium", - "trademark": "selenium", + "trademark": "Selenium", "release": true, "upstream": { - "image": "https://hub.docker.com/r/selenium/standalone-chrome" + "image": "https://hub.docker.com/r/selenium/standalone-chrome", + "docs": [ + "https://github.com/SeleniumHQ/docker-selenium" + ] }, "edition": [ { "dist": "community", "version": [ - "137.0-20250727", + "153.0", "latest" ] } @@ -19,11 +22,21 @@ "web": { "port": 4444, "path": "/" + }, + "admin": { + "port": 7900, + "path": "/?autoconnect=1&resize=scale" + } + }, + "credentials": { + "password": { + "source": "container-env", + "name": "W9_LOGIN_PASSWORD" } }, "requirements": { - "cpu": "1", - "memory": "2", - "disk": "1" + "cpu": "2", + "memory": "4", + "disk": "2" } } diff --git a/apps/semaphore/variables.json b/apps/semaphore/variables.json index 5a318c439..1e3b2aa0e 100644 --- a/apps/semaphore/variables.json +++ b/apps/semaphore/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 3000, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "2", diff --git a/apps/sqlserver/Notes.md b/apps/sqlserver/Notes.md deleted file mode 100644 index d1e76931d..000000000 --- a/apps/sqlserver/Notes.md +++ /dev/null @@ -1,9 +0,0 @@ -# SQLSERVER - -https://hub.docker.com/_/microsoft-mssql-server - -MSSQL_PID 区分发行版 - -## To do - -Suggest use Microsoft Docker repo: https://mcr.microsoft.com/ diff --git a/apps/strapi/variables.json b/apps/strapi/variables.json index f03f5b786..8d5fdae1e 100644 --- a/apps/strapi/variables.json +++ b/apps/strapi/variables.json @@ -25,10 +25,6 @@ "port": 1337, "path": "/" }, - "admin": { - "port": 1337, - "path": "/admin" - }, "api": { "port": 1337, "path": "/api" diff --git a/apps/superset/Notes.md b/apps/superset/Notes.md deleted file mode 100644 index b993528bc..000000000 --- a/apps/superset/Notes.md +++ /dev/null @@ -1,10 +0,0 @@ -## Strapi - -Superset 是一种强大的大数据分析工具 - - -## 安装 - -- latest 实际上对应的是开发版本,所以需要指定具体。例如:1.3.0 -- src/docker 文件夹是其中容器启动的必要文件,需要和上游项目定期同步; -- src/docker 文件夹中的脚本是通过路径直接执行,需要执行权限,所以修改上传时需要注意不能改变其权限,一般来说,直接在linux服务器上提交不会产生问题。下载 windows 本地后,通过 git 上传会产生权限问题,导致多个容器无法正常启动。 \ No newline at end of file diff --git a/apps/tensorflow/variables.json b/apps/tensorflow/variables.json index c83e0863b..e9f2185ad 100644 --- a/apps/tensorflow/variables.json +++ b/apps/tensorflow/variables.json @@ -24,10 +24,6 @@ "port": 8888, "path": "/" }, - "admin": { - "port": 8888, - "path": "/lab" - }, "metrics": { "port": 6006, "path": "/" diff --git a/apps/timescaledb/.env b/apps/timescaledb/.env new file mode 100644 index 000000000..e09063f89 --- /dev/null +++ b/apps/timescaledb/.env @@ -0,0 +1,48 @@ +W9_REPO=timescale/timescaledb-ha +W9_DIST=community +W9_VERSION=pg18 +W9_POWER_PASSWORD="8nQp4wL7sR2kV6" + +# Optional password seed: enable only when the package actually controls a DB or built-in login. +# See docs/w9-env-spec.md for when W9_POWER_PASSWORD is appropriate. +# W9_POWER_PASSWORD="{power_password}" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=timescaledb +W9_DB_PORT=5432 +W9_DB_PORT_SET=5432 +W9_DB_EXPOSE=postgresql +W9_LOGIN_USER=postgres +W9_LOGIN_PASSWORD=${W9_POWER_PASSWORD} + +W9_NETWORK=websoft9 + +#### ----------------------------------------------------------------------------------------- #### + +#W9_NAME="" +#W9_RCODE="" + +# ============================================================ +# Timescale image environment variables +# Docs: https://hub.docker.com/r/timescale/timescaledb-ha +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +POSTGRES_DB=${W9_ID} +POSTGRES_USER=${W9_LOGIN_USER} +POSTGRES_PASSWORD=${W9_POWER_PASSWORD} +PGDATA=/home/postgres/pgdata/data + +# Not used by default; enable only when needed: +# POSTGRES_INITDB_ARGS= +# POSTGRES_INITDB_WALDIR= +# POSTGRES_HOST_AUTH_METHOD=scram-sha-256 +# POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password +# POSTGRES_USER_FILE=/run/secrets/postgres_user diff --git a/apps/timescaledb/CHANGELOG.md b/apps/timescaledb/CHANGELOG.md new file mode 100644 index 000000000..98ae9874d --- /dev/null +++ b/apps/timescaledb/CHANGELOG.md @@ -0,0 +1,5 @@ +# CHANGELOG + +## 2026-10-09 +- Initial Websoft9 package for TimescaleDB using the official `timescale/timescaledb-ha:pg18` image. +- Added persistent PostgreSQL deployment, healthcheck, metadata, and validation tests. diff --git a/apps/timescaledb/README.md b/apps/timescaledb/README.md new file mode 100644 index 000000000..2dbd589dc --- /dev/null +++ b/apps/timescaledb/README.md @@ -0,0 +1,89 @@ +# Timescale on Docker + +## Quick Start + +### Deploy Verification + +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Timescale**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + + +### Usage + +1. Make sure you are signed in to the Timescale admin console. +2. Try a core feature. + +### Change Password + +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + + +## Configuration Reference + +Websoft9 packages this app from the official [Timescale Docker image](https://hub.docker.com/r/timescale/timescaledb-ha) and makes some improvements below. + + + + + +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: pg18, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| PostgreSQL | 5432 | + + +### Data Directory + + +Data is persisted in the `timescaledb` volume, mounted at `/home/postgres/pgdata`. + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +Note: `POSTGRES_DB`, `POSTGRES_PASSWORD`, `POSTGRES_USER` take effect on first startup only; changing them after deployment may not take effect until the app is re-initialized. + + +### Configuration Files + + +Configuration files live inside the image; mount a single file read-only to override, and never replace the whole directory. + + +## References + +- [Timescale Administrator Guide](https://support.websoft9.com/docs/timescaledb) by Websoft9 + +- [Docker Hub image](https://hub.docker.com/r/timescale/timescaledb-ha) + +- [Releases](https://github.com/timescale/timescaledb/releases) + +- [GitHub docs](https://github.com/timescale/timescaledb) + +- [Official docs](https://docs.tigerdata.com/self-hosted/latest/install/installation-docker/) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/apps/timescaledb/docker-compose.yml b/apps/timescaledb/docker-compose.yml new file mode 100644 index 000000000..66f7ed237 --- /dev/null +++ b/apps/timescaledb/docker-compose.yml @@ -0,0 +1,24 @@ +services: + timescaledb: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} + restart: unless-stopped + ports: + - "${W9_DB_PORT_SET}:5432" # PostgreSQL + volumes: + - timescaledb:/home/postgres/pgdata + env_file: .env + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${W9_LOGIN_USER} -d ${W9_ID}"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 30s + +volumes: + timescaledb: + +networks: + default: + name: ${W9_NETWORK} + external: true diff --git a/apps/metabase/src/filelist b/apps/timescaledb/src/.gitkeep similarity index 100% rename from apps/metabase/src/filelist rename to apps/timescaledb/src/.gitkeep diff --git a/apps/timescaledb/tests/cases.yml b/apps/timescaledb/tests/cases.yml new file mode 100644 index 000000000..1189a0009 --- /dev/null +++ b/apps/timescaledb/tests/cases.yml @@ -0,0 +1,4 @@ +custom: + - id: timescaledb-extension + type: script + script: check.sh diff --git a/apps/timescaledb/tests/check.sh b/apps/timescaledb/tests/check.sh new file mode 100755 index 000000000..b69b1e9b7 --- /dev/null +++ b/apps/timescaledb/tests/check.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +container="${W9_ID:?W9_ID is required}" +user="${W9_LOGIN_USER:?W9_LOGIN_USER is required}" +password="${W9_LOGIN_PASSWORD:?W9_LOGIN_PASSWORD is required}" +db="${W9_ID:?W9_ID is required}" + +deadline=$((SECONDS + 180)) +while [ "${SECONDS}" -lt "${deadline}" ]; do + result="$(docker exec -e PGPASSWORD="${password}" "${container}" psql -U "${user}" -d "${db}" -tAc "SELECT extname FROM pg_extension WHERE extname = 'timescaledb';" 2>/dev/null | tr -d '[:space:]' || true)" + if [ "${result}" = "timescaledb" ]; then + echo "TimescaleDB extension is available in the default database" + exit 0 + fi + sleep 5 +done + +echo "TimescaleDB extension was not detected before timeout" >&2 +exit 1 diff --git a/apps/timescaledb/variables.json b/apps/timescaledb/variables.json new file mode 100644 index 000000000..09ff17ae6 --- /dev/null +++ b/apps/timescaledb/variables.json @@ -0,0 +1,47 @@ +{ + "name": "timescaledb", + "trademark": "Timescale", + "release": true, + "upstream": { + "image": "https://hub.docker.com/r/timescale/timescaledb-ha", + "releases": "https://github.com/timescale/timescaledb/releases", + "docs": [ + "https://github.com/timescale/timescaledb", + "https://docs.tigerdata.com/self-hosted/latest/install/installation-docker/" + ] + }, + "edition": [ + { + "dist": "community", + "version": [ + "pg18", + "latest" + ] + } + ], + "requirements": { + "cpu": "1", + "memory": "2", + "disk": "1" + }, + "credentials": { + "username": { + "value": "postgres", + "source": "inline" + }, + "password": { + "name": "W9_LOGIN_PASSWORD", + "source": "container-env" + } + }, + "env": { + "first_startup_only": [ + "POSTGRES_DB", + "POSTGRES_PASSWORD", + "POSTGRES_USER" + ] + }, + "help": { + "db": "TimescaleDB HA is PostgreSQL with the TimescaleDB extension preloaded. Connect with the postgres account, then verify the extension with SELECT extname, extversion FROM pg_extension WHERE extname = 'timescaledb';" + } +} diff --git a/apps/tomcat/Notes.md b/apps/tomcat/Notes.md index 37abe7bdb..017764130 100644 --- a/apps/tomcat/Notes.md +++ b/apps/tomcat/Notes.md @@ -1,51 +1,51 @@ # Tomcat Notes -> 内部维护说明;面向客户的文档以 `README.md` 为准。 +> Internal maintenance notes; customer-facing documentation lives in `README.md`. -## 来源 +## Sources -- 官方镜像:https://hub.docker.com/_/tomcat -- 镜像源码:https://github.com/docker-library/tomcat -- 版本列表:https://hub.docker.com/_/tomcat/tags +- Official image: https://hub.docker.com/_/tomcat +- Image source: https://github.com/docker-library/tomcat +- Version list: https://hub.docker.com/_/tomcat/tags -## 版本 +## Versions -- `W9_VERSION=11.0-jdk21-temurin`:Tomcat 11 稳定线 + JDK21 LTS。 -- `variables.json` 只保留当前上游仍发布的 temurin 变体(`11.0` / `10.1` / `9.0`);官方已移除 `corretto` 变体,故不再列出。 -- 数据卷 `tomcat:/usr/local/tomcat` 持久化整个 Tomcat 目录(含 `webapps` 与 `conf`)。 +- `W9_VERSION=11.0-jdk21-temurin`: Tomcat 11 stable line + JDK21 LTS. +- `variables.json` only keeps the temurin variants still published upstream (`11.0` / `10.1` / `9.0`); the official `corretto` variant was removed, so it is no longer listed. +- The `tomcat:/usr/local/tomcat` data volume persists the entire Tomcat directory (including `webapps` and `conf`). -## 启动机制(runtime-app 约定) +## Startup Mechanism (runtime-app convention) -参照 `docs/runtime-app-spec.md`,与 `springboot` 一致,但**不**引入非 root 用户/permissions 侧车(Tomcat 官方镜像以 root 运行,改动风险大)。 +Follows `docs/runtime-app-spec.md`, consistent with `springboot`, but does **not** introduce a non-root user/permissions sidecar (the official Tomcat image runs as root, and the change would be high-risk). ``` -src/entrypoint.sh # orchestrator,挂到 /opt/websoft9/entrypoint.sh -src/entrypoint.d/*.sh # 包内钩子,挂到 /opt/websoft9/entrypoint.d(只读) -src/start.sh # 默认启动,挂到 /opt/websoft9/start.sh(只读) +src/entrypoint.sh # orchestrator, mounted at /opt/websoft9/entrypoint.sh +src/entrypoint.d/*.sh # in-package hooks, mounted at /opt/websoft9/entrypoint.d (read-only) +src/start.sh # default start, mounted at /opt/websoft9/start.sh (read-only) ``` -- 钩子来源两处,同名用户钩子覆盖包内钩子,按文件名排序,每次启动都执行且必须幂等: - - 包内:`/opt/websoft9/entrypoint.d` - - 用户:`${APP_DIR}/.w9/entrypoint.d`,即 `/usr/local/tomcat/.w9/entrypoint.d` -- `APP_DIR=/usr/local/tomcat`(复用数据卷);用户可放 `${APP_DIR}/.w9/start.sh` 覆盖默认启动。 -- 默认钩子 `10-webapps.sh`:`cp -a webapps.dist/. webapps/`,恢复 ROOT/docs/examples 默认应用。 -- `start.sh` 用 `exec catalina.sh run`,保证 Tomcat 是 PID1、能收到 SIGTERM。 -- 与 runtime-app-spec 的差异:不使用 `DATABASE_URL` 覆盖,不使用非 root 用户。 +- Hooks come from two locations; a user hook with the same name overrides the in-package hook, they are sorted by filename, and they run on every startup and must be idempotent: + - In-package: `/opt/websoft9/entrypoint.d` + - User: `${APP_DIR}/.w9/entrypoint.d`, i.e. `/usr/local/tomcat/.w9/entrypoint.d` +- `APP_DIR=/usr/local/tomcat` (reuses the data volume); users can place `${APP_DIR}/.w9/start.sh` to override the default start. +- Default hook `10-webapps.sh`: `cp -a webapps.dist/. webapps/`, restoring the default ROOT/docs/examples applications. +- `start.sh` uses `exec catalina.sh run`, ensuring Tomcat is PID1 and can receive SIGTERM. +- Differences from runtime-app-spec: no `DATABASE_URL` override, no non-root user. -## 运行 war 包 +## Running a WAR Package -进入 **tomcat** 容器,下载官方示例,会自动解压: +Enter the **tomcat** container, download the official sample, and it will auto-extract: ``` cd /usr/local/tomcat/webapps && wget https://tomcat.apache.org/tomcat-11.0-doc/appdev/sample/sample.war cd /usr/local/tomcat/webapps && wget https://tomcat.apache.org/tomcat-11.0-doc/appdev/sample/sample.war -O ROOT.war ``` -`ROOT.war` 会自动解压到根目录(不包含路径)。 +`ROOT.war` auto-extracts to the root directory (without a path). -## 测试 +## Tests -- `tests/cases.yml`:默认自适应检查(compose-config / container-up / container-healthy / web-access `/`)之外,加两个 `script` 用例: - - `smoke.sh`:校验欢迎页内容,证明 `10-webapps.sh` 的默认应用已恢复。 - - `war-deploy.sh`:在容器内用 `jar` 造一个极小 WAR,放进 `webapps/`,等待自动解压并校验 context,验证真实 WAR 部署路径。 -- `script` 用例默认在**部署目标**执行(remote 时走 SSH,见 `docs/app-tests.md`),因此 `war-deploy.sh` 可以使用远端 `docker exec`;`BASE_URL` 在远端被改写为 `http://localhost:${W9_HTTP_PORT_SET}`。 +- `tests/cases.yml`: in addition to the default adaptive checks (compose-config / container-up / container-healthy / web-access `/`), it adds two `script` cases: + - `smoke.sh`: verifies the welcome page content, proving the default applications from `10-webapps.sh` have been restored. + - `war-deploy.sh`: builds a tiny WAR inside the container with `jar`, places it in `webapps/`, waits for auto-extraction, and verifies the context, validating the real WAR deployment path. +- `script` cases run on the **deployment target** by default (over SSH when remote, see `docs/app-tests.md`), so `war-deploy.sh` can use remote `docker exec`; `BASE_URL` is rewritten on the remote to `http://localhost:${W9_HTTP_PORT_SET}`. diff --git a/apps/tomcat/variables.json b/apps/tomcat/variables.json index a8094d465..2b4422569 100644 --- a/apps/tomcat/variables.json +++ b/apps/tomcat/variables.json @@ -21,6 +21,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/vaultwarden/variables.json b/apps/vaultwarden/variables.json index 3a70c2364..bb1114adb 100644 --- a/apps/vaultwarden/variables.json +++ b/apps/vaultwarden/variables.json @@ -11,6 +11,17 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + }, + "admin": { + "port": 80, + "path": "/admin" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/vespa/variables.json b/apps/vespa/variables.json index 91b8d095e..506a621aa 100644 --- a/apps/vespa/variables.json +++ b/apps/vespa/variables.json @@ -22,5 +22,12 @@ "docs": [ "https://docs.vespa.ai/en/operations/self-managed/docker-containers.html" ] + }, + "access": { + "defaultScheme": "http", + "api": { + "port": 8080, + "path": "/" + } } } diff --git a/apps/zentao/variables.json b/apps/zentao/variables.json index 6ed0f020c..a0af726c6 100644 --- a/apps/zentao/variables.json +++ b/apps/zentao/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "credentials": {}, "requirements": { "cpu": "1", diff --git a/apps/zulip/variables.json b/apps/zulip/variables.json index 5c52a4669..47cfd98e5 100644 --- a/apps/zulip/variables.json +++ b/apps/zulip/variables.json @@ -14,10 +14,6 @@ "web": { "port": 443, "path": "/" - }, - "admin": { - "port": 443, - "path": "/login/" } }, "requirements": { diff --git a/apps/oneapi/.env b/archive/apps/oneapi/.env similarity index 100% rename from apps/oneapi/.env rename to archive/apps/oneapi/.env diff --git a/apps/oneapi/CHANGELOG.md b/archive/apps/oneapi/CHANGELOG.md similarity index 100% rename from apps/oneapi/CHANGELOG.md rename to archive/apps/oneapi/CHANGELOG.md diff --git a/apps/oneapi/Notes.md b/archive/apps/oneapi/Notes.md similarity index 100% rename from apps/oneapi/Notes.md rename to archive/apps/oneapi/Notes.md diff --git a/apps/oneapi/README.md b/archive/apps/oneapi/README.md similarity index 100% rename from apps/oneapi/README.md rename to archive/apps/oneapi/README.md diff --git a/apps/oneapi/docker-compose.yml b/archive/apps/oneapi/docker-compose.yml similarity index 100% rename from apps/oneapi/docker-compose.yml rename to archive/apps/oneapi/docker-compose.yml diff --git a/apps/oneapi/src/README.md b/archive/apps/oneapi/src/README.md similarity index 100% rename from apps/oneapi/src/README.md rename to archive/apps/oneapi/src/README.md diff --git a/apps/oneapi/src/nginx-proxy.conf.template b/archive/apps/oneapi/src/nginx-proxy.conf.template similarity index 100% rename from apps/oneapi/src/nginx-proxy.conf.template rename to archive/apps/oneapi/src/nginx-proxy.conf.template diff --git a/apps/oneapi/src/php_exra.ini b/archive/apps/oneapi/src/php_exra.ini similarity index 100% rename from apps/oneapi/src/php_exra.ini rename to archive/apps/oneapi/src/php_exra.ini diff --git a/apps/oneapi/variables.json b/archive/apps/oneapi/variables.json similarity index 87% rename from apps/oneapi/variables.json rename to archive/apps/oneapi/variables.json index 6c4d9f629..ba39e4dd7 100644 --- a/apps/oneapi/variables.json +++ b/archive/apps/oneapi/variables.json @@ -19,10 +19,6 @@ "web": { "port": 3000, "path": "/" - }, - "admin": { - "port": 3000, - "path": "/login" } }, "requirements": { diff --git a/apps/onyx/.env b/archive/apps/onyx/.env similarity index 100% rename from apps/onyx/.env rename to archive/apps/onyx/.env diff --git a/apps/onyx/CHANGELOG.md b/archive/apps/onyx/CHANGELOG.md similarity index 100% rename from apps/onyx/CHANGELOG.md rename to archive/apps/onyx/CHANGELOG.md diff --git a/apps/onyx/Notes.md b/archive/apps/onyx/Notes.md similarity index 100% rename from apps/onyx/Notes.md rename to archive/apps/onyx/Notes.md diff --git a/apps/onyx/README.md b/archive/apps/onyx/README.md similarity index 100% rename from apps/onyx/README.md rename to archive/apps/onyx/README.md diff --git a/apps/onyx/docker-compose.yml b/archive/apps/onyx/docker-compose.yml similarity index 100% rename from apps/onyx/docker-compose.yml rename to archive/apps/onyx/docker-compose.yml diff --git a/apps/onyx/src/app.conf.template b/archive/apps/onyx/src/app.conf.template similarity index 100% rename from apps/onyx/src/app.conf.template rename to archive/apps/onyx/src/app.conf.template diff --git a/apps/onyx/src/mcp.conf.inc.template b/archive/apps/onyx/src/mcp.conf.inc.template similarity index 100% rename from apps/onyx/src/mcp.conf.inc.template rename to archive/apps/onyx/src/mcp.conf.inc.template diff --git a/apps/onyx/src/mcp_upstream.conf.inc.template b/archive/apps/onyx/src/mcp_upstream.conf.inc.template similarity index 100% rename from apps/onyx/src/mcp_upstream.conf.inc.template rename to archive/apps/onyx/src/mcp_upstream.conf.inc.template diff --git a/apps/onyx/src/run-nginx.sh b/archive/apps/onyx/src/run-nginx.sh similarity index 100% rename from apps/onyx/src/run-nginx.sh rename to archive/apps/onyx/src/run-nginx.sh diff --git a/apps/onyx/variables.json b/archive/apps/onyx/variables.json similarity index 85% rename from apps/onyx/variables.json rename to archive/apps/onyx/variables.json index 5af13c38b..a70a6615f 100644 --- a/apps/onyx/variables.json +++ b/archive/apps/onyx/variables.json @@ -19,10 +19,6 @@ "web": { "port": 80, "path": "/" - }, - "admin": { - "port": 80, - "path": "/admin/indexing/status" } }, "requirements": { diff --git a/apps/opencost/.env b/archive/apps/opencost/.env similarity index 100% rename from apps/opencost/.env rename to archive/apps/opencost/.env diff --git a/apps/opencost/CHANGELOG.md b/archive/apps/opencost/CHANGELOG.md similarity index 100% rename from apps/opencost/CHANGELOG.md rename to archive/apps/opencost/CHANGELOG.md diff --git a/apps/opencost/Notes.md b/archive/apps/opencost/Notes.md similarity index 100% rename from apps/opencost/Notes.md rename to archive/apps/opencost/Notes.md diff --git a/apps/opencost/README.md b/archive/apps/opencost/README.md similarity index 100% rename from apps/opencost/README.md rename to archive/apps/opencost/README.md diff --git a/apps/opencost/docker-compose.yml b/archive/apps/opencost/docker-compose.yml similarity index 100% rename from apps/opencost/docker-compose.yml rename to archive/apps/opencost/docker-compose.yml diff --git a/apps/opencost/src/README.md b/archive/apps/opencost/src/README.md similarity index 100% rename from apps/opencost/src/README.md rename to archive/apps/opencost/src/README.md diff --git a/apps/opencost/variables.json b/archive/apps/opencost/variables.json similarity index 67% rename from apps/opencost/variables.json rename to archive/apps/opencost/variables.json index 76162e700..d6af4ac17 100644 --- a/apps/opencost/variables.json +++ b/archive/apps/opencost/variables.json @@ -11,6 +11,17 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 9090, + "path": "/" + }, + "api": { + "port": 9003, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/opencv/.env b/archive/apps/opencv/.env similarity index 100% rename from apps/opencv/.env rename to archive/apps/opencv/.env diff --git a/apps/opencv/CHANGELOG.md b/archive/apps/opencv/CHANGELOG.md similarity index 100% rename from apps/opencv/CHANGELOG.md rename to archive/apps/opencv/CHANGELOG.md diff --git a/apps/opencv/Notes.md b/archive/apps/opencv/Notes.md similarity index 100% rename from apps/opencv/Notes.md rename to archive/apps/opencv/Notes.md diff --git a/apps/opencv/README.md b/archive/apps/opencv/README.md similarity index 100% rename from apps/opencv/README.md rename to archive/apps/opencv/README.md diff --git a/apps/opencv/docker-compose.yml b/archive/apps/opencv/docker-compose.yml similarity index 100% rename from apps/opencv/docker-compose.yml rename to archive/apps/opencv/docker-compose.yml diff --git a/apps/opencv/src/filelist b/archive/apps/opencv/src/filelist similarity index 100% rename from apps/opencv/src/filelist rename to archive/apps/opencv/src/filelist diff --git a/apps/opencv/variables.json b/archive/apps/opencv/variables.json similarity index 100% rename from apps/opencv/variables.json rename to archive/apps/opencv/variables.json diff --git a/apps/opengauss/.env b/archive/apps/opengauss/.env similarity index 100% rename from apps/opengauss/.env rename to archive/apps/opengauss/.env diff --git a/apps/opengauss/CHANGELOG.md b/archive/apps/opengauss/CHANGELOG.md similarity index 100% rename from apps/opengauss/CHANGELOG.md rename to archive/apps/opengauss/CHANGELOG.md diff --git a/apps/opengauss/Notes.md b/archive/apps/opengauss/Notes.md similarity index 100% rename from apps/opengauss/Notes.md rename to archive/apps/opengauss/Notes.md diff --git a/apps/opengauss/README.md b/archive/apps/opengauss/README.md similarity index 100% rename from apps/opengauss/README.md rename to archive/apps/opengauss/README.md diff --git a/apps/opengauss/docker-compose.yml b/archive/apps/opengauss/docker-compose.yml similarity index 100% rename from apps/opengauss/docker-compose.yml rename to archive/apps/opengauss/docker-compose.yml diff --git a/apps/opengauss/src/README.md b/archive/apps/opengauss/src/README.md similarity index 100% rename from apps/opengauss/src/README.md rename to archive/apps/opengauss/src/README.md diff --git a/apps/opengauss/variables.json b/archive/apps/opengauss/variables.json similarity index 100% rename from apps/opengauss/variables.json rename to archive/apps/opengauss/variables.json diff --git a/apps/openjdk/.env b/archive/apps/openjdk/.env similarity index 100% rename from apps/openjdk/.env rename to archive/apps/openjdk/.env diff --git a/apps/openjdk/CHANGELOG.md b/archive/apps/openjdk/CHANGELOG.md similarity index 100% rename from apps/openjdk/CHANGELOG.md rename to archive/apps/openjdk/CHANGELOG.md diff --git a/apps/openjdk/Notes.md b/archive/apps/openjdk/Notes.md similarity index 100% rename from apps/openjdk/Notes.md rename to archive/apps/openjdk/Notes.md diff --git a/apps/openjdk/README.md b/archive/apps/openjdk/README.md similarity index 100% rename from apps/openjdk/README.md rename to archive/apps/openjdk/README.md diff --git a/apps/openjdk/docker-compose.yml b/archive/apps/openjdk/docker-compose.yml similarity index 100% rename from apps/openjdk/docker-compose.yml rename to archive/apps/openjdk/docker-compose.yml diff --git a/apps/openjdk/src/README.md b/archive/apps/openjdk/src/README.md similarity index 100% rename from apps/openjdk/src/README.md rename to archive/apps/openjdk/src/README.md diff --git a/apps/openjdk/src/cmd.sh b/archive/apps/openjdk/src/cmd.sh similarity index 100% rename from apps/openjdk/src/cmd.sh rename to archive/apps/openjdk/src/cmd.sh diff --git a/apps/openjdk/variables.json b/archive/apps/openjdk/variables.json similarity index 100% rename from apps/openjdk/variables.json rename to archive/apps/openjdk/variables.json diff --git a/apps/openproject/.env b/archive/apps/openproject/.env similarity index 100% rename from apps/openproject/.env rename to archive/apps/openproject/.env diff --git a/apps/openproject/CHANGELOG.md b/archive/apps/openproject/CHANGELOG.md similarity index 100% rename from apps/openproject/CHANGELOG.md rename to archive/apps/openproject/CHANGELOG.md diff --git a/apps/openproject/Notes.md b/archive/apps/openproject/Notes.md similarity index 100% rename from apps/openproject/Notes.md rename to archive/apps/openproject/Notes.md diff --git a/apps/openproject/README.md b/archive/apps/openproject/README.md similarity index 100% rename from apps/openproject/README.md rename to archive/apps/openproject/README.md diff --git a/apps/openproject/docker-compose.yml b/archive/apps/openproject/docker-compose.yml similarity index 100% rename from apps/openproject/docker-compose.yml rename to archive/apps/openproject/docker-compose.yml diff --git a/apps/openproject/src/README.md b/archive/apps/openproject/src/README.md similarity index 100% rename from apps/openproject/src/README.md rename to archive/apps/openproject/src/README.md diff --git a/apps/openproject/variables.json b/archive/apps/openproject/variables.json similarity index 100% rename from apps/openproject/variables.json rename to archive/apps/openproject/variables.json diff --git a/apps/opentelemetry/.env b/archive/apps/opentelemetry/.env similarity index 100% rename from apps/opentelemetry/.env rename to archive/apps/opentelemetry/.env diff --git a/apps/opentelemetry/CHANGELOG.md b/archive/apps/opentelemetry/CHANGELOG.md similarity index 100% rename from apps/opentelemetry/CHANGELOG.md rename to archive/apps/opentelemetry/CHANGELOG.md diff --git a/apps/opentelemetry/Notes.md b/archive/apps/opentelemetry/Notes.md similarity index 100% rename from apps/opentelemetry/Notes.md rename to archive/apps/opentelemetry/Notes.md diff --git a/apps/opentelemetry/docker-compose.yml b/archive/apps/opentelemetry/docker-compose.yml similarity index 100% rename from apps/opentelemetry/docker-compose.yml rename to archive/apps/opentelemetry/docker-compose.yml diff --git a/apps/opentelemetry/src/README.md b/archive/apps/opentelemetry/src/README.md similarity index 100% rename from apps/opentelemetry/src/README.md rename to archive/apps/opentelemetry/src/README.md diff --git a/apps/opentelemetry/variables.json b/archive/apps/opentelemetry/variables.json similarity index 100% rename from apps/opentelemetry/variables.json rename to archive/apps/opentelemetry/variables.json diff --git a/apps/outline/.env b/archive/apps/outline/.env similarity index 100% rename from apps/outline/.env rename to archive/apps/outline/.env diff --git a/apps/outline/CHANGELOG.md b/archive/apps/outline/CHANGELOG.md similarity index 100% rename from apps/outline/CHANGELOG.md rename to archive/apps/outline/CHANGELOG.md diff --git a/apps/outline/Notes.md b/archive/apps/outline/Notes.md similarity index 100% rename from apps/outline/Notes.md rename to archive/apps/outline/Notes.md diff --git a/apps/outline/README.jinja2 b/archive/apps/outline/README.jinja2 similarity index 100% rename from apps/outline/README.jinja2 rename to archive/apps/outline/README.jinja2 diff --git a/apps/outline/README.md b/archive/apps/outline/README.md similarity index 100% rename from apps/outline/README.md rename to archive/apps/outline/README.md diff --git a/apps/outline/docker-compose.yml b/archive/apps/outline/docker-compose.yml similarity index 100% rename from apps/outline/docker-compose.yml rename to archive/apps/outline/docker-compose.yml diff --git a/apps/outline/src/README.md b/archive/apps/outline/src/README.md similarity index 100% rename from apps/outline/src/README.md rename to archive/apps/outline/src/README.md diff --git a/apps/outline/variables.json b/archive/apps/outline/variables.json similarity index 100% rename from apps/outline/variables.json rename to archive/apps/outline/variables.json diff --git a/apps/palworld/.env b/archive/apps/palworld/.env similarity index 100% rename from apps/palworld/.env rename to archive/apps/palworld/.env diff --git a/apps/palworld/CHANGELOG.md b/archive/apps/palworld/CHANGELOG.md similarity index 100% rename from apps/palworld/CHANGELOG.md rename to archive/apps/palworld/CHANGELOG.md diff --git a/apps/palworld/Notes.md b/archive/apps/palworld/Notes.md similarity index 100% rename from apps/palworld/Notes.md rename to archive/apps/palworld/Notes.md diff --git a/apps/palworld/README.md b/archive/apps/palworld/README.md similarity index 100% rename from apps/palworld/README.md rename to archive/apps/palworld/README.md diff --git a/apps/palworld/docker-compose.yml b/archive/apps/palworld/docker-compose.yml similarity index 100% rename from apps/palworld/docker-compose.yml rename to archive/apps/palworld/docker-compose.yml diff --git a/apps/palworld/src/get_version.sh b/archive/apps/palworld/src/get_version.sh similarity index 100% rename from apps/palworld/src/get_version.sh rename to archive/apps/palworld/src/get_version.sh diff --git a/apps/palworld/variables.json b/archive/apps/palworld/variables.json similarity index 100% rename from apps/palworld/variables.json rename to archive/apps/palworld/variables.json diff --git a/apps/pangolin/.env b/archive/apps/pangolin/.env similarity index 100% rename from apps/pangolin/.env rename to archive/apps/pangolin/.env diff --git a/apps/pangolin/CHANGELOG.md b/archive/apps/pangolin/CHANGELOG.md similarity index 100% rename from apps/pangolin/CHANGELOG.md rename to archive/apps/pangolin/CHANGELOG.md diff --git a/apps/pangolin/Notes.md b/archive/apps/pangolin/Notes.md similarity index 100% rename from apps/pangolin/Notes.md rename to archive/apps/pangolin/Notes.md diff --git a/apps/pangolin/README.md b/archive/apps/pangolin/README.md similarity index 100% rename from apps/pangolin/README.md rename to archive/apps/pangolin/README.md diff --git a/apps/pangolin/docker-compose.yml b/archive/apps/pangolin/docker-compose.yml similarity index 100% rename from apps/pangolin/docker-compose.yml rename to archive/apps/pangolin/docker-compose.yml diff --git a/apps/pangolin/src/README.md b/archive/apps/pangolin/src/README.md similarity index 100% rename from apps/pangolin/src/README.md rename to archive/apps/pangolin/src/README.md diff --git a/apps/pangolin/variables.json b/archive/apps/pangolin/variables.json similarity index 76% rename from apps/pangolin/variables.json rename to archive/apps/pangolin/variables.json index bb8c0f295..d8451e545 100644 --- a/apps/pangolin/variables.json +++ b/archive/apps/pangolin/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/fosrl/pangolin" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/paperlessngx/.env b/archive/apps/paperlessngx/.env similarity index 100% rename from apps/paperlessngx/.env rename to archive/apps/paperlessngx/.env diff --git a/apps/paperlessngx/CHANGELOG.md b/archive/apps/paperlessngx/CHANGELOG.md similarity index 100% rename from apps/paperlessngx/CHANGELOG.md rename to archive/apps/paperlessngx/CHANGELOG.md diff --git a/apps/paperlessngx/Notes.md b/archive/apps/paperlessngx/Notes.md similarity index 100% rename from apps/paperlessngx/Notes.md rename to archive/apps/paperlessngx/Notes.md diff --git a/apps/paperlessngx/README.md b/archive/apps/paperlessngx/README.md similarity index 100% rename from apps/paperlessngx/README.md rename to archive/apps/paperlessngx/README.md diff --git a/apps/paperlessngx/docker-compose.yml b/archive/apps/paperlessngx/docker-compose.yml similarity index 100% rename from apps/paperlessngx/docker-compose.yml rename to archive/apps/paperlessngx/docker-compose.yml diff --git a/apps/paperlessngx/src/README.md b/archive/apps/paperlessngx/src/README.md similarity index 100% rename from apps/paperlessngx/src/README.md rename to archive/apps/paperlessngx/src/README.md diff --git a/apps/graylog/src/after_up.sh b/archive/apps/paperlessngx/src/after_up.sh similarity index 100% rename from apps/graylog/src/after_up.sh rename to archive/apps/paperlessngx/src/after_up.sh diff --git a/apps/metabase/src/encrypt.sh b/archive/apps/paperlessngx/src/encrypt.sh similarity index 100% rename from apps/metabase/src/encrypt.sh rename to archive/apps/paperlessngx/src/encrypt.sh diff --git a/apps/paperlessngx/src/filelist b/archive/apps/paperlessngx/src/filelist similarity index 100% rename from apps/paperlessngx/src/filelist rename to archive/apps/paperlessngx/src/filelist diff --git a/apps/paperlessngx/src/get_version.sh b/archive/apps/paperlessngx/src/get_version.sh similarity index 100% rename from apps/paperlessngx/src/get_version.sh rename to archive/apps/paperlessngx/src/get_version.sh diff --git a/apps/paperlessngx/src/nginx-proxy.conf.template b/archive/apps/paperlessngx/src/nginx-proxy.conf.template similarity index 100% rename from apps/paperlessngx/src/nginx-proxy.conf.template rename to archive/apps/paperlessngx/src/nginx-proxy.conf.template diff --git a/apps/paperlessngx/src/php_exra.ini b/archive/apps/paperlessngx/src/php_exra.ini similarity index 100% rename from apps/paperlessngx/src/php_exra.ini rename to archive/apps/paperlessngx/src/php_exra.ini diff --git a/apps/paperlessngx/src/replace_url.sh b/archive/apps/paperlessngx/src/replace_url.sh similarity index 100% rename from apps/paperlessngx/src/replace_url.sh rename to archive/apps/paperlessngx/src/replace_url.sh diff --git a/apps/paperlessngx/variables.json b/archive/apps/paperlessngx/variables.json similarity index 77% rename from apps/paperlessngx/variables.json rename to archive/apps/paperlessngx/variables.json index 296a03699..cb3de851d 100644 --- a/apps/paperlessngx/variables.json +++ b/archive/apps/paperlessngx/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/papermc/.env b/archive/apps/papermc/.env similarity index 100% rename from apps/papermc/.env rename to archive/apps/papermc/.env diff --git a/apps/papermc/CHANGELOG.md b/archive/apps/papermc/CHANGELOG.md similarity index 100% rename from apps/papermc/CHANGELOG.md rename to archive/apps/papermc/CHANGELOG.md diff --git a/apps/papermc/Notes.md b/archive/apps/papermc/Notes.md similarity index 100% rename from apps/papermc/Notes.md rename to archive/apps/papermc/Notes.md diff --git a/apps/papermc/README.md b/archive/apps/papermc/README.md similarity index 100% rename from apps/papermc/README.md rename to archive/apps/papermc/README.md diff --git a/apps/papermc/docker-compose.yml b/archive/apps/papermc/docker-compose.yml similarity index 100% rename from apps/papermc/docker-compose.yml rename to archive/apps/papermc/docker-compose.yml diff --git a/apps/papermc/src/README.md b/archive/apps/papermc/src/README.md similarity index 100% rename from apps/papermc/src/README.md rename to archive/apps/papermc/src/README.md diff --git a/apps/papermc/src/server.properties b/archive/apps/papermc/src/server.properties similarity index 100% rename from apps/papermc/src/server.properties rename to archive/apps/papermc/src/server.properties diff --git a/apps/papermc/variables.json b/archive/apps/papermc/variables.json similarity index 100% rename from apps/papermc/variables.json rename to archive/apps/papermc/variables.json diff --git a/apps/passbolt/.env b/archive/apps/passbolt/.env similarity index 100% rename from apps/passbolt/.env rename to archive/apps/passbolt/.env diff --git a/apps/passbolt/CHANGELOG.md b/archive/apps/passbolt/CHANGELOG.md similarity index 100% rename from apps/passbolt/CHANGELOG.md rename to archive/apps/passbolt/CHANGELOG.md diff --git a/apps/passbolt/Notes.md b/archive/apps/passbolt/Notes.md similarity index 100% rename from apps/passbolt/Notes.md rename to archive/apps/passbolt/Notes.md diff --git a/apps/passbolt/README.md b/archive/apps/passbolt/README.md similarity index 100% rename from apps/passbolt/README.md rename to archive/apps/passbolt/README.md diff --git a/apps/passbolt/docker-compose.yml b/archive/apps/passbolt/docker-compose.yml similarity index 100% rename from apps/passbolt/docker-compose.yml rename to archive/apps/passbolt/docker-compose.yml diff --git a/apps/passbolt/src/README.md b/archive/apps/passbolt/src/README.md similarity index 100% rename from apps/passbolt/src/README.md rename to archive/apps/passbolt/src/README.md diff --git a/apps/passbolt/variables.json b/archive/apps/passbolt/variables.json similarity index 77% rename from apps/passbolt/variables.json rename to archive/apps/passbolt/variables.json index c65576079..ac041cd7f 100644 --- a/apps/passbolt/variables.json +++ b/archive/apps/passbolt/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/penpot/.env b/archive/apps/penpot/.env similarity index 100% rename from apps/penpot/.env rename to archive/apps/penpot/.env diff --git a/apps/penpot/CHANGELOG.md b/archive/apps/penpot/CHANGELOG.md similarity index 100% rename from apps/penpot/CHANGELOG.md rename to archive/apps/penpot/CHANGELOG.md diff --git a/apps/penpot/Notes.md b/archive/apps/penpot/Notes.md similarity index 100% rename from apps/penpot/Notes.md rename to archive/apps/penpot/Notes.md diff --git a/apps/penpot/README.md b/archive/apps/penpot/README.md similarity index 100% rename from apps/penpot/README.md rename to archive/apps/penpot/README.md diff --git a/apps/penpot/docker-compose.yml b/archive/apps/penpot/docker-compose.yml similarity index 100% rename from apps/penpot/docker-compose.yml rename to archive/apps/penpot/docker-compose.yml diff --git a/apps/penpot/src/README.md b/archive/apps/penpot/src/README.md similarity index 100% rename from apps/penpot/src/README.md rename to archive/apps/penpot/src/README.md diff --git a/apps/penpot/variables.json b/archive/apps/penpot/variables.json similarity index 76% rename from apps/penpot/variables.json rename to archive/apps/penpot/variables.json index 342a7dd0a..bbec57789 100644 --- a/apps/penpot/variables.json +++ b/archive/apps/penpot/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/photoprism/.env b/archive/apps/photoprism/.env similarity index 100% rename from apps/photoprism/.env rename to archive/apps/photoprism/.env diff --git a/apps/photoprism/CHANGELOG.md b/archive/apps/photoprism/CHANGELOG.md similarity index 100% rename from apps/photoprism/CHANGELOG.md rename to archive/apps/photoprism/CHANGELOG.md diff --git a/apps/photoprism/Notes.md b/archive/apps/photoprism/Notes.md similarity index 100% rename from apps/photoprism/Notes.md rename to archive/apps/photoprism/Notes.md diff --git a/apps/photoprism/README.md b/archive/apps/photoprism/README.md similarity index 100% rename from apps/photoprism/README.md rename to archive/apps/photoprism/README.md diff --git a/apps/photoprism/docker-compose.yml b/archive/apps/photoprism/docker-compose.yml similarity index 100% rename from apps/photoprism/docker-compose.yml rename to archive/apps/photoprism/docker-compose.yml diff --git a/apps/photoprism/src/README.md b/archive/apps/photoprism/src/README.md similarity index 100% rename from apps/photoprism/src/README.md rename to archive/apps/photoprism/src/README.md diff --git a/apps/photoprism/variables.json b/archive/apps/photoprism/variables.json similarity index 77% rename from apps/photoprism/variables.json rename to archive/apps/photoprism/variables.json index a5caaaac8..c3af6b7b9 100644 --- a/apps/photoprism/variables.json +++ b/archive/apps/photoprism/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 2342, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/phpfpmapache/.env b/archive/apps/phpfpmapache/.env similarity index 100% rename from apps/phpfpmapache/.env rename to archive/apps/phpfpmapache/.env diff --git a/apps/phpfpmapache/CHANGELOG.md b/archive/apps/phpfpmapache/CHANGELOG.md similarity index 100% rename from apps/phpfpmapache/CHANGELOG.md rename to archive/apps/phpfpmapache/CHANGELOG.md diff --git a/apps/phpfpmapache/Dockerfile b/archive/apps/phpfpmapache/Dockerfile similarity index 100% rename from apps/phpfpmapache/Dockerfile rename to archive/apps/phpfpmapache/Dockerfile diff --git a/apps/phpfpmapache/Notes.md b/archive/apps/phpfpmapache/Notes.md similarity index 100% rename from apps/phpfpmapache/Notes.md rename to archive/apps/phpfpmapache/Notes.md diff --git a/apps/phpfpmapache/README.md b/archive/apps/phpfpmapache/README.md similarity index 100% rename from apps/phpfpmapache/README.md rename to archive/apps/phpfpmapache/README.md diff --git a/apps/phpfpmapache/docker-compose.yml b/archive/apps/phpfpmapache/docker-compose.yml similarity index 100% rename from apps/phpfpmapache/docker-compose.yml rename to archive/apps/phpfpmapache/docker-compose.yml diff --git a/apps/phpfpmapache/src/000-default.conf b/archive/apps/phpfpmapache/src/000-default.conf similarity index 100% rename from apps/phpfpmapache/src/000-default.conf rename to archive/apps/phpfpmapache/src/000-default.conf diff --git a/apps/phpfpmapache/src/README.md b/archive/apps/phpfpmapache/src/README.md similarity index 100% rename from apps/phpfpmapache/src/README.md rename to archive/apps/phpfpmapache/src/README.md diff --git a/apps/phpfpmapache/src/apt_install.sh b/archive/apps/phpfpmapache/src/apt_install.sh similarity index 100% rename from apps/phpfpmapache/src/apt_install.sh rename to archive/apps/phpfpmapache/src/apt_install.sh diff --git a/apps/phpfpmapache/src/cmd.sh b/archive/apps/phpfpmapache/src/cmd.sh similarity index 100% rename from apps/phpfpmapache/src/cmd.sh rename to archive/apps/phpfpmapache/src/cmd.sh diff --git a/apps/phpfpmapache/src/entrypoint.sh b/archive/apps/phpfpmapache/src/entrypoint.sh similarity index 100% rename from apps/phpfpmapache/src/entrypoint.sh rename to archive/apps/phpfpmapache/src/entrypoint.sh diff --git a/apps/phpfpmapache/src/extensions.ini b/archive/apps/phpfpmapache/src/extensions.ini similarity index 100% rename from apps/phpfpmapache/src/extensions.ini rename to archive/apps/phpfpmapache/src/extensions.ini diff --git a/apps/phpfpmapache/src/fpm_extra.conf b/archive/apps/phpfpmapache/src/fpm_extra.conf similarity index 100% rename from apps/phpfpmapache/src/fpm_extra.conf rename to archive/apps/phpfpmapache/src/fpm_extra.conf diff --git a/apps/phpfpmapache/src/php_extra.ini b/archive/apps/phpfpmapache/src/php_extra.ini similarity index 100% rename from apps/phpfpmapache/src/php_extra.ini rename to archive/apps/phpfpmapache/src/php_extra.ini diff --git a/apps/phpfpmapache/src/php_install.sh b/archive/apps/phpfpmapache/src/php_install.sh similarity index 100% rename from apps/phpfpmapache/src/php_install.sh rename to archive/apps/phpfpmapache/src/php_install.sh diff --git a/apps/phpfpmapache/src/supervisord.conf b/archive/apps/phpfpmapache/src/supervisord.conf similarity index 100% rename from apps/phpfpmapache/src/supervisord.conf rename to archive/apps/phpfpmapache/src/supervisord.conf diff --git a/apps/phpfpmapache/variables.json b/archive/apps/phpfpmapache/variables.json similarity index 82% rename from apps/phpfpmapache/variables.json rename to archive/apps/phpfpmapache/variables.json index 151518c8c..86989ef8e 100644 --- a/apps/phpfpmapache/variables.json +++ b/archive/apps/phpfpmapache/variables.json @@ -26,5 +26,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/php" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/phpfpmnginx/.env b/archive/apps/phpfpmnginx/.env similarity index 100% rename from apps/phpfpmnginx/.env rename to archive/apps/phpfpmnginx/.env diff --git a/apps/phpfpmnginx/CHANGELOG.md b/archive/apps/phpfpmnginx/CHANGELOG.md similarity index 100% rename from apps/phpfpmnginx/CHANGELOG.md rename to archive/apps/phpfpmnginx/CHANGELOG.md diff --git a/apps/phpfpmnginx/Dockerfile b/archive/apps/phpfpmnginx/Dockerfile similarity index 100% rename from apps/phpfpmnginx/Dockerfile rename to archive/apps/phpfpmnginx/Dockerfile diff --git a/apps/phpfpmnginx/Notes.md b/archive/apps/phpfpmnginx/Notes.md similarity index 100% rename from apps/phpfpmnginx/Notes.md rename to archive/apps/phpfpmnginx/Notes.md diff --git a/apps/phpfpmnginx/README.md b/archive/apps/phpfpmnginx/README.md similarity index 100% rename from apps/phpfpmnginx/README.md rename to archive/apps/phpfpmnginx/README.md diff --git a/apps/phpfpmnginx/docker-compose.yml b/archive/apps/phpfpmnginx/docker-compose.yml similarity index 100% rename from apps/phpfpmnginx/docker-compose.yml rename to archive/apps/phpfpmnginx/docker-compose.yml diff --git a/apps/phpfpmnginx/src/README.md b/archive/apps/phpfpmnginx/src/README.md similarity index 100% rename from apps/phpfpmnginx/src/README.md rename to archive/apps/phpfpmnginx/src/README.md diff --git a/apps/phpfpmnginx/src/apt_install.sh b/archive/apps/phpfpmnginx/src/apt_install.sh similarity index 100% rename from apps/phpfpmnginx/src/apt_install.sh rename to archive/apps/phpfpmnginx/src/apt_install.sh diff --git a/apps/phpfpmnginx/src/cmd.sh b/archive/apps/phpfpmnginx/src/cmd.sh similarity index 100% rename from apps/phpfpmnginx/src/cmd.sh rename to archive/apps/phpfpmnginx/src/cmd.sh diff --git a/apps/phpfpmnginx/src/entrypoint.sh b/archive/apps/phpfpmnginx/src/entrypoint.sh similarity index 100% rename from apps/phpfpmnginx/src/entrypoint.sh rename to archive/apps/phpfpmnginx/src/entrypoint.sh diff --git a/apps/phpfpmnginx/src/extensions.ini b/archive/apps/phpfpmnginx/src/extensions.ini similarity index 100% rename from apps/phpfpmnginx/src/extensions.ini rename to archive/apps/phpfpmnginx/src/extensions.ini diff --git a/apps/phpfpmnginx/src/fpm_extra.conf b/archive/apps/phpfpmnginx/src/fpm_extra.conf similarity index 100% rename from apps/phpfpmnginx/src/fpm_extra.conf rename to archive/apps/phpfpmnginx/src/fpm_extra.conf diff --git a/apps/phpfpmnginx/src/nginx.conf b/archive/apps/phpfpmnginx/src/nginx.conf similarity index 100% rename from apps/phpfpmnginx/src/nginx.conf rename to archive/apps/phpfpmnginx/src/nginx.conf diff --git a/apps/phpfpmnginx/src/php_extra.ini b/archive/apps/phpfpmnginx/src/php_extra.ini similarity index 100% rename from apps/phpfpmnginx/src/php_extra.ini rename to archive/apps/phpfpmnginx/src/php_extra.ini diff --git a/apps/phpfpmnginx/src/php_install.sh b/archive/apps/phpfpmnginx/src/php_install.sh similarity index 100% rename from apps/phpfpmnginx/src/php_install.sh rename to archive/apps/phpfpmnginx/src/php_install.sh diff --git a/apps/phpfpmnginx/src/supervisord.conf b/archive/apps/phpfpmnginx/src/supervisord.conf similarity index 100% rename from apps/phpfpmnginx/src/supervisord.conf rename to archive/apps/phpfpmnginx/src/supervisord.conf diff --git a/apps/phpfpmnginx/variables.json b/archive/apps/phpfpmnginx/variables.json similarity index 82% rename from apps/phpfpmnginx/variables.json rename to archive/apps/phpfpmnginx/variables.json index eb53ab7a5..c0baca0c6 100644 --- a/apps/phpfpmnginx/variables.json +++ b/archive/apps/phpfpmnginx/variables.json @@ -19,6 +19,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/plane/.env b/archive/apps/plane/.env similarity index 100% rename from apps/plane/.env rename to archive/apps/plane/.env diff --git a/apps/plane/CHANGELOG.md b/archive/apps/plane/CHANGELOG.md similarity index 100% rename from apps/plane/CHANGELOG.md rename to archive/apps/plane/CHANGELOG.md diff --git a/apps/plane/Dockerfile b/archive/apps/plane/Dockerfile similarity index 100% rename from apps/plane/Dockerfile rename to archive/apps/plane/Dockerfile diff --git a/apps/plane/Notes.md b/archive/apps/plane/Notes.md similarity index 100% rename from apps/plane/Notes.md rename to archive/apps/plane/Notes.md diff --git a/apps/plane/README.jinja2 b/archive/apps/plane/README.jinja2 similarity index 100% rename from apps/plane/README.jinja2 rename to archive/apps/plane/README.jinja2 diff --git a/apps/plane/README.md b/archive/apps/plane/README.md similarity index 100% rename from apps/plane/README.md rename to archive/apps/plane/README.md diff --git a/apps/plane/docker-compose.yml b/archive/apps/plane/docker-compose.yml similarity index 100% rename from apps/plane/docker-compose.yml rename to archive/apps/plane/docker-compose.yml diff --git a/apps/plane/src/README.md b/archive/apps/plane/src/README.md similarity index 100% rename from apps/plane/src/README.md rename to archive/apps/plane/src/README.md diff --git a/apps/plane/src/nginx-proxy.conf.template b/archive/apps/plane/src/nginx-proxy.conf.template similarity index 100% rename from apps/plane/src/nginx-proxy.conf.template rename to archive/apps/plane/src/nginx-proxy.conf.template diff --git a/apps/plane/src/php_exra.ini b/archive/apps/plane/src/php_exra.ini similarity index 100% rename from apps/plane/src/php_exra.ini rename to archive/apps/plane/src/php_exra.ini diff --git a/apps/plane/variables.json b/archive/apps/plane/variables.json similarity index 70% rename from apps/plane/variables.json rename to archive/apps/plane/variables.json index 388878748..9e748807b 100644 --- a/apps/plane/variables.json +++ b/archive/apps/plane/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/archive/apps/plausible/.env b/archive/apps/plausible/.env new file mode 100644 index 000000000..f1434aab0 --- /dev/null +++ b/archive/apps/plausible/.env @@ -0,0 +1,43 @@ +W9_REPO=ghcr.io/plausible/community-edition +W9_DIST=community +W9_VERSION=v3.2.1 +W9_POWER_PASSWORD="zOvhr8@0TWGcP8yd" + +# Canonical semantics live in docs/w9-env-spec.md. +# This template controls layout; the spec controls meaning and decision rules. + +#### -- Not allowed to edit below environments when recreate app based on existing data -- #### + +W9_ID=plausible +W9_HTTP_PORT=8000 +W9_HTTP_PORT_SET=9001 +W9_DB_VERSION=16 +W9_DB_EXPOSE=postgresql +W9_URL=plausible.example.com +W9_URL_REPLACE=true +W9_NETWORK=websoft9 + +#### ----------------------------------------------------------------------------------------- #### + +# ============================================================ +# Plausible image environment variables +# Docs: https://github.com/plausible/community-edition/wiki/Configuration +# Follow docs/w9-env-spec.md when deciding which vars belong here. +# Enable the vars actually used in docker-compose.yml below; list up +# to 5 unused vars commented out. Full reference lives in the Docs URL. +# ============================================================ + +# Used by docker-compose.yml: +BASE_URL=http://${W9_URL} +SECRET_KEY_BASE=J4KfL6nP9rTs3XvW7yZaB2cDeF5gHiJ8kLmNoPqRsTuVwXyZ0123456789abcdefghi +HTTP_PORT=${W9_HTTP_PORT} +DATABASE_URL=postgres://postgres:${W9_POWER_PASSWORD}@${W9_ID}-postgresql:5432/plausible_db +CLICKHOUSE_DATABASE_URL=http://${W9_ID}-clickhouse:8123/plausible_events_db +TMPDIR=/var/lib/plausible/tmp + +# Not used by default; enable only when needed: +# DISABLE_REGISTRATION=false +# ENABLE_EMAIL_VERIFICATION=true +# SMTP_HOST_ADDR= +# SMTP_HOST_PORT=25 +# TOTP_VAULT_KEY= diff --git a/archive/apps/plausible/CHANGELOG.md b/archive/apps/plausible/CHANGELOG.md new file mode 100644 index 000000000..8020bd4b5 --- /dev/null +++ b/archive/apps/plausible/CHANGELOG.md @@ -0,0 +1,7 @@ +# CHANGELOG + +## 2026-10-09 + +- Updated Plausible from `v2.0` to `v3.2.1`. +- Switched to the official Community Edition GHCR image and refreshed PostgreSQL/ClickHouse dependencies to the current upstream compose baseline. +- Normalized package metadata and environment layout to current repository rules. diff --git a/archive/apps/plausible/README.md b/archive/apps/plausible/README.md new file mode 100644 index 000000000..29f754db7 --- /dev/null +++ b/archive/apps/plausible/README.md @@ -0,0 +1,96 @@ +# Plausible on Docker + +## Quick Start + +### Deploy Verification + +1. In the [Websoft9](https://www.websoft9.com) console, open **My Apps** and select **Plausible**. +2. In the **Access** tab, get the login URL and credentials. +3. Open the login URL in a browser and sign in to confirm the app works. + + +### Usage + +1. Make sure you are signed in to the Plausible admin console. +2. Try a core feature. + +### Change Password + +1. In the [Websoft9](https://www.websoft9.com) console, open the app's **Compose** tab. +2. Update the password in `.env` and save. +3. Rebuild the app. + + +## Configuration Reference + +Websoft9 packages this app from the official [Plausible Docker image](https://github.com/plausible/analytics/pkgs/container/community-edition) and makes some improvements below. + + + + + +Apps run as containers; rebuild after any configuration change. + +### Version Support + +Supported versions: v3.2.1, latest. + +The `latest` tag is not guaranteed to remain valid; pin a specific version for production. + + +### Ports + +| Purpose | Port | +| --- | --- | +| Web Console | 8000 | + + +### Data Directory + + +- `db-data` → `/var/lib/postgresql/data` +- `event-data` → `/var/lib/clickhouse` +- `event-logs` → `/var/log/clickhouse-server` +- `plausible-data` → `/var/lib/plausible` + + + +### Environment Variables + +Environment variables are defined in the app's `.env` file; see the reference section at the end of `.env` for supported variables. + + +### Configuration Files + + +- `./src/clickhouse/clickhouse-config.xml` → `/etc/clickhouse-server/config.d/logs.xml` +- `./src/clickhouse/clickhouse-user-config.xml` → `/etc/clickhouse-server/users.d/default-profile-low-resources-overrides.xml` + + + +## References + +- [Plausible Administrator Guide](https://support.websoft9.com/docs/plausible) by Websoft9 + +- [Docker Hub image](https://github.com/plausible/analytics/pkgs/container/community-edition) + +- [Releases](https://github.com/plausible/analytics/releases) + +- [Official compose](https://github.com/plausible/community-edition/blob/v3.2.1/compose.yml) + +- [Official docs](https://plausible.io/docs/self-hosting) + +- [GitHub docs](https://github.com/plausible/community-edition/blob/v3.2.1/README.md) + +- [GitHub docs](https://github.com/plausible/community-edition/wiki/Upgrade-PostgreSQL) + + + +## Troubleshooting + +**App fails to start?** +- Check `docker compose logs`. + +**Port not reachable?** +- Ensure the firewall / security group allows the port. + diff --git a/archive/apps/plausible/docker-compose.yml b/archive/apps/plausible/docker-compose.yml new file mode 100644 index 000000000..f47ead8d9 --- /dev/null +++ b/archive/apps/plausible/docker-compose.yml @@ -0,0 +1,71 @@ +services: + plausible_db: + image: postgres:${W9_DB_VERSION}-alpine + container_name: ${W9_ID}-postgresql + restart: unless-stopped + volumes: + - db-data:/var/lib/postgresql/data + environment: + POSTGRES_DB: plausible_db + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${W9_POWER_PASSWORD} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d plausible_db"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 60s + + plausible_events_db: + image: clickhouse/clickhouse-server:24.12-alpine + container_name: ${W9_ID}-clickhouse + restart: unless-stopped + volumes: + - event-data:/var/lib/clickhouse + - event-logs:/var/log/clickhouse-server + - ./src/clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logs.xml:ro + - ./src/clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/default-profile-low-resources-overrides.xml:ro + ulimits: + nofile: + soft: 262144 + hard: 262144 + environment: + CLICKHOUSE_SKIP_USER_SETUP: "1" + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 60s + + plausible: + image: ${W9_REPO}:${W9_VERSION} + container_name: ${W9_ID} + restart: unless-stopped + command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run" + depends_on: + plausible_db: + condition: service_healthy + plausible_events_db: + condition: service_healthy + ports: + - "${W9_HTTP_PORT_SET}:8000" # Web Console + env_file: + - .env + volumes: + - plausible-data:/var/lib/plausible + ulimits: + nofile: + soft: 65535 + hard: 65535 + +networks: + default: + name: ${W9_NETWORK} + external: true + +volumes: + db-data: + event-data: + event-logs: + plausible-data: diff --git a/apps/plausible/src/clickhouse/clickhouse-config.xml b/archive/apps/plausible/src/clickhouse/clickhouse-config.xml similarity index 100% rename from apps/plausible/src/clickhouse/clickhouse-config.xml rename to archive/apps/plausible/src/clickhouse/clickhouse-config.xml diff --git a/apps/plausible/src/clickhouse/clickhouse-user-config.xml b/archive/apps/plausible/src/clickhouse/clickhouse-user-config.xml similarity index 100% rename from apps/plausible/src/clickhouse/clickhouse-user-config.xml rename to archive/apps/plausible/src/clickhouse/clickhouse-user-config.xml diff --git a/apps/plausible/src/filelist b/archive/apps/plausible/src/filelist similarity index 100% rename from apps/plausible/src/filelist rename to archive/apps/plausible/src/filelist diff --git a/archive/apps/plausible/tests/cases.yml b/archive/apps/plausible/tests/cases.yml new file mode 100644 index 000000000..e24b793ac --- /dev/null +++ b/archive/apps/plausible/tests/cases.yml @@ -0,0 +1,2 @@ +skip: + - id: web-access diff --git a/archive/apps/plausible/variables.json b/archive/apps/plausible/variables.json new file mode 100644 index 000000000..949cc4fc0 --- /dev/null +++ b/archive/apps/plausible/variables.json @@ -0,0 +1,45 @@ +{ + "name": "plausible", + "trademark": "Plausible", + "release": true, + "edition": [ + { + "dist": "community", + "version": [ + "v3.2.1", + "latest" + ] + } + ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8000, + "path": "/" + } + }, + "requirements": { + "cpu": "2", + "memory": "2", + "disk": "2" + }, + "upstream": { + "image": "https://github.com/plausible/analytics/pkgs/container/community-edition", + "releases": "https://github.com/plausible/analytics/releases", + "compose": { + "compose": "https://github.com/plausible/community-edition/blob/v3.2.1/compose.yml" + }, + "docs": [ + "https://plausible.io/docs/self-hosting", + "https://github.com/plausible/community-edition/blob/v3.2.1/README.md", + "https://github.com/plausible/community-edition/wiki/Upgrade-PostgreSQL" + ] + }, + "credentials": {}, + "env": { + "first_startup_only": [] + }, + "help": { + "db": "This package uses PostgreSQL 16 and ClickHouse 24.12, aligned with Plausible Community Edition v3.2.1. Existing PostgreSQL 14 data should be migrated before reusing old volumes." + } +} diff --git a/apps/plex/.env b/archive/apps/plex/.env similarity index 100% rename from apps/plex/.env rename to archive/apps/plex/.env diff --git a/apps/plausible/CHANGELOG.md b/archive/apps/plex/CHANGELOG.md similarity index 100% rename from apps/plausible/CHANGELOG.md rename to archive/apps/plex/CHANGELOG.md diff --git a/apps/plex/Notes.md b/archive/apps/plex/Notes.md similarity index 100% rename from apps/plex/Notes.md rename to archive/apps/plex/Notes.md diff --git a/apps/plex/README.md b/archive/apps/plex/README.md similarity index 100% rename from apps/plex/README.md rename to archive/apps/plex/README.md diff --git a/apps/plex/docker-compose.yml b/archive/apps/plex/docker-compose.yml similarity index 100% rename from apps/plex/docker-compose.yml rename to archive/apps/plex/docker-compose.yml diff --git a/apps/plex/src/README.md b/archive/apps/plex/src/README.md similarity index 100% rename from apps/plex/src/README.md rename to archive/apps/plex/src/README.md diff --git a/apps/plex/variables.json b/archive/apps/plex/variables.json similarity index 75% rename from apps/plex/variables.json rename to archive/apps/plex/variables.json index 80f78d276..dce070995 100644 --- a/apps/plex/variables.json +++ b/archive/apps/plex/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 32400, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/pmm/.env b/archive/apps/pmm/.env similarity index 100% rename from apps/pmm/.env rename to archive/apps/pmm/.env diff --git a/apps/plex/CHANGELOG.md b/archive/apps/pmm/CHANGELOG.md similarity index 100% rename from apps/plex/CHANGELOG.md rename to archive/apps/pmm/CHANGELOG.md diff --git a/apps/pmm/Notes.md b/archive/apps/pmm/Notes.md similarity index 100% rename from apps/pmm/Notes.md rename to archive/apps/pmm/Notes.md diff --git a/apps/pmm/README.md b/archive/apps/pmm/README.md similarity index 100% rename from apps/pmm/README.md rename to archive/apps/pmm/README.md diff --git a/apps/pmm/docker-compose.yml b/archive/apps/pmm/docker-compose.yml similarity index 100% rename from apps/pmm/docker-compose.yml rename to archive/apps/pmm/docker-compose.yml diff --git a/apps/pmm/variables.json b/archive/apps/pmm/variables.json similarity index 100% rename from apps/pmm/variables.json rename to archive/apps/pmm/variables.json diff --git a/apps/portkey/.env b/archive/apps/portkey/.env similarity index 100% rename from apps/portkey/.env rename to archive/apps/portkey/.env diff --git a/apps/pmm/CHANGELOG.md b/archive/apps/portkey/CHANGELOG.md similarity index 100% rename from apps/pmm/CHANGELOG.md rename to archive/apps/portkey/CHANGELOG.md diff --git a/apps/portkey/Notes.md b/archive/apps/portkey/Notes.md similarity index 100% rename from apps/portkey/Notes.md rename to archive/apps/portkey/Notes.md diff --git a/apps/portkey/README.md b/archive/apps/portkey/README.md similarity index 100% rename from apps/portkey/README.md rename to archive/apps/portkey/README.md diff --git a/apps/portkey/docker-compose.yml b/archive/apps/portkey/docker-compose.yml similarity index 100% rename from apps/portkey/docker-compose.yml rename to archive/apps/portkey/docker-compose.yml diff --git a/apps/portkey/src/README.md b/archive/apps/portkey/src/README.md similarity index 100% rename from apps/portkey/src/README.md rename to archive/apps/portkey/src/README.md diff --git a/apps/portkey/variables.json b/archive/apps/portkey/variables.json similarity index 87% rename from apps/portkey/variables.json rename to archive/apps/portkey/variables.json index 55a732cd1..5f89a82fc 100644 --- a/apps/portkey/variables.json +++ b/archive/apps/portkey/variables.json @@ -19,10 +19,6 @@ "web": { "port": 8787, "path": "/" - }, - "admin": { - "port": 8787, - "path": "/public" } }, "requirements": { diff --git a/apps/posteio/.env b/archive/apps/posteio/.env similarity index 100% rename from apps/posteio/.env rename to archive/apps/posteio/.env diff --git a/apps/portkey/CHANGELOG.md b/archive/apps/posteio/CHANGELOG.md similarity index 100% rename from apps/portkey/CHANGELOG.md rename to archive/apps/posteio/CHANGELOG.md diff --git a/apps/posteio/Dockerfile b/archive/apps/posteio/Dockerfile similarity index 100% rename from apps/posteio/Dockerfile rename to archive/apps/posteio/Dockerfile diff --git a/apps/posteio/Notes.md b/archive/apps/posteio/Notes.md similarity index 100% rename from apps/posteio/Notes.md rename to archive/apps/posteio/Notes.md diff --git a/apps/posteio/README.jinja2 b/archive/apps/posteio/README.jinja2 similarity index 100% rename from apps/posteio/README.jinja2 rename to archive/apps/posteio/README.jinja2 diff --git a/apps/posteio/README.md b/archive/apps/posteio/README.md similarity index 100% rename from apps/posteio/README.md rename to archive/apps/posteio/README.md diff --git a/apps/posteio/docker-compose.yml b/archive/apps/posteio/docker-compose.yml similarity index 100% rename from apps/posteio/docker-compose.yml rename to archive/apps/posteio/docker-compose.yml diff --git a/apps/posteio/src/README.md b/archive/apps/posteio/src/README.md similarity index 100% rename from apps/posteio/src/README.md rename to archive/apps/posteio/src/README.md diff --git a/apps/posteio/src/nginx-proxy.conf.template b/archive/apps/posteio/src/nginx-proxy.conf.template similarity index 100% rename from apps/posteio/src/nginx-proxy.conf.template rename to archive/apps/posteio/src/nginx-proxy.conf.template diff --git a/apps/posteio/src/php_exra.ini b/archive/apps/posteio/src/php_exra.ini similarity index 100% rename from apps/posteio/src/php_exra.ini rename to archive/apps/posteio/src/php_exra.ini diff --git a/apps/posteio/variables.json b/archive/apps/posteio/variables.json similarity index 76% rename from apps/posteio/variables.json rename to archive/apps/posteio/variables.json index 9f5a8d72c..586cde43d 100644 --- a/apps/posteio/variables.json +++ b/archive/apps/posteio/variables.json @@ -17,5 +17,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/analogic/poste.io" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } } } diff --git a/apps/postgrest/.env b/archive/apps/postgrest/.env similarity index 100% rename from apps/postgrest/.env rename to archive/apps/postgrest/.env diff --git a/apps/posteio/CHANGELOG.md b/archive/apps/postgrest/CHANGELOG.md similarity index 100% rename from apps/posteio/CHANGELOG.md rename to archive/apps/postgrest/CHANGELOG.md diff --git a/apps/postgrest/Notes.md b/archive/apps/postgrest/Notes.md similarity index 100% rename from apps/postgrest/Notes.md rename to archive/apps/postgrest/Notes.md diff --git a/apps/postgrest/README.md b/archive/apps/postgrest/README.md similarity index 100% rename from apps/postgrest/README.md rename to archive/apps/postgrest/README.md diff --git a/apps/postgrest/docker-compose.yml b/archive/apps/postgrest/docker-compose.yml similarity index 100% rename from apps/postgrest/docker-compose.yml rename to archive/apps/postgrest/docker-compose.yml diff --git a/apps/postgrest/src/README.md b/archive/apps/postgrest/src/README.md similarity index 100% rename from apps/postgrest/src/README.md rename to archive/apps/postgrest/src/README.md diff --git a/apps/postgrest/variables.json b/archive/apps/postgrest/variables.json similarity index 76% rename from apps/postgrest/variables.json rename to archive/apps/postgrest/variables.json index 4cd5afc39..407c1c8ac 100644 --- a/apps/postgrest/variables.json +++ b/archive/apps/postgrest/variables.json @@ -18,5 +18,12 @@ }, "upstream": { "image": "https://hub.docker.com/r/postgrest/postgrest" + }, + "access": { + "defaultScheme": "http", + "api": { + "port": 3000, + "path": "/" + } } } diff --git a/apps/puter/.env b/archive/apps/puter/.env similarity index 100% rename from apps/puter/.env rename to archive/apps/puter/.env diff --git a/apps/postgrest/CHANGELOG.md b/archive/apps/puter/CHANGELOG.md similarity index 100% rename from apps/postgrest/CHANGELOG.md rename to archive/apps/puter/CHANGELOG.md diff --git a/apps/puter/Notes.md b/archive/apps/puter/Notes.md similarity index 100% rename from apps/puter/Notes.md rename to archive/apps/puter/Notes.md diff --git a/apps/puter/README.md b/archive/apps/puter/README.md similarity index 100% rename from apps/puter/README.md rename to archive/apps/puter/README.md diff --git a/apps/puter/docker-compose.yml b/archive/apps/puter/docker-compose.yml similarity index 100% rename from apps/puter/docker-compose.yml rename to archive/apps/puter/docker-compose.yml diff --git a/apps/posthog/src/README.md b/archive/apps/puter/src/README.md similarity index 100% rename from apps/posthog/src/README.md rename to archive/apps/puter/src/README.md diff --git a/apps/puter/variables.json b/archive/apps/puter/variables.json similarity index 74% rename from apps/puter/variables.json rename to archive/apps/puter/variables.json index 1f3dbc1c2..9676a1104 100644 --- a/apps/puter/variables.json +++ b/archive/apps/puter/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 4100, + "path": "/" + } + }, "requirements": { "cpu": "2", "memory": "4", diff --git a/apps/pydio/.env b/archive/apps/pydio/.env similarity index 100% rename from apps/pydio/.env rename to archive/apps/pydio/.env diff --git a/apps/puter/CHANGELOG.md b/archive/apps/pydio/CHANGELOG.md similarity index 100% rename from apps/puter/CHANGELOG.md rename to archive/apps/pydio/CHANGELOG.md diff --git a/apps/pydio/Notes.md b/archive/apps/pydio/Notes.md similarity index 100% rename from apps/pydio/Notes.md rename to archive/apps/pydio/Notes.md diff --git a/apps/pydio/README.md b/archive/apps/pydio/README.md similarity index 100% rename from apps/pydio/README.md rename to archive/apps/pydio/README.md diff --git a/apps/pydio/docker-compose.yml b/archive/apps/pydio/docker-compose.yml similarity index 100% rename from apps/pydio/docker-compose.yml rename to archive/apps/pydio/docker-compose.yml diff --git a/apps/pocketbase/src/get_version.sh b/archive/apps/pydio/src/get_version.sh similarity index 100% rename from apps/pocketbase/src/get_version.sh rename to archive/apps/pydio/src/get_version.sh diff --git a/apps/pydio/src/install-conf.yml b/archive/apps/pydio/src/install-conf.yml similarity index 100% rename from apps/pydio/src/install-conf.yml rename to archive/apps/pydio/src/install-conf.yml diff --git a/apps/pydio/variables.json b/archive/apps/pydio/variables.json similarity index 76% rename from apps/pydio/variables.json rename to archive/apps/pydio/variables.json index 10d595378..7abcb8c42 100644 --- a/apps/pydio/variables.json +++ b/archive/apps/pydio/variables.json @@ -11,6 +11,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } + }, "requirements": { "cpu": "1", "memory": "1", diff --git a/apps/ragflow/.env b/archive/apps/ragflow/.env similarity index 100% rename from apps/ragflow/.env rename to archive/apps/ragflow/.env diff --git a/apps/pydio/CHANGELOG.md b/archive/apps/ragflow/CHANGELOG.md similarity index 100% rename from apps/pydio/CHANGELOG.md rename to archive/apps/ragflow/CHANGELOG.md diff --git a/apps/ragflow/Notes.md b/archive/apps/ragflow/Notes.md similarity index 100% rename from apps/ragflow/Notes.md rename to archive/apps/ragflow/Notes.md diff --git a/apps/ragflow/README.md b/archive/apps/ragflow/README.md similarity index 100% rename from apps/ragflow/README.md rename to archive/apps/ragflow/README.md diff --git a/apps/ragflow/docker-compose.yml b/archive/apps/ragflow/docker-compose.yml similarity index 100% rename from apps/ragflow/docker-compose.yml rename to archive/apps/ragflow/docker-compose.yml diff --git a/apps/puter/src/README.md b/archive/apps/ragflow/src/README.md similarity index 100% rename from apps/puter/src/README.md rename to archive/apps/ragflow/src/README.md diff --git a/apps/ragflow/src/entrypoint.sh b/archive/apps/ragflow/src/entrypoint.sh similarity index 100% rename from apps/ragflow/src/entrypoint.sh rename to archive/apps/ragflow/src/entrypoint.sh diff --git a/apps/ragflow/src/infinity_conf.toml b/archive/apps/ragflow/src/infinity_conf.toml similarity index 100% rename from apps/ragflow/src/infinity_conf.toml rename to archive/apps/ragflow/src/infinity_conf.toml diff --git a/apps/ragflow/src/init.sql b/archive/apps/ragflow/src/init.sql similarity index 100% rename from apps/ragflow/src/init.sql rename to archive/apps/ragflow/src/init.sql diff --git a/apps/ragflow/src/nginx/nginx.conf b/archive/apps/ragflow/src/nginx/nginx.conf similarity index 100% rename from apps/ragflow/src/nginx/nginx.conf rename to archive/apps/ragflow/src/nginx/nginx.conf diff --git a/apps/ragflow/src/nginx/proxy.conf b/archive/apps/ragflow/src/nginx/proxy.conf similarity index 100% rename from apps/ragflow/src/nginx/proxy.conf rename to archive/apps/ragflow/src/nginx/proxy.conf diff --git a/apps/ragflow/src/nginx/ragflow.conf b/archive/apps/ragflow/src/nginx/ragflow.conf similarity index 100% rename from apps/ragflow/src/nginx/ragflow.conf rename to archive/apps/ragflow/src/nginx/ragflow.conf diff --git a/apps/ragflow/src/nginx/ragflow.https.conf b/archive/apps/ragflow/src/nginx/ragflow.https.conf similarity index 100% rename from apps/ragflow/src/nginx/ragflow.https.conf rename to archive/apps/ragflow/src/nginx/ragflow.https.conf diff --git a/apps/ragflow/src/service_conf.yaml.template b/archive/apps/ragflow/src/service_conf.yaml.template similarity index 100% rename from apps/ragflow/src/service_conf.yaml.template rename to archive/apps/ragflow/src/service_conf.yaml.template diff --git a/apps/ragflow/variables.json b/archive/apps/ragflow/variables.json similarity index 76% rename from apps/ragflow/variables.json rename to archive/apps/ragflow/variables.json index 8c5366fc6..328e622df 100644 --- a/apps/ragflow/variables.json +++ b/archive/apps/ragflow/variables.json @@ -10,6 +10,13 @@ ] } ], + "access": { + "defaultScheme": "http", + "web": { + "port": 80, + "path": "/" + } + }, "requirements": { "cpu": "4", "memory": "16", diff --git a/apps/rethinkdb/.env b/archive/apps/rethinkdb/.env similarity index 100% rename from apps/rethinkdb/.env rename to archive/apps/rethinkdb/.env diff --git a/apps/ragflow/CHANGELOG.md b/archive/apps/rethinkdb/CHANGELOG.md similarity index 100% rename from apps/ragflow/CHANGELOG.md rename to archive/apps/rethinkdb/CHANGELOG.md diff --git a/apps/rethinkdb/Notes.md b/archive/apps/rethinkdb/Notes.md similarity index 100% rename from apps/rethinkdb/Notes.md rename to archive/apps/rethinkdb/Notes.md diff --git a/apps/rethinkdb/README.md b/archive/apps/rethinkdb/README.md similarity index 100% rename from apps/rethinkdb/README.md rename to archive/apps/rethinkdb/README.md diff --git a/apps/rethinkdb/docker-compose.yml b/archive/apps/rethinkdb/docker-compose.yml similarity index 100% rename from apps/rethinkdb/docker-compose.yml rename to archive/apps/rethinkdb/docker-compose.yml diff --git a/apps/rethinkdb/src/get_version.sh b/archive/apps/rethinkdb/src/get_version.sh similarity index 100% rename from apps/rethinkdb/src/get_version.sh rename to archive/apps/rethinkdb/src/get_version.sh diff --git a/apps/rethinkdb/variables.json b/archive/apps/rethinkdb/variables.json similarity index 100% rename from apps/rethinkdb/variables.json rename to archive/apps/rethinkdb/variables.json diff --git a/apps/rocketchat/.env b/archive/apps/rocketchat/.env similarity index 100% rename from apps/rocketchat/.env rename to archive/apps/rocketchat/.env diff --git a/apps/rethinkdb/CHANGELOG.md b/archive/apps/rocketchat/CHANGELOG.md similarity index 100% rename from apps/rethinkdb/CHANGELOG.md rename to archive/apps/rocketchat/CHANGELOG.md diff --git a/apps/rocketchat/Notes.md b/archive/apps/rocketchat/Notes.md similarity index 100% rename from apps/rocketchat/Notes.md rename to archive/apps/rocketchat/Notes.md diff --git a/apps/rocketchat/README.md b/archive/apps/rocketchat/README.md similarity index 100% rename from apps/rocketchat/README.md rename to archive/apps/rocketchat/README.md diff --git a/apps/rocketchat/docker-compose.yml b/archive/apps/rocketchat/docker-compose.yml similarity index 100% rename from apps/rocketchat/docker-compose.yml rename to archive/apps/rocketchat/docker-compose.yml diff --git a/apps/rocketchat/src/get_version.sh b/archive/apps/rocketchat/src/get_version.sh similarity index 100% rename from apps/rocketchat/src/get_version.sh rename to archive/apps/rocketchat/src/get_version.sh diff --git a/apps/rocketchat/variables.json b/archive/apps/rocketchat/variables.json similarity index 100% rename from apps/rocketchat/variables.json rename to archive/apps/rocketchat/variables.json diff --git a/apps/ruby/.env b/archive/apps/ruby/.env similarity index 100% rename from apps/ruby/.env rename to archive/apps/ruby/.env diff --git a/apps/rocketchat/CHANGELOG.md b/archive/apps/ruby/CHANGELOG.md similarity index 100% rename from apps/rocketchat/CHANGELOG.md rename to archive/apps/ruby/CHANGELOG.md diff --git a/apps/ruby/Notes.md b/archive/apps/ruby/Notes.md similarity index 100% rename from apps/ruby/Notes.md rename to archive/apps/ruby/Notes.md diff --git a/apps/ruby/README.md b/archive/apps/ruby/README.md similarity index 100% rename from apps/ruby/README.md rename to archive/apps/ruby/README.md diff --git a/apps/ruby/docker-compose.yml b/archive/apps/ruby/docker-compose.yml similarity index 100% rename from apps/ruby/docker-compose.yml rename to archive/apps/ruby/docker-compose.yml diff --git a/apps/ragflow/src/README.md b/archive/apps/ruby/src/README.md similarity index 100% rename from apps/ragflow/src/README.md rename to archive/apps/ruby/src/README.md diff --git a/apps/ruby/src/cmd.sh b/archive/apps/ruby/src/cmd.sh similarity index 100% rename from apps/ruby/src/cmd.sh rename to archive/apps/ruby/src/cmd.sh diff --git a/apps/ruby/variables.json b/archive/apps/ruby/variables.json similarity index 79% rename from apps/ruby/variables.json rename to archive/apps/ruby/variables.json index 78adc634b..08db2fcee 100644 --- a/apps/ruby/variables.json +++ b/archive/apps/ruby/variables.json @@ -24,5 +24,12 @@ }, "upstream": { "image": "https://hub.docker.com/_/ruby" + }, + "access": { + "defaultScheme": "http", + "web": { + "port": 8080, + "path": "/" + } } } diff --git a/cli/libs/__pycache__/app_tests.cpython-312.pyc b/cli/libs/__pycache__/app_tests.cpython-312.pyc index 7708641ac..2df3e2d98 100644 Binary files a/cli/libs/__pycache__/app_tests.cpython-312.pyc and b/cli/libs/__pycache__/app_tests.cpython-312.pyc differ diff --git a/cli/libs/__pycache__/dblifecycle.cpython-312.pyc b/cli/libs/__pycache__/dblifecycle.cpython-312.pyc index e7a8dde0e..6cf5966bd 100644 Binary files a/cli/libs/__pycache__/dblifecycle.cpython-312.pyc and b/cli/libs/__pycache__/dblifecycle.cpython-312.pyc differ diff --git a/cli/libs/__pycache__/main.cpython-312.pyc b/cli/libs/__pycache__/main.cpython-312.pyc index a5ff0f37c..f2e4f22f3 100644 Binary files a/cli/libs/__pycache__/main.cpython-312.pyc and b/cli/libs/__pycache__/main.cpython-312.pyc differ diff --git a/cli/libs/__pycache__/validate.cpython-312.pyc b/cli/libs/__pycache__/validate.cpython-312.pyc index 78ee8e54b..51e37cccc 100644 Binary files a/cli/libs/__pycache__/validate.cpython-312.pyc and b/cli/libs/__pycache__/validate.cpython-312.pyc differ diff --git a/cli/libs/app_tests.py b/cli/libs/app_tests.py index d420f3f57..d2b58459d 100644 --- a/cli/libs/app_tests.py +++ b/cli/libs/app_tests.py @@ -81,13 +81,21 @@ def load_env(app_name: str) -> dict: return resolved -def _base_url(env: dict, explicit: str | None, ssh_host: str | None) -> str | None: +def _target_mode(target: str | None, ssh_host: str | None) -> str: + if target: + return target + if ssh_host: + return "remote" + return remote.default_target() + + +def _base_url(env: dict, explicit: str | None, target: str, ssh_host: str | None) -> str | None: if explicit: return explicit.rstrip("/") port = env.get("W9_HTTP_PORT_SET") if not port: return None - resolved_ssh_host = ssh_host or (remote.ssh_host() if remote.default_target() == "remote" else None) + resolved_ssh_host = ssh_host or (remote.ssh_host() if target == "remote" else None) if resolved_ssh_host: return f"http://{resolved_ssh_host}:{port}" return f"http://localhost:{port}" @@ -190,8 +198,15 @@ def _wait_for(wait_timeout: int, wait_interval: int, attempt: Callable[[], dict] return last -def _remote_context(app_name: str, ssh_host: str | None, ssh_user: str | None, ssh_secret_path: str | None, deploy_root: str | None) -> dict | None: - resolved_host = ssh_host or (remote.ssh_host() if remote.default_target() == "remote" else None) +def _remote_context( + app_name: str, + target: str, + ssh_host: str | None, + ssh_user: str | None, + ssh_secret_path: str | None, + deploy_root: str | None, +) -> dict | None: + resolved_host = ssh_host or (remote.ssh_host() if target == "remote" else None) if not resolved_host: return None secret_path = remote.resolve_secret_path(ssh_secret_path) @@ -326,6 +341,7 @@ def _default_cases(env: dict, compose: dict, base_url: str | None, app_name: str def run_app_tests( app_name: str, base_url: str | None = None, + target: str | None = None, ssh_host: str | None = None, ssh_user: str | None = None, ssh_secret_path: str | None = None, @@ -338,8 +354,9 @@ def run_app_tests( env = load_env(app_name) cases = load_cases(app_name) compose = load_compose(app_name) - resolved_base_url = _base_url(env, base_url, ssh_host) - remote_ctx = _remote_context(app_name, ssh_host, ssh_user, ssh_secret_path, deploy_root) + mode = _target_mode(target, ssh_host) + resolved_base_url = _base_url(env, base_url, mode, ssh_host) + remote_ctx = _remote_context(app_name, mode, ssh_host, ssh_user, ssh_secret_path, deploy_root) skip_ids = {item["id"] for item in (cases.get("skip") or [])} results = [] @@ -422,7 +439,7 @@ def attempt() -> dict: return { "app": app_name, "base_url": resolved_base_url, - "target": "remote" if remote_ctx else "local", + "target": mode, "ok": all(item.get("ok") for item in results), "results": results, } diff --git a/cli/libs/dblifecycle.py b/cli/libs/dblifecycle.py index da620398e..6d50182f1 100644 --- a/cli/libs/dblifecycle.py +++ b/cli/libs/dblifecycle.py @@ -16,6 +16,7 @@ "postgresql": lambda lts: "stable", "clickhouse": lambda lts: "lts" if lts else "stable", "redis": lambda lts: "stable", + "mongodb": lambda lts: "lts" if lts else "stable", } diff --git a/cli/libs/main.py b/cli/libs/main.py index 630579189..a7a1dcd20 100644 --- a/cli/libs/main.py +++ b/cli/libs/main.py @@ -894,6 +894,7 @@ def dns_delete_command( def app_tests_command( app_name: str = typer.Option(..., "--app", help="App name"), base_url: str | None = typer.Option(None, "--base-url", help="Override the base URL used by web checks"), + target: str | None = typer.Option(None, "--target", help="local | remote"), ssh_host: str | None = typer.Option(None, "--ssh-host", help="Remote host IP or name"), ssh_user: str | None = typer.Option(None, "--ssh-user", help="Remote SSH user (default root)"), ssh_secret_path: str | None = typer.Option(None, "--ssh-secret-path", help="SSH secret path (key or password file)"), @@ -909,6 +910,7 @@ def app_tests_command( payload = app_tests.run_app_tests( app_name, base_url=base_url, + target=target, ssh_host=ssh_host, ssh_user=ssh_user, ssh_secret_path=ssh_secret_path, diff --git a/cli/libs/validate.py b/cli/libs/validate.py index 39e14ea29..ff9a01a01 100644 --- a/cli/libs/validate.py +++ b/cli/libs/validate.py @@ -144,6 +144,12 @@ def _policy_result(target: Path) -> dict: dependency_tag_policy_ok = not dependency_patch_tags access_missing_ports = [] + secrets_declared: list[str] = [] + secrets_missing: list[str] = [] + secrets_empty: list[str] = [] + setup_missing_access: list[dict] = [] + setup_missing_services: list[dict] = [] + setup_duplicate_ids: list[str] = [] variables_path = target / "variables.json" if variables_path.exists(): try: @@ -151,13 +157,46 @@ def _policy_result(target: Path) -> dict: except json.JSONDecodeError: variables = {} container_ports = _compose_container_ports(compose) + compose_services = set((compose.get("services") or {}).keys()) + access_keys = set((variables.get("access") or {}).keys()) for key, entry in (variables.get("access") or {}).items(): if not isinstance(entry, dict): continue port = entry.get("port") if isinstance(port, int) and port not in container_ports: access_missing_ports.append({"key": key, "port": port}) + for name in (variables.get("env") or {}).get("secrets") or []: + if not isinstance(name, str): + continue + secrets_declared.append(name) + if name not in env_map: + secrets_missing.append(name) + elif env_map[name].strip().strip("'\"").strip() == "": + secrets_empty.append(name) + seen_setup_ids: set[str] = set() + for step in (variables.get("setup") or {}).get("steps") or []: + if not isinstance(step, dict): + continue + step_id = step.get("id") + if isinstance(step_id, str): + if step_id in seen_setup_ids: + setup_duplicate_ids.append(step_id) + seen_setup_ids.add(step_id) + action = step.get("action") + if not isinstance(action, dict): + continue + action_type = action.get("type") + if action_type == "open": + access_key = action.get("access") + if isinstance(access_key, str) and access_key not in access_keys: + setup_missing_access.append({"step": step_id, "access": access_key}) + if action_type == "show-log": + service = action.get("service") + if isinstance(service, str) and service not in compose_services: + setup_missing_services.append({"step": step_id, "service": service}) access_ports_ok = not access_missing_ports + secrets_ok = not secrets_missing and not secrets_empty + setup_ok = not setup_missing_access and not setup_missing_services and not setup_duplicate_ids ok = ( not missing_translation @@ -167,6 +206,8 @@ def _policy_result(target: Path) -> dict: and url_replace_required_ok and dependency_tag_policy_ok and access_ports_ok + and secrets_ok + and setup_ok ) return { "ok": ok, @@ -180,6 +221,14 @@ def _policy_result(target: Path) -> dict: "dependency_tag_policy_ok": dependency_tag_policy_ok, "access_ports_ok": access_ports_ok, "access_missing_ports": access_missing_ports, + "secrets_ok": secrets_ok, + "secrets_declared": secrets_declared, + "secrets_missing": secrets_missing, + "secrets_empty": secrets_empty, + "setup_ok": setup_ok, + "setup_missing_access": setup_missing_access, + "setup_missing_services": setup_missing_services, + "setup_duplicate_ids": setup_duplicate_ids, } diff --git a/cli/tests/__pycache__/test_app.cpython-312-pytest-9.1.1.pyc b/cli/tests/__pycache__/test_app.cpython-312-pytest-9.1.1.pyc index 0dd4cc4d5..3347ca2c6 100644 Binary files a/cli/tests/__pycache__/test_app.cpython-312-pytest-9.1.1.pyc and b/cli/tests/__pycache__/test_app.cpython-312-pytest-9.1.1.pyc differ diff --git a/cli/tests/__pycache__/test_app_tests.cpython-312-pytest-9.1.1.pyc b/cli/tests/__pycache__/test_app_tests.cpython-312-pytest-9.1.1.pyc index c32936c15..b86beffe8 100644 Binary files a/cli/tests/__pycache__/test_app_tests.cpython-312-pytest-9.1.1.pyc and b/cli/tests/__pycache__/test_app_tests.cpython-312-pytest-9.1.1.pyc differ diff --git a/cli/tests/__pycache__/test_consistency.cpython-312-pytest-9.1.1.pyc b/cli/tests/__pycache__/test_consistency.cpython-312-pytest-9.1.1.pyc index 04b446d4d..8226a2ff6 100644 Binary files a/cli/tests/__pycache__/test_consistency.cpython-312-pytest-9.1.1.pyc and b/cli/tests/__pycache__/test_consistency.cpython-312-pytest-9.1.1.pyc differ diff --git a/cli/tests/__pycache__/test_main.cpython-312-pytest-9.1.1.pyc b/cli/tests/__pycache__/test_main.cpython-312-pytest-9.1.1.pyc index f2c36c8af..fe9178b70 100644 Binary files a/cli/tests/__pycache__/test_main.cpython-312-pytest-9.1.1.pyc and b/cli/tests/__pycache__/test_main.cpython-312-pytest-9.1.1.pyc differ diff --git a/cli/tests/__pycache__/test_validate.cpython-312-pytest-9.1.1.pyc b/cli/tests/__pycache__/test_validate.cpython-312-pytest-9.1.1.pyc index 890b68999..3065b82df 100644 Binary files a/cli/tests/__pycache__/test_validate.cpython-312-pytest-9.1.1.pyc and b/cli/tests/__pycache__/test_validate.cpython-312-pytest-9.1.1.pyc differ diff --git a/cli/tests/test_app_tests.py b/cli/tests/test_app_tests.py index 96c5d8792..1138b1887 100644 --- a/cli/tests/test_app_tests.py +++ b/cli/tests/test_app_tests.py @@ -111,9 +111,10 @@ def test_app_tests_cli_contract(monkeypatch): monkeypatch.setattr( app_tests, "run_app_tests", - lambda app_name=None, base_url=None, ssh_host=None, ssh_user=None, ssh_secret_path=None, deploy_root=None, wait_timeout=60, wait_interval=5, progress=None, verbose=False: { + lambda app_name=None, base_url=None, target=None, ssh_host=None, ssh_user=None, ssh_secret_path=None, deploy_root=None, wait_timeout=60, wait_interval=5, progress=None, verbose=False: { "app": app_name, "base_url": base_url, + "target": target or "local", "ok": True, "results": [], }, @@ -127,6 +128,23 @@ def test_app_tests_cli_contract(monkeypatch): assert payload["base_url"] == "http://localhost:8080" +def test_app_tests_cli_forwards_target(monkeypatch): + calls = {} + + def fake_run_app_tests(app_name=None, **kwargs): + calls["app_name"] = app_name + calls.update(kwargs) + return {"app": app_name, "target": kwargs.get("target") or "local", "ok": True, "results": []} + + monkeypatch.setattr(app_tests, "run_app_tests", fake_run_app_tests) + + result = runner.invoke(main.app, ["app-tests", "--app", "demo", "--target", "local", "--json"]) + + assert result.exit_code == 0 + assert calls["app_name"] == "demo" + assert calls["target"] == "local" + + def test_app_tests_cli_forwards_wait_options(monkeypatch): calls = {} @@ -286,7 +304,7 @@ def test_remote_context_accepts_legacy_remote_path_profile(repo_fixture, app_fac encoding="utf-8", ) - remote_ctx = app_tests._remote_context("demo", None, None, None, None) + remote_ctx = app_tests._remote_context("demo", "remote", None, None, None, None) assert remote_ctx is not None assert remote_ctx["app_target"] == "/legacy/apps/demo" @@ -315,6 +333,7 @@ def fake_run_app_tests(app_name=None, **kwargs): main.app_tests_command( app_name="demo", base_url=None, + target=None, ssh_host=None, ssh_user=None, ssh_secret_path=None, @@ -330,6 +349,27 @@ def fake_run_app_tests(app_name=None, **kwargs): ] +def test_run_app_tests_target_local_ignores_remote_default(repo_fixture, app_factory, monkeypatch): + app_factory("demo", env="W9_HTTP_PORT_SET=8080\nW9_ID=demo\n") + + monkeypatch.setattr(app_tests.remote, "default_target", lambda: "remote") + monkeypatch.setattr(app_tests.remote, "ssh_host", lambda value=None: value or "1.2.3.4") + + def fake_run(command): + if command[:2] == ["docker", "ps"]: + return types.SimpleNamespace(returncode=0, stdout="demo Up\n", stderr="") + return types.SimpleNamespace(returncode=0, stdout="", stderr="") + + monkeypatch.setattr(app_tests, "_run_subprocess", fake_run) + monkeypatch.setattr(app_tests.requests, "get", lambda *args, **kwargs: DummyResponse(200, url=args[0])) + + payload = app_tests.run_app_tests("demo", target="local") + + assert payload["ok"] is True + assert payload["target"] == "local" + assert payload["base_url"] == "http://localhost:8080" + + def test_run_app_tests_remote_progress_starts_with_connectivity_check(repo_fixture, app_factory, monkeypatch): app_factory("demo", env="W9_HTTP_PORT_SET=8080\nW9_ID=demo\n") secret_path = repo_fixture / ".secrets" / "ssh" / "default.pem" diff --git a/cli/tests/test_consistency.py b/cli/tests/test_consistency.py index e915d79e9..614d9b600 100644 --- a/cli/tests/test_consistency.py +++ b/cli/tests/test_consistency.py @@ -114,6 +114,127 @@ def test_new_app_schema_accepts_sample_request(): jsonschema.Draft202012Validator(schema).validate(sample) +def test_variables_schema_accepts_env_secrets(): + schema = json.loads((REPO_ROOT / "metadata" / "variables.schema.json").read_text(encoding="utf-8")) + sample = { + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "env": {"secrets": ["APP_KEY", "OH_KEY"], "first_startup_only": ["APP_KEY"]}, + } + + jsonschema.Draft202012Validator(schema).validate(sample) + + +def test_variables_schema_rejects_unknown_env_keys(): + import pytest + + schema = json.loads((REPO_ROOT / "metadata" / "variables.schema.json").read_text(encoding="utf-8")) + sample = { + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "env": {"rules": ["APP_KEY"]}, + } + + with pytest.raises(jsonschema.ValidationError): + jsonschema.Draft202012Validator(schema).validate(sample) + + +def test_variables_schema_accepts_setup_steps(): + schema = json.loads((REPO_ROOT / "metadata" / "variables.schema.json").read_text(encoding="utf-8")) + sample = { + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "access": {"web": {"port": 8080, "path": "/"}}, + "setup": { + "summary": "Bootstrap this app first.", + "steps": [ + { + "id": "setup-token", + "text": "Read the one-time token from logs.", + "action": {"type": "show-log", "service": "app", "tail": 50}, + }, + { + "id": "setup-wizard", + "text": "Open the setup screen.", + "action": {"type": "open", "access": "web", "path": "/setup"}, + }, + ], + }, + } + + jsonschema.Draft202012Validator(schema).validate(sample) + + +def test_variables_schema_rejects_setup_pattern_group_model(): + import pytest + + schema = json.loads((REPO_ROOT / "metadata" / "variables.schema.json").read_text(encoding="utf-8")) + sample = { + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "setup": { + "steps": [ + { + "id": "setup-token", + "text": "Bad old pattern model.", + "action": { + "type": "show-log", + "service": "app", + "pattern": "token=(.+)", + "group": 1, + }, + } + ] + }, + } + + with pytest.raises(jsonschema.ValidationError): + jsonschema.Draft202012Validator(schema).validate(sample) + + +def test_repository_variables_json_match_schema(): + schema = json.loads((REPO_ROOT / "metadata" / "variables.schema.json").read_text(encoding="utf-8")) + validator = jsonschema.Draft202012Validator(schema) + problems: dict[str, list[str]] = {} + for variables_path in sorted((REPO_ROOT / "apps").glob("*/variables.json")): + data = json.loads(variables_path.read_text(encoding="utf-8")) + errors = sorted(validator.iter_errors(data), key=lambda e: list(e.path)) + if errors: + problems[variables_path.parent.name] = [ + f"{'/'.join(map(str, e.path)) or ''}: {e.message}" for e in errors + ] + assert problems == {}, f"apps with variables.json schema violations: {problems}" + + +def test_declared_env_secrets_exist_in_dotenv(): + from libs.drift import parse_env_file + + problems: dict[str, list[str]] = {} + for variables_path in sorted((REPO_ROOT / "apps").glob("*/variables.json")): + data = json.loads(variables_path.read_text(encoding="utf-8")) + secrets = (data.get("env") or {}).get("secrets") or [] + if not secrets: + continue + env_path = variables_path.parent / ".env" + env = parse_env_file(env_path) if env_path.exists() else {} + missing = [name for name in secrets if name not in env] + if missing: + problems[variables_path.parent.name] = missing + assert problems == {}, f"apps declare env.secrets missing from .env: {problems}" + + def test_repository_variables_json_have_consistent_shapes(): for variables_path in sorted((REPO_ROOT / "apps").glob("*/variables.json")): data = json.loads(variables_path.read_text(encoding="utf-8")) diff --git a/cli/tests/test_validate.py b/cli/tests/test_validate.py index 836bd20ca..c8155ae63 100644 --- a/cli/tests/test_validate.py +++ b/cli/tests/test_validate.py @@ -189,6 +189,135 @@ def test_policy_result_accepts_access_port_present_in_compose(repo_fixture, app_ assert result["access_missing_ports"] == [] +def test_policy_result_requires_declared_secrets_present_and_non_empty(repo_fixture, app_factory): + app_path = app_factory( + "demo", + env="APP_KEY=secretvalue\nEMPTY_KEY=\n", + variables={ + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "env": {"secrets": ["APP_KEY", "MISSING_KEY", "EMPTY_KEY"]}, + }, + ) + + result = validate._policy_result(app_path) + + assert result["ok"] is False + assert result["secrets_ok"] is False + assert result["secrets_declared"] == ["APP_KEY", "MISSING_KEY", "EMPTY_KEY"] + assert result["secrets_missing"] == ["MISSING_KEY"] + assert result["secrets_empty"] == ["EMPTY_KEY"] + + +def test_policy_result_accepts_declared_secrets_with_values(repo_fixture, app_factory): + app_path = app_factory( + "demo", + env="APP_KEY=secretvalue\nOH_KEY=anothervalue\n", + variables={ + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "env": {"secrets": ["APP_KEY", "OH_KEY"]}, + }, + ) + + result = validate._policy_result(app_path) + + assert result["ok"] is True + assert result["secrets_ok"] is True + assert result["secrets_missing"] == [] + assert result["secrets_empty"] == [] + + +def test_policy_result_flags_invalid_setup_access_service_and_duplicate_ids(repo_fixture, app_factory): + app_path = app_factory( + "demo", + compose=( + "services:\n" + " app:\n" + " ports:\n" + ' - "${W9_HTTP_PORT_SET}:8080"\n' + ), + variables={ + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "access": {"web": {"port": 8080, "path": "/"}}, + "setup": { + "steps": [ + { + "id": "setup-token", + "text": "Read logs.", + "action": {"type": "show-log", "service": "missing", "tail": 50}, + }, + { + "id": "setup-token", + "text": "Open setup.", + "action": {"type": "open", "access": "admin", "path": "/setup"}, + }, + ] + }, + }, + ) + + result = validate._policy_result(app_path) + + assert result["ok"] is False + assert result["setup_ok"] is False + assert result["setup_missing_services"] == [{"step": "setup-token", "service": "missing"}] + assert result["setup_missing_access"] == [{"step": "setup-token", "access": "admin"}] + assert result["setup_duplicate_ids"] == ["setup-token"] + + +def test_policy_result_accepts_valid_setup_steps(repo_fixture, app_factory): + app_path = app_factory( + "demo", + compose=( + "services:\n" + " app:\n" + " ports:\n" + ' - "${W9_HTTP_PORT_SET}:8080"\n' + ), + variables={ + "name": "demo", + "trademark": "Demo", + "release": True, + "edition": [{"dist": "community", "version": ["1.0"]}], + "requirements": {"cpu": "1", "memory": "1", "disk": "1"}, + "access": {"web": {"port": 8080, "path": "/"}}, + "setup": { + "steps": [ + { + "id": "setup-token", + "text": "Read logs.", + "action": {"type": "show-log", "service": "app", "tail": 50}, + }, + { + "id": "setup-wizard", + "text": "Open setup.", + "action": {"type": "open", "access": "web", "path": "/setup"}, + }, + ] + }, + }, + ) + + result = validate._policy_result(app_path) + + assert result["ok"] is True + assert result["setup_ok"] is True + assert result["setup_missing_services"] == [] + assert result["setup_missing_access"] == [] + assert result["setup_duplicate_ids"] == [] + + def test_check_app_returns_gate_specific_payload(repo_fixture, app_factory): app_factory("demo") diff --git a/docs/appstore-release-spec.md b/docs/appstore-release-spec.md index dbc2ed4df..2ebeda391 100644 --- a/docs/appstore-release-spec.md +++ b/docs/appstore-release-spec.md @@ -31,6 +31,8 @@ - 每个 key 一条单句字符串 - 若个别版本要求不同,在同一句话中注明,例如 `MySQL 8.0+ (7.0+ requires 8.4+)` - 不做版本键控对象,避免额外维护负担 +- 复杂登录(例如必须先完成一次性初始化、再使用固定账号密码)**必须**声明 `help.login`,且界面应把它展示在凭据区**之上**,让用户先阅读说明再登录 +- `help.login` 不可省略:凭据区只展示最终账号密码,缺少 `help.login` 时用户不知道还存在初始化步骤 ### 凭据获取元数据 @@ -38,6 +40,7 @@ - `credentials` 不是人类文案;它是消费端执行固定逻辑时读取的结构化声明 - `credentials` 不替代 `.env` 中已有的字面值凭据;若 `W9_LOGIN_PASSWORD` 本身就是固定值,仍直接使用 `.env` +- 复杂登录(一次性初始化 + 固定终态账号):`.env` 的 `W9_LOGIN_USER` / `W9_LOGIN_PASSWORD` 供当前前端渲染,同时用 `variables.json.credentials`(如 `container-env` 指向 `W9_LOGIN_PASSWORD`)供 machine-readable 消费端与未来渲染;并配置 `help.login` 说明初始化步骤,不要用 `container-log` + 易变 `pattern` 去解析一次性密码 - `credentials` 仅描述“凭据从哪里取”,不允许在仓库中写任意宿主级 shell 当前约定支持 3 个固定槽位:`username`、`password`、`token`。每个槽位都声明“值从哪里来”的 source。 @@ -131,6 +134,144 @@ } ``` +### 声明式 Secret(`env.secrets`) + +有些应用在启动前就需要一组**明文 secret**(典型来源是 `.env`,并在 `docker compose up` 之前注入)。`credentials` 只解决“部署后从哪里读回凭据”,解决不了“启动前先有值”。为此 `variables.json` 提供 `env.secrets`。 + +它**只声明名字,不声明任何生成规则**: + +```json +{ + "env": { + "secrets": ["LOCAL_BACKEND_API_KEY", "OH_SECRET_KEY"] + } +} +``` + +语义(固定,不随应用变化): + +- `.env` 里为每个声明名提供一个**明文默认值**,该默认值同时充当“形状模板”。 +- 消费端(AppOS/Console)可以在**创建实例时**生成、或在界面上由用户触发**“重新生成”**,用新值覆盖实例 `.env`。 +- **重建 / redeploy 绝不自动重算**,否则每次 `up` 都会更换密钥,导致数据或加密失效。 +- 生成规则只有一条:**产出与当前值同形状(同长度、同字符类)的随机串**。因此不提供 length/charset 规则。 +- 生成结果必须能安全放进 `.env`/compose:**不得包含 `$`、空格、`#`、换行**(`$` 会触发 compose 插值)。默认使用 `alnum` 或 `base64url`(去掉 `=`)。 +- 默认值是**占位/形状模板,不是生产密钥**,可以进 git;规范要求默认值本身必须形状正确且接近生产强度。 + +`W9_POWER_PASSWORD` 是这套机制的**单值特例**,等价于: + +```json +{ "env": { "secrets": ["W9_POWER_PASSWORD"] } } +``` + +因此已有使用 `W9_POWER_PASSWORD` 的应用无需迁移;需要**多个、形状不同**的 secret 时,改用 `env.secrets` 列多个名字即可。 + +校验规则(`libs app-check --gate policy`): + +- `env.secrets` 中每个名字都必须真实存在于该应用的 `.env` +- 每个名字的默认值不得为空 + +非目标: + +- 不引入 per-secret 的 length/charset/pattern 规则,也不引入模板语言 +- 格式极端(校验位、派生、特定编码)的 secret 仍由应用包内生成(init/entrypoint),不进 `env.secrets` + +示例(`openhands`): + +`.env` + +```env +LOCAL_BACKEND_API_KEY=Kx7Qm2TpR9wZb4HnV1sLc6Dg0Fj3YaQd +OH_SECRET_KEY=Pv5Rt8Wy2Nk7Mc4Xb1Lz6Df0Gh3Jq9Ue +``` + +`variables.json` + +```json +{ + "env": { + "secrets": ["LOCAL_BACKEND_API_KEY", "OH_SECRET_KEY"] + } +} +``` + +### 登录前步骤(`setup.steps`) + +有些应用在最终登录之前,必须先完成一组前置动作,例如:查看容器日志中的一次性 token、 +读取容器文件中的初始化密码、执行官方只读 CLI 查看 bootstrap 信息、或者打开初始化向导。 + +为此 `variables.json` 提供 `setup` 对象: + +```json +{ + "setup": { + "summary": "可选,总说明", + "steps": [ + { + "id": "setup-token", + "text": "先查看容器日志,复制其中的一次性 setup token。", + "action": { + "type": "show-log", + "service": "portainer", + "tail": 50 + } + }, + { + "id": "setup-wizard", + "text": "打开页面并完成初始化向导。", + "action": { + "type": "open", + "access": "web" + } + } + ] + } +} +``` + +前端渲染顺序: + +- `setup` 区域必须显示在 login / credentials 区域之前 +- `setup.summary` 为整体摘要,可省略 +- `setup.steps[].text` 为每一步的人类说明 + +`action` 的 v1 支持范围(封闭词汇): + +- `show-log`: 展示某个 compose service 的容器日志原文;字段:`service`,可选 `tail` +- `show-env`: 展示容器运行环境中的某个变量;字段:`name` +- `show-file`: 展示容器内文件或从结构化文件读值;字段:`path`,可选 `format=text|json|env`,以及 `jsonPath` / `key` +- `show-cli`: 执行容器内官方只读 CLI 并展示输出;字段:`argv`,可选 `format=text|json|env`,以及 `jsonPath` / `key` +- `open`: 打开应用入口;字段:`access`,可选 `path` + +容器目标规则: + +- `show-env` / `show-file` / `show-cli` 默认作用于主应用容器(即 `${W9_ID}`),与现有 `credentials` 的读取规则保持一致 +- `show-log` 因为日志通常需要区分 compose service,所以显式声明 `service` + +`open` 与 `access` 的统一规则: + +- `open` 不再自己定义 host / port / scheme +- `access` 必须引用 `variables.json.access` 中已有键(如 `web` / `admin` / `api`) +- 最终 URL 的 scheme / port 来自 `access[]` +- 若声明了 `action.path`,它覆盖该 access 的默认 path;否则使用 `access[].path`(缺省视为 `/`) + +边界与非目标: + +- 不支持 `pattern` / `group` +- 不支持任意 shell,不支持宿主命令 +- 不支持自动执行有副作用的命令;v1 只负责渲染说明、展示值、打开页面 +- 不支持条件分支、多结果工作流或状态机 + +与 `credentials` 的职责分工: + +- `setup`:登录前需要看到或完成的临时/初始化信息 +- `credentials`:最终登录时要使用的 username / password / token + +迁移建议: + +- 现有 `credentials.container-log` + `pattern` / `group` 保留兼容 +- 新 app 或被触达的 app,如果日志中的值只是 setup token / bootstrap 信息,优先改用 `setup.steps[].action.type=show-log` +- `help.login` 继续保留,用来描述 setup 完成后的最终登录方式 + ### 职责边界 | 本项目负责 | 本项目不负责 | diff --git a/docs/upstream-spec.md b/docs/upstream-spec.md index 4a8c47861..e039ec889 100644 --- a/docs/upstream-spec.md +++ b/docs/upstream-spec.md @@ -320,9 +320,21 @@ Rules: - Use `scheme: https` when the package default entry is HTTPS-only or when the documented default access expects HTTPS first. - Surface keys are a closed vocabulary: - `web` (end-user UI), `admin` (privileged console), `api` (programmatic API), + `web` (primary browser entry), `admin` (additional management entry), `api` (programmatic API), `ws` (WebSocket), `ssh` (shell), `metrics` (monitoring). Add a custom key only when none applies, and document its meaning. +- `web` and `admin` describe the role of an entry, not the privilege level at the path. + - The primary browser entry is always `web`, even when its path is not `/`. A unique + entry such as `/admin`, `/console`, `/app`, or `/web/login` is still `web`. + - `admin` is only for an additional management entry that is distinct from `web` and + worth exposing on its own, for example `/wp-admin`, `/umbraco`, `/_utils`, `/dashboard/`. + - Do not declare `admin` merely because the entry requires login, is called `admin`, or + is the only entry. +- Default binding rule: the primary URL binding is `web` by convention. Extra bindings + also default to `web` when they are browser entries. Non-browser surfaces such as + `api`, `ws`, `ssh`, and `metrics` must be declared explicitly and never default to `web`. + The default applies to the surface role only; `port`, `path`, and `scheme` still have to + be declared. - A surface may override `defaultScheme` with its own `scheme` (for example `wss` for a WebSocket surface, or `ssh` for a shell surface). - `path` and `port` keep their existing meaning per surface. diff --git a/docs/w9-env-spec.md b/docs/w9-env-spec.md index 146cc4ece..9a692a9fb 100644 --- a/docs/w9-env-spec.md +++ b/docs/w9-env-spec.md @@ -137,6 +137,26 @@ Rules: - do not keep dead helper variables in `.env` - if the upstream has no package-controlled credential flow, omit these keys +### Declared Secrets + +When a package must ship several plain-text secrets that are injected before `docker compose up` +(shared across services, or needed by the UI at login), list their `.env` key names in +`variables.json`: + +```json +{ "env": { "secrets": ["LOCAL_BACKEND_API_KEY", "OH_SECRET_KEY"] } } +``` + +Rules: + +- declare names only; there are no per-secret length/charset/pattern rules +- each declared name must exist in `.env` with a non-empty plain-text default; that default is the + shape template, not a production secret +- consumers may regenerate a same-shaped value and overwrite the instance `.env`; redeploy must never + auto-rotate it +- `W9_POWER_PASSWORD` is the single-value special case of this mechanism +- the canonical consumer contract lives in `docs/appstore-release-spec.md` + ### Dependency Modeling | Variable | Meaning | Typical use | @@ -310,6 +330,25 @@ Examples: - no: apps that create the first admin interactively in the browser - no: apps with no built-in auth +### Complex Or Multi-Stage Login + +Some apps log in in two stages: a one-time bootstrap credential (often generated at first startup and +shown only in the container logs) followed by a fixed account that the package controls. Treat this as a +complex login: + +- keep the fixed final credential in `.env` as `W9_LOGIN_USER` and `W9_LOGIN_PASSWORD`; the current + front end renders these directly +- also declare the same fixed credential in `variables.json.credentials` for machine-readable consumers + and future rendering; point `credentials.password` at `W9_LOGIN_PASSWORD` with `source=container-env` + instead of copying the literal value, so it follows `.env` +- when the app requires structured pre-login steps (for example, read a setup token from logs and then + open a wizard), declare `variables.json.setup.steps`; the front end renders setup before the login area +- keep `variables.json.help.login` as the final sign-in note shown with the rendered credentials +- `help.login` is required for a complex login, not optional: the credential area only shows the final + account and password, so without it users do not know which account works after setup +- for setup tokens or one-time bootstrap values printed in logs, prefer `setup.steps[].action.type=show-log` + over `credentials.container-log` with `pattern` / `group`; the former is simpler and more stable + ## Translation Rule Keys requiring entries in `i18n/translation.json`: diff --git a/i18n/translation.json b/i18n/translation.json index 944f0a061..0ad027aaf 100644 --- a/i18n/translation.json +++ b/i18n/translation.json @@ -135,6 +135,10 @@ "", "" ], + "W9_LOGIN_MYSQL_CONNECTION_STRING_PASSWORD": [ + "", + "" + ], "W9_LOGIN_WORKSPACE": [ "Login Workspace", "Workspace" @@ -263,6 +267,10 @@ "ADMIN GUI PORT", "管理页面端口" ], + "W9_ADMIN_PORT_SET": [ + "Admin Port", + "管理端口" + ], "W9_URI_SET": [ "URI", "连接URI" diff --git a/metadata/archive.yaml b/metadata/archive.yaml index b8bdfe6ee..b65173be9 100644 --- a/metadata/archive.yaml +++ b/metadata/archive.yaml @@ -51,12 +51,43 @@ apps: - mediawiki - mingdao - nodebb +- oneapi - onlyoffice +- onyx +- opencost +- opencv +- opengauss +- openjdk +- openproject +- opentelemetry +- outline +- palworld +- pangolin +- paperlessngx +- papermc +- passbolt +- penpot +- photoprism +- phpfpmapache +- phpfpmnginx +- pydio +- plane +- plausible +- plex +- pmm +- portkey +- posteio +- postgrest +- puter +- ragflow - rainbond - rclone - redash +- rethinkdb +- rocketchat - rocketmq - rowy +- ruby - rudderstack - runtime - rustdesk @@ -268,3 +299,39 @@ overrides: archive_reason: Low user demand redash: archive_reason: Low user demand + rethinkdb: + archive_reason: Low user demand + rocketchat: + archive_reason: Low user demand + ruby: + archive_reason: Low user demand + ragflow: + archive_reason: Low user demand + palworld: + archive_reason: Low user demand + pangolin: + archive_reason: Low user demand + paperlessngx: + archive_reason: Low user demand + papermc: + archive_reason: Low user demand + passbolt: + archive_reason: Low user demand + penpot: + archive_reason: Low user demand + photoprism: + archive_reason: Low user demand + phpfpmapache: + archive_reason: Low user demand + phpfpmnginx: + archive_reason: Low user demand + plane: + archive_reason: Low user demand + plex: + archive_reason: Low user demand + pmm: + archive_reason: Low user demand + portkey: + archive_reason: Low user demand + posteio: + archive_reason: Low user demand diff --git a/metadata/catalog/posthog.json b/metadata/catalog/posthog.json new file mode 100644 index 000000000..73da2acf8 --- /dev/null +++ b/metadata/catalog/posthog.json @@ -0,0 +1,16 @@ +{ + "trademark": "PostHog", + "catalogBindings": [ + { + "parentKey": "analytics", + "childKey": "web-analytics" + } + ], + "summary": "Product analytics platform for web and apps.", + "overview": "Self-hosted product analytics platform with event capture, feature flags, session replay, and product usage insights.", + "description": "PostHog is an open-source product analytics platform for websites and applications. It combines event ingestion, dashboards, feature flags, session replay, experiments, and product usage analysis in one self-hosted stack.\n\nThis package deploys a Docker Compose based PostHog stack built around the official PostHog images, plus the required PostgreSQL, ClickHouse, Redis, Redpanda, and object storage services. It is suitable for teams that want control over data residency, infrastructure, and upgrade timing while keeping the PostHog self-hosted experience.\n\nTypical use cases include web and product analytics, feature flag rollouts, funnel and retention analysis, session replay, and self-hosted product observability for engineering and growth teams.", + "websiteurl": "https://posthog.com", + "screenshots": [ + "https://posthog.com/images/docs/self-host/self-hosted-dashboard.png" + ] +} diff --git a/metadata/catalog/qdrant.json b/metadata/catalog/qdrant.json new file mode 100644 index 000000000..b3b8e84f6 --- /dev/null +++ b/metadata/catalog/qdrant.json @@ -0,0 +1,20 @@ +{ + "trademark": "Qdrant", + "catalogBindings": [ + { + "parentKey": "database", + "childKey": "vector-databases" + }, + { + "parentKey": "ai", + "childKey": "ai-agent-chat" + } + ], + "summary": "Vector database for AI search.", + "overview": "Qdrant stores embeddings and payloads for vector search, hybrid retrieval, and semantic AI applications.", + "description": "Qdrant is an open-source vector database and similarity search engine designed for production AI workloads. It stores embeddings with JSON payloads, exposes REST and gRPC APIs, and supports filtering, hybrid search, quantization, multitenancy, snapshots, and a built-in web UI.\n\nThis package deploys the official single-node Qdrant server, publishes both the REST and gRPC ports, and persists vector storage in a named volume. The default deployment keeps authentication disabled to match the upstream quickstart, so operators should enable API keys before exposing it to untrusted networks.\n\nTypical use cases include RAG systems, semantic search, recommendation engines, multimodal retrieval, and other applications that need fast vector indexing and nearest-neighbor search.", + "websiteurl": "https://qdrant.tech/", + "screenshots": [ + "https://qdrant.tech/documentation/gettingstarted/web-ui.png" + ] +} diff --git a/metadata/catalog/timescaledb.json b/metadata/catalog/timescaledb.json new file mode 100644 index 000000000..0552b141d --- /dev/null +++ b/metadata/catalog/timescaledb.json @@ -0,0 +1,16 @@ +{ + "trademark": "Timescale", + "catalogBindings": [ + { + "parentKey": "database", + "childKey": "timedbs" + } + ], + "summary": "Time-series PostgreSQL database.", + "overview": "TimescaleDB extends PostgreSQL for time-series ingest, retention, compression, and real-time analytics workloads.", + "description": "TimescaleDB is an open-source time-series database built as a PostgreSQL extension. It keeps full PostgreSQL compatibility while adding hypertables, compression, continuous aggregates, retention policies, and other features for high-ingest time-series workloads and real-time analytics.\n\nThis package deploys the official TimescaleDB HA image on PostgreSQL 18, publishes the PostgreSQL port, and persists database data in a named volume. The default `postgres` account is package-managed, and the bundled health and validation checks verify that the TimescaleDB extension is available after startup.\n\nTypical use cases include IoT telemetry, observability, financial events, industrial metrics, and any workload that needs SQL analytics on fast-growing time-series data.", + "websiteurl": "https://www.tigerdata.com/", + "screenshots": [ + "https://docs.timescale.com/_next/image/?url=%2Fimages%2Fhero.webp&w=1920&q=75" + ] +} diff --git a/metadata/db-lifecycle.json b/metadata/db-lifecycle.json index 242b5510d..83f5a3501 100644 --- a/metadata/db-lifecycle.json +++ b/metadata/db-lifecycle.json @@ -1,6 +1,6 @@ { "version": 1, - "updated_at": "2026-08-20", + "updated_at": "2026-09-30", "engines": { "clickhouse": { "source": "https://endoflife.date/api/clickhouse.json", @@ -171,6 +171,26 @@ "eol": "2027-04-01" } ] + }, + "mongodb": { + "source": "https://endoflife.date/api/mongodb.json", + "tracks": [ + { + "version": "8.3", + "track": "stable", + "eol": "2029-10-31" + }, + { + "version": "8.0", + "track": "stable", + "eol": "2029-10-31" + }, + { + "version": "7.0", + "track": "stable", + "eol": "2027-08-31" + } + ] } } } diff --git a/metadata/maintenance.yaml b/metadata/maintenance.yaml index ba3597b6c..6fac13012 100644 --- a/metadata/maintenance.yaml +++ b/metadata/maintenance.yaml @@ -26,6 +26,7 @@ cadence: - owncloud - portainer - postgresql + - timescaledb - prestashop - rabbitmq - redmine diff --git a/metadata/variables.schema.json b/metadata/variables.schema.json index d5c35f91d..fe3ed9f0b 100644 --- a/metadata/variables.schema.json +++ b/metadata/variables.schema.json @@ -106,6 +106,18 @@ }, "api": { "$ref": "#/$defs/accessEntry" + }, + "grpc": { + "$ref": "#/$defs/accessEntry" + }, + "ws": { + "$ref": "#/$defs/accessEntry" + }, + "ssh": { + "$ref": "#/$defs/accessEntry" + }, + "metrics": { + "$ref": "#/$defs/accessEntry" } } }, @@ -201,6 +213,15 @@ "items": { "type": "string" } + }, + "secrets": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" + }, + "description": "Names of .env keys that hold pre-generated secrets. The .env value is a plain-text, correctly-shaped default; a consumer may regenerate a similar value and overwrite it. No per-secret generation rules are declared here." } } }, @@ -219,6 +240,26 @@ } } }, + "setup": { + "type": "object", + "additionalProperties": false, + "required": [ + "steps" + ], + "properties": { + "summary": { + "type": "string", + "minLength": 1 + }, + "steps": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/setupStep" + } + } + } + }, "help": { "type": "object", "additionalProperties": { @@ -581,6 +622,240 @@ } ] }, + "setupStep": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "text" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9-]*$" + }, + "text": { + "type": "string", + "minLength": 1 + }, + "action": { + "$ref": "#/$defs/setupAction" + } + } + }, + "setupAction": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "service" + ], + "properties": { + "type": { + "const": "show-log" + }, + "service": { + "type": "string", + "minLength": 1 + }, + "tail": { + "type": "integer", + "minimum": 1 + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "name" + ], + "properties": { + "type": { + "const": "show-env" + }, + "name": { + "type": "string", + "minLength": 1 + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "path" + ], + "properties": { + "type": { + "const": "show-file" + }, + "path": { + "type": "string", + "minLength": 1 + }, + "format": { + "type": "string", + "enum": [ + "text", + "json", + "env" + ] + }, + "jsonPath": { + "type": "string", + "minLength": 1 + }, + "key": { + "type": "string", + "minLength": 1 + } + }, + "allOf": [ + { + "if": { + "properties": { + "format": { + "const": "json" + } + }, + "required": [ + "format" + ] + }, + "then": { + "required": [ + "jsonPath" + ] + } + }, + { + "if": { + "properties": { + "format": { + "const": "env" + } + }, + "required": [ + "format" + ] + }, + "then": { + "required": [ + "key" + ] + } + } + ] + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "argv" + ], + "properties": { + "type": { + "const": "show-cli" + }, + "argv": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "minLength": 1 + } + }, + "format": { + "type": "string", + "enum": [ + "text", + "json", + "env" + ] + }, + "jsonPath": { + "type": "string", + "minLength": 1 + }, + "key": { + "type": "string", + "minLength": 1 + } + }, + "allOf": [ + { + "if": { + "properties": { + "format": { + "const": "json" + } + }, + "required": [ + "format" + ] + }, + "then": { + "required": [ + "jsonPath" + ] + } + }, + { + "if": { + "properties": { + "format": { + "const": "env" + } + }, + "required": [ + "format" + ] + }, + "then": { + "required": [ + "key" + ] + } + } + ] + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "access" + ], + "properties": { + "type": { + "const": "open" + }, + "access": { + "type": "string", + "enum": [ + "web", + "admin", + "api", + "grpc", + "ws", + "ssh", + "metrics" + ] + }, + "path": { + "type": "string", + "pattern": "^/" + } + } + } + ] + }, "accessEntry": { "type": "object", "additionalProperties": false, @@ -598,6 +873,11 @@ "type": "string", "pattern": "^/", "description": "URL path; omit for '/'." + }, + "scheme": { + "type": "string", + "minLength": 1, + "description": "Optional per-surface scheme override, e.g. wss or ssh." } } } diff --git a/skills/app-update/SKILL.md b/skills/app-update/SKILL.md index 01259229e..0aa8c17e6 100644 --- a/skills/app-update/SKILL.md +++ b/skills/app-update/SKILL.md @@ -7,7 +7,7 @@ description: Use when the user wants to implement an approved app update after a Implement one approved app update with minimal app-local changes. -When the caller provides only an app name, first detect a candidate target version and gather upstream references, then present that candidate for owner confirmation before implementation. Do not skip confirmation unless the target version is already fixed by an issue, an approved assessment, or an explicit owner instruction in the current conversation. +When the caller provides only an app name, first detect the best candidate stable target version and gather upstream references. Continue implementation automatically when the candidate is clear and fits the maintenance policy. Stop and obtain owner confirmation only when the candidate is ambiguous, risky, `review-first`, or multiple reasonable targets exist. This skill follows `docs/ai-sdlc/03-update-pipeline.md`, `docs/ai-sdlc/05-quality-gates.md`, and `docs/ai-sdlc/06-test-report-format.md`. @@ -20,13 +20,13 @@ Supporting files in this skill: ## Inputs - app name (required) -- target version (optional at entry; required before editing files unless already fixed by the issue, an approved assessment, or an explicit owner confirmation after detection) +- target version (optional at entry; required before editing files, but may be auto-detected by this workflow when the upstream choice is clear) - upstream references (required before editing files) ## Steps 1. Read repository facts from `apps//`, `metadata/maintenance.yaml`, and the app notes when relevant. -2. If the caller did not provide a target version, detect a candidate target version first by checking the current package version, the upstream image tags, and the upstream release notes or changelog. If the candidate is not already fixed by issue context or approved assessment, stop and obtain owner confirmation before editing files. +2. If the caller did not provide a target version, detect the best candidate stable target version first by checking the current package version, the upstream image tags, and the upstream release notes or changelog. Prefer the newest stable version that matches the app's maintenance policy and image-tag policy. If one candidate is clearly correct, proceed with implementation and report the chosen target version. Stop and obtain owner confirmation only when the candidate is ambiguous, risky, `review-first`, or not clearly better than alternatives. 3. Read `docs/w9-env-spec.md` before touching `.env` or `docker-compose.yml`; use it as the canonical `W9_*` reference, then mirror `metadata/templates/new-app/.env.tmpl` for layout. 4. Read the approved assessment result, if one exists. 5. Read upstream release notes, upgrade notes, image tags, and requirements. @@ -59,7 +59,7 @@ Supporting files in this skill: ## Rules - Do not start implementation for a `review-first` candidate unless the owner has approved continuation. -- When only an app name is provided, discovery is allowed, but file edits must wait until the owner confirms the detected candidate version unless approval already exists in issue context or a prior assessment. +- When only an app name is provided, the workflow should normally detect the best stable target version and continue automatically. Ask the owner before editing only when the detected target is ambiguous, risky, `review-first`, or otherwise needs judgment beyond the documented maintenance policy. - Keep the smallest correct change. - The update is not a blind version bump. The changed app must still pass the current quality gates after the work is complete. - Do not perform broad cosmetic template re-alignment. Fix only the app-local conformance items that are blocking, directly relevant to the update, or required by current gates and generators.