Compare commits

...

91 Commits

Author SHA1 Message Date
eball
046ff2c5fb authelia: update bridge builder to accept pointer to configuration 2026-03-05 18:55:26 +08:00
Meow33
776848d2e2 docs: add application environment variables (#2577)
* docs: updated installation env vars and runtime values references

* docs: fix content

* docs: update content

* Update table of contents, and refactored docs.

* Fixed capitalization.

* batch update to fix readability

* refactored declarative env var

* Updated translation.

* Updated based on suggestions.

* Updated based on suggestions.

---------

Co-authored-by: yajing wang <413741312@qq.com>
2026-03-05 17:52:22 +08:00
Power-One-2025
480cecfe84 docs: generalize Olares Space Basic redemption instructions for broader audience (#2627)
* generalize instructions for broader audience

* update zh version and fix punctuation
2026-03-05 16:15:52 +08:00
Meow33
22a364d58a docs: update UI and screenshots for Windows VM (#2612)
* Updated UI and screenshots.

* Updated for Olares One

* Apply suggestions from code review

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Updated links and screenshot.

* Fixed typos.

---------

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-03-05 16:15:33 +08:00
eball
683e31c6ef fix(cli): remove error logging for GB10 chip check (#2626) 2026-03-05 14:15:11 +08:00
Yajing
1ae3a78286 docs: add LarePass VPN troubleshooting docs (#2606)
* add larepass vpn troubleshooting

* Apply suggestions

Co-authored-by: Meow33 <supermonkey03@163.com>

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
2026-03-05 12:38:30 +08:00
aby913
7404674a20 fix(bfl): remove set custom domain on cloudflare (#2624)
* fix(bfl): remove set custom domain on cloudflare (#2619)

* fix(bfl): remove set custom domain on cloudflare
2026-03-05 11:04:15 +08:00
Power-One-2025
f116970ad0 docs: add manual restart instructions and refine discord channel config (#2617)
* add note and faq for manual restart

* update channel configuration for accuracy

* change for consistency
2026-03-05 10:29:42 +08:00
wiy
b6e866ce75 feat(olares-app): update version to v1.9.12 (#2623) 2026-03-04 23:51:04 +08:00
dkeven
39bd546ac8 fix(manifest): add password reset path for cli in auth provider (#2622) 2026-03-04 23:50:19 +08:00
eball
5820b5612e fix(daemon): increase retry count for USB device detection (#2620) 2026-03-04 23:49:37 +08:00
Teng
ef78e21933 docs: update Olares Manifest to 0.11.0 (#2527)
* update Olares Manifest to 0.11.0

* fix typo

* Update manifest.md

* Update manifest.md

* Update manifest.md

* Apply suggestions from code review

Co-authored-by: Meow33 <supermonkey03@163.com>

* Apply suggestions from code review

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Meow33 <supermonkey03@163.com>

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
2026-03-04 19:11:16 +08:00
eball
8ce8b6c976 feat(cli): add time synchronization check using chronyc (#2616)
* feat(cli): add time synchronization check using chronyc

* feat(cli): update time synchronization check to validate stratum value
2026-03-04 14:43:42 +08:00
dkeven
cbab40a597 feat(bfl): use unified remote api env to query external ip (#2614)
* feat(bfl): use unified remote api env to query external ip (#2611)

* chore(bfl): update bfl image version to v0.4.41
2026-03-04 00:19:03 +08:00
dkeven
14691ea3ec feat(daemon): use unified remote api env to query external ip (#2613) 2026-03-04 00:18:25 +08:00
Power-One-2025
98f123fbf1 docs: add persona setup for OpenClaw tutorial (#2605)
* Add: Personalize OpenClaw

* simplify a message

* refinements for accuracy

* remove redundant text

* tag the step with Optional

* address comments

* adjust image size

* adjust image size
2026-03-03 21:43:07 +08:00
Jeremiah Lee
8f5023ce17 docs: fix broken shields images and architecture link in README (#2608)
- shields.io is case sensitive for the repo name (capital O Olares), resulting in "invalid" text rendering in badge
- architecture URL in docs moved without redirect
2026-03-03 20:39:48 +08:00
Yajing
4467bc61df docs: restructure factory reset and reinstall docs for Olares One (#2607)
* restructure factory reset and reinstall docs

* address comment
2026-03-03 20:35:52 +08:00
eball
85f1224616 cli: update etcd service template to use network-online.target (#2603) 2026-03-03 15:00:56 +08:00
eball
4b3a42d728 authelia: fix bug of sub-policy failed if set it to two-factor (#2601)
authelia: fix sub-policy failed when the main policy is internal
2026-03-03 13:11:00 +08:00
berg
3c821cbedb system frontend: fix system app launch and display bugs. (#2600)
* feat: update system frontend version

* feat: update system frontend version

---------

Co-authored-by: eball <liuy102@hotmail.com>
2026-03-03 13:10:36 +08:00
aby913
3129b295ce l4-bfl-proxy: fix multi users app custom domain (#2599)
* l4-bfl-proxy: fix multi users app custom domain (#2597)

* l4-bfl-proxy: fix multi users app custom domain

* fix: update error handling to check for both 403 and 404 HTTP status codes in upload scripts

---------

Co-authored-by: eball <liuy102@hotmail.com>
2026-03-03 13:09:56 +08:00
eball
76bde01b86 daemon: enhance USB device mounting by dynamically setting options based on filesystem type (#2596)
fix: enhance USB device mounting by dynamically setting options based on filesystem type
2026-03-03 13:09:11 +08:00
dkeven
32c652205d fix(appservice): avoid race condition between upgrade & applyenv (#2594)
* fix(appservice): avoid race condition between upgrade & applyenv (#2593)

* chore(appservice): update image version to 0.5.5

---------

Co-authored-by: eball <liuy102@hotmail.com>
2026-03-03 13:08:33 +08:00
Meow33
817316c1d6 docs: updated wise and desktop docs (#2586)
* docs: updated wise and desktop docs

* Refined expressions.

* Updated larepass index

* refine wording

* Updated translation.

* Update docs/manual/larepass/index.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

---------

Co-authored-by: yajing wang <413741312@qq.com>
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-03-03 11:54:15 +08:00
eball
e03eb40ed8 fix: coscmd invalid parameters 2026-03-03 00:44:47 +08:00
eball
79b7d82748 Add VERSION environment variable to workflow 2026-03-02 23:59:23 +08:00
eball
20344416f8 fix: update error handling to check for both 403 and 404 HTTP status codes in upload scripts 2026-03-02 22:33:27 +08:00
eball
8c59050529 fix: remove unnecessary 'cp' argument from coscmd upload commands in release workflows 2026-03-02 15:18:40 +08:00
eball
f932d10916 fix: update upload command in release workflows to remove unnecessary 'cp' argument 2026-03-02 15:15:45 +08:00
eball
e4762d880b fix: remove public-read ACL from coscmd upload commands in release workflows 2026-03-02 15:08:27 +08:00
eball
017b2e2acd ci: change cdn backend storage to cos (#2592) 2026-03-02 14:55:26 +08:00
dkeven
d3adeced3f fix(cli): dynamic creation of nvidia runtimeclass (#2591) 2026-03-02 13:50:29 +08:00
hysyeah
48038504a7 fix: add kubeblocks addon chart image to manifest (#2590) 2026-03-02 13:50:04 +08:00
Yajing
d17d8fca14 docs: update Windows local access steps & tidy wording (#2587)
update Windows .local access & tidy wording
2026-03-02 13:23:57 +08:00
Teng
35770fbe46 docs: fix model name used in tutorial (#2582)
* fix model name used in tutorial

* Update docs/use-cases/openclaw.md

---------

Co-authored-by: Power-One-2025 <zhengchunhong@bytetrade.io>
2026-02-28 22:37:40 +08:00
Yajing
39cb3335d6 docs: fix & streamline ssh access (#2584)
fix & streamline ssh access
2026-02-28 22:29:49 +08:00
Yajing
0e1208d555 docs: add how to check SSH password in vault (#2571)
* add how to check SSH password in vault

* reuse reset ssh content, improve wording & flow
2026-02-28 14:24:10 +08:00
Yajing
65fa0c0da8 docs: add factory reset via BIOS and reinstall via USB (#2576)
* add factory reset via BIOS and reinstall via USB

* refine wording & add screenshots

* add zh docs

* address comments
2026-02-28 13:12:21 +08:00
eball
cf7125aac8 cli, daemon: enhance DGX Spark support and update GPU type handling (#2496)
* feat(gpu): enhance DGX Spark support and update GPU type handling

* feat(amdgpu): refactor AMD GPU detection and support for GB10 chip and APU

* feat(connector): enhance GB10 chip detection with environment variable support

* feat(gpu): enhance DGX Spark support and update GPU type handling

* feat(amdgpu): refactor AMD GPU detection and support for GB10 chip and APU

* feat(connector): enhance GB10 chip detection with environment variable support

* feat: add nvidia device plugin for gb10

* fix(gpu): update pod selector for hami-device-plugin based on GB10 chip detection

fix(deploy): bump app-service image version to 0.4.78

* feat: enable CGO for building on ARM architecture and adjust build constraints for Linux

* feat: enhance multi-architecture support for ARM64 in release workflow

* feat: update multi-arch setup for ARM64 in release workflow

* feat: enhance ARM64 multi-architecture support in release workflow

* feat: streamline ARM64 cross-compilation setup in release workflow

* feat: enhance ARM64 support by adding architecture-specific package installations

* feat: update ARM64 package sources in release workflow for improved compatibility

* feat: amd device plugin and container toolkit install

* refactor: remove GB10 chip type check from GPU info update

* feat(gpu): update hami version to v2.6.10-compatible for spark

* fix: remove gb10 device plugin checking

* fix: update klauspost/cpuid to v2.3.0

* fix: amd gpu check (#2522)

* feat: enhance storage device detection with USB serial properties

* feat: update hami version to v2.6.11-compatible-arm

* feat: add chip type support for AMD and NVIDIA GPUs in node label updates

* feat(gpu): supports auto binding GPU to app

* feat(gpu): remove chip type handling from GPU label updates

* feat(gpu): remove GPU type specification from DaemonSet and values.yaml

* feat(gpu): remove GB10 device plugin installation and related checks

* feat(gpu): update HAMi to v2.6.11

---------

Co-authored-by: dkeven <dkvvven@gmail.com>
Co-authored-by: hys <hysyeah@gmail.com>
2026-02-28 11:44:02 +08:00
eball
46ba0e64e8 app-service: support injecting gpu memory and container selection (#2581)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* fix: set amd apu/gpu limit key to amd.com/gpu

* fix: stop app if it is hami cause unschedule no wait (#2531)

* fix: stop app if it is hami cause unschedule

* ingore param from req if size=0

* update appservice image tag to 0.5.3

* feat: support injecting gpu memory and container selection (#2580)

* refactor: unify GPU resource handling and remove hardcoded values

* fix: handle CPU type selection in GPU resource management

* feat: enhance GPU resource management with memory limits and chip type handling

* feat: update GPU resource patching to support selective container injection

* feat: adjust GPU memory format in deployment patching for compatibility

* fix: revert unchanged file

* Revert "fix: revert unchanged file"

This reverts commit 5f48862758.

* fix: revert unchanged file

* chore: update app-service image tag to 0.5.4

---------

Co-authored-by: hys <hysyeah@gmail.com>
2026-02-27 23:43:29 +08:00
Power-One-2025
a15fe1e3e0 docs: revamp the "Advanced" page (previously "Developer") (#2534)
* update images and related descriptions

* Revamp the Developer resources page

* address previous comments

* Revamp zh version of Developer resources

* update Settings index page
2026-02-27 23:28:27 +08:00
dkeven
1b3305dd98 fix: conditionally install storage for juicefs (#2579) 2026-02-27 21:44:11 +08:00
Yajing
54f2996efe docs: add troubleshooting guide for missing apps in Market (#2574)
* add troubleshooting guide for missing apps in Market

* address comment
2026-02-27 19:36:35 +08:00
wiy
7870520b57 feat(olares-app): update olares-app version to v1.9.6 (#2573) 2026-02-27 14:25:52 +08:00
Power-One-2025
2dbd99d64a docs: update installation method of drivers on windows (#2566)
* update installation method

* add image, update zh version

* add missing en version

* refine link style

* add one package driver installation for windows

* update toc labels

* update zh version

* naming consistency

* address comments

* update method to use drive package only

* update zh version

* update a note

* fix tip display

* remove redundant word
2026-02-26 23:22:17 +08:00
Power-One-2025
44d3f5d26a docs: update the initialization steps for OpenClaw tutorial (#2567)
* update initialization steps

* remove outdated steps, fix indentation

* add image for easy understanding

* add images

* update initialization, pairing, add upgrade notes

* change to use complete command name

* refine title to be concise

* address comment
2026-02-26 22:41:39 +08:00
Yajing
0f67f6227f docs: add troubleshooting guide for memory not released after stopping apps (#2565)
* add troubleshooting guide for memory not released after stopping apps

* add zh-cn version & fix wording

* Apply suggestions

* Apply suggestions
2026-02-26 22:35:38 +08:00
Power-One-2025
21e1c06794 docs: updates for releasing resources and uninstalling shared apps (#2568)
* faq on free up resources

* update zh version

* update UI label in zh version for accuracy
2026-02-26 22:04:34 +08:00
wiy
838c146fc0 feat(olares-app): update olares-app version to v1.9.5 (#2563) 2026-02-26 10:44:38 +08:00
Power-One-2025
403460b9c2 docs: update method for installing drivers on windows (#2564)
* update installation method

* add image, update zh version

* add missing en version

* refine link style
2026-02-25 23:50:39 +08:00
Yajing
9f1800c8c6 docs: fix space nav display, extract use-case/developer sidebars, add note in space docs (#2562)
* fix nav display issues, extract use case & developer docs

* fix wording for space docs note

* fix links

* address comments
2026-02-25 23:17:59 +08:00
wiy
29756b392e olares app: Use the Roboto font to match the theme of the rest of the applications (#2554) 2026-02-25 22:27:19 +08:00
Yajing
fd122768e7 docs: update custom domain tutorial screenshots and align copy with latest UI (#2559)
update screenshots to align with latest UI
2026-02-25 22:17:59 +08:00
hysyeah
6c40d3a288 cli: upgrade l4-bfl-proxy to v0.3.11 (#2557) 2026-02-25 21:46:22 +08:00
eball
5b843d19e4 l4-bfl-proxy: skip nginx reload if configuration has not changed (#2556)
* fix: skip invalid expose port (#2434)

* fix: skip nginx reload if configuration has not changed

* fix: update L4_PROXY_IMAGE_VERSION to v0.3.11 in bfl_deploy.yaml and Olares.yaml

---------

Co-authored-by: hysyeah <hysyeah@gmail.com>
2026-02-25 17:44:08 +08:00
Power-One-2025
97e2b82d0e docs: update content related to reference app (#2530)
* updates for reference apps

* more updates for reference app
2026-02-25 13:29:45 +08:00
Ethan Collins
8614fa6253 Use the Robot font to match the theme of the rest of the applications 2026-02-24 09:35:36 -07:00
eball
b4966d5e38 bfl: add sync urls to master node (#2540)
* fix: myapps api add rawAppName field

* update bfl api image tag to v0.4.39

* feat: enhance user login background handling with style support (#2462)

* bfl: enhance user login background handling with style support

* fix: remove deprecated ingress mode handling from NginxController

* fix: update ingress image version to v0.3.29

* feat(bfl): supports switch on/off access from external network (#2513)

* fix: bfl add sync urls to master node (#2537)

* fix: update bfl-ingress image to v0.3.30 (#2539)

update bfl-ingress to v0.3.30

---------

Co-authored-by: hys <hysyeah@gmail.com>
Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
Co-authored-by: lovehunter9 <39935488+lovehunter9@users.noreply.github.com>
2026-02-13 19:48:13 +08:00
hysyeah
a7f698faf7 appservice: stop app if it is hami cause unschedule no wait (#2533)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* fix: set amd apu/gpu limit key to amd.com/gpu

* fix: stop app if it is hami cause unschedule no wait (#2531)

* fix: stop app if it is hami cause unschedule

* ingore param from req if size=0

* update appservice image tag to 0.5.3
2026-02-12 21:33:36 +08:00
dkeven
d7ea9b40d6 fix(cli): ignore finished pods in readiness check (#2528) 2026-02-12 20:55:17 +08:00
Power-One-2025
5a5d00d910 docs: add SMB account management to Settings (#2526)
add: SMB account manage in Settings
2026-02-12 17:14:54 +08:00
Power-One-2025
7de7ff989c docs: resolve comments on managing apps (#2523)
resolve comments on managing apps
2026-02-12 15:56:08 +08:00
wiy
1a1fcfac89 olares-app: update version to v1.9.3 (#2524)
* olares-app: update version to v1.9.3

* olares-app: update version to v1.9.3
2026-02-12 00:01:22 +08:00
Power-One-2025
452a6f2e78 docs: add skills and plugins management for OpenClaw (#2521)
* add skills and plugins management for OpenClaw

* resize images

* update: add minimum permissions
2026-02-11 17:54:18 +08:00
wiy
2d1abe8965 olares-app: update version to v1.9.2 (#2520)
* olares-app: update version to v1.9.2

* login: update version to v1.9.2
2026-02-11 00:33:47 +08:00
eball
744b4a3666 authelia: add auth type param to user regulation (#2518) 2026-02-10 20:28:01 +08:00
Power-One-2025
eb61923584 docs: update instructions per latest operations (#2517)
update step per latest operation
2026-02-10 15:35:21 +08:00
wiy
991d4e1dce olares-app: update version to v1.9.1 (#2515) 2026-02-09 23:49:27 +08:00
Yajing
5f513e2155 docs: fix sunshine address for .local domain and formatting for olares one docs (#2512)
* improve wording for olares one iso image download

* update the local address for sunshine

* fix formatting for ssh access
2026-02-09 23:22:03 +08:00
eball
7c3246dd9b bfl: remove deprecated ingress mode handling from NginxController (#2511)
* fix: myapps api add rawAppName field

* update bfl api image tag to v0.4.39

* feat: enhance user login background handling with style support (#2462)

* bfl: enhance user login background handling with style support

* fix: remove deprecated ingress mode handling from NginxController

* fix: update ingress image version to v0.3.29

---------

Co-authored-by: hys <hysyeah@gmail.com>
2026-02-09 20:06:34 +08:00
eball
362c6f1cde appservice: handle case for system applications without configuration in provider list (#2509)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* feat(appservice): support updating more fields in api & controller (#2472)

* fix: app uninstall delete data (#2478)

* fix: handle case for system apps without configuration in permission API (#2498)

* app-service: handle case for system apps without configuration in permission API

* fix: handle case for system applications without configuration in provider list (#2507)

* fix: update app-service image version to 0.5.2

---------

Co-authored-by: hys <hysyeah@gmail.com>
Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2026-02-09 20:06:17 +08:00
Power-One-2025
d2e685abd8 docs: add OpenClaw tutorial (#2506)
* add OpenClaw tutorial

* modify images, refine text for clarity

* add to index page, add description

* adjust table

* remove hidden text

* refinements for consistency

* update for clarity and concise
2026-02-09 11:03:05 +08:00
Yajing
ae2b6b1353 docs: batch add docs for one (#2457)
* add index and faq

* add comfyui

* add vpn and ssh

* add deerflow

* add expand storage

* fix link

* fix meta

* refine first boot & spec

* refine redeem basic plan

* add open webui & fix formatting

* batch review

* add rest image

* update introduction

* add zh-cn

* add nav

* add screenshots

* add single-drive setup & update dual-drive setup

* add egpu

* add steam

* fix lint

* align en and zh-cn

* fix image path

* fix lint
2026-02-07 15:58:15 +08:00
berg
8cbdc32725 settings, market, files, vault, desktop: fix some ui bugs (#2503)
feat: update system frontend version
2026-02-05 23:51:13 +08:00
dkeven
c696be90e6 feat(cli): add more lines to default journalctl limit (#2502) 2026-02-05 23:50:46 +08:00
eball
9487ef8862 app-service: handle case for system apps without configuration in permission API (#2499)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* feat(appservice): support updating more fields in api & controller (#2472)

* fix: app uninstall delete data (#2478)

* fix: handle case for system apps without configuration in permission API (#2498)

* app-service: handle case for system apps without configuration in permission API

---------

Co-authored-by: hys <hysyeah@gmail.com>
Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2026-02-05 23:50:09 +08:00
dkeven
a982a1568a fix(cli): seperate dmesg args for dmesg logs (#2497) 2026-02-05 23:49:05 +08:00
Power-One-2025
60d445f92a docs: add FAQs about activation and login (#2481)
* add: FAQs about activation and login

* Apply suggestion from @fnalways

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Apply suggestion from @fnalways

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* address comments

---------

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-02-05 23:38:51 +08:00
Meow33
839133fc27 docs: add middleware data access and integration guides (#2444)
* docs: add guides to view middleware data

* docs: add guide for grafana

* docs: add guide for otel and integration guides for other middleware

* docs: add guide for elasticsearch

* docs: update based on suggestions

* Update zh.ts

* docs: update content

* docs: resolve conflict
2026-02-05 23:34:59 +08:00
Meow33
2e6405ae1b docs: add docs for distributing olares apps (#2484)
* docs: add docs for distributing olares apps

* docs: update translation

* Apply suggestion from @fnalways

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs: refine documentation structure

* docs: fix punctuations

---------

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-02-05 20:22:47 +08:00
eball
5109ad001c Modify release-daemon.yaml for arm64 support
Add support for arm64 architecture in release daemon workflow
2026-02-05 14:24:33 +08:00
lovehunter9
4d850312f0 fix: seafile trim commit_id for syncing and change psql ccnet init (#2495) 2026-02-05 12:09:16 +08:00
aby913
1265ca929c backup: sync systemEnv default remote url (#2492)
* fix: get systemenv remove host

* backup: sync systemEnv default value
2026-02-05 00:30:52 +08:00
simon
6302bee05d download-server: nats message publish modify (#2489)
download
2026-02-05 00:29:45 +08:00
dkeven
2838d95f25 fix(cli): clear master host config when uninstalling (#2488) 2026-02-05 00:29:11 +08:00
berg
d3d7fc372d market, settings: support optional data deletion and fix bugs. (#2486)
* feat: support optional data deletion when uninstalling apps in Market

* market: add deleteData switch, add users info

* feat: update system frontend version

---------

Co-authored-by: aby913 <aby913@163.com>
2026-02-04 21:51:14 +08:00
dkeven
2bc061fcd8 fix(cli): do not override upgrade target version by config file (#2483) 2026-02-04 21:50:00 +08:00
hysyeah
f14cc982b5 app-service: feat app uninstall delete data (#2480)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* feat(appservice): support updating more fields in api & controller (#2472)

* fix: app uninstall delete data (#2478)

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2026-02-03 21:52:20 +08:00
dkeven
dd727befe7 fix(cli): bind config item to the effective command (#2474) 2026-02-03 20:14:14 +08:00
dkeven
83561bf1b7 feat: support more scheme update to env crs (#2473) 2026-02-03 20:09:19 +08:00
587 changed files with 22968 additions and 3460 deletions

View File

@@ -11,10 +11,22 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
bash build/build-redis.sh linux/amd64 glibc-231

View File

@@ -11,12 +11,24 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
bash build/build-redis.sh linux/amd64
push-arm64:
@@ -34,10 +46,22 @@ jobs:
run: |
sudo apt install -y make gcc
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
sudo -E sh -c "bash build/build-redis.sh linux/arm64 && rm -rf redis*"

View File

@@ -11,10 +11,22 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
bash build/build-ubuntu2204.sh

View File

@@ -11,10 +11,23 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
bash build/build-wsl-install-msi.sh

View File

@@ -60,14 +60,6 @@ jobs:
- name: Run chart-testing (lint)
run: ct lint --chart-dirs .dist/wizard/config,.dist/wizard/config/apps,.dist/wizard/config/gpu --check-version-increment=false --all
# - name: Create kind cluster
# if: steps.list-changed.outputs.changed == 'true'
# uses: helm/kind-action@v1.7.0
# - name: Run chart-testing (install)
# if: steps.list-changed.outputs.changed == 'true'
# run: ct install --chart-dirs wizard/charts,wizard/config --target-branch ${{ github.event.repository.default_branch }}
test-version:
runs-on: ubuntu-latest
outputs:
@@ -107,12 +99,23 @@ jobs:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- run: |
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf
push-image-arm64:
@@ -132,12 +135,23 @@ jobs:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Install coscmd
run: pip install coscmd
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- run: |
export PATH=$PATH:/usr/local/bin:/home/ubuntu/.local/bin
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf linux/arm64
@@ -154,11 +168,23 @@ jobs:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ needs.test-version.outputs.version }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
run: |
@@ -179,11 +205,21 @@ jobs:
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ needs.test-version.outputs.version }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
run: |
@@ -206,15 +242,28 @@ jobs:
run: |
bash build/build.sh ${{ needs.test-version.outputs.version }}
- name: Upload package
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload package
run: |
md5sum install-wizard-v${{ needs.test-version.outputs.version }}.tar.gz > install-wizard-v${{ needs.test-version.outputs.version }}.md5sum.txt && \
aws s3 cp install-wizard-v${{ needs.test-version.outputs.version }}.md5sum.txt s3://terminus-os-install/install-wizard-v${{ needs.test-version.outputs.version }}.md5sum.txt --acl=public-read && \
aws s3 cp install-wizard-v${{ needs.test-version.outputs.version }}.tar.gz s3://terminus-os-install/install-wizard-v${{ needs.test-version.outputs.version }}.tar.gz --acl=public-read
coscmd upload install-wizard-v${{ needs.test-version.outputs.version }}.md5sum.txt /install-wizard-v${{ needs.test-version.outputs.version }}.md5sum.txt && \
coscmd upload install-wizard-v${{ needs.test-version.outputs.version }}.tar.gz /install-wizard-v${{ needs.test-version.outputs.version }}.tar.gz
install-test:

View File

@@ -60,12 +60,24 @@ jobs:
OLARES_RELEASE_ID: ${{ inputs.release-id }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to S3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload to CDN
run: |
cd cli/output && for file in $(ls *.tar.gz | grep -v no-release-id); do
aws s3 cp "$file" s3://terminus-os-install${{ secrets.REPO_PATH }}${file} --acl=public-read
coscmd upload "$file" ${{ secrets.REPO_PATH }}${file}
done

View File

@@ -46,7 +46,15 @@ jobs:
- name: install udev-devel and pcap-devel
run: |
sudo apt update && sudo apt install -y libudev-dev libpcap-dev
sudo dpkg --add-architecture arm64
# Only modify ubuntu official sources, not third-party sources
sudo sed -i 's/^deb http:\/\/azure.archive.ubuntu.com/deb [arch=amd64] http:\/\/azure.archive.ubuntu.com/' /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || true
sudo sed -i 's/^Types: deb$/Types: deb\nArchitectures: amd64/' /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || true
# Add arm64 sources
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse" | sudo tee /etc/apt/sources.list.d/arm64.list
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/arm64.list
sudo apt update
sudo apt install -y libudev-dev libpcap-dev libudev-dev:arm64 libpcap-dev:arm64
- name: Install x86_64 cross-compiler
run: sudo apt-get update && sudo apt-get install -y build-essential
@@ -64,12 +72,25 @@ jobs:
version: v1.18.2
args: release --clean
- name: Upload to CDN
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload to CDN
run: |
cd daemon/output && for file in $(ls *.tar.gz | grep -v no-release-id); do
aws s3 cp "$file" s3://terminus-os-install${{ secrets.REPO_PATH }}${file} --acl=public-read
coscmd upload "$file" ${{ secrets.REPO_PATH }}${file}
done

View File

@@ -55,11 +55,23 @@ jobs:
- name: 'Checkout source code'
uses: actions/checkout@v3
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- run: |
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf
push-images-arm64:
@@ -69,11 +81,23 @@ jobs:
- name: 'Checkout source code'
uses: actions/checkout@v3
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- run: |
export PATH=$PATH:/usr/local/bin:/home/ubuntu/.local/bin
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf linux/arm64
@@ -85,11 +109,24 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ needs.daily-version.outputs.version }}
RELEASE_ID: ${{ needs.release-id.outputs.id }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
@@ -104,11 +141,24 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ needs.daily-version.outputs.version }}
RELEASE_ID: ${{ needs.release-id.outputs.id }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
@@ -129,19 +179,31 @@ jobs:
run: |
bash build/build.sh ${{ needs.daily-version.outputs.version }} ${{ needs.release-id.outputs.id }}
- name: Upload to S3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload to COS
id: upload
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
run: |
md5sum install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz > install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt && \
aws s3 cp install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt --acl=public-read && \
aws s3 cp install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz --acl=public-read && \
coscmd upload install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt ${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt && \
coscmd upload install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz ${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz && \
aws s3 cp install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.${{ needs.release-id.outputs.id }}.md5sum.txt --acl=public-read && \
aws s3 cp install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.${{ needs.release-id.outputs.id }}.tar.gz --acl=public-read
coscmd upload install-wizard-v${{ needs.daily-version.outputs.version }}.md5sum.txt ${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.${{ needs.release-id.outputs.id }}.md5sum.txt && \
coscmd upload install-wizard-v${{ needs.daily-version.outputs.version }}.tar.gz ${{ secrets.REPO_PATH }}install-wizard-v${{ needs.daily-version.outputs.version }}.${{ needs.release-id.outputs.id }}.tar.gz
release:

View File

@@ -60,12 +60,24 @@ jobs:
args: release --clean --skip-validate -f .goreleaser.agent.yml
workdir: './daemon'
- name: Upload to CDN
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload to CDN
run: |
cd daemon/output && for file in *.tar.gz; do
aws s3 cp "$file" s3://terminus-os-install/$file --acl=public-read
coscmd upload "$file" ${{ secrets.REPO_PATH }}$file
done

View File

@@ -51,10 +51,23 @@ jobs:
with:
ref: ${{ github.event.inputs.tags }}
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
VERSION: ${{ github.event.inputs.tags }}
run: |
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf
@@ -68,10 +81,24 @@ jobs:
with:
ref: ${{ github.event.inputs.tags }}
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
VERSION: ${{ github.event.inputs.tags }}
run: |
export PATH=$PATH:/usr/local/bin:/home/ubuntu/.local/bin
@@ -85,11 +112,24 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ github.event.inputs.tags }}
RELEASE_ID: ${{ needs.release-id.outputs.id }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
@@ -104,11 +144,25 @@ jobs:
- name: "Checkout source code"
uses: actions/checkout@v3
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ github.event.inputs.tags }}
RELEASE_ID: ${{ needs.release-id.outputs.id }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
@@ -131,18 +185,30 @@ jobs:
run: |
bash build/build.sh ${{ github.event.inputs.tags }} ${{ needs.release-id.outputs.id }}
- name: Upload to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: 'us-east-1'
- name: Install coscmd
run: pip install coscmd
- name: Configure coscmd
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
COS_BUCKET: ${{ secrets.COS_BUCKET }}
COS_REGION: ${{ secrets.COS_REGION }}
END_POINT: ${{ secrets.END_POINT }}
run: |
coscmd config -a $TENCENT_SECRET_ID \
-s $TENCENT_SECRET_KEY \
-b $COS_BUCKET \
-r $COS_REGION
- name: Upload to COS
run: |
md5sum install-wizard-v${{ github.event.inputs.tags }}.tar.gz > install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt && \
aws s3 cp install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt --acl=public-read && \
aws s3 cp install-wizard-v${{ github.event.inputs.tags }}.tar.gz s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.tar.gz --acl=public-read
coscmd upload install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt ${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt && \
coscmd upload install-wizard-v${{ github.event.inputs.tags }}.tar.gz ${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.tar.gz
aws s3 cp install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.${{ needs.release-id.outputs.id }}.md5sum.txt --acl=public-read && \
aws s3 cp install-wizard-v${{ github.event.inputs.tags }}.tar.gz s3://terminus-os-install${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.${{ needs.release-id.outputs.id }}.tar.gz --acl=public-read
coscmd upload install-wizard-v${{ github.event.inputs.tags }}.md5sum.txt ${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.${{ needs.release-id.outputs.id }}.md5sum.txt && \
coscmd upload install-wizard-v${{ github.event.inputs.tags }}.tar.gz ${{ secrets.REPO_PATH }}install-wizard-v${{ github.event.inputs.tags }}.${{ needs.release-id.outputs.id }}.tar.gz
release:
runs-on: ubuntu-latest

View File

@@ -3,10 +3,10 @@
# Olares: An Open-Source Personal Cloud to </br>Reclaim Your Data<!-- omit in toc -->
[![Mission](https://img.shields.io/badge/Mission-Let%20people%20own%20their%20data%20again-purple)](#)<br/>
[![Last Commit](https://img.shields.io/github/last-commit/beclab/olares)](https://github.com/beclab/olares/commits/main)
[![Last Commit](https://img.shields.io/github/last-commit/beclab/Olares)](https://github.com/beclab/olares/commits/main)
![Build Status](https://github.com/beclab/olares/actions/workflows/release-daily.yaml/badge.svg)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/beclab/olares)](https://github.com/beclab/olares/releases)
[![GitHub Repo stars](https://img.shields.io/github/stars/beclab/olares?style=social)](https://github.com/beclab/olares/stargazers)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/beclab/Olares)](https://github.com/beclab/olares/releases)
[![GitHub Repo stars](https://img.shields.io/github/stars/beclab/Olares?style=social)](https://github.com/beclab/Olares/stargazers)
[![Discord](https://img.shields.io/badge/Discord-7289DA?logo=discord&logoColor=white)](https://discord.gg/olares)
[![License](https://img.shields.io/badge/License-AGPL--3.0-blue)](https://github.com/beclab/olares/blob/main/LICENSE)
@@ -45,7 +45,7 @@ Just as Public clouds offer IaaS, PaaS, and SaaS layers, Olares provides open-so
![Tech Stacks](https://app.cdn.olares.com/github/olares/olares-architecture.jpg)
For detailed description of each component, refer to [Olares architecture](https://docs.olares.com/manual/concepts/system-architecture.html).
For detailed description of each component, refer to [Olares architecture](https://docs.olares.com/developer/concepts/system-architecture.html).
> 🔍 **How is Olares different from traditional NAS?**
>

View File

@@ -317,7 +317,7 @@ spec:
chown -R 1000:1000 /uploadstemp && \
chown -R 1000:1000 /appdata
- name: olares-app-init
image: beclab/system-frontend:v1.8.5
image: beclab/system-frontend:v1.9.12
imagePullPolicy: IfNotPresent
command:
- /bin/sh
@@ -439,7 +439,7 @@ spec:
- name: NATS_SUBJECT_VAULT
value: os.vault.{{ .Values.bfl.username}}
- name: user-service
image: beclab/user-service:v0.0.85
image: beclab/user-service:v0.0.86
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000

View File

@@ -415,7 +415,7 @@ export default defineComponent({
background-color: $background-1;
.app_title {
font-family: 'Inter';
font-family: 'Roboto' !important;
font-style: normal;
font-weight: 600;
font-size: 16px;

View File

@@ -358,7 +358,7 @@ export default defineComponent({
left: 0;
.app_title {
font-family: 'Source Han Sans CN';
font-family: 'Roboto' !important;
font-style: normal;
font-weight: 500;
font-size: 16px;

View File

@@ -202,11 +202,15 @@ if [ "$PREINSTALL" == "1" ]; then
fi
echo "configuring storage ..."
$sh_c "$INSTALL_OLARES_CLI install storage"
if [[ $? -ne 0 ]]; then
echo "error: failed to configure storage"
exit 1
if [[ "$JUICEFS" == "1" ]]; then
echo "configuring storage for juicefs ..."
$sh_c "$INSTALL_OLARES_CLI install storage"
if [[ $? -ne 0 ]]; then
echo "error: failed to configure storage"
exit 1
fi
else
echo "juicefs is not enabled, skip configuring storage"
fi

View File

@@ -27,4 +27,5 @@ mkdir redis-5.0.14 && \
cp /usr/local/bin/redis* ./redis-5.0.14/
tar czvf ./redis-5.0.14.tar.gz ./redis-5.0.14/ && \
aws s3 cp redis-5.0.14.tar.gz s3://terminus-os-install/redis-5.0.14_${os}_${arch}${SUFFIX}.tar.gz --acl=public-read
# aws s3 cp redis-5.0.14.tar.gz s3://terminus-os-install/redis-5.0.14_${os}_${arch}${SUFFIX}.tar.gz --acl=public-read
coscmd upload redis-5.0.14.tar.gz /redis-5.0.14_${os}_${arch}${SUFFIX}.tar.gz --acl=public-read

View File

@@ -6,4 +6,5 @@ set -xe
curl -Lo Ubuntu2204.appx https://wslstorestorage.blob.core.windows.net/wslblob/Ubuntu2204-221101.AppxBundle
ubuntu2204=$(md5sum Ubuntu2204.appx|awk '{print $1}')
aws s3 cp Ubuntu2204.appx s3://terminus-os-install/${ubuntu2204} --acl=public-read
# aws s3 cp Ubuntu2204.appx s3://terminus-os-install/${ubuntu2204} --acl=public-read
coscmd upload Ubuntu2204.appx /${ubuntu2204} --acl=public-read

View File

@@ -6,9 +6,11 @@ set -xe
curl -Lo wsl.2.3.26.0.amd64.msi https://github.com/microsoft/WSL/releases/download/2.3.26/wsl.2.3.26.0.x64.msi
wsl_2_3_26=$(md5sum wsl.2.3.26.0.amd64.msi|awk '{print $1}')
aws s3 cp wsl.2.3.26.0.amd64.msi s3://terminus-os-install/${wsl_2_3_26} --acl=public-read
# aws s3 cp wsl.2.3.26.0.amd64.msi s3://terminus-os-install/${wsl_2_3_26} --acl=public-read
coscmd upload wsl.2.3.26.0.amd64.msi /${wsl_2_3_26} --acl=public-read
curl -Lo wsl.2.3.26.0.arm64.msi https://github.com/microsoft/WSL/releases/download/2.3.26/wsl.2.3.26.0.arm64.msi
wsl_2_3_26_arm64=$(md5sum wsl.2.3.26.0.arm64.msi|awk '{print $1}')
aws s3 cp wsl.2.3.26.0.arm64.msi s3://terminus-os-install/arm64/${wsl_2_3_26_arm64} --acl=public-read
# aws s3 cp wsl.2.3.26.0.arm64.msi s3://terminus-os-install/arm64/${wsl_2_3_26_arm64} --acl=public-read
coscmd upload wsl.2.3.26.0.arm64.msi /arm64/${wsl_2_3_26_arm64} --acl=public-read

View File

@@ -31,7 +31,7 @@ while read line; do
curl -fsSLI https://cdn.olares.com/$path$name > /dev/null
if [ $? -ne 0 ]; then
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://cdn.olares.com/$path$name)
if [ $code -eq 403 ]; then
if [[ $code -eq 403 || $code -eq 404 ]]; then
bash ${BASE_DIR}/download-deps.sh $PLATFORM $line
if [ $? -ne 0 ]; then
@@ -46,28 +46,25 @@ while read line; do
fi
set -ex
aws s3 cp $name s3://terminus-os-install/$path$name --acl=public-read
aws s3 cp $name s3://terminus-os-install/backup/$path$backup_file --acl=public-read
aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
echo "upload $name to s3 completed"
# aws s3 cp $name s3://terminus-os-install/$path$name --acl=public-read
# aws s3 cp $name s3://terminus-os-install/backup/$path$backup_file --acl=public-read
# aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
# echo "upload $name to s3 completed"
coscmd upload ./$name /$path$name
coscmd upload ./$name /backup/$path$backup_file
coscmd upload ./$checksum /$path$checksum
echo "upload $name to cos completed"
set +ex
else
if [ $code -ne 200 ]; then
echo "failed to check image"
echo "failed to check file"
exit -1
fi
fi
fi
# upload to tencent cloud cos
# curl -fsSLI https://cdn.joinolares.cn/$path$name > /dev/null
# if [ $? -ne 0 ]; then
# set -ex
# coscmd upload ./$name /$path$name
# coscmd upload ./$checksum /$path$checksum
# echo "upload $name to cos completed"
# set +ex
# fi
done < components
popd

View File

@@ -15,7 +15,7 @@ cat $1|while read image; do
curl -fsSLI https://cdn.olares.com/$path$name.tar.gz > /dev/null
if [ $? -ne 0 ]; then
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://cdn.olares.com/$path$name.tar.gz)
if [ $code -eq 403 ]; then
if [[ $code -eq 403 || $code -eq 404 ]]; then
set -ex
skopeo copy --insecure-policy docker://$image oci-archive:$name.tar
gzip $name.tar
@@ -28,11 +28,16 @@ cat $1|while read image; do
fi
echo "start to upload [$name.tar.gz]"
aws s3 cp $name.tar.gz s3://terminus-os-install/$path$name.tar.gz --acl=public-read
aws s3 cp $name.tar.gz s3://terminus-os-install/backup/$path$backup_file --acl=public-read
aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
echo "upload $name completed"
# aws s3 cp $name.tar.gz s3://terminus-os-install/$path$name.tar.gz --acl=public-read
# aws s3 cp $name.tar.gz s3://terminus-os-install/backup/$path$backup_file --acl=public-read
# aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
# echo "upload $name completed"
coscmd upload ./$name.tar.gz /$path$name.tar.gz
coscmd upload ./$name.tar.gz /backup/$path$backup_file
coscmd upload ./$checksum /$path$checksum
echo "upload $name to cos completed"
set +ex
else
if [ $code -ne 200 ]; then
@@ -48,7 +53,7 @@ cat $1|while read image; do
curl -fsSLI https://cdn.olares.com/$path$checksum > /dev/null
if [ $? -ne 0 ]; then
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://cdn.olares.com/$path$checksum)
if [ $code -eq 403 ]; then
if [[ $code -eq 403 || $code -eq 404 ]]; then
set -ex
skopeo copy --insecure-policy docker://$image oci-archive:$name.tar
gzip $name.tar
@@ -60,10 +65,16 @@ cat $1|while read image; do
exit 1
fi
aws s3 cp $name.tar.gz s3://terminus-os-install/$path$name.tar.gz --acl=public-read
aws s3 cp $name.tar.gz s3://terminus-os-install/backup/$path$backup_file --acl=public-read
aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
echo "upload $name completed"
# aws s3 cp $name.tar.gz s3://terminus-os-install/$path$name.tar.gz --acl=public-read
# aws s3 cp $name.tar.gz s3://terminus-os-install/backup/$path$backup_file --acl=public-read
# aws s3 cp $checksum s3://terminus-os-install/$path$checksum --acl=public-read
# echo "upload $name completed"
coscmd upload ./$name.tar.gz /$path$name.tar.gz
coscmd upload ./$name.tar.gz /backup/$path$backup_file
coscmd upload ./$checksum /$path$checksum
echo "upload $name to cos completed"
set +ex
else
if [ $code -ne 200 ]; then
@@ -77,13 +88,16 @@ cat $1|while read image; do
curl -fsSLI https://cdn.olares.com/$path$manifest > /dev/null
if [ $? -ne 0 ]; then
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://cdn.olares.com/$path$manifest)
if [ $code -eq 403 ]; then
if [[ $code -eq 403 || $code -eq 404 ]]; then
set -ex
BASE_DIR=$(dirname $(realpath -s $0))
python3 $BASE_DIR/get-manifest.py $image -o $manifest
aws s3 cp $manifest s3://terminus-os-install/$path$manifest --acl=public-read
# aws s3 cp $manifest s3://terminus-os-install/$path$manifest --acl=public-read
coscmd upload $manifest /$path$manifest
echo "upload $name manifest completed"
set +ex
else
if [ $code -ne 200 ]; then

View File

@@ -43,6 +43,15 @@ userEnvs:
- envName: OLARES_USER_SMTP_SECURITY_PROTOCOLS
type: string
editable: true
options:
- title: "TLS"
value: "tls"
- title: "SSL"
value: "ssl"
- title: "StartTLS"
value: "starttls"
- title: "None"
value: "none"
- envName: OLARES_USER_OPENAI_APIKEY
type: password
editable: true

View File

@@ -281,7 +281,7 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
func collectDmesgLogs(tw *tar.Writer, options *LogCollectOptions) error {
cmd := exec.Command("dmesg -T")
cmd := exec.Command("dmesg", "-T")
output, err := cmd.Output()
if err != nil {
return err
@@ -645,7 +645,7 @@ func checkServiceExists(service string) bool {
func NewCmdLogs() *cobra.Command {
options := &LogCollectOptions{
Since: "7d",
MaxLines: 3000,
MaxLines: 20000,
OutputDir: "./olares-logs",
IgnoreKubeErrors: false,
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/beclab/Olares/cli/cmd/ctl/user"
"github.com/beclab/Olares/cli/version"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func NewDefaultCommand() *cobra.Command {
@@ -25,6 +26,11 @@ func NewDefaultCommand() *cobra.Command {
Short: "Olares Installer",
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: version.VERSION,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.InheritedFlags())
viper.BindPFlags(cmd.PersistentFlags())
viper.BindPFlags(cmd.Flags())
},
Run: func(cmd *cobra.Command, args []string) {
if showVendor {
fmt.Println(version.VENDOR)

121
cli/pkg/amdgpu/module.go Normal file
View File

@@ -0,0 +1,121 @@
package amdgpu
import (
"time"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/prepare"
"github.com/beclab/Olares/cli/pkg/core/task"
)
// InstallAmdContainerToolkitModule installs AMD container toolkit on supported Ubuntu if ROCm is installed.
type InstallAmdContainerToolkitModule struct {
common.KubeModule
Skip bool // conditional execution based on ROCm detection
SkipRocmCheck bool
}
func (m *InstallAmdContainerToolkitModule) IsSkip() bool {
return m.Skip
}
func (m *InstallAmdContainerToolkitModule) Init() {
m.Name = "InstallAmdContainerToolkit"
if m.IsSkip() {
return
}
prepareCollection := prepare.PrepareCollection{}
if !m.SkipRocmCheck {
prepareCollection = append(prepareCollection, new(RocmInstalled))
}
updateAmdSource := &task.RemoteTask{
Name: "UpdateAmdContainerToolkitSource",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Action: new(UpdateAmdContainerToolkitSource),
Prepare: &prepareCollection,
Parallel: false,
Retry: 1,
}
installAmdContainerToolkit := &task.RemoteTask{
Name: "InstallAmdContainerToolkit",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Prepare: &prepareCollection,
Action: new(InstallAmdContainerToolkit),
Parallel: false,
Retry: 1,
}
generateAndValidateCDI := &task.RemoteTask{
Name: "GenerateAndValidateAmdCDI",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Prepare: &prepareCollection,
Action: new(GenerateAndValidateAmdCDI),
Parallel: false,
Retry: 1,
}
m.Tasks = []task.Interface{
updateAmdSource,
installAmdContainerToolkit,
generateAndValidateCDI,
}
}
// InstallAmdPluginModule installs AMD GPU device plugin on Kubernetes.
type InstallAmdPluginModule struct {
common.KubeModule
Skip bool // conditional execution based on GPU enablement
}
func (m *InstallAmdPluginModule) IsSkip() bool {
return m.Skip
}
func (m *InstallAmdPluginModule) Init() {
m.Name = "InstallAmdPlugin"
// update node with AMD GPU labels
updateNode := &task.RemoteTask{
Name: "UpdateNodeAmdGPUInfo",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Prepare: &prepare.PrepareCollection{
new(common.OnlyFirstMaster),
},
Action: new(UpdateNodeAmdGPUInfo),
Parallel: false,
Retry: 1,
}
installPlugin := &task.RemoteTask{
Name: "InstallAmdPlugin",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Prepare: &prepare.PrepareCollection{
new(common.OnlyFirstMaster),
},
Action: new(InstallAmdPlugin),
Parallel: false,
Retry: 1,
}
checkGpuState := &task.RemoteTask{
Name: "CheckAmdGPUState",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Prepare: &prepare.PrepareCollection{
new(common.OnlyFirstMaster),
new(RocmInstalled),
},
Action: new(CheckAmdGpuStatus),
Parallel: false,
Retry: 50,
Delay: 10 * time.Second,
}
m.Tasks = []task.Interface{
updateNode,
installPlugin,
checkGpuState,
}
}

View File

@@ -0,0 +1,56 @@
package amdgpu
import (
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
)
// RocmInstalled checks if AMD ROCm is installed on the system.
type RocmInstalled struct {
common.KubePrepare
}
func (p *RocmInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
rocmV, err := connector.RocmVersion()
if err != nil {
logger.Debugf("ROCm version check error: %v", err)
return false, nil
}
if rocmV == nil {
return false, nil
}
logger.Infof("Detected ROCm version: %s", rocmV.Original())
return true, nil
}
// RocmNotInstalled checks if AMD ROCm is NOT installed on the system.
type RocmNotInstalled struct {
common.KubePrepare
RocmInstalled
}
func (p *RocmNotInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
installed, err := p.RocmInstalled.PreCheck(runtime)
if err != nil {
return false, err
}
return !installed, nil
}
// ContainerdInstalled checks if containerd is installed on the system.
type ContainerdInstalled struct {
common.KubePrepare
}
func (p *ContainerdInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
containerdCheck := precheck.ConflictingContainerdCheck{}
if err := containerdCheck.Check(runtime); err != nil {
return true, nil
}
logger.Info("containerd is not installed, ignore task")
return false, nil
}

View File

@@ -1,17 +1,20 @@
package amdgpu
import (
"context"
"fmt"
"os/exec"
"path"
"path/filepath"
"github.com/beclab/Olares/cli/pkg/clientset"
"github.com/beclab/Olares/cli/pkg/common"
cc "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
@@ -26,8 +29,8 @@ func (m *InstallAmdRocmModule) Init() {
m.Name = "InstallAMDGPU"
installAmd := &task.RemoteTask{
Name: "InstallAmdRocm",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Name: "InstallAmdRocm",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Action: &InstallAmdRocm{
// no manifest needed
},
@@ -51,7 +54,7 @@ func (t *InstallAmdRocm) Execute(runtime connector.Runtime) error {
return nil
}
amdGPUExists, err := utils.HasAmdIGPU(runtime)
amdGPUExists, err := connector.HasAmdAPUOrGPU(runtime)
if err != nil {
return err
}
@@ -59,7 +62,7 @@ func (t *InstallAmdRocm) Execute(runtime connector.Runtime) error {
if !amdGPUExists {
return nil
}
rocmV, _ := utils.RocmVersion()
rocmV, _ := connector.RocmVersion()
min := semver.MustParse("7.1.1")
if rocmV != nil && rocmV.LessThan(min) {
return fmt.Errorf("detected ROCm version %s, which is lower than required %s; please uninstall existing ROCm/AMDGPU components before installation with command: olares-cli amdgpu uninstall", rocmV.Original(), min.Original())
@@ -131,3 +134,163 @@ func (t *AmdgpuUninstallAction) Execute(runtime connector.Runtime) error {
logger.Warn("Warning: Please reboot your machine after uninstall to fully remove ROCm components.")
return nil
}
// UpdateAmdContainerToolkitSource configures the AMD container toolkit APT repository.
type UpdateAmdContainerToolkitSource struct {
common.KubeAction
}
func (t *UpdateAmdContainerToolkitSource) Execute(runtime connector.Runtime) error {
// Install prerequisites
if _, err := runtime.GetRunner().SudoCmd("apt update && apt install -y wget gnupg2", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install prerequisites for AMD container toolkit")
}
if _, err := runtime.GetRunner().SudoCmd("install -d -m 0755 /etc/apt/keyrings", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create /etc/apt/keyrings directory")
}
cmd := "wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | gpg --dearmor | tee /etc/apt/keyrings/rocm.gpg > /dev/null"
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to download and install AMD ROCm GPG key")
}
si := runtime.GetSystemInfo()
var ubuntuCodename string
if si.IsUbuntuVersionEqual(connector.Ubuntu2404) {
ubuntuCodename = "noble"
} else if si.IsUbuntuVersionEqual(connector.Ubuntu2204) {
ubuntuCodename = "jammy"
} else {
return fmt.Errorf("unsupported Ubuntu version for AMD container toolkit")
}
aptSourceLine := fmt.Sprintf("deb [signed-by=/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/amd-container-toolkit/apt/ %s main", ubuntuCodename)
cmd = fmt.Sprintf("echo '%s' > /etc/apt/sources.list.d/amd-container-toolkit.list", aptSourceLine)
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to add AMD container toolkit APT source")
}
logger.Infof("AMD container toolkit repository configured successfully")
return nil
}
// InstallAmdContainerToolkit installs the AMD container toolkit package.
type InstallAmdContainerToolkit struct {
common.KubeAction
}
func (t *InstallAmdContainerToolkit) Execute(runtime connector.Runtime) error {
logger.Infof("Installing AMD container toolkit...")
if _, err := runtime.GetRunner().SudoCmd("apt update && apt install -y amd-container-toolkit", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install AMD container toolkit")
}
logger.Infof("AMD container toolkit installed successfully")
return nil
}
// GenerateAndValidateAmdCDI generates and validates the AMD CDI spec.
type GenerateAndValidateAmdCDI struct {
common.KubeAction
}
func (t *GenerateAndValidateAmdCDI) Execute(runtime connector.Runtime) error {
// Ensure /etc/cdi directory exists
if _, err := runtime.GetRunner().SudoCmd("install -d -m 0755 /etc/cdi", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create /etc/cdi directory")
}
// Generate CDI spec
logger.Infof("Generating AMD CDI spec...")
if _, err := runtime.GetRunner().SudoCmd("amd-ctk cdi generate --output=/etc/cdi/amd.json", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to generate AMD CDI spec")
}
// Validate CDI spec
logger.Infof("Validating AMD CDI spec...")
if _, err := runtime.GetRunner().SudoCmd("amd-ctk cdi validate --path=/etc/cdi/amd.json", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to validate AMD CDI spec")
}
logger.Infof("AMD CDI spec generated and validated successfully")
return nil
}
// UpdateNodeAmdGPUInfo updates Kubernetes node labels with AMD GPU information.
type UpdateNodeAmdGPUInfo struct {
common.KubeAction
}
func (u *UpdateNodeAmdGPUInfo) Execute(runtime connector.Runtime) error {
client, err := clientset.NewKubeClient()
if err != nil {
return errors.Wrap(errors.WithStack(err), "kubeclient create error")
}
// Check if AMD GPU/APU exists
amdGPUExists, err := connector.HasAmdAPUOrGPU(runtime)
if err != nil {
return err
}
if !amdGPUExists {
logger.Info("AMD GPU/APU is not detected")
return nil
}
// Get ROCm version
rocmV, err := connector.RocmVersion()
if err != nil || rocmV == nil {
logger.Info("ROCm is not installed")
return nil
}
rocmVersion := rocmV.Original()
// Determine GPU type (APU vs discrete GPU)
gpuType := gpu.AmdGpuCardType
if runtime.GetSystemInfo().IsAmdApu() {
gpuType = gpu.AmdApuCardType
}
// Use ROCm version as both driver and "cuda" version for AMD
return gpu.UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), &rocmVersion, nil, nil, &gpuType)
}
// InstallAmdPlugin installs the AMD GPU device plugin DaemonSet.
type InstallAmdPlugin struct {
common.KubeAction
}
func (t *InstallAmdPlugin) Execute(runtime connector.Runtime) error {
amdPluginPath := path.Join(runtime.GetInstallerDir(), "wizard/config/gpu/nvidia/amdgpu-device-plugin.yaml")
_, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("kubectl apply -f %s", amdPluginPath), false, true)
if err != nil {
return errors.Wrap(errors.WithStack(err), "failed to apply AMD GPU device plugin")
}
logger.Infof("AMD GPU device plugin installed successfully")
return nil
}
// CheckAmdGpuStatus checks if the AMD GPU device plugin pod is running.
type CheckAmdGpuStatus struct {
common.KubeAction
}
func (t *CheckAmdGpuStatus) Execute(runtime connector.Runtime) error {
kubectlpath, err := util.GetCommand(common.CommandKubectl)
if err != nil {
return fmt.Errorf("kubectl not found")
}
// Check AMD device plugin pod status using the label from amdgpu-device-plugin.yaml
selector := "name=amdgpu-dp-ds"
cmd := fmt.Sprintf("%s get pod -n kube-system -l '%s' -o jsonpath='{.items[*].status.phase}'", kubectlpath, selector)
rphase, _ := runtime.GetRunner().SudoCmd(cmd, false, false)
if rphase == "Running" {
logger.Infof("AMD GPU device plugin is running")
return nil
}
return fmt.Errorf("AMD GPU device plugin state is not Running (current: %s)", rphase)
}

View File

@@ -59,7 +59,7 @@ func (t *PatchTask) Execute(runtime connector.Runtime) error {
pre_reqs = pre_reqs + " network-manager "
}
pre_reqs += " conntrack socat apache2-utils net-tools make gcc bison flex tree unzip "
pre_reqs += " conntrack socat apache2-utils net-tools make gcc bison flex tree unzip lshw"
var systemInfo = runtime.GetSystemInfo()
var platformFamily = systemInfo.GetOsPlatformFamily()

View File

@@ -338,7 +338,9 @@ func (c *CudaChecker) Name() string {
}
func (c *CudaChecker) Check(runtime connector.Runtime) error {
if !runtime.GetSystemInfo().IsLinux() {
if !runtime.GetSystemInfo().IsLinux() ||
// Skip check on NVIDIA DGX Spark systems, which have their own GPU management
runtime.GetSystemInfo().IsGB10Chip() {
return nil
}
@@ -388,17 +390,17 @@ func (r *RocmChecker) Check(runtime connector.Runtime) error {
return nil
}
// detect AMD GPU presence
amdGPUExists, err := utils.HasAmdIGPU(runtime)
// detect AMD APU/GPU presence
amdGPUExists, err := connector.HasAmdAPUOrGPU(runtime)
if err != nil {
return err
}
// no AMD GPU found, no need to check rocm
// no AMD APU/GPU found, no need to check rocm
if !amdGPUExists {
return nil
}
curV, err := utils.RocmVersion()
curV, err := connector.RocmVersion()
if err != nil && !os.IsNotExist(err) {
return err
}

View File

@@ -159,6 +159,7 @@ const (
CommandUpdatePciids = "update-pciids"
CommandNmcli = "nmcli"
CommandZRAMCtl = "zramctl"
CommandChronyc = "chronyc"
CacheCommandKubectlPath = "kubectl_bin_path"
CacheCommandMinikubePath = "minikube_bin_path"

View File

@@ -210,7 +210,11 @@ func NewArgument() *Argument {
arg.IsCloudInstance, _ = strconv.ParseBool(os.Getenv(ENV_TERMINUS_IS_CLOUD_VERSION))
arg.IsOlaresInContainer = os.Getenv(ENV_CONTAINER_MODE) == "oic"
si.IsOIC = arg.IsOlaresInContainer
si.ProductName = arg.GetProductName()
// Ensure BaseDir is initialized before loading master.conf
// so master host config can be loaded from ${base-dir}/master.conf reliably.
arg.SetBaseDir(viper.GetString(FlagBaseDir))
arg.loadMasterHostConfig()
return arg
}
@@ -382,6 +386,10 @@ func (a *Argument) loadMasterHostConfig() {
}
}
func (a *Argument) ClearMasterHostConfig() {
a.MasterHostConfig = &MasterHostConfig{}
}
func (a *Argument) SetManifest(manifest string) {
a.Manifest = manifest
}
@@ -408,6 +416,57 @@ func (a *Argument) SetSwapConfig(config SwapConfig) {
a.Swappiness = config.Swappiness
}
func (a *Argument) SetMasterHostOverride(config MasterHostConfig) {
if config.MasterHost != "" {
a.MasterHost = config.MasterHost
}
if config.MasterNodeName != "" {
a.MasterNodeName = config.MasterNodeName
}
// set a dummy name to bypass validity checks
// as it will be overridden later when the node name is fetched
if a.MasterNodeName == "" {
a.MasterNodeName = "master"
}
if config.MasterSSHPassword != "" {
a.MasterSSHPassword = config.MasterSSHPassword
}
if config.MasterSSHUser != "" {
a.MasterSSHUser = config.MasterSSHUser
}
if config.MasterSSHPort != 0 {
a.MasterSSHPort = config.MasterSSHPort
}
if config.MasterSSHPrivateKeyPath != "" {
a.MasterSSHPrivateKeyPath = config.MasterSSHPrivateKeyPath
}
}
func (a *Argument) LoadMasterHostConfigIfAny() error {
if a.BaseDir == "" {
return errors.New("basedir unset")
}
content, err := os.ReadFile(filepath.Join(a.BaseDir, MasterHostConfigFile))
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
return json.Unmarshal(content, a.MasterHostConfig)
}
func (a *Argument) GetProductName() string {
data, err := os.ReadFile("/sys/class/dmi/id/product_name")
if err != nil {
fmt.Printf("\nCannot get product name on this device, %s\n", err)
return ""
}
return strings.TrimSpace(string(data))
}
func NewKubeRuntime(arg Argument) (*KubeRuntime, error) {
loader := NewLoader(arg)
cluster, err := loader.Load()

View File

@@ -98,4 +98,6 @@ const (
const (
ZfsSnapshotter = "/var/lib/containerd/io.containerd.snapshotter.v1.zfs"
ENV_GB10_CHIP = "GB10_CHIP" // for building images for NVIDIA GB10 Superchip systems
)

View File

@@ -0,0 +1,117 @@
package connector
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/Masterminds/semver/v3"
)
func hasAmdAPU(cmdExec func(s string) (string, error)) (bool, error) {
// Detect by CPU model names that bundle AMD AI NPU/graphics
targets := []string{
"AMD Ryzen AI Max+ 395",
"AMD Ryzen AI Max 390",
"AMD Ryzen AI Max 385",
"AMD Ryzen AI 9 HX 375",
"AMD Ryzen AI 9 HX 370",
"AMD Ryzen AI 9 365",
}
// try lscpu first: extract 'Model name' field
out, err := cmdExec("lscpu 2>/dev/null | awk -F': *' '/^Model name/{print $2; exit}' || true")
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
// fallback to /proc/cpuinfo
out, err = cmdExec("awk -F': *' '/^model name/{print $2; exit}' /proc/cpuinfo 2>/dev/null || true")
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
return false, nil
}
func hasAmdAPUOrGPU(cmdExec func(s string) (string, error)) (bool, error) {
out, err := cmdExec("lspci -d '1002:' 2>/dev/null | grep 'AMD' || true")
if err != nil {
return false, err
}
if out != "" {
return true, nil
}
out, err = cmdExec("lshw -c display -numeric -disable network 2>/dev/null | grep 'vendor: .* \\[1002\\]' || true")
if err != nil {
return false, err
}
if out != "" {
return true, nil
}
return false, nil
}
func HasAmdAPU(execRuntime Runtime) (bool, error) {
return hasAmdAPU(func(s string) (string, error) {
return execRuntime.GetRunner().SudoCmd(s, false, false)
})
}
func HasAmdAPULocal() (bool, error) {
return hasAmdAPU(func(s string) (string, error) {
out, err := exec.Command("sh", "-c", s).Output()
if err != nil {
return "", err
}
return string(out), nil
})
}
func HasAmdAPUOrGPULocal() (bool, error) {
return hasAmdAPUOrGPU(func(s string) (string, error) {
out, err := exec.Command("sh", "-c", s).Output()
if err != nil {
return "", err
}
return string(out), nil
})
}
func HasAmdAPUOrGPU(execRuntime Runtime) (bool, error) {
return hasAmdAPUOrGPU(func(s string) (string, error) {
return execRuntime.GetRunner().SudoCmd(s, false, false)
})
}
func RocmVersion() (*semver.Version, error) {
const rocmVersionFile = "/opt/rocm/.info/version"
data, err := os.ReadFile(rocmVersionFile)
if err != nil {
// no ROCm installed, nothing to check
if os.IsNotExist(err) {
return nil, err
}
return nil, err
}
curStr := strings.TrimSpace(string(data))
cur, err := semver.NewVersion(curStr)
if err != nil {
return nil, fmt.Errorf("invalid rocm version: %s", curStr)
}
return cur, nil
}

View File

@@ -76,6 +76,10 @@ type Systems interface {
IsPveOrPveLxc() bool
IsRaspbian() bool
IsLinux() bool
IsGB10Chip() bool
IsAmdApu() bool
IsAmdGPU() bool
IsAmdGPUOrAPU() bool
IsUbuntu() bool
IsDebian() bool
@@ -111,16 +115,18 @@ type Systems interface {
}
type SystemInfo struct {
HostInfo *HostInfo `json:"host"`
CpuInfo *CpuInfo `json:"cpu"`
DiskInfo *DiskInfo `json:"disk"`
MemoryInfo *MemoryInfo `json:"memory"`
FsInfo *FileSystemInfo `json:"filesystem"`
CgroupInfo *CgroupInfo `json:"cgroup,omitempty"`
LocalIp string `json:"local_ip"`
NatGateway string `json:"nat_gateway"`
PkgManager string `json:"pkg_manager"`
IsOIC bool `json:"is_oic,omitempty"`
HostInfo *HostInfo `json:"host"`
CpuInfo *CpuInfo `json:"cpu"`
DiskInfo *DiskInfo `json:"disk"`
MemoryInfo *MemoryInfo `json:"memory"`
FsInfo *FileSystemInfo `json:"filesystem"`
CgroupInfo *CgroupInfo `json:"cgroup,omitempty"`
LocalIp string `json:"local_ip"`
NatGateway string `json:"nat_gateway"`
PkgManager string `json:"pkg_manager"`
IsOIC bool `json:"is_oic,omitempty"`
ProductName string `json:"product_name,omitempty"`
HasAmdGPU bool `json:"has_amd_gpu,omitempty"`
}
func (s *SystemInfo) IsSupport() error {
@@ -235,6 +241,22 @@ func (s *SystemInfo) IsLinux() bool {
return s.HostInfo.OsType == common.Linux
}
func (s *SystemInfo) IsGB10Chip() bool {
return s.CpuInfo.IsGB10Chip
}
func (s *SystemInfo) IsAmdApu() bool {
return s.CpuInfo.HasAmdAPU
}
func (s *SystemInfo) IsAmdGPU() bool {
return s.HasAmdGPU
}
func (s *SystemInfo) IsAmdGPUOrAPU() bool {
return s.CpuInfo.HasAmdAPU || s.HasAmdGPU
}
func (s *SystemInfo) IsUbuntu() bool {
return s.HostInfo.OsPlatformFamily == common.Ubuntu
}
@@ -322,6 +344,12 @@ func GetSystemInfo() *SystemInfo {
si.MemoryInfo = getMem()
si.FsInfo = getFs()
hasAmdGPU, err := getAmdGPU()
if err != nil {
panic(errors.Wrap(err, "failed to get amd apu/gpu"))
}
si.HasAmdGPU = hasAmdGPU
localIP, err := util.GetLocalIP()
if err != nil {
panic(errors.Wrap(err, "failed to get local ip"))
@@ -437,6 +465,28 @@ type CpuInfo struct {
CpuModel string `json:"cpu_model"`
CpuLogicalCount int `json:"cpu_logical_count"`
CpuPhysicalCount int `json:"cpu_physical_count"`
IsGB10Chip bool `json:"is_gb10_chip,omitempty"`
HasAmdAPU bool `json:"has_amd_apu,omitempty"`
}
// Not considering the case where AMD GPU and AMD APU coexist.
func getAmdGPU() (bool, error) {
APUOrGPUExists, err := HasAmdAPUOrGPULocal()
if err != nil {
fmt.Printf("Error checking AMD APU/GPU: %v\n", err)
return false, err
}
hasAmdAPU, err := HasAmdAPULocal()
if err != nil {
fmt.Printf("Error checking AMD APU: %v\n", err)
return false, err
}
if APUOrGPUExists && !hasAmdAPU {
return true, nil
}
return false, nil
}
func getCpu() *CpuInfo {
@@ -452,10 +502,35 @@ func getCpu() *CpuInfo {
cpuModel = cpuInfo[0].ModelName
}
// check if is GB10 chip
isGB10Chip := false
// In Linux systems, it is recognized via lspci as "NVIDIA Corporation Device 2e12 (rev a1)
// or NVIDIA Corporation GB20B [GB10] (rev a1)
cmd := exec.Command("sh", "-c", "lspci | grep -i vga | egrep 'GB10|2e12'")
output, err := cmd.Output()
if err == nil && strings.TrimSpace(string(output)) != "" {
isGB10Chip = true
} else {
gb10env := os.Getenv(common.ENV_GB10_CHIP)
if gb10env == "1" || strings.EqualFold(gb10env, "true") {
isGB10Chip = true
}
}
// check if it has amd igpu
hasAmdAPU, err := HasAmdAPULocal()
if err != nil {
fmt.Printf("Error checking AMD iGPU: %v\n", err)
hasAmdAPU = false
}
return &CpuInfo{
CpuModel: cpuModel,
CpuLogicalCount: cpuLogicalCount,
CpuPhysicalCount: cpuPhysicalCount,
IsGB10Chip: isGB10Chip,
HasAmdAPU: hasAmdAPU,
}
}

View File

@@ -27,7 +27,7 @@ var (
ETCDService = template.Must(template.New("etcd.service").Parse(
dedent.Dedent(`[Unit]
Description=etcd
After=network.target
After=network-online.target
StartLimitIntervalSec=0
[Service]

View File

@@ -37,6 +37,11 @@ type CudaInstalled struct {
}
func (p *CudaInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
if runtime.GetSystemInfo().IsGB10Chip() {
logger.Debug("Assume DGX Spark or GB10 OEM system has CUDA installed")
return true, nil
}
st, err := utils.GetNvidiaStatus(runtime)
if err != nil {
return false, err
@@ -50,17 +55,15 @@ func (p *CudaInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
type CudaNotInstalled struct {
common.KubePrepare
CudaInstalled
}
func (p *CudaNotInstalled) PreCheck(runtime connector.Runtime) (bool, error) {
st, err := utils.GetNvidiaStatus(runtime)
installed, err := p.CudaInstalled.PreCheck(runtime)
if err != nil {
return false, err
}
if st == nil || !st.Installed {
return true, nil
}
return false, nil
return !installed, nil
}
type CurrentNodeInK8s struct {

View File

@@ -325,7 +325,8 @@ func (t *CheckGpuStatus) Execute(runtime connector.Runtime) error {
return fmt.Errorf("kubectl not found")
}
cmd := fmt.Sprintf("%s get pod -n kube-system -l 'app.kubernetes.io/component=hami-device-plugin' -o jsonpath='{.items[*].status.phase}'", kubectlpath)
selector := "app.kubernetes.io/component=hami-device-plugin"
cmd := fmt.Sprintf("%s get pod -n kube-system -l '%s' -o jsonpath='{.items[*].status.phase}'", kubectlpath, selector)
rphase, _ := runtime.GetRunner().SudoCmd(cmd, false, false)
if rphase == "Running" {
@@ -363,7 +364,16 @@ func (u *UpdateNodeGPUInfo) Execute(runtime connector.Runtime) error {
driverVersion = st.LibraryVersion
}
return UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), &driverVersion, &st.CudaVersion, &supported)
// TODO:
gpuType := NvidiaCardType
switch {
case runtime.GetSystemInfo().IsAmdApu():
gpuType = AmdApuCardType
case runtime.GetSystemInfo().IsGB10Chip():
gpuType = GB10ChipType
}
return UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), &driverVersion, &st.CudaVersion, &supported, &gpuType)
}
type RemoveNodeLabels struct {
@@ -376,12 +386,12 @@ func (u *RemoveNodeLabels) Execute(runtime connector.Runtime) error {
return errors.Wrap(errors.WithStack(err), "kubeclient create error")
}
return UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), nil, nil, nil)
return UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), nil, nil, nil, nil)
}
// update k8s node labels gpu.bytetrade.io/driver and gpu.bytetrade.io/cuda.
// if labels are not exists, create it.
func UpdateNodeGpuLabel(ctx context.Context, client kubernetes.Interface, driver, cuda *string, supported *string) error {
func UpdateNodeGpuLabel(ctx context.Context, client kubernetes.Interface, driver, cuda *string, supported *string, gpuType *string) error {
// get node name from hostname
nodeName, err := os.Hostname()
if err != nil {
@@ -408,6 +418,7 @@ func UpdateNodeGpuLabel(ctx context.Context, client kubernetes.Interface, driver
{GpuDriverLabel, driver},
{GpuCudaLabel, cuda},
{GpuCudaSupportedLabel, supported},
{GpuType, gpuType},
} {
old, ok := labels[label.key]
switch {

View File

@@ -8,4 +8,13 @@ var (
GpuDriverLabel = GpuLabelGroup + "/driver"
GpuCudaLabel = GpuLabelGroup + "/cuda"
GpuCudaSupportedLabel = GpuLabelGroup + "/cuda-supported"
GpuType = GpuLabelGroup + "/type"
)
const (
NvidiaCardType = "nvidia" // handling by HAMi
AmdGpuCardType = "amd-gpu" //
AmdApuCardType = "amd-apu" // AMD APU with integrated GPU , AI Max 395 etc.
GB10ChipType = "nvidia-gb10" // NVIDIA GB10 Superchip & unified system memory
StrixHaloChipType = "strix-halo" // AMD Strix Halo GPU & unified system memory
)

View File

@@ -1,6 +1,7 @@
package cluster
import (
"github.com/beclab/Olares/cli/pkg/amdgpu"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/gpu"
@@ -58,6 +59,12 @@ func (l *linuxInstallPhaseBuilder) installGpuPlugin() phase {
return []module.Module{
&gpu.RestartK3sServiceModule{Skip: !(l.runtime.Arg.Kubetype == common.K3s)},
&gpu.InstallPluginModule{Skip: skipGpuPlugin},
&amdgpu.InstallAmdPluginModule{Skip: func() bool {
if l.runtime.GetSystemInfo().IsAmdGPUOrAPU() {
return false
}
return true
}()},
}
}

View File

@@ -83,6 +83,13 @@ func (l *linuxPhaseBuilder) build() []module.Module {
addModule(gpuModuleBuilder(func() []module.Module {
return []module.Module{
&amdgpu.InstallAmdRocmModule{},
&amdgpu.InstallAmdContainerToolkitModule{Skip: func() bool {
if l.runtime.GetSystemInfo().IsAmdGPUOrAPU() {
return false
}
return true
}(),
},
&gpu.InstallDriversModule{
ManifestModule: manifest.ManifestModule{
Manifest: l.manifestMap,

View File

@@ -18,7 +18,6 @@ func AddNodePipeline() error {
}
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("addnode.log", true)
if err := arg.MasterHostConfig.Validate(); err != nil {

View File

@@ -19,7 +19,6 @@ func ChangeIPPipeline() error {
var arg = common.NewArgument()
arg.SetOlaresVersion(terminusVersion)
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("changeip.log", true)
arg.SetKubeVersion(kubeType)
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))

View File

@@ -12,7 +12,6 @@ import (
func CheckDownloadInstallationPackage() error {
arg := common.NewArgument()
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {

View File

@@ -13,7 +13,6 @@ import (
func DownloadInstallationPackage() error {
arg := common.NewArgument()
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetOlaresCDNService(viper.GetString(common.FlagCDNService))

View File

@@ -13,7 +13,6 @@ import (
func DownloadInstallationWizard() error {
arg := common.NewArgument()
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetOlaresCDNService(viper.GetString(common.FlagCDNService))
runtime, err := common.NewKubeRuntime(*arg)

View File

@@ -15,7 +15,6 @@ import (
func InstallGpuDrivers() error {
arg := common.NewArgument()
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("gpuinstall.log", true)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {

View File

@@ -20,7 +20,6 @@ func CliInstallTerminusPipeline() error {
}
arg := common.NewArgument()
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetKubeVersion(viper.GetString(common.FlagKubeType))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))

View File

@@ -8,7 +8,6 @@ import (
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/beclab/Olares/cli/pkg/terminus"
"github.com/spf13/viper"
)
func MasterInfoPipeline() error {
@@ -17,7 +16,6 @@ func MasterInfoPipeline() error {
fmt.Println("error: Only Linux nodes can be added to an Olares cluster!")
os.Exit(1)
}
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("masterinfo.log", true)
if err := arg.MasterHostConfig.Validate(); err != nil {

View File

@@ -11,7 +11,6 @@ import (
func StartPreCheckPipeline() error {
var arg = common.NewArgument()
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("precheck.log", true)
runtime, err := common.NewKubeRuntime(*arg)

View File

@@ -28,7 +28,6 @@ func PrepareSystemPipeline(components []string) error {
}
var arg = common.NewArgument()
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetKubeVersion(viper.GetString(common.FlagKubeType))
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))

View File

@@ -18,7 +18,6 @@ func CliInstallStoragePipeline() error {
}
arg := common.NewArgument()
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetStorage(getStorageConfig())

View File

@@ -20,10 +20,10 @@ func UninstallTerminusPipeline() error {
var arg = common.NewArgument()
arg.SetOlaresVersion(version)
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetConsoleLog("uninstall.log", true)
arg.SetKubeVersion(kubeType)
arg.SetStorage(getStorageConfig())
arg.ClearMasterHostConfig()
phase := viper.GetString(common.FlagUninstallPhase)
all := viper.GetBool(common.FlagUninstallAll)

View File

@@ -30,13 +30,7 @@ func UpgradeOlaresPipeline() error {
return fmt.Errorf("error parsing current Olares version: %v", err)
}
// should only be and defaults to the current cli version
// this argument is for backwards-compatibility with older olaresd
targetVersionStr := viper.GetString(common.FlagVersion)
if targetVersionStr == "" {
targetVersionStr = version.VERSION
}
targetVersion, err := utils.ParseOlaresVersionString(targetVersionStr)
targetVersion, err := utils.ParseOlaresVersionString(version.VERSION)
if err != nil {
return fmt.Errorf("error parsing target Olares version: %v", err)
}
@@ -46,7 +40,6 @@ func UpgradeOlaresPipeline() error {
}
arg := common.NewArgument()
arg.SetBaseDir(viper.GetString(common.FlagBaseDir))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetConsoleLog("upgrade.log", true)
arg.SetKubeVersion(phase.GetKubeType())

View File

@@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/util"
)
@@ -57,6 +58,10 @@ func (m *Manager) Package() error {
return err
}
if err := m.packageEnvConfig(); err != nil {
return err
}
return nil
}
@@ -121,3 +126,19 @@ func (m *Manager) packageGPU() error {
filepath.Join(m.distPath, "wizard/config/gpu"),
)
}
func (m *Manager) packageEnvConfig() error {
fmt.Println("packaging env config ...")
systemEnvSrc := filepath.Join(m.olaresRepoRoot, "build", common.OLARES_SYSTEM_ENV_FILENAME)
userEnvSrc := filepath.Join(m.olaresRepoRoot, "build", common.OLARES_USER_ENV_FILENAME)
if err := util.CopyFile(systemEnvSrc, filepath.Join(m.distPath, common.OLARES_SYSTEM_ENV_FILENAME)); err != nil {
return err
}
if err := util.CopyFile(userEnvSrc, filepath.Join(m.distPath, common.OLARES_USER_ENV_FILENAME)); err != nil {
return err
}
return nil
}

View File

@@ -116,8 +116,14 @@ func (m *CheckPreparedModule) Init() {
Action: &CheckPrepared{Force: m.Force},
}
checkTimeSync := &task.LocalTask{
Name: "CheckTimeSynced",
Action: &WaitTimeSyncTask{},
}
m.Tasks = []task.Interface{
checkPrepared,
checkTimeSync,
}
}

View File

@@ -125,6 +125,11 @@ func (t *CreateUserEnvConfigMap) Execute(runtime connector.Runtime) error {
return nil
}
desiredBytes, err := os.ReadFile(userEnvPath)
if err != nil {
return errors.Wrap(err, "failed to read user env config file")
}
configK8s, err := ctrl.GetConfig()
if err != nil {
return errors.Wrap(err, "failed to get kubernetes config")
@@ -144,17 +149,24 @@ func (t *CreateUserEnvConfigMap) Execute(runtime connector.Runtime) error {
defer cancel()
name := "user-env"
namespace := common.NamespaceOsFramework
cm := &corev1.ConfigMap{}
err = ctrlclient.Get(ctx, types.NamespacedName{Name: name, Namespace: common.NamespaceOsFramework}, cm)
err = ctrlclient.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, cm)
if apierrors.IsNotFound(err) {
// create via kubectl from file
kubectl, _ := util.GetCommand(common.CommandKubectl)
cmd := fmt.Sprintf("%s -n %s create configmap %s --from-file=%s=%s",
kubectl, common.NamespaceOsFramework, name, common.OLARES_USER_ENV_FILENAME, userEnvPath,
)
if _, cerr := runtime.GetRunner().SudoCmd(cmd, false, true); cerr != nil {
return errors.Wrap(errors.WithStack(cerr), "failed to create user-env configmap")
cm = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string]string{
common.OLARES_USER_ENV_FILENAME: string(desiredBytes),
},
}
if err := ctrlclient.Create(ctx, cm); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrap(err, "failed to create user-env configmap")
}
logger.Infof("Created user env configmap from %s", userEnvPath)
return nil
}
@@ -162,57 +174,21 @@ func (t *CreateUserEnvConfigMap) Execute(runtime connector.Runtime) error {
return errors.Wrap(err, "failed to get user-env configmap")
}
// If exists, merge missing envs and update via client
newDataBytes, err := os.ReadFile(userEnvPath)
if err != nil {
return errors.Wrap(err, "failed to read user env config file")
}
var newCfg UserEnvConfig
if err := yaml.Unmarshal(newDataBytes, &newCfg); err != nil {
return errors.Wrap(err, "failed to parse user env config file")
}
var existingCfg UserEnvConfig
existingContent := cm.Data[common.OLARES_USER_ENV_FILENAME]
if existingContent != "" {
if err := yaml.Unmarshal([]byte(existingContent), &existingCfg); err != nil {
return errors.Wrap(err, "failed to parse existing user env configmap data")
}
}
existingSet := make(map[string]struct{}, len(existingCfg.UserEnvs))
for _, e := range existingCfg.UserEnvs {
existingSet[e.EnvName] = struct{}{}
}
missing := 0
for _, e := range newCfg.UserEnvs {
if _, ok := existingSet[e.EnvName]; !ok {
existingCfg.UserEnvs = append(existingCfg.UserEnvs, e)
missing++
}
}
if missing == 0 {
logger.Infof("No new user envs to add; configmap up to date")
return nil
}
updatedBytes, err := yaml.Marshal(existingCfg)
if err != nil {
return errors.Wrap(err, "failed to marshal updated user env config")
}
if cm.Data == nil {
cm.Data = map[string]string{}
}
cm.Data[common.OLARES_USER_ENV_FILENAME] = string(updatedBytes)
if cm.Data[common.OLARES_USER_ENV_FILENAME] == string(desiredBytes) {
logger.Infof("user-env configmap is up to date")
return nil
}
cm.Data[common.OLARES_USER_ENV_FILENAME] = string(desiredBytes)
if err := ctrlclient.Update(ctx, cm); err != nil {
return errors.Wrap(err, "failed to update user-env configmap")
}
logger.Infof("Appended %d missing user env(s) and updated configmap", missing)
logger.Infof("Updated user env configmap from %s", userEnvPath)
return nil
}

View File

@@ -1033,3 +1033,37 @@ func (a *SaveMasterHostConfig) Execute(runtime connector.Runtime) error {
}
return os.WriteFile(filepath.Join(runtime.GetBaseDir(), common.MasterHostConfigFile), content, 0644)
}
type WaitTimeSyncTask struct {
common.KubeAction
}
func (t *WaitTimeSyncTask) Execute(runtime connector.Runtime) error {
if chronyc, err := util.GetCommand(common.CommandChronyc); err == nil && chronyc != "" {
ticker := time.NewTicker(2 * time.Second)
timeout := time.NewTimer(5 * time.Minute)
defer ticker.Stop()
defer timeout.Stop()
for {
select {
case <-ticker.C:
// output format:
// 68839BAF,104.131.155.175,3,1772592384.619310832,-0.001840593,0.001674238,0.001874871,-5.194,-0.001,0.112,0.162520304,0.010412607,1035.0,Normal
if res, err := runtime.GetRunner().Cmd(fmt.Sprintf("%s -c tracking", chronyc), false, true); err != nil {
logger.Errorf("failed to execute chronyc tracking: %v", err)
return err
} else {
resToken := strings.Split(res, ",")
// if the stratum of the server is 10 which means the local reference (hardware RTC) is active.
if strings.ToLower(resToken[2]) != "10" { // Stratum
logger.Infof("time synchronization is normal")
return nil
}
}
case <-timeout.C:
return fmt.Errorf("timeout waiting for time synchronization")
}
}
}
return nil
}

View File

@@ -9,7 +9,6 @@ import (
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/utils"
)
type WelcomeMessage struct {
@@ -73,7 +72,7 @@ func (t *WelcomeMessage) Execute(runtime connector.Runtime) error {
// If AMD GPU on Ubuntu 22.04/24.04, print warning about reboot for ROCm
if si := runtime.GetSystemInfo(); si.IsUbuntu() && (si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
if hasAmd, _ := utils.HasAmdIGPU(runtime); hasAmd {
if hasAmd, _ := connector.HasAmdAPUOrGPU(runtime); hasAmd {
logger.Warnf("\x1b[31mWarning: To enable ROCm, please reboot your machine after activation.\x1b[0m")
fmt.Println()
}

View File

@@ -7,19 +7,19 @@ import (
"github.com/beclab/Olares/cli/pkg/core/task"
)
type upgrader_1_12_6_20260122 struct {
type upgrader_1_12_5_20260225 struct {
breakingUpgraderBase
}
func (u upgrader_1_12_6_20260122) Version() *semver.Version {
return semver.MustParse("1.12.6-20260122")
func (u upgrader_1_12_5_20260225) Version() *semver.Version {
return semver.MustParse("1.12.5-20260225")
}
func (u upgrader_1_12_6_20260122) UpgradeSystemComponents() []task.Interface {
func (u upgrader_1_12_5_20260225) UpgradeSystemComponents() []task.Interface {
pre := []task.Interface{
&task.LocalTask{
Name: "UpgradeL4BFLProxy",
Action: &upgradeL4BFLProxy{Tag: "v0.3.10"},
Action: &upgradeL4BFLProxy{Tag: "v0.3.11"},
Retry: 3,
Delay: 5 * time.Second,
},
@@ -28,5 +28,5 @@ func (u upgrader_1_12_6_20260122) UpgradeSystemComponents() []task.Interface {
}
func init() {
registerDailyUpgrader(upgrader_1_12_6_20260122{})
registerDailyUpgrader(upgrader_1_12_5_20260225{})
}

View File

@@ -380,7 +380,7 @@ func (a *upgradeGPUDriverIfNeeded) Execute(runtime connector.Runtime) error {
if err != nil {
return errors.Wrap(errors.WithStack(err), "kubeclient create error")
}
err = gpu.UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), &targetDriverVersionStr, ptr.To(common.CurrentVerifiedCudaVersion), ptr.To("true"))
err = gpu.UpdateNodeGpuLabel(context.Background(), client.Kubernetes(), &targetDriverVersionStr, ptr.To(common.CurrentVerifiedCudaVersion), ptr.To("true"), ptr.To(gpu.NvidiaCardType))
if err != nil {
return err
}

View File

@@ -1,67 +0,0 @@
package utils
import (
"fmt"
"os"
"strings"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/core/connector"
)
func HasAmdIGPU(execRuntime connector.Runtime) (bool, error) {
// Detect by CPU model names that bundle AMD AI NPU/graphics
targets := []string{
"AMD Ryzen AI Max+ 395",
"AMD Ryzen AI Max 390",
"AMD Ryzen AI Max 385",
"AMD Ryzen AI 9 HX 375",
"AMD Ryzen AI 9 HX 370",
"AMD Ryzen AI 9 365",
}
// try lscpu first: extract 'Model name' field
out, err := execRuntime.GetRunner().SudoCmd("lscpu 2>/dev/null | awk -F': *' '/^Model name/{print $2; exit}' || true", false, false)
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
// fallback to /proc/cpuinfo
out, err = execRuntime.GetRunner().SudoCmd("awk -F': *' '/^model name/{print $2; exit}' /proc/cpuinfo 2>/dev/null || true", false, false)
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
return false, nil
}
func RocmVersion() (*semver.Version, error) {
const rocmVersionFile = "/opt/rocm/.info/version"
data, err := os.ReadFile(rocmVersionFile)
if err != nil {
// no ROCm installed, nothing to check
if os.IsNotExist(err) {
return nil, err
}
return nil, err
}
curStr := strings.TrimSpace(string(data))
cur, err := semver.NewVersion(curStr)
if err != nil {
return nil, fmt.Errorf("invalid rocm version: %s", curStr)
}
return cur, nil
}

View File

@@ -11,6 +11,13 @@ func AssertPodReady(pod *corev1.Pod) error {
return fmt.Errorf("pod is nil")
}
// simply ignore finished pod
// it can be seen as just an execution record, not a running pod
// and the deployment will create a new replica
if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
return nil
}
podKey := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)
if pod.DeletionTimestamp != nil {
return fmt.Errorf("pod %s is terminating", podKey)

View File

@@ -1,7 +1,7 @@
project_name: olaresd
builds:
- env:
- CGO_ENABLED=0
- CGO_ENABLED=1
# - CC=aarch64-linux-gnu-gcc
# - CXX=aarch64-linux-gnu-g++
main: ./cmd/terminusd/main.go
@@ -17,6 +17,12 @@ builds:
goamd64: v1
env:
- CGO_ENABLED=1
- goarch: arm64
goos: linux
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
- CXX=aarch64-linux-gnu-g++
tags:
containers_image_openpgp
ldflags:

View File

@@ -20,6 +20,9 @@ build: fmt vet ;$(info $(M)...Begin to build terminusd.) @
build-linux: fmt vet ;$(info $(M)...Begin to build terminusd (linux version).) @
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o bin/olaresd cmd/terminusd/main.go
build-arm: fmt vet ;$(info $(M)...Begin to build terminusd (linux version).) @
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o bin/olaresd cmd/terminusd/main.go
build-linux-in-docker:
docker run -it --platform linux/amd64 --rm \
-v $(current_dir):/olaresd \
@@ -27,3 +30,11 @@ build-linux-in-docker:
-e DEBIAN_FRONTEND=noninteractive \
golang:1.24.11 \
sh -c "apt-get -y update; apt-get -y install libudev-dev libpcap-dev; make build-linux"
build-arm-in-docker:
docker run -it --platform linux/arm64 --rm \
-v $(current_dir):/olaresd \
-w /olaresd \
-e DEBIAN_FRONTEND=noninteractive \
golang:1.24.11 \
sh -c "apt-get -y update; apt-get -y install libudev-dev libpcap-dev; make build-arm"

View File

@@ -31,7 +31,7 @@ require (
github.com/jaypipes/ghw v0.13.0
github.com/jochenvg/go-udev v0.0.0-20171110120927-d6b62d56d37b
github.com/joho/godotenv v1.5.1
github.com/klauspost/cpuid/v2 v2.2.8
github.com/klauspost/cpuid/v2 v2.3.0
github.com/labstack/echo/v4 v4.0.0-00010101000000-000000000000
github.com/libp2p/go-netroute v0.2.2
github.com/mackerelio/go-osstat v0.2.5

View File

@@ -205,8 +205,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -471,7 +471,6 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=

View File

@@ -1,5 +1,5 @@
//go:build !(linux && amd64)
// +build !linux !amd64
//go:build !linux
// +build !linux
package intranet

View File

@@ -1,5 +1,5 @@
//go:build linux && amd64
// +build linux,amd64
//go:build linux
// +build linux
package intranet

View File

@@ -27,7 +27,7 @@ func WithSerial(ctx context.Context, serial string) context.Context {
}
func (w *usbWatcher) Watch(ctx context.Context) {
retry := 1
retry := 3
devs, err := utils.DetectdUsbDevices(ctx)
for {
if err != nil {

View File

@@ -43,11 +43,12 @@ type state struct {
Disk string `json:"disk"`
// network info
WikiConnected bool `json:"wifiConnected"`
WifiSSID *string `json:"wifiSSID,omitempty"`
WiredConnected bool `json:"wiredConnected"`
HostIP string `json:"hostIp"`
ExternalIP string `json:"externalIp"`
WikiConnected bool `json:"wifiConnected"`
WifiSSID *string `json:"wifiSSID,omitempty"`
WiredConnected bool `json:"wiredConnected"`
HostIP string `json:"hostIp"`
ExternalIP string `json:"externalIp"`
ExternalIPProbeTime time.Time `json:"-"`
// installing / uninstalling / upgrading state
InstallingState ProcessingState `json:"installingState"`
@@ -130,7 +131,8 @@ func CheckCurrentStatus(ctx context.Context) error {
klog.Info("current state: ", CurrentState.TerminusState)
}()
utils.ForceMountHdd(ctx)
// Deprecated, only for Olares Zero
// utils.ForceMountHdd(ctx)
// set default value
if CurrentState.TerminusVersion == nil {
@@ -255,7 +257,10 @@ func CheckCurrentStatus(ctx context.Context) error {
}
CurrentState.HostIP = hostIp
CurrentState.ExternalIP = nets.GetMyExternalIPAddr()
if time.Since(CurrentState.ExternalIPProbeTime) > 1*time.Minute {
CurrentState.ExternalIP = nets.GetMyExternalIPAddr()
CurrentState.ExternalIPProbeTime = time.Now()
}
// get olares state

View File

@@ -181,6 +181,7 @@ var (
// {"installing k8s and kubesphere", "3%", 3},
// {"Generating \"ca\" certificate and key", "3%", 3},
// {"PatchKsCoreStatus success", "6%", 6},
{"time synchronization is normal", "3%", 3},
{"k8s and kubesphere installation is complete", "10%", 10},
{"Installing account ...", "15%", 15},
{"Installing settings ...", "20%", 20},

View File

@@ -4,14 +4,17 @@ import (
"crypto/tls"
"encoding/json"
"errors"
"io/ioutil"
"io"
"net"
"net/http"
"net/netip"
"net/url"
"os"
"strings"
"time"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/gofiber/fiber/v2/log"
"github.com/libp2p/go-netroute"
pkg_errors "github.com/pkg/errors"
"github.com/txn2/txeh"
@@ -267,15 +270,7 @@ func GetHostIpFromHostsFile(domain string) (string, error) {
return ip, nil
}
// GetMyExternalIPAddr get my network outgoing ip address
func GetMyExternalIPAddr() string {
sites := map[string]string{
"httpbin": "https://httpbin.org/ip",
"ifconfigme": "https://ifconfig.me/all.json",
"externalip": "https://myexternalip.com/json",
"joinolares": "https://myip.joinolares.cn/ip",
}
type httpBin struct {
Origin string `json:"origin"`
}
@@ -295,80 +290,80 @@ func GetMyExternalIPAddr() string {
IP string `json:"ip"`
}
var unmarshalFuncs = map[string]func(v []byte) string{
"httpbin": func(v []byte) string {
var hb httpBin
if err := json.Unmarshal(v, &hb); err == nil && hb.Origin != "" {
return hb.Origin
}
return ""
},
"ifconfigme": func(v []byte) string {
var ifMe ifconfigMe
if err := json.Unmarshal(v, &ifMe); err == nil && ifMe.IPAddr != "" {
return ifMe.IPAddr
}
return ""
},
"externalip": func(v []byte) string {
var extip externalIP
if err := json.Unmarshal(v, &extip); err == nil && extip.IP != "" {
return extip.IP
}
return ""
},
"joinolares": func(v []byte) string {
return strings.TrimSpace(string(v))
},
type siteConfig struct {
url string
unmarshalFunc func(v []byte) string
}
ch := make(chan any, len(sites))
for site := range sites {
go func(name string) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
c := http.Client{Timeout: 5 * time.Second}
resp, err := c.Get(sites[name])
if err != nil {
ch <- err
return
}
defer resp.Body.Close()
respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
ch <- err
return
}
ip := unmarshalFuncs[name](respBytes)
//println(name, site, ip)
ch <- ip
}(site)
externalIPServiceURL, err := url.JoinPath(commands.OLARES_REMOTE_SERVICE, "/myip/ip")
if err != nil {
klog.Error("failed to parse external IP service URL, ", err)
return ""
}
tr := time.NewTimer(time.Duration(5*len(sites)+3) * time.Second)
LOOP:
for i := 0; i < len(sites); i++ {
select {
case r, ok := <-ch:
if !ok {
continue
}
switch v := r.(type) {
case string:
ip := net.ParseIP(v)
if ip != nil && ip.To4() != nil && !ip.IsLoopback() && !ip.IsMulticast() {
return v
sites := []siteConfig{
{
url: externalIPServiceURL,
unmarshalFunc: func(v []byte) string {
return strings.TrimSpace(string(v))
},
},
{
url: "https://httpbin.org/ip",
unmarshalFunc: func(v []byte) string {
var hb httpBin
if err := json.Unmarshal(v, &hb); err == nil && hb.Origin != "" {
return hb.Origin
}
case error:
klog.Warningf("got an error, %v", v)
}
case <-tr.C:
tr.Stop()
klog.Warning("timed out")
break LOOP
return ""
},
},
{
url: "https://ifconfig.me/all.json",
unmarshalFunc: func(v []byte) string {
var ifMe ifconfigMe
if err := json.Unmarshal(v, &ifMe); err == nil && ifMe.IPAddr != "" {
return ifMe.IPAddr
}
return ""
},
},
{
url: "https://myexternalip.com/json",
unmarshalFunc: func(v []byte) string {
var extip externalIP
if err := json.Unmarshal(v, &extip); err == nil && extip.IP != "" {
return extip.IP
}
return ""
},
},
}
client := http.Client{
Timeout: 3 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
for _, site := range sites {
resp, err := client.Get(site.url)
if err != nil {
log.Warnf("failed to get external ip from %s, %v", site.url, err)
continue
}
respBytes, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
log.Warnf("failed to read response from %s, %v", site.url, readErr)
continue
}
ipStr := site.unmarshalFunc(respBytes)
ip := net.ParseIP(ipStr)
if ip != nil && ip.To4() != nil && !ip.IsLoopback() && !ip.IsMulticast() {
return ipStr
}
}

View File

@@ -5,6 +5,7 @@ package utils
import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
@@ -42,7 +43,7 @@ func detectdStorageDevices(ctx context.Context, bus string) (usbDevs []storageDe
for _, d := range ds {
if d.Properties()["ID_BUS"] == bus {
usbs = append(usbs, d)
} else if d.Properties()["ID_BUS"] == "ata" &&
} else if (d.Properties()["ID_BUS"] == "ata" || d.Properties()["ID_BUS"] == "scsi") &&
d.Properties()["ID_USB_TYPE"] == "disk" &&
bus == "usb" {
usbs = append(usbs, d)
@@ -97,14 +98,18 @@ func detectdStorageDevices(ctx context.Context, bus string) (usbDevs []storageDe
idSerial := device.Properties()["ID_SERIAL"]
idSerialShort := device.Properties()["ID_SERIAL_SHORT"]
idUsbSerial := device.Properties()["ID_USB_SERIAL"]
idUsbSerialShort := device.Properties()["ID_USB_SERIAL_SHORT"]
partUUID := device.Properties()["ID_PART_ENTRY_UUID"]
usbDevs = append(usbDevs, storageDevice{
DevPath: devPath,
Vender: vender,
IDSerial: idSerial,
IDSerialShort: idSerialShort,
PartitionUUID: partUUID,
DevPath: devPath,
Vender: vender,
IDSerial: idSerial,
IDSerialShort: idSerialShort,
IDUsbSerial: idUsbSerial,
IDUsbSerialShort: idUsbSerialShort,
PartitionUUID: partUUID,
})
}
@@ -199,7 +204,10 @@ func MountedHddPath(ctx context.Context) ([]string, error) {
func FilterBySerial(serial string) func(dev storageDevice) bool {
return func(dev storageDevice) bool {
return strings.HasSuffix(serial, dev.IDSerial) || strings.HasSuffix(serial, dev.IDSerialShort)
return strings.HasSuffix(serial, dev.IDSerial) ||
strings.HasSuffix(serial, dev.IDSerialShort) ||
strings.HasSuffix(serial, dev.IDUsbSerial) ||
strings.HasSuffix(serial, dev.IDUsbSerialShort)
}
}
@@ -270,7 +278,17 @@ func MountUsbDevice(ctx context.Context, mountBaseDir string, dev []storageDevic
continue
}
if err = mounter.Mount(d.DevPath, mkMountDir, "", []string{"uid=1000", "gid=1000"}); err != nil {
options := []string{}
fsType, err := getFsTypeOfDevice(ctx, d.DevPath)
if err != nil {
klog.Warning("get fs type of device error, ", err, ", ", d.DevPath)
} else {
if strings.Contains(fsType, "FAT") || strings.Contains(fsType, "NTFS") {
options = append(options, "uid=1000", "gid=1000")
}
}
if err = mounter.Mount(d.DevPath, mkMountDir, "", options); err != nil {
klog.Warning("mount usb error, ", err, ", ", d.DevPath, ", ", mkMountDir)
// clear the empty mount dir
// do not use remove all, only remove the mount point path, assume it's an empty dir
@@ -685,3 +703,35 @@ func isDeviceExists(devicePath string) bool {
_, err := os.Stat(devicePath)
return !os.IsNotExist(err)
}
func getFsTypeOfDevice(ctx context.Context, devicePath string) (string, error) {
// output format
// {
// "blockdevices": [
// {
// "fstype": "ext4"
// }
// ]
// }
cmd := exec.CommandContext(ctx, "lsblk", "-f", devicePath, "-o", "fstype", "-J")
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
var result struct {
BlockDevices []struct {
FsType string `json:"fstype"`
} `json:"blockdevices"`
}
if err := json.Unmarshal(output, &result); err != nil {
return "", err
}
if len(result.BlockDevices) == 0 {
return "", fmt.Errorf("no block devices found for %s", devicePath)
}
return result.BlockDevices[0].FsType, nil
}

View File

@@ -3,11 +3,13 @@ package utils
import "strings"
type storageDevice struct {
DevPath string
Vender string
IDSerial string
IDSerialShort string
PartitionUUID string
DevPath string
Vender string
IDSerial string
IDSerialShort string
IDUsbSerial string
IDUsbSerialShort string
PartitionUUID string
}
type mountedPath struct {

View File

@@ -0,0 +1,492 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const developerSidebar: DefaultTheme.Sidebar = {
"/developer/": [
{
text: "Concepts",
link: "/developer/concepts/",
items: [
{ text: "Olares architecture", link: "/developer/concepts/system-architecture" },
{
text: "Olares ID",
link: "/developer/concepts/olares-id",
collapsed: true,
items: [
{
text: "Decentralized ID",
link: "/developer/concepts/did",
},
{
text: "Blockchain Registry",
link: "/developer/concepts/registry",
},
{
text: "Verifiable Credential",
link: "/developer/concepts/vc",
},
{
text: "Autonomous Reputation",
link: "/developer/concepts/reputation",
},
// {
// text: "Self-Sovereign Network",
// link: "/developer/concepts/self-sovereign-network",
// },
{
text: "Identity Wallet",
link: "/developer/concepts/wallet",
},
],
},
{ text: "Account", link: "/developer/concepts/account" },
{ text: "Application", link: "/developer/concepts/application" },
{ text: "Network", link: "/developer/concepts/network" },
{ text: "Data", link: "/developer/concepts/data" },
{ text: "Secrets", link: "/developer/concepts/secrets" },
],
},
{
text: "Installation deep-dive",
link: "/developer/install/",
items: [
{
text: "Installation architecture",
link: "/developer/install/installation-overview",
},
{
text: "Installation process",
link: "/developer/install/installation-process",
},
{
text: "Olares Home",
link: "/developer/install/olares-home",
},
{
text: "Environment variables",
link: "/developer/install/environment-variables",
},
{
text: "Olares CLI",
link: "/developer/install/cli/olares-cli",
collapsed: true,
items: [
{ text: "Access Olares terminal", link: "/developer/reference/access-olares-terminal" },
{
text: "backups",
link: "/developer/install/cli/backups",
collapsed: true,
items: [
{ text: "backup", link: "/developer/install/cli/backups-backup" },
{ text: "download", link: "/developer/install/cli/backups-download" },
{ text: "region", link: "/developer/install/cli/backups-region" },
{ text: "restore", link: "/developer/install/cli/backups-restore" },
{ text: "snapshots", link: "/developer/install/cli/backups-snapshots" },
],
},
{ text: "change-ip", link: "/developer/install/cli/change-ip" },
{ text: "disk", link: "/developer/install/cli/disk" },
{ text: "download", link: "/developer/install/cli/download" },
{ text: "gpu", link: "/developer/install/cli/gpu" },
{ text: "info", link: "/developer/install/cli/info" },
{ text: "install", link: "/developer/install/cli/install" },
{ text: "logs", link: "/developer/install/cli/logs" },
{ text: "node", link: "/developer/install/cli/node" },
{ text: "osinfo", link: "/developer/install/cli/osinfo" },
{ text: "precheck", link: "/developer/install/cli/precheck" },
{ text: "prepare", link: "/developer/install/cli/prepare" },
{ text: "release", link: "/developer/install/cli/release" },
{ text: "start", link: "/developer/install/cli/start" },
{ text: "stop", link: "/developer/install/cli/stop" },
{ text: "uninstall", link: "/developer/install/cli/uninstall" },
{ text: "upgrade", link: "/developer/install/cli/upgrade" },
{
text: "user",
link: "/developer/install/cli/user",
collapsed: true,
items: [
{ text: "activate", link: "/developer/install/cli/user-activate" },
{ text: "create", link: "/developer/install/cli/user-create" },
{ text: "delete", link: "/developer/install/cli/user-delete" },
{ text: "get", link: "/developer/install/cli/user-get" },
{ text: "list", link: "/developer/install/cli/user-list" },
{ text: "reset-password", link: "/developer/install/cli/user-reset-password" },
],
},
],
},
{
text: "Olares versioning",
link: "/developer/install/versioning",
},
],
},
{
text: "Develop Olares apps",
link: "/developer/develop/",
items: [
{
text: "Develop with Studio",
collapsed: true,
link: "/developer/develop/tutorial/",
items: [
{
text: "Deploy an app",
link: "/developer/develop/tutorial/deploy",
},
{
text: "Develop in a dev container",
link: "/developer/develop/tutorial/develop",
},
{
text: "Package and upload",
link: "/developer/develop/tutorial/package-upload",
},
{
text: "Add app assets",
link: "/developer/develop/tutorial/assets",
},
],
},
{
text: "Application package",
collapsed: true,
items: [
{
text: "Application chart",
link: "/developer/develop/package/chart",
},
{
text: "OlaresManifest",
link: "/developer/develop/package/manifest",
},
/*{
text: "Recommendation",
link: "/developer/develop/package/recommend",
},*/
{
text: "Helm extension",
link: "/developer/develop/package/extension",
},
],
},
// {
// text: "Advanced",
// collapsed: true,
// items: [
// {
// text: "terminus-info",
// link: "/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service provider",
// link: "/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/developer/develop/advanced/ai",
// },
// { text: "Cookie", link: "/developer/develop/advanced/cookie" },
// { text: "Database", link: "/developer/develop/advanced/database" },
// {
// text: "Account",
// link: "/developer/develop/advanced/account",
// },
// {
// text: "Market",
// link: "/developer/develop/advanced/market",
// },
// {
// text: "Websocket",
// link: "/developer/develop/advanced/websocket",
// },
// {
// text: "File upload",
// link: "/developer/develop/advanced/file-upload",
// },
// {
// text: "Secret",
// link: "/developer/develop/advanced/secret",
// },
// {
// text: "Kubesphere",
// link: "/developer/develop/advanced/kubesphere",
// },
// ],
// },
{
text: "Application environment variables",
link: "/developer/develop/app-env-index",
collapsed: true,
items: [
{
text: "Declarative environment variables",
link: "/developer/develop/app-env-vars",
collapsed: true,
},
{
text: "System-injected variables",
link: "/developer/develop/app-sys-injected-variables",
},
]
},
{
text: "Middleware",
link: "/developer/develop/mw-overview",
collapsed: true,
items: [
/*{
text: "Elasticsearch",
collapsed: true,
items :[
{
text: "Integrate with Elasticsearch",
link: "/developer/develop/mw-integrate-with-es", },
{
text: "View Elasticsearch data",
link: "/developer/develop/mw-view-es-data",
},
]
},*/
{
text: "Grafana",
link :"/developer/develop/mw-view-grafana-data",
},
{
text: "MariaDB",
collapsed: true,
items :[
{
text: "Integrate with MariaDB",
link: "/developer/develop/mw-integrate-with-mariadb", },
{
text: "View MariaDB data",
link: "/developer/develop/mw-view-mariadb-data",
},
]
},
{
text: "MinIO",
collapsed: true,
items :[
{
text: "Integrate with MinIO",
link: "/developer/develop/mw-integrate-with-minio", },
{
text: "View MinIO data",
link: "/developer/develop/mw-view-minio-data",
},
]
},
{
text: "MongoDB",
collapsed: true,
items :[
{
text: "Integrate with MongoDB",
link: "/developer/develop/mw-integrate-with-mongodb", },
{
text: "View MongoDB data",
link: "/developer/develop/mw-view-mongodb-data",
},
]
},
{
text: "MySQL",
collapsed: true,
items :[
{
text: "Integrate with MySQL",
link: "/developer/develop/mw-integrate-with-mysql", },
{
text: "View MySQL data",
link: "/developer/develop/mw-view-mysql-data",
},
]
},
{
text: "NATS",
link :"/developer/develop/mw-view-nats-data",
},
{
text: "OpenTelemetry",
link :"/developer/develop/mw-view-otel-data",
},
{
text: "PostgreSQL",
collapsed: true,
items :[
{
text: "Integrate with PostgreSQL",
link: "/developer/develop/mw-integrate-with-pg", },
{
text: "View PostgreSQL data",
link: "/developer/develop/mw-view-pg-data",
}
]
},
{
text: "RabbitMQ",
collapsed: true,
items :[
{
text: "Integrate with RabbitMQ",
link: "/developer/develop/mw-integrate-with-rabbitmq", },
{
text: "View RabbitMQ data",
link: "/developer/develop/mw-view-rabbitmq-data",
}
]
},
{
text: "Redis",
collapsed: true,
items :[
{
text: "Integrate with Redis",
link: "/developer/develop/mw-integrate-with-redis", },
{
text: "View Redis data",
link: "/developer/develop/mw-view-redis-data",
}
]
},
]
},
],
},
{
text: "Distribute Olares apps",
link: "/developer/develop/distribute-index",
items: [
{
text: "Summit apps",
link: "/developer/develop/submit-apps",
},
{
text: "Manage app lifecycle",
link: "/developer/develop/manage-apps",
},
{
text: "Promote your apps",
link:"/developer/develop/promote-apps"
},
{
text: "Publish paid apps",
link: "/developer/develop/paid-apps",
},
],
},
{
text: "Contribute to Olares",
items: [
{
text: "Develop system app",
collapsed: true,
items: [
{
text: "Overview",
link: "/developer/contribute/system-app/overview",
},
{
text: "Configure deployment",
link: "/developer/contribute/system-app/deployment",
},
{
text: "Configure permissions",
link: "/developer/contribute/system-app/olares-manifest",
},
{
text: "Install",
link: "/developer/contribute/system-app/install",
},
{
text: "Other",
link: "/developer/contribute/system-app/other",
},
],
},
{
text: "Develop protocols",
collapsed: true,
items: [
{
text: "Contract",
link: "/developer/contribute/olares-id/contract/contract",
collapsed: true,
items: [
{
text: "Architecture",
link: "/developer/contribute/olares-id/contract/architecture",
},
{
text: "DID",
collapsed: true,
items: [
{
text: "Design",
link: "/developer/contribute/olares-id/contract/did/design",
},
{
text: "Official Taggers",
link: "/developer/contribute/olares-id/contract/did/official-taggers",
},
{
text: "Release History",
link: "/developer/contribute/olares-id/contract/did/release-history",
},
{
text: "FAQ",
link: "/developer/contribute/olares-id/contract/did/faq",
},
],
},
{
text: "Reputation",
link: "/developer/contribute/olares-id/contract/contract-reputation",
},
{
text: "Manage",
collapsed: true,
items: [
{
text: "Contract",
link: "/developer/contribute/olares-id/contract/manage/contract",
},
{
text: "SDK",
link: "/developer/contribute/olares-id/contract/manage/sdk",
},
{
text: "Environment",
link: "/developer/contribute/olares-id/contract/manage/environment",
},
],
},
],
},
{
text: "Verifiable Credential",
link: "/developer/contribute/olares-id/verifiable-credential/overview",
collapsed: true,
items: [
{
text: "Issuer",
link: "/developer/contribute/olares-id/verifiable-credential/issuer",
},
{
text: "Verifer",
link: "/developer/contribute/olares-id/verifiable-credential/verifer",
},
{
text: "Olares",
link: "/developer/contribute/olares-id/verifiable-credential/olares",
},
],
},
],
},
],
},
],
}

View File

@@ -0,0 +1,507 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const developerSidebar: DefaultTheme.Sidebar = {
"/zh/developer/": [
{
text: "概念",
link: "/zh/developer/concepts/",
items: [
{ text: "系统架构", link: "/zh/developer/concepts/system-architecture" },
{
text: "Olares ID",
link: "/zh/developer/concepts/olares-id",
collapsed: true,
items: [
{
text: "去中心化标识符",
link: "/zh/developer/concepts/did",
},
{
text: "DID Registry",
link: "/zh/developer/concepts/registry",
},
{
text: "可验证凭证",
link: "/zh/developer/concepts/vc",
},
{
text: "自治声誉",
link: "/zh/developer/concepts/reputation",
},
// {
// text: "主权网络",
// link: "/zh/developer/concepts/self-sovereign-network",
// },
{
text: "身份钱包",
link: "/zh/developer/concepts/wallet",
},
],
},
{ text: "账户", link: "/zh/developer/concepts/account" },
{ text: "应用", link: "/zh/developer/concepts/application" },
{ text: "网络", link: "/zh/developer/concepts/network" },
{ text: "数据", link: "/zh/developer/concepts/data" },
{ text: "密钥", link: "/zh/developer/concepts/secrets" },
],
},
{
text: "Olares 安装详解",
link: "/zh/developer/install/",
items: [
{
text: "安装概述",
link: "/zh/developer/install/installation-overview",
},
{
text: "安装流程",
link: "/zh/developer/install/installation-process",
},
{
text: "Olares Home",
link: "/zh/developer/install/olares-home",
},
{
text: "环境变量",
link: "/zh/developer/install/environment-variables",
},
{
text: "Olares CLI",
link: "/zh/developer/install/cli/olares-cli",
collapsed: true,
items: [
{
text: "backups",
link: "/zh/developer/install/cli/backups",
collapsed: true,
items: [
{ text: "backup", link: "/zh/developer/install/cli/backups-backup" },
{ text: "download", link: "/zh/developer/install/cli/backups-download" },
{ text: "region", link: "/zh/developer/install/cli/backups-region" },
{ text: "restore", link: "/zh/developer/install/cli/backups-restore" },
{ text: "snapshots", link: "/zh/developer/install/cli/backups-snapshots" },
],
},
{ text: "change-ip", link: "/zh/developer/install/cli/change-ip" },
{ text: "disk", link: "/zh/developer/install/cli/disk" },
{ text: "download", link: "/zh/developer/install/cli/download" },
{ text: "gpu", link: "/zh/developer/install/cli/gpu" },
{ text: "info", link: "/zh/developer/install/cli/info" },
{ text: "install", link: "/zh/developer/install/cli/install" },
{ text: "logs", link: "/zh/developer/install/cli/logs" },
{ text: "node", link: "/zh/developer/install/cli/node" },
{ text: "osinfo", link: "/zh/developer/install/cli/osinfo" },
{ text: "precheck", link: "/zh/developer/install/cli/precheck" },
{ text: "prepare", link: "/zh/developer/install/cli/prepare" },
{ text: "release", link: "/zh/developer/install/cli/release" },
{ text: "start", link: "/zh/developer/install/cli/start" },
{ text: "stop", link: "/zh/developer/install/cli/stop" },
{ text: "uninstall", link: "/zh/developer/install/cli/uninstall" },
{ text: "upgrade", link: "/zh/developer/install/cli/upgrade" },
{
text: "user",
link: "/zh/developer/install/cli/user",
collapsed: true,
items: [
{ text: "activate", link: "/zh/developer/install/cli/user-activate" },
{ text: "create", link: "/zh/developer/install/cli/user-create" },
{ text: "delete", link: "/zh/developer/install/cli/user-delete" },
{ text: "get", link: "/zh/developer/install/cli/user-get" },
{ text: "list", link: "/zh/developer/install/cli/user-list" },
{ text: "reset-password", link: "/zh/developer/install/cli/user-reset-password" },
],
},
],
},
{
text: "版本说明",
link: "/zh/developer/install/versioning",
},
],
},
{
text: "开发 Olares 应用",
link: "/zh/developer/develop/",
items: [
{
text: "使用 Studio 开发",
collapsed: true,
link: "/zh/developer/develop/tutorial/",
items: [
{
text: "部署应用",
link: "/zh/developer/develop/tutorial/deploy",
},
{
text: "使用开发容器",
link: "/zh/developer/develop/tutorial/develop",
},
{
text: "打包与上传",
link: "/zh/developer/develop/tutorial/package-upload",
},
{
text: "添加应用素材",
link: "/zh/developer/develop/tutorial/assets",
},
],
},
{
text: "应用包管理",
collapsed: true,
items: [
{
text: "应用 Chart 包",
link: "/zh/developer/develop/package/chart",
},
{
text: "OlaresManifest",
link: "/zh/developer/develop/package/manifest",
},
/*{
text: "推荐算法",
link: "/zh/developer/develop/package/recommend",
},*/
{
text: "Helm 扩展",
link: "/zh/developer/develop/package/extension",
},
],
},
// {
// text: "进阶",
// collapsed: true,
// items: [
// {
// text: "terminus-info",
// link: "/zh/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service Provider",
// link: "/zh/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/zh/developer/develop/advanced/ai",
// },
// { text: "Cookie", link: "/zh/developer/develop/advanced/cookie" },
// { text: "数据库", link: "/zh/developer/develop/advanced/database" },
// {
// text: "账户",
// link: "/zh/developer/develop/advanced/account",
// },
// {
// text: "应用市场",
// link: "/zh/developer/develop/advanced/market",
// },
// {
// text: "Analytic",
// link: "/zh/developer/develop/advanced/analytic",
// },
// {
// text: "Websocket",
// link: "/zh/developer/develop/advanced/websocket",
// },
// {
// text: "文件上传",
// link: "/zh/developer/develop/advanced/file-upload",
// },
// {
// text: "Rss",
// link: "/zh/developer/develop/advanced/rss",
// },
// {
// text: "密钥",
// link: "/zh/developer/develop/advanced/secret",
// },
// {
// text: "Notification",
// link: "/zh/developer/develop/advanced/notification",
// },
// {
// text: "Frontend",
// link: "/zh/developer/develop/advanced/frontend",
// },
// {
// text: "Kubesphere",
// link: "/zh/developer/develop/advanced/kubesphere",
// },
// ],
// },
{
text: "应用环境变量",
link: "/zh/developer/develop/app-env-index",
collapsed: true,
items: [
{
text: "声明式环境变量",
link: "/zh/developer/develop/app-env-vars",
},
{
text: "系统注入的运行时变量",
link: "/zh/developer/develop/app-sys-injected-variables",
},
]
},
{
text: "中间件",
link: "/zh/developer/develop/mw-overview",
collapsed: true,
items: [
/*{
text: "Elasticsearch",
collapsed: true,
items :[
{
text: "集成 Elasticsearch",
link: "zh/developer/develop/mw-integrate-with-es", },
{
text: "查看 Elasticsearch 数据",
link: "zh/developer/develop/mw-view-es-data",
},
]
},*/
{
text: "Grafana",
link: "zh/developer/develop/mw-view-grafana-data",
},
{
text: "MariaDB",
collapsed: true,
items :[
{
text: "集成 MariaDB",
link: "zh/developer/develop/mw-integrate-with-mariadb", },
{
text: "查看 MariaDB 数据",
link: "zh/developer/develop/mw-view-mariadb-data",
},
]
},
{
text: "MinIO",
collapsed: true,
items :[
{
text: "集成 MinIO",
link: "zh/developer/develop/mw-integrate-with-minio", },
{
text: "查看 MinIO 数据",
link: "zh/developer/develop/mw-view-minio-data",
},
]
},
{
text: "MongoDB",
collapsed: true,
items :[
{
text: "集成 MongoDB",
link: "zh/developer/develop/mw-integrate-with-mongodb", },
{
text: "查看 MongoDB 数据",
link: "zh/developer/develop/mw-view-mongodb-data",
},
]
},
{
text: "MySQL",
collapsed: true,
items :[
{
text: "集成 MySQL",
link: "zh/developer/develop/mw-integrate-with-mysql", },
{
text: "查看 MySQL 数据",
link: "zh/developer/develop/mw-view-mysql-data",
},
]
},
{
text: "NATS",
link :"zh/developer/develop/mw-view-nats-data",
},
{
text: "OpenTelemetry",
link :"zh/developer/develop/mw-view-otel-data",
},
{
text: "PostgreSQL",
collapsed: true,
items :[
{
text: "集成 PostgreSQL",
link: "zh/developer/develop/mw-integrate-with-pg", },
{
text: "查看 PostgreSQL 数据",
link: "zh/developer/develop/mw-view-pg-data",
}
]
},
{
text: "RabbitMQ",
collapsed: true,
items :[
{
text: "集成 RabbitMQ",
link: "zh/developer/develop/mw-integrate-with-rabbitmq", },
{
text: "查看 RabbitMQ 数据",
link: "zh/developer/develop/mw-view-rabbitmq-data",
}
]
},
{
text: "Redis",
collapsed: true,
items :[
{
text: "集成 Redis",
link: "zh/developer/develop/mw-integrate-with-redis", },
{
text: "查看 Redis 数据",
link: "zh/developer/develop/mw-view-redis-data",
},
]
},
]
},
],
},
{
text: "分发 Olares 应用",
link: "/zh/developer/develop/distribute-index",
items: [
{
text: "提交应用",
link: "/zh/developer/develop/submit-apps",
},
{
text: "管理应用",
link: "/zh/developer/develop/manage-apps",
},
{
text: "推广应用",
link:"/zh/developer/develop/promote-apps"
},
{
text: "发布付费应用",
link: "/zh/developer/develop/paid-apps",
},
],
},
{
text: "参与贡献",
items: [
{
text: "开发系统应用",
collapsed: true,
items: [
{
text: "概述",
link: "/zh/developer/contribute/system-app/overview",
},
{
text: "应用部署配置",
link: "/zh/developer/contribute/system-app/deployment",
},
{
text: "Olares 权限配置",
link: "/zh/developer/contribute/system-app/olares-manifest",
},
{
text: "安装",
link: "/zh/developer/contribute/system-app/install",
},
{
text: "其他",
link: "/zh/developer/contribute/system-app/other",
},
],
},
{
text: "开发协议",
collapsed: true,
items: [
{
text: "合约",
link: "/zh/developer/contribute/olares-id/contract/contract",
collapsed: true,
items: [
{
text: "架构",
link: "/zh/developer/contribute/olares-id/contract/architecture",
},
{
text: "DID",
collapsed: true,
items: [
{
text: "设计",
link: "/zh/developer/contribute/olares-id/contract/did/design",
},
{
text: "官方 Tagger",
link: "/zh/developer/contribute/olares-id/contract/did/official-taggers",
},
{
text: "发布历史",
link: "/zh/developer/contribute/olares-id/contract/did/release-history",
},
{
text: "FAQ",
link: "/zh/developer/contribute/olares-id/contract/did/faq",
},
],
},
{
text: "声誉",
link: "/zh/developer/contribute/olares-id/contract/contract-reputation",
},
{
text: "管理",
collapsed: true,
items: [
{
text: "合约",
link: "/zh/developer/contribute/olares-id/contract/manage/contract",
},
{
text: "SDK",
link: "/zh/developer/contribute/olares-id/contract/manage/sdk",
},
{
text: "环境",
link: "/zh/developer/contribute/olares-id/contract/manage/environment",
},
],
},
],
},
{
text: "可验证凭证VC",
link: "/zh/developer/contribute/olares-id/verifiable-credential/overview",
collapsed: true,
items: [
{
text: "发行方",
link: "/zh/developer/contribute/olares-id/verifiable-credential/issuer",
},
{
text: "验证方",
link: "/zh/developer/contribute/olares-id/verifiable-credential/verifer",
},
{
text: "Olares 案例",
link: "/zh/developer/contribute/olares-id/verifiable-credential/olares",
},
],
},
],
},
],
},
],
}

View File

@@ -1,7 +1,9 @@
import { defineConfig, type DefaultTheme } from "vitepress";
import { oneSidebar } from './one.en.ts';
import { useCaseSidebar } from './usecase.en.ts';
import { developerSidebar } from './developer.en.ts';
const side = {
"/manual/": [
"/manual/": [
{
text: "What is Olares",
link: "/manual/overview",
@@ -17,7 +19,7 @@ const side = {
link: "/manual/help/olares",
},
{
text: "Installation FAQs",
text: "Setup & access FAQs",
link: "/manual/help/installation",
},
{
@@ -28,10 +30,25 @@ const side = {
// text: "Request support",
// link: "/manual/help/request-technical-support",
// },
// {
// text: "Troubleshooting",
// link: "/manual/help/troubleshooting",
// },
],
},
{
text: "Troubleshooting",
collapsed: true,
items: [
{
text: "Insufficient memory or memory not freed",
link: "/manual/help/ts-free-memory",
},
{
text: "Missing apps in Market",
link: "/manual/help/ts-missing-apps",
},
{
text: "LarePass VPN not working",
link: "/manual/help/ts-larepass-vpn-not-working",
},
],
},
],
@@ -133,54 +150,8 @@ const side = {
},
],
},
{
text: "LarePass",
link: "/manual/larepass/",
collapsed: true,
items: [
{
text: "Manage accounts",
collapsed: true,
items: [
{ text: "Create accounts", link: "/manual/larepass/create-account" },
{ text: "Back up mnemonics", link: "/manual/larepass/back-up-mnemonics" },
{ text: "Manage integrations", link: "/manual/larepass/integrations" },
],
},
{ text: "Use VPN", link: "/manual/larepass/private-network" },
{
text: "Manage device",
collapsed: true,
items: [
{ text: "Activate Olares", link: "/manual/larepass/activate-olares" },
{ text: "Manage Olares", link: "/manual/larepass/manage-olares" },
],
},
{ text: "Manage files", link: "/manual/larepass/manage-files" },
// collapsed: true,
//items: [
// {text: "Common file operations", link:"/manual/larepass/manage-files"},
// {text: "Sync and share", link:"/manual/larepass/sync-share"}
// ]
// },
{
text: "Manage passwords",
collapsed: true,
items: [
{ text: "Autofill passwords", link: "/manual/larepass/autofill" },
{ text: "Generate 2FA codes", link: "/manual/larepass/two-factor-verification" },
],
},
/*{
text: "Manage knowledge",
link: "/manual/larepass/manage-knowledge",
},*/
],
},
{
text: "Olares applications",
collapsed: true,
link: "/manual/olares/",
items: [
{ text: "Desktop", link: "/manual/olares/desktop", },
{
@@ -375,7 +346,7 @@ const side = {
collapsed: true,
items: [
{
text: "Change revere proxy",
text: "Change reverse proxy",
link: "/manual/olares/settings/change-frp",
},
{
@@ -395,13 +366,101 @@ const side = {
{ text: "Restore", link: "/manual/olares/settings/restore" },
],
},
{ text: "Developer resources", link: "/manual/olares/settings/developer" },
{ text: "Advanced settings", link: "/manual/olares/settings/developer" },
]
},
{ text: "Dashboard", link: "/manual/olares/resources-usage" },
{ text: "Profile", link: "/manual/olares/profile" },
],
},
{
text: "LarePass",
link: "/manual/larepass/",
collapsed: true,
items: [
{
text: "Manage accounts",
collapsed: true,
items: [
{ text: "Create accounts", link: "/manual/larepass/create-account" },
{ text: "Back up mnemonics", link: "/manual/larepass/back-up-mnemonics" },
{ text: "Manage integrations", link: "/manual/larepass/integrations" },
],
},
{ text: "Use VPN", link: "/manual/larepass/private-network" },
{
text: "Manage device",
collapsed: true,
items: [
{ text: "Activate Olares", link: "/manual/larepass/activate-olares" },
{ text: "Manage Olares", link: "/manual/larepass/manage-olares" },
],
},
{ text: "Manage files", link: "/manual/larepass/manage-files" },
// collapsed: true,
//items: [
// {text: "Common file operations", link:"/manual/larepass/manage-files"},
// {text: "Sync and share", link:"/manual/larepass/sync-share"}
// ]
// },
{
text: "Manage passwords",
collapsed: true,
items: [
{ text: "Autofill passwords", link: "/manual/larepass/autofill" },
{ text: "Generate 2FA codes", link: "/manual/larepass/two-factor-verification" },
],
},
/*{
text: "Manage knowledge",
link: "/manual/larepass/manage-knowledge",
},*/
],
},
{
text: "Olares Space",
link: "/manual/space/",
collapsed: true,
items: [
{
text: "Manage accounts",
link: "/manual/space/manage-accounts",
},
{
text: "Host Olares",
collapsed: true,
items: [
{
text: "Create Olares",
link: "/manual/space/create-olares",
},
{
text: "Manage Olares",
link: "/manual/space/manage-olares",
},
],
},
{
text: "Host domains",
collapsed: true,
items: [
{
text: "Set up a custom domain",
link: "/manual/space/host-domain",
},
{
text: "Manage a domain",
link: "/manual/space/manage-domain",
},
],
},
{
text: "Back up and restore",
link: "/manual/space/backup-restore",
},
{ text: "Billing", link: "/manual/space/billing" },
],
},
{
text: "Tutorials",
link: "/manual/best-practices/",
@@ -435,475 +494,6 @@ const side = {
},
{ text: "Glossary", link: "/manual/glossary" },
],
"/space/": [
{
text: "Olares Space",
link: "/space/",
items: [
{
text: "Manage accounts",
link: "/space/manage-accounts",
},
{
text: "Host Olares",
collapsed: true,
items: [
{
text: "Create Olares",
link: "/space/create-olares",
},
{
text: "Manage Olares",
link: "/space/manage-olares",
},
],
},
{
text: "Host domains",
collapsed: true,
items: [
{
text: "Set up a custom domain",
link: "/space/host-domain",
},
{
text: "Manage a domain",
link: "/space/manage-domain",
},
],
},
{
text: "Back up and restore",
link: "/space/backup-restore",
},
{ text: "Billing", link: "/space/billing" },
],
},
],
"/use-cases/": [
{
text: "Use cases",
link: "/use-cases/",
items: [
{
text: "Stable Diffusion",
link: "/use-cases/stable-diffusion",
},
{
text: "ComfyUI",
link: "/use-cases/comfyui",
collapsed: true,
items: [
{
text: "Manage ComfyUI",
link: "/use-cases/comfyui-launcher",
},
{
text: "Use ComfyUI for Krita",
link: "/use-cases/comfyui-for-krita",
},
]
},
{
text: "Ollama",
link: "/use-cases/ollama",
},
{
text: "Open WebUI",
link: "/use-cases/openwebui",
},
{
text: "Perplexica",
link: "/use-cases/perplexica",
},
{
text: "Dify",
link: "/use-cases/dify",
},
{
text: "Jellyfin",
link: "/use-cases/stream-media",
},
{
text: "Steam",
collapsed: true,
items: [
{
text: "Play directly on Olares",
link: "/use-cases/play-games-directly",
},
{
text: "Stream to other devices",
link: "/use-cases/stream-game",
}
]
},
// {
// text: "Redroid",
// link: "/use-cases/host-cloud-android",
// },
{
text: "Windows",
link: "/use-cases/windows",
},
{
text: "DeerFlow",
link: "/use-cases/deerflow",
},
{
text: "Duix.Avatar",
link: "/use-cases/duix-avatar",
},
{
text: "ACE-Step",
link: "/use-cases/ace-step",
},
{
text: "Stirling PDF",
link: "/use-cases/stirling-pdf",
},
{
text: "PDFMathTranslate",
link: "/use-cases/pdfmathtranslate",
},
{
text: "LobeChat",
link: "/use-cases/lobechat",
},
],
},
],
"/developer/": [
{
text: "Concepts",
link: "/developer/concepts/",
items: [
{ text: "Olares architecture", link: "/developer/concepts/system-architecture" },
{
text: "Olares ID",
link: "/developer/concepts/olares-id",
collapsed: true,
items: [
{
text: "Decentralized ID",
link: "/developer/concepts/did",
},
{
text: "Blockchain Registry",
link: "/developer/concepts/registry",
},
{
text: "Verifiable Credential",
link: "/developer/concepts/vc",
},
{
text: "Autonomous Reputation",
link: "/developer/concepts/reputation",
},
// {
// text: "Self-Sovereign Network",
// link: "/developer/concepts/self-sovereign-network",
// },
{
text: "Identity Wallet",
link: "/developer/concepts/wallet",
},
],
},
{ text: "Account", link: "/developer/concepts/account" },
{ text: "Application", link: "/developer/concepts/application" },
{ text: "Network", link: "/developer/concepts/network" },
{ text: "Data", link: "/developer/concepts/data" },
{ text: "Secrets", link: "/developer/concepts/secrets" },
],
},
{
text: "Installation deep-dive",
link: "/developer/install/",
items: [
{
text: "Installation architecture",
link: "/developer/install/installation-overview",
},
{
text: "Installation process",
link: "/developer/install/installation-process",
},
{
text: "Olares Home",
link: "/developer/install/olares-home",
},
{
text: "Environment variables",
link: "/developer/install/environment-variables",
},
{
text: "Olares CLI",
link: "/developer/install/cli/olares-cli",
collapsed: true,
items: [
{ text: "Access Olares terminal", link: "/developer/reference/access-olares-terminal" },
{
text: "backups",
link: "/developer/install/cli/backups",
collapsed: true,
items: [
{ text: "backup", link: "/developer/install/cli/backups-backup" },
{ text: "download", link: "/developer/install/cli/backups-download" },
{ text: "region", link: "/developer/install/cli/backups-region" },
{ text: "restore", link: "/developer/install/cli/backups-restore" },
{ text: "snapshots", link: "/developer/install/cli/backups-snapshots" },
],
},
{ text: "change-ip", link: "/developer/install/cli/change-ip" },
{ text: "disk", link: "/developer/install/cli/disk" },
{ text: "download", link: "/developer/install/cli/download" },
{ text: "gpu", link: "/developer/install/cli/gpu" },
{ text: "info", link: "/developer/install/cli/info" },
{ text: "install", link: "/developer/install/cli/install" },
{ text: "logs", link: "/developer/install/cli/logs" },
{ text: "node", link: "/developer/install/cli/node" },
{ text: "osinfo", link: "/developer/install/cli/osinfo" },
{ text: "precheck", link: "/developer/install/cli/precheck" },
{ text: "prepare", link: "/developer/install/cli/prepare" },
{ text: "release", link: "/developer/install/cli/release" },
{ text: "start", link: "/developer/install/cli/start" },
{ text: "stop", link: "/developer/install/cli/stop" },
{ text: "uninstall", link: "/developer/install/cli/uninstall" },
{ text: "upgrade", link: "/developer/install/cli/upgrade" },
{
text: "user",
link: "/developer/install/cli/user",
collapsed: true,
items: [
{ text: "activate", link: "/developer/install/cli/user-activate" },
{ text: "create", link: "/developer/install/cli/user-create" },
{ text: "delete", link: "/developer/install/cli/user-delete" },
{ text: "get", link: "/developer/install/cli/user-get" },
{ text: "list", link: "/developer/install/cli/user-list" },
{ text: "reset-password", link: "/developer/install/cli/user-reset-password" },
],
},
],
},
{
text: "Olares versioning",
link: "/developer/install/versioning",
},
],
},
{
text: "Develop Olares apps",
link: "/developer/develop/",
items: [
{
text: "Develop with Studio",
collapsed: true,
link: "/developer/develop/tutorial/",
items: [
{
text: "Deploy an app",
link: "/developer/develop/tutorial/deploy",
},
{
text: "Develop in a dev container",
link: "/developer/develop/tutorial/develop",
},
{
text: "Package and upload",
link: "/developer/develop/tutorial/package-upload",
},
{
text: "Add app assets",
link: "/developer/develop/tutorial/assets",
},
],
},
{
text: "Application package",
collapsed: true,
items: [
{
text: "Application chart",
link: "/developer/develop/package/chart",
},
{
text: "OlaresManifest",
link: "/developer/develop/package/manifest",
},
/*{
text: "Recommendation",
link: "/developer/develop/package/recommend",
},*/
{
text: "Helm extension",
link: "/developer/develop/package/extension",
},
],
},
// {
// text: "Advanced",
// collapsed: true,
// items: [
// {
// text: "terminus-info",
// link: "/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service provider",
// link: "/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/developer/develop/advanced/ai",
// },
// { text: "Cookie", link: "/developer/develop/advanced/cookie" },
// { text: "Database", link: "/developer/develop/advanced/database" },
// {
// text: "Account",
// link: "/developer/develop/advanced/account",
// },
// {
// text: "Market",
// link: "/developer/develop/advanced/market",
// },
// {
// text: "Websocket",
// link: "/developer/develop/advanced/websocket",
// },
// {
// text: "File upload",
// link: "/developer/develop/advanced/file-upload",
// },
// {
// text: "Secret",
// link: "/developer/develop/advanced/secret",
// },
// {
// text: "Kubesphere",
// link: "/developer/develop/advanced/kubesphere",
// },
// ],
// },
{
text: "Submit application",
collapsed: true,
link: "/developer/develop/submit/",
},
],
},
{
text: "Contribute to Olares",
items: [
{
text: "Develop system app",
collapsed: true,
items: [
{
text: "Overview",
link: "/developer/contribute/system-app/overview",
},
{
text: "Configure deployment",
link: "/developer/contribute/system-app/deployment",
},
{
text: "Configure permissions",
link: "/developer/contribute/system-app/olares-manifest",
},
{
text: "Install",
link: "/developer/contribute/system-app/install",
},
{
text: "Other",
link: "/developer/contribute/system-app/other",
},
],
},
{
text: "Develop protocols",
collapsed: true,
items: [
{
text: "Contract",
link: "/developer/contribute/olares-id/contract/contract",
collapsed: true,
items: [
{
text: "Architecture",
link: "/developer/contribute/olares-id/contract/architecture",
},
{
text: "DID",
collapsed: true,
items: [
{
text: "Design",
link: "/developer/contribute/olares-id/contract/did/design",
},
{
text: "Official Taggers",
link: "/developer/contribute/olares-id/contract/did/official-taggers",
},
{
text: "Release History",
link: "/developer/contribute/olares-id/contract/did/release-history",
},
{
text: "FAQ",
link: "/developer/contribute/olares-id/contract/did/faq",
},
],
},
{
text: "Reputation",
link: "/developer/contribute/olares-id/contract/contract-reputation",
},
{
text: "Manage",
collapsed: true,
items: [
{
text: "Contract",
link: "/developer/contribute/olares-id/contract/manage/contract",
},
{
text: "SDK",
link: "/developer/contribute/olares-id/contract/manage/sdk",
},
{
text: "Environment",
link: "/developer/contribute/olares-id/contract/manage/environment",
},
],
},
],
},
{
text: "Verifiable Credential",
link: "/developer/contribute/olares-id/verifiable-credential/overview",
collapsed: true,
items: [
{
text: "Issuer",
link: "/developer/contribute/olares-id/verifiable-credential/issuer",
},
{
text: "Verifer",
link: "/developer/contribute/olares-id/verifiable-credential/verifer",
},
{
text: "Olares",
link: "/developer/contribute/olares-id/verifiable-credential/olares",
},
],
},
],
},
],
},
],
};
export const en = defineConfig({
@@ -913,12 +503,17 @@ export const en = defineConfig({
socialLinks: [{ icon: "github", link: "https://github.com/beclab/olares" }],
nav: [
{ text: "Olares", link: "/manual/overview" },
{ text: "Olares Space", link: "/space/" },
{ text: "Use Cases", link: "/use-cases/" },
{ text: "Developer Guide", link: "/developer/concepts/" },
{ text: "Olares OS", link: "/manual/overview" },
{ text: "Olares One", link: "/one/" },
{ text: "Use cases", link: "/use-cases/" },
{ text: "Developer guide", link: "/developer/concepts/" },
],
sidebar: side,
sidebar: {
...side,
...oneSidebar,
...useCaseSidebar,
...developerSidebar,
},
},
});

243
docs/.vitepress/one.en.ts Normal file
View File

@@ -0,0 +1,243 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const oneSidebar: DefaultTheme.Sidebar = {
"/one/": [
{
text: "Olares One",
link: "/one/",
items: [
{
text: "Technical spec",
link: "/one/spec",
},
{
text: "FAQs",
link: "/one/faq",
},
],
},
{
text: "Initial setup",
items: [
{
text: "First boot",
link: "/one/first-boot",
},
{
text: "Access Olares via VPN",
link: "/one/access-olares-via-vpn",
},
{
text: "Access Olares via .local domain",
link: "/one/access-olares-via-local-domain",
},
{
text: "Redeem membership",
link: "/one/redeem-membership",
},
]
},
{
text: "Onboarding",
items: [
{
text: "Open WebUI with Ollama",
link: "/one/open-webui",
},
{
text: "Generate images with ComfyUI",
link: "/one/comfyui",
},
{
text: "Switch GPU mode",
link: "/one/gpu",
},
]
},
{
text: "Use",
items: [
{
text: "Customize Olares",
link: "/one/customize",
},
{
text: "Manage files",
link: "/one/files",
},
{
text: "Install & update apps",
link: "/one/market",
},
{
text: "Secure passwords",
link: "/one/vault",
},
{
text: "Download YouTube videos",
link: "/one/wise-download",
},
{
text: "Deploy an app",
link: "/one/deploy",
},
]
},
// {
// text: "Manage",
// items: [
// {
// text: "Set up app entrances",
// link: "/one/app-entrances",
// },
// {
// text: "Create users",
// link: "/one/users",
// },
// ]
// },
{
text: "Monitor",
items: [
{
text: "System resources",
link: "/one/dashboard",
},
{
text: "Traffic",
link: "/one/space",
},
]
},
{
text: "Explore",
items: [
{
text: "Play Steam games",
collapsed: true,
items: [
{
text: "Streaming",
link: "/one/steam-stream"
},
{
text: "Direct play",
link: "/one/steam-direct-play",
}]
},
{
text: "Access Windows in Olares",
link: "/one/windows",
},
{
text: "Generate music with Ace-Step",
link: "/one/ace-step",
},
{
text: "Deep research with DeerFlow",
link: "/one/deerflow",
},
]
},
{
text: "Advanced",
items: [
{
text: "SSH into Olares One",
link: "/one/access-terminal-ssh",
},
{
text: "Expand storage",
collapsed: true,
items:
[
{
text: "USB drive",
link: "/one/expand-storage-usb-drive",
},
{
text: "External SSD",
link: "/one/expand-storage-external-ssd",
},
{
text: "NVMe SSD",
link: "/one/expand-storage-internal-ssd",
},
]
},
{
text: "Connect two Olares One",
link: "/one/connect-two-olares-one"
// items:
// [
// {
// text: "Manage GPU",
// link: "/one/two-one-gpu",
// },
// {
// text: "Run larger local LLMs",
// link: "/one/two-one-llm",
// }
// ]
},
{
text: "Set up with eGPU",
link: "/one/egpu",
},
{
text: "Dual-boot Olares OS with Windows",
collapsed: true,
items:
[
{
text: "Dual-drive setup (Recommended)",
link: "/one/dual-boot-dual-drive",
},
{
text: "Single-drive setup",
link: "/one/dual-boot-single-drive",
}
,
{
text: "Install drivers on Windows",
link: "/one/install-nvidia-driver",
}
]
},
]
},
{
text: "System update",
items: [
{
text: "Update OS",
link: "/one/update",
},
{
text: "Back up & restore data",
link: "/one/backup-resotre",
},
{
text: "Restore Olares One",
collapsed: true,
items: [
{
text: "Factory reset",
link: "/one/factory-reset",
},
{
text: "Restore BIOS defaults",
link: "/one/factory-reset-in-bios",
},
{
text: "Reinstall Olares OS",
link: "/one/create-drive",
},
],
},
]
},
],
}

243
docs/.vitepress/one.zh.ts Normal file
View File

@@ -0,0 +1,243 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const oneSidebar: DefaultTheme.Sidebar = {
"/zh/one/": [
{
text: "Olares One",
link: "/zh/one/",
items: [
{
text: "Technical spec",
link: "/zh/one/spec",
},
{
text: "FAQs",
link: "/zh/one/faq",
},
],
},
{
text: "Initial setup",
items: [
{
text: "First boot",
link: "/zh/one/first-boot",
},
{
text: "Access Olares via VPN",
link: "/zh/one/access-olares-via-vpn",
},
{
text: "Access Olares via .local domain",
link: "/zh/one/access-olares-via-local-domain",
},
{
text: "Redeem membership",
link: "/zh/one/redeem-membership",
},
]
},
{
text: "Onboarding",
items: [
{
text: "Open WebUI with Ollama",
link: "/zh/one/open-webui",
},
{
text: "Generate images with ComfyUI",
link: "/zh/one/comfyui",
},
{
text: "Switch GPU mode",
link: "/zh/one/gpu",
},
]
},
{
text: "Use",
items: [
{
text: "Customize Olares",
link: "/zh/one/customize",
},
{
text: "Manage files",
link: "/zh/one/files",
},
{
text: "Install & update apps",
link: "/zh/one/market",
},
{
text: "Secure passwords",
link: "/zh/one/vault",
},
{
text: "Download YouTube videos",
link: "/zh/one/wise-download",
},
{
text: "Deploy an app",
link: "/zh/one/deploy",
},
]
},
// {
// text: "Manage",
// items: [
// {
// text: "Set up app entrances",
// link: "/zh/one/app-entrances",
// },
// {
// text: "Create users",
// link: "/zh/one/users",
// },
// ]
// },
{
text: "Monitor",
items: [
{
text: "System resources",
link: "/zh/one/dashboard",
},
{
text: "Traffic",
link: "/zh/one/space",
},
]
},
{
text: "Explore",
items: [
{
text: "Play Steam games",
collapsed: true,
items: [
{
text: "Streaming",
link: "/zh/one/steam-stream"
},
{
text: "Direct play",
link: "/zh/one/steam-direct-play",
}]
},
{
text: "Access Windows in Olares",
link: "/zh/one/windows",
},
{
text: "Generate music with Ace-Step",
link: "/zh/one/ace-step",
},
{
text: "Deep research with DeerFlow",
link: "/zh/one/deerflow",
},
]
},
{
text: "Advanced",
items: [
{
text: "SSH into Olares One",
link: "/zh/one/access-terminal-ssh",
},
{
text: "Expand storage",
collapsed: true,
items:
[
{
text: "USB drive",
link: "/zh/one/expand-storage-usb-drive",
},
{
text: "External SSD",
link: "/zh/one/expand-storage-external-ssd",
},
{
text: "NVMe SSD",
link: "/zh/one/expand-storage-internal-ssd",
},
]
},
{
text: "Connect two Olares One",
link: "/zh/one/connect-two-olares-one",
// items:
// [
// {
// text: "Manage GPU",
// link: "/zh/one/two-one-gpu",
// },
// {
// text: "Run larger local LLMs",
// link: "/zh/one/two-one-llm",
// }
// ]
},
{
text: "Set up with eGPU",
link: "/zh/one/egpu",
},
{
text: "Dual-boot Olares OS with Windows",
collapsed: true,
items:
[
{
text: "Dual-drive setup (Recommended)",
link: "/zh/one/dual-boot-dual-drive",
},
{
text: "Single-drive setup",
link: "/zh/one/dual-boot-single-drive",
}
,
{
text: "Install drivers on Windows",
link: "/zh/one/install-nvidia-driver",
}
]
},
]
},
{
text: "System update",
items: [
{
text: "Update OS",
link: "/zh/one/update",
},
{
text: "Back up & restore data",
link: "/zh/one/backup-resotre",
},
{
text: "Restore Olares One",
collapsed: true,
items: [
{
text: "Factory reset",
link: "/zh/one/factory-reset",
},
{
text: "Restore BIOS defaults",
link: "/zh/one/factory-reset-in-bios",
},
{
text: "Reinstall Olares OS",
link: "/zh/one/create-drive",
},
],
},
]
},
],
}

View File

@@ -0,0 +1,101 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const useCaseSidebar: DefaultTheme.Sidebar = {
"/use-cases/": [
{
text: "Use cases",
link: "/use-cases/",
items: [
{
text: "Stable Diffusion",
link: "/use-cases/stable-diffusion",
},
{
text: "ComfyUI",
link: "/use-cases/comfyui",
collapsed: true,
items: [
{
text: "Manage ComfyUI",
link: "/use-cases/comfyui-launcher",
},
{
text: "Use ComfyUI for Krita",
link: "/use-cases/comfyui-for-krita",
},
]
},
{
text: "Ollama",
link: "/use-cases/ollama",
},
{
text: "Open WebUI",
link: "/use-cases/openwebui",
},
{
text: "Perplexica",
link: "/use-cases/perplexica",
},
{
text: "Dify",
link: "/use-cases/dify",
},
{
text: "Jellyfin",
link: "/use-cases/stream-media",
},
{
text: "Steam",
collapsed: true,
items: [
{
text: "Play directly on Olares",
link: "/use-cases/play-games-directly",
},
{
text: "Stream to other devices",
link: "/use-cases/stream-game",
}
]
},
// {
// text: "Redroid",
// link: "/use-cases/host-cloud-android",
// },
{
text: "Windows",
link: "/use-cases/windows",
},
{
text: "DeerFlow",
link: "/use-cases/deerflow",
},
{
text: "Duix.Avatar",
link: "/use-cases/duix-avatar",
},
{
text: "ACE-Step",
link: "/use-cases/ace-step",
},
{
text: "Stirling PDF",
link: "/use-cases/stirling-pdf",
},
{
text: "PDFMathTranslate",
link: "/use-cases/pdfmathtranslate",
},
{
text: "LobeChat",
link: "/use-cases/lobechat",
},
{
text: "OpenClaw",
link: "/use-cases/openclaw",
},
],
},
],
}

View File

@@ -0,0 +1,69 @@
import { defineConfig, type DefaultTheme } from "vitepress";
export const useCaseSidebar: DefaultTheme.Sidebar = {
"/zh/use-cases/": [
{
text: "应用示例",
link: "/zh/use-cases/",
items: [
{
text: "Stable Diffusion",
link: "/zh/use-cases/stable-diffusion",
},
{
text: "ComfyUI",
link: "/zh/use-cases/comfyui",
collapsed: true,
items: [
{
text: "Manage ComfyUI",
link: "/zh/use-cases/comfyui-launcher",
},
{
text: "Use ComfyUI for Krita",
link: "/zh/use-cases/comfyui-for-krita",
},
]
},
{
text: "Ollama",
link: "/zh/use-cases/ollama",
},
{
text: "Open WebUI",
link: "/zh/use-cases/openwebui",
},
{
text: "Perplexica",
link: "/zh/use-cases/perplexica",
},
{
text: "Dify",
link: "/zh/use-cases/dify",
},
{
text: "Jellyfin",
link: "/zh/use-cases/stream-media",
},
{
text: "Steam",
collapsed: true,
items: [
{
text: "在 Olares 本机游玩",
link: "/zh/use-cases/play-games-directly",
},
{
text: "串流到其他设备",
link: "/zh/use-cases/stream-game",
}
]
},
// {
// text: "Redroid",
// link: "/zh/use-cases/host-cloud-android",
// },
],
},
],
}

View File

@@ -1,5 +1,7 @@
import { defineConfig, type DefaultTheme } from "vitepress";
import { oneSidebar } from './one.zh.ts';
import { useCaseSidebar } from './usecase.zh.ts';
import { developerSidebar } from './developer.zh.ts';
const side = {
"/zh/manual/": [
{
@@ -17,7 +19,7 @@ const side = {
link: "/zh/manual/help/olares",
},
{
text: "安装激活",
text: "安装配置与访问",
link: "/zh/manual/help/installation",
},
{
@@ -28,10 +30,24 @@ const side = {
// text: "技术支持",
// link: "/zh/manual/help/request-technical-support",
// },
// {
// text: "Troubleshooting Guide",
// link: "/zh/manual/help/troubleshooting-guide",
// },
],
},
{
text: "故障排查",
collapsed: true,
items: [
{
text: "内存不足或没有释放",
link: "/zh/manual/help/ts-free-memory",
},
{
text: "应用市场应用缺失",
link: "/zh/manual/help/ts-missing-apps",
},
{
text: "LarePass VPN 无法使用",
link: "/zh/manual/help/ts-larepass-vpn-not-working",
}
],
},
],
@@ -132,54 +148,8 @@ const side = {
},
],
},
{
text: "LarePass",
link: "/zh/manual/larepass/",
collapsed: true,
items: [
{
text: "管理账户",
collapsed: true,
items: [
{ text: "创建账户", link: "/zh/manual/larepass/create-account" },
{ text: "备份助记词", link: "/zh/manual/larepass/back-up-mnemonics" },
{ text: "管理集成", link: "/zh/manual/larepass/integrations" },
],
},
{ text: "使用专用网络", link: "/zh/manual/larepass/private-network" },
{
text: "管理设备",
collapsed: true,
items: [
{ text: "激活 Olares", link: "/zh/manual/larepass/activate-olares" },
{ text: "管理 Olares", link: "/zh/manual/larepass/manage-olares" },
],
},
{ text: "管理文件", link: "/zh/manual/larepass/manage-files" },
// collapsed: true,
// items: [
// {text: "常用文件操作", link:"/zh/manual/larepass/manage-files"},
// {text: "同步与共享", link:"/zh/manual/larepass/sync-share"}
// ]
// },
{
text: "管理密码",
collapsed: true,
items: [
{ text: "自动填充", link: "/zh/manual/larepass/autofill" },
{ text: "双重验证", link: "/zh/manual/larepass/two-factor-verification" },
],
},
/*{
text: "管理内容",
link: "/zh/manual/larepass/manage-knowledge",
},*/
],
},
{
"text": "Olares 应用",
"collapsed": true,
"link": "/zh/manual/olares/",
"items": [
{ "text": "桌面", "link": "/zh/manual/olares/desktop" },
{
@@ -391,7 +361,7 @@ const side = {
{ text: "恢复", link: "/zh/manual/olares/settings/restore" },
],
},
{ text: "开发者资源", link: "/zh/manual/olares/settings/developer" },
{ text: "高级设置", link: "/zh/manual/olares/settings/developer" },
]
},
{ "text": "仪表盘", "link": "/zh/manual/olares/resources-usage" },
@@ -399,18 +369,106 @@ const side = {
]
},
{
text: "教程",
text: "LarePass",
link: "/zh/manual/larepass/",
collapsed: true,
items: [
{
text: "管理账户",
collapsed: true,
items: [
{ text: "创建账户", link: "/zh/manual/larepass/create-account" },
{ text: "备份助记词", link: "/zh/manual/larepass/back-up-mnemonics" },
{ text: "管理集成", link: "/zh/manual/larepass/integrations" },
],
},
{ text: "使用专用网络", link: "/zh/manual/larepass/private-network" },
{
text: "管理设备",
collapsed: true,
items: [
{ text: "激活 Olares", link: "/zh/manual/larepass/activate-olares" },
{ text: "管理 Olares", link: "/zh/manual/larepass/manage-olares" },
],
},
{ text: "管理文件", link: "/zh/manual/larepass/manage-files" },
// collapsed: true,
// items: [
// {text: "常用文件操作", link:"/zh/manual/larepass/manage-files"},
// {text: "同步与共享", link:"/zh/manual/larepass/sync-share"}
// ]
// },
{
text: "管理密码",
collapsed: true,
items: [
{ text: "自动填充", link: "/zh/manual/larepass/autofill" },
{ text: "双重验证", link: "/zh/manual/larepass/two-factor-verification" },
],
},
/*{
text: "管理内容",
link: "/zh/manual/larepass/manage-knowledge",
},*/
],
},
{
text: "Olares Space",
link: "/zh/manual/space/index",
collapsed: true,
items: [
{
text: "管理账号",
link: "/zh/manual/space/manage-accounts",
},
{
text: "托管 Olares",
collapsed: true,
items: [
{
text: "创建 Olares",
link: "/zh/manual/space/create-olares",
},
{
text: "管理 Olares",
link: "/zh/manual/space/manage-olares",
},
],
},
{
text: "托管域名",
collapsed: true,
items: [
{
text: "设置自定义域名",
link: "/zh/manual/space/host-domain",
},
{
text: "管理域名",
link: "/zh/manual/space/manage-domain",
},
],
},
{
text: "备份与恢复",
link: "/zh/manual/space/backup-restore",
},
{ text: "计费", link: "/zh/manual/space/billing" },
],
},
{
text: "教程",
link: "/zh/manual/best-practices/",
collapsed: true,
items: [
{
text: "设置自定义域名",
link: "/zh/manual/best-practices/set-custom-domain",
},
{
/*{
text: "使用 Wise 管理知识",
link: "/zh/manual/best-practices/organize-content",
},
},*/
{
text: "安装多节点",
link: "/zh/manual/best-practices/install-olares-multi-node",
@@ -435,464 +493,6 @@ const side = {
},
{ text: "术语", link: "/zh/manual/glossary" },
],
"/zh/space/": [
{
text: "Olares Space",
link: "/zh/space/",
collapsed: true,
items: [
{
text: "管理账号",
link: "/zh/space/manage-accounts",
},
{
text: "托管 Olares",
collapsed: true,
items: [
{
text: "创建 Olares",
link: "/zh/space/create-olares",
},
{
text: "管理 Olares",
link: "/zh/space/manage-olares",
},
],
},
{
text: "托管域名",
collapsed: true,
items: [
{
text: "设置自定义域名",
link: "/zh/space/host-domain",
},
{
text: "管理域名",
link: "/zh/space/manage-domain",
},
],
},
{
text: "备份与恢复",
link: "/zh/space/backup-restore",
},
{ text: "计费", link: "/zh/space/billing" },
],
},
],
"/zh/use-cases/": [
{
text: "应用示例",
link: "/zh/use-cases/",
items: [
{
text: "Stable Diffusion",
link: "/zh/use-cases/stable-diffusion",
},
{
text: "ComfyUI",
link: "/zh/use-cases/comfyui",
collapsed: true,
items: [
{
text: "Manage ComfyUI",
link: "/zh/use-cases/comfyui-launcher",
},
{
text: "Use ComfyUI for Krita",
link: "/zh/use-cases/comfyui-for-krita",
},
]
},
{
text: "Ollama",
link: "/zh/use-cases/ollama",
},
{
text: "Open WebUI",
link: "/zh/use-cases/openwebui",
},
{
text: "Perplexica",
link: "/zh/use-cases/perplexica",
},
{
text: "Dify",
link: "/zh/use-cases/dify",
},
{
text: "Jellyfin",
link: "/zh/use-cases/stream-media",
},
{
text: "Steam",
collapsed: true,
items: [
{
text: "在 Olares 本机游玩",
link: "/zh/use-cases/play-games-directly",
},
{
text: "串流到其他设备",
link: "/zh/use-cases/stream-game",
}
]
},
// {
// text: "Redroid",
// link: "/zh/use-cases/host-cloud-android",
// },
],
},
],
"/zh/developer/": [
{
text: "概念",
link: "/zh/developer/concepts/",
items: [
{ text: "系统架构", link: "/zh/developer/concepts/system-architecture" },
{
text: "Olares ID",
link: "/zh/developer/concepts/olares-id",
collapsed: true,
items: [
{
text: "去中心化标识符",
link: "/zh/developer/concepts/did",
},
{
text: "DID Registry",
link: "/zh/developer/concepts/registry",
},
{
text: "可验证凭证",
link: "/zh/developer/concepts/vc",
},
{
text: "自治声誉",
link: "/zh/developer/concepts/reputation",
},
// {
// text: "主权网络",
// link: "/zh/developer/concepts/self-sovereign-network",
// },
{
text: "身份钱包",
link: "/zh/developer/concepts/wallet",
},
],
},
{ text: "账户", link: "/zh/developer/concepts/account" },
{ text: "应用", link: "/zh/developer/concepts/application" },
{ text: "网络", link: "/zh/developer/concepts/network" },
{ text: "数据", link: "/zh/developer/concepts/data" },
{ text: "密钥", link: "/zh/developer/concepts/secrets" },
],
},
{
text: "Olares 安装详解",
link: "/zh/developer/install/",
items: [
{
text: "安装概述",
link: "/zh/developer/install/installation-overview",
},
{
text: "安装流程",
link: "/zh/developer/install/installation-process",
},
{
text: "Olares Home",
link: "/zh/developer/install/olares-home",
},
{
text: "环境变量",
link: "/zh/developer/install/environment-variables",
},
{
text: "Olares CLI",
link: "/zh/developer/install/cli/olares-cli",
collapsed: true,
items: [
{ text: "访问 Olares 终端", link: "/zh/developer/reference/access-olares-terminal" },
{
text: "backups",
link: "/zh/developer/install/cli/backups",
collapsed: true,
items: [
{ text: "backup", link: "/zh/developer/install/cli/backups-backup" },
{ text: "download", link: "/zh/developer/install/cli/backups-download" },
{ text: "region", link: "/zh/developer/install/cli/backups-region" },
{ text: "restore", link: "/zh/developer/install/cli/backups-restore" },
{ text: "snapshots", link: "/zh/developer/install/cli/backups-snapshots" },
],
},
{ text: "change-ip", link: "/zh/developer/install/cli/change-ip" },
{ text: "disk", link: "/zh/developer/install/cli/disk" },
{ text: "download", link: "/zh/developer/install/cli/download" },
{ text: "gpu", link: "/zh/developer/install/cli/gpu" },
{ text: "info", link: "/zh/developer/install/cli/info" },
{ text: "install", link: "/zh/developer/install/cli/install" },
{ text: "logs", link: "/zh/developer/install/cli/logs" },
{ text: "node", link: "/zh/developer/install/cli/node" },
{ text: "osinfo", link: "/zh/developer/install/cli/osinfo" },
{ text: "precheck", link: "/zh/developer/install/cli/precheck" },
{ text: "prepare", link: "/zh/developer/install/cli/prepare" },
{ text: "release", link: "/zh/developer/install/cli/release" },
{ text: "start", link: "/zh/developer/install/cli/start" },
{ text: "stop", link: "/zh/developer/install/cli/stop" },
{ text: "uninstall", link: "/zh/developer/install/cli/uninstall" },
{ text: "upgrade", link: "/zh/developer/install/cli/upgrade" },
{
text: "user",
link: "/zh/developer/install/cli/user",
collapsed: true,
items: [
{ text: "activate", link: "/zh/developer/install/cli/user-activate" },
{ text: "create", link: "/zh/developer/install/cli/user-create" },
{ text: "delete", link: "/zh/developer/install/cli/user-delete" },
{ text: "get", link: "/zh/developer/install/cli/user-get" },
{ text: "list", link: "/zh/developer/install/cli/user-list" },
{ text: "reset-password", link: "/zh/developer/install/cli/user-reset-password" },
],
},
],
},
{
text: "版本说明",
link: "/zh/developer/install/versioning",
},
],
},
{
text: "开发 Olares 应用",
link: "/zh/developer/develop/",
items: [
{
text: "使用 Studio 开发",
collapsed: true,
link: "/zh/developer/develop/tutorial/",
items: [
{
text: "部署应用",
link: "/zh/developer/develop/tutorial/deploy",
},
{
text: "使用开发容器",
link: "/zh/developer/develop/tutorial/develop",
},
{
text: "打包与上传",
link: "/zh/developer/develop/tutorial/package-upload",
},
{
text: "添加应用素材",
link: "/zh/developer/develop/tutorial/assets",
},
],
},
{
text: "应用包管理",
collapsed: true,
items: [
{
text: "应用 Chart 包",
link: "/zh/developer/develop/package/chart",
},
{
text: "OlaresManifest",
link: "/zh/developer/develop/package/manifest",
},
/*{
text: "推荐算法",
link: "/zh/developer/develop/package/recommend",
},*/
{
text: "Helm 扩展",
link: "/zh/developer/develop/package/extension",
},
],
},
// {
// text: "进阶",
// collapsed: true,
// items: [
// {
// text: "terminus-info",
// link: "/zh/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service Provider",
// link: "/zh/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/zh/developer/develop/advanced/ai",
// },
// { text: "Cookie", link: "/zh/developer/develop/advanced/cookie" },
// { text: "数据库", link: "/zh/developer/develop/advanced/database" },
// {
// text: "账户",
// link: "/zh/developer/develop/advanced/account",
// },
// {
// text: "应用市场",
// link: "/zh/developer/develop/advanced/market",
// },
// {
// text: "Analytic",
// link: "/zh/developer/develop/advanced/analytic",
// },
// {
// text: "Websocket",
// link: "/zh/developer/develop/advanced/websocket",
// },
// {
// text: "文件上传",
// link: "/zh/developer/develop/advanced/file-upload",
// },
// {
// text: "Rss",
// link: "/zh/developer/develop/advanced/rss",
// },
// {
// text: "密钥",
// link: "/zh/developer/develop/advanced/secret",
// },
// {
// text: "Notification",
// link: "/zh/developer/develop/advanced/notification",
// },
// {
// text: "Frontend",
// link: "/zh/developer/develop/advanced/frontend",
// },
// {
// text: "Kubesphere",
// link: "/zh/developer/develop/advanced/kubesphere",
// },
// ],
// },
{
text: "提交应用",
collapsed: true,
link: "/zh/developer/develop/submit/",
},
],
},
{
text: "参与贡献",
items: [
{
text: "开发系统应用",
collapsed: true,
items: [
{
text: "概述",
link: "/zh/developer/contribute/system-app/overview",
},
{
text: "应用部署配置",
link: "/zh/developer/contribute/system-app/deployment",
},
{
text: "Olares 权限配置",
link: "/zh/developer/contribute/system-app/olares-manifest",
},
{
text: "安装",
link: "/zh/developer/contribute/system-app/install",
},
{
text: "其他",
link: "/zh/developer/contribute/system-app/other",
},
],
},
{
text: "开发协议",
collapsed: true,
items: [
{
text: "合约",
link: "/zh/developer/contribute/olares-id/contract/contract",
collapsed: true,
items: [
{
text: "架构",
link: "/zh/developer/contribute/olares-id/contract/architecture",
},
{
text: "DID",
collapsed: true,
items: [
{
text: "设计",
link: "/zh/developer/contribute/olares-id/contract/did/design",
},
{
text: "官方 Tagger",
link: "/zh/developer/contribute/olares-id/contract/did/official-taggers",
},
{
text: "发布历史",
link: "/zh/developer/contribute/olares-id/contract/did/release-history",
},
{
text: "FAQ",
link: "/zh/developer/contribute/olares-id/contract/did/faq",
},
],
},
{
text: "声誉",
link: "/zh/developer/contribute/olares-id/contract/contract-reputation",
},
{
text: "管理",
collapsed: true,
items: [
{
text: "合约",
link: "/zh/developer/contribute/olares-id/contract/manage/contract",
},
{
text: "SDK",
link: "/zh/developer/contribute/olares-id/contract/manage/sdk",
},
{
text: "环境",
link: "/zh/developer/contribute/olares-id/contract/manage/environment",
},
],
},
],
},
{
text: "可验证凭证VC",
link: "/zh/developer/contribute/olares-id/verifiable-credential/overview",
collapsed: true,
items: [
{
text: "发行方",
link: "/zh/developer/contribute/olares-id/verifiable-credential/issuer",
},
{
text: "验证方",
link: "/zh/developer/contribute/olares-id/verifiable-credential/verifer",
},
{
text: "Olares 案例",
link: "/zh/developer/contribute/olares-id/verifiable-credential/olares",
},
],
},
],
},
],
},
],
};
export const zh = defineConfig({
@@ -902,12 +502,17 @@ export const zh = defineConfig({
socialLinks: [{ icon: "github", link: "https://github.com/beclab/olares" }],
nav: [
{ text: "Olares", link: "zh/manual/overview" },
{ text: "Olares Space", link: "/zh/space/" },
{ text: "Olares OS", link: "zh/manual/overview" },
{ text: "Olares One", link: "/zh/one/" },
{ text: "应用示例", link: "/zh/use-cases/" },
{ text: "开发者文档", link: "/zh/developer/concepts/" },
],
sidebar: side,
sidebar: {
...side,
...oneSidebar,
...useCaseSidebar,
...developerSidebar,
},
},
});

View File

@@ -89,15 +89,9 @@ Key characteristics of shared applications include:
* **Centralized management**: Only administrators can install the core service of a shared application. Administrators are responsible for installing, configuring, and hosting the app's service, resources, and runtime environment within the cluster.
* **Easy identification**: In Olares Market, shared applications are typically marked with a "Shared" label for easy identification.
* **Flexible access**: The method for accessing a shared application depends on the app's form:
* **Headless backend service**: For shared applications that typically run as a background service without a graphical UI (e.g., Ollama), users need to install a **reference application** to call the service. For example, users within the cluster can access the Ollama service via Open WebUI or LobeChat.
* **Headless backend service**: For shared applications that typically run as a background service without a graphical UI (e.g., Ollama), no dedicated reference application is required. The service exposes standard APIs and shared entrances that can be directly consumed by any compatible thirdparty client such as LobeChat and Open WebUI. Users install the client and point it to the shared apps API endpoint found in the Olares **Settings** > **Applications** > **Entrances**.
* **Complete application with built-in UI**: For shared applications that include a complete user interface and backend service themselves (e.g., ComfyUI Shared or Dify Shared), administrators and other users in the cluster can obtain the service access point by directly installing the shared application itself.
### Reference applications
Reference applications are applications that have been granted access to specific shared applications within Olares. They typically provide a user-friendly interface, allowing users to easily access the APIs or services exposed by the shared applications.
For example, Open WebUI, LobeChat, and n8n are reference applications for Ollama. Dify Shared is the reference application of itself.
### Dependencies
Dependencies are prerequisite applications that must be present for certain applications to function properly. Before installing an application with dependencies, users must ensure all required dependencies are already installed in the cluster.

View File

@@ -0,0 +1,25 @@
---
outline: [2, 3]
description: Learn how variables are injected during Olares app deployment, including declarative environment variables (.Values.olaresEnv) and system-injected runtime Helm values (.Values.*).
---
# Environment variables overview
Olares apps use app-service to inject runtime context and configuration into the app's `values.yaml`. In Helm templates, you can reference these values via `.Values.*`.
:::info Variables and Helm values
In this document, "variables" mainly refer to Helm values. They are not automatically passed into container environment variables. If you need them inside containers, explicitly map them to `env:` in your templates.
:::
## How variables are injected
Olares injects variables through two channels:
- **Declarative environment variables**: The developer declares variables under `envs` in `OlaresManifest.yaml`. At deployment, app-service resolves and injects the values into `.Values.olaresEnv` in `values.yaml`.
- **System-injected runtime variables**: Injected automatically by Olares at deployment time. No declaration is required, though some values are only available after you declare the relevant dependency, such as middleware.
## Next steps
1. [Declarative environment variables](app-env-vars.md): Field reference for the `envs` schema, including variable mapping and variable references.
2. [System-injected runtime variables](app-sys-injected-variables.md): Full reference for all system-injected runtime variables.

View File

@@ -0,0 +1,199 @@
---
outline: [2, 4]
description: Declare and validate app configuration via envs in `OlaresManifest.yaml`, and reference values in templates through `.Values.olaresEnv`.
---
# Declarative environment variables
Use `envs` in `OlaresManifest.yaml` to declare the configuration parameters, such as passwords, API endpoints, or feature flags. During deployment, app-service resolves the values and injects them into `.Values.olaresEnv` in `values.yaml`. Reference them in Helm templates as <code v-pre>{{ .Values.olaresEnv.&lt;envName&gt; }}</code>.
## Variable sources
Declarative variables can obtain values from configurations managed outside the application:
- **System variables**: Environment variables defined at the Olares cluster level. They are set during system installation or centrally managed by administrators, and are shared by all users within the cluster.
- **User variables**: Environment variables defined at the Olares user level. They are managed individually by each user, and are isolated from one another within the same cluster.
Applications cannot modify these variables directly. To use them, map the variable via the `valueFrom` field.
## Map environment variables
Both system environment variables and user environment variables use the same mapping mechanism via `valueFrom`.
The following example maps the system variable `OLARES_SYSTEM_CDN_SERVICE` to an application variable `APP_CDN_ENDPOINT`:
1. In `OlaresManifest.yaml`, declare an app variable under `envs` and set `valueFrom.envName` to the system variable name.
```yaml
# Map system variable OLARES_SYSTEM_CDN_SERVICE to app variable APP_CDN_ENDPOINT
olaresManifest.version: '0.10.0'
olaresManifest.type: app
envs:
- envName: APP_CDN_ENDPOINT
required: true
applyOnChange: true
valueFrom:
envName: OLARES_SYSTEM_CDN_SERVICE
```
2. In your Helm template, reference the app variable via `.Values.olaresEnv.<envName>`.
```yaml
# Use APP_CDN_ENDPOINT in a container environment variable
env:
- name: CDN_ENDPOINT
value: "{{ .Values.olaresEnv.APP_CDN_ENDPOINT }}"
```
At deployment, app-service resolves the referenced variable and injects the value into `values.yaml`:
```yaml
# Injected by app-service into values.yaml at deployment
olaresEnv:
APP_CDN_ENDPOINT: "https://cdn.olares.com"
```
For the full list of available environment variables, see [Variable references](#variable-references).
## Declaration fields
The following fields are available under each `envs` entry.
### envName
The name of the variable as injected into `values.yaml`. Reference it in templates as <code v-pre>{{ .Values.olaresEnv.&lt;envName&gt; }}</code>.
### default
The default value for the variable. Provided by the developer at authoring time. Users cannot modify it. Used when no value is supplied by the user or by `valueFrom`.
### valueFrom
Maps this variable to a system or user environment variable. When set, the current variable inherits all fields from the referenced variable (`type`, `editable`, `regex`, and so on). Any fields defined locally on the current variable are ignored. `default` and `options` have no effect when `valueFrom` is used.
**Example**: map the app variable `APP_CDN_ENDPOINT` to the system variable `OLARES_SYSTEM_CDN_SERVICE`.
```yaml
# Map app env APP_CDN_ENDPOINT to system variable OLARES_SYSTEM_CDN_SERVICE
envs:
- envName: APP_CDN_ENDPOINT
required: true
applyOnChange: true
valueFrom:
envName: OLARES_SYSTEM_CDN_SERVICE
```
### required
Boolean. When `true`, the variable must have a value for installation to proceed. If no `default` is set, the user is prompted to enter one. After installation, the value cannot be set to empty.
### editable
Boolean. When `true`, the variable can be modified after installation.
### applyOnChange
Boolean. When `true`, changing this variable automatically restarts all apps or components that use it. When `false`, a change only takes effect after the app is upgraded or reinstalled. Stopping and starting the app manually has no effect.
### type
The expected type of the value. Used for validation before the value is accepted. Supported types: `int`, `bool`, `url`, `ip`, `domain`, `email`, `string`, `password`.
### regex
A regular expression the value must match. If validation fails, the value cannot be set and installation or upgrade may fail.
### options
Restricts the variable to a fixed list of allowed values. The system presents users with a selection UI.
**Example**: a dropdown list of supported Windows versions for installation.
```yaml
# Dropdown: title shown in UI, value stored internally
envs:
- envName: VERSION
options:
- title: "Windows 11 Pro"
value: "iso/Win11_24H2_English_x64.iso"
- title: "Windows 7 Ultimate"
value: "iso/win7_sp1_x64_1.iso"
```
### remoteOptions
Loads the options list from a URL instead of defining it inline. The response body must be a JSON-encoded array in the same format as `options`.
**Example**: options fetched from a remote endpoint.
```yaml
# Options list fetched from remote URL at install time
envs:
- envName: VERSION
remoteOptions: https://app.cdn.olares.com/appstore/windows/version_options.json
```
### description
A human-readable description of the variable's purpose and valid values. Displayed in the Olares interface.
## Variable references
### System environment variables
The following table lists system-level environment variables that can be referenced via `valueFrom`.
| Variable | Type | Default | Editable | Required | Description |
| --- | --- | --- | --- | --- | --- |
| `OLARES_SYSTEM_REMOTE_SERVICE` | `url` | `https://api.olares.com` | Yes | Yes | Remote service endpoint for Olares, such as Market and Olares Space. |
| `OLARES_SYSTEM_CDN_SERVICE` | `url` | `https://cdn.olares.com` | Yes | Yes | CDN endpoint for system resources. |
| `OLARES_SYSTEM_DOCKERHUB_SERVICE` | `url` | None | Yes | No | Docker Hub mirror or accelerator endpoint. |
| `OLARES_SYSTEM_ROOT_PATH` | `string` | `/olares` | No | Yes | Olares root directory path. |
| `OLARES_SYSTEM_ROOTFS_TYPE` | `string` | `fs` | No | Yes | Olares filesystem type. |
| `OLARES_SYSTEM_CUDA_VERSION` | `string` | None | No | No | Host CUDA version. |
### User environment variables
All user environment variables are editable by the user.
#### User information
| Variable | Type | Default | Description |
| --- | --- | --- | --- |
| `OLARES_USER_EMAIL` | `string` | None | User email address. |
| `OLARES_USER_USERNAME` | `string` | None | Username. |
| `OLARES_USER_PASSWORD` | `password` | None | User password. |
| `OLARES_USER_TIMEZONE` | `string` | None | User timezone. For example, `Asia/Shanghai`. |
#### SMTP settings
| Variable | Type | Default | Description |
| --- | --- | --- | --- |
| `OLARES_USER_SMTP_ENABLED` | `bool` | None | Whether to enable SMTP. |
| `OLARES_USER_SMTP_SERVER` | `domain` | None | SMTP server domain. |
| `OLARES_USER_SMTP_PORT` | `int` | None | SMTP server port. Typically `465` or `587`. |
| `OLARES_USER_SMTP_USERNAME` | `string` | None | SMTP username. |
| `OLARES_USER_SMTP_PASSWORD` | `password` | None | SMTP password or authorization code. |
| `OLARES_USER_SMTP_FROM_ADDRESS` | `email` | None | Sender email address. |
| `OLARES_USER_SMTP_SECURE` | `bool` | `"true"` | Whether to use a secure protocol. |
| `OLARES_USER_SMTP_USE_TLS` | `bool` | None | Whether to use TLS. |
| `OLARES_USER_SMTP_USE_SSL` | `bool` | None | Whether to use SSL. |
| `OLARES_USER_SMTP_SECURITY_PROTOCOLS` | `string` | None | Security protocol. Allowed values: `tls`, `ssl`, `starttls`, `none`. |
#### Mirror and proxy endpoints
| Variable | Type | Default | Description |
| --- | --- | --- | --- |
| `OLARES_USER_HUGGINGFACE_SERVICE` | `url` | `https://huggingface.co/` | Hugging Face service URL. |
| `OLARES_USER_HUGGINGFACE_TOKEN` | `string` | None | Hugging Face access token. |
| `OLARES_USER_PYPI_SERVICE` | `url` | `https://pypi.org/simple/` | PyPI mirror URL. |
| `OLARES_USER_GITHUB_SERVICE` | `url` | `https://github.com/` | GitHub mirror URL. |
| `OLARES_USER_GITHUB_TOKEN` | `string` | None | GitHub personal access token. |
#### API keys
| Variable | Type | Default | Description |
| --- | --- | --- | --- |
| `OLARES_USER_OPENAI_APIKEY` | `password` | None | OpenAI API key. |
| `OLARES_USER_CUSTOM_OPENAI_SERVICE` | `url` | None | Custom OpenAI-compatible service URL. |
| `OLARES_USER_CUSTOM_OPENAI_APIKEY` | `password` | None | API key for the custom OpenAI-compatible service. |

View File

@@ -0,0 +1,216 @@
---
outline: [2, 4]
description: Reference for runtime values injected into application `values.yaml` during Olares deployment.
---
# System-injected runtime values
At deployment, Olares automatically injects a set of system-managed values into the app's `values.yaml`. These values are read-only and cover user identity, storage paths, cluster metadata, app dependencies, and middleware credentials.
Because they are Helm values, they are not automatically available inside containers. To pass one into a container, map it explicitly under `env:` in your deployment template.
## Use in your app
Reference these values directly in your Helm templates, such as `deployment.yaml`.
**Example**: pass the current username and Postgres host into container environment variables.
```yaml
# Pass system-injected runtime values into container environment variables
spec:
containers:
- name: my-app
env:
- name: APP_USER
value: "{{ .Values.bfl.username }}"
- name: DB_HOST
value: "{{ .Values.postgres.host }}"
```
For the full list of available values, see [Value reference](#value-reference).
## Value references
The Type column describes the Helm value data type. It does not correspond to the `type` field in `OlaresManifest.yaml`.
### User and identity
| Value | Type | Description |
| --- | --- | --- |
| `.Values.bfl.username` | String | Current username. |
| `.Values.user.zone` | String | Current user's domain. |
| `.Values.admin` | String | Administrator username. |
### Application and system information
| Value | Type | Description |
| --- | --- | --- |
| `.Values.domain` | Map\<String,String> | App entrance URLs. Each entry maps an entrance name to its URL. |
| `.Values.sysVersion` | String | Current Olares system version. |
| `.Values.deviceName` | String | Device name. |
| `.Values.downloadCdnURL` | String | CDN address used for system resource downloads. |
### Storage paths
| Value | Type | Description |
| --- | --- | --- |
| `.Values.userspace.appData` | String | Cluster storage path for the app. Path: `/Data/<appname>`. |
| `.Values.userspace.appCache` | String | Node-local cache path for the app. Path: `/Cache/<appname>`. |
| `.Values.userspace.userData` | String | User's home data directory. Path: `/Files/Home/`. |
| `.Values.sharedlib` | String | User's external storage directory. Path: `/Files/External/<devicename>/`. |
### Cluster hardware metadata
| Value | Type | Description |
| --- | --- | --- |
| `.Values.cluster.arch` | String | Cluster CPU architecture, such as `amd64`. Mixed-architecture clusters are not supported. |
| `.Values.nodes` | List\<NodeInfo> | Hardware metadata for each node in the cluster. |
Each entry in `.Values.nodes` follows this structure:
```json
// Single entry in the .Values.nodes list
[
{
"cudaVersion": "12.9",
"cpu": [
{
"coreNumber": 16,
"arch": "amd64",
"frequency": 4900000000,
"model": "151",
"modelName": "12th Gen Intel(R) Core(TM) i5-12600KF",
"vendor": "GenuineIntel"
}
],
"memory": {
"total": 50351353856
},
"gpus": [
{
"vendor": "NVIDIA",
"arch": "Ada Lovelace",
"model": "4060",
"memory": 17175674880,
"modelName": "NVIDIA GeForce RTX 4060 Ti"
}
]
}
]
```
### Application dependencies
When an app declares a dependency in `OlaresManifest.yaml`, Olares injects connection information into `values.yaml`.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.deps` | Map\<String,Value> | Main entry host and port for each declared dependency. Keys follow the pattern `<entry_name>_host` and `<entry_name>_port`. |
| `.Values.svcs` | Map\<String,Value> | All service hosts and ports for each declared dependency. Keys follow the pattern `<service_name>_host` and `<service_name>_port`. Port values are lists to support multiple ports per service. |
**Example**: for a dependency with entry name `aserver` and service name `aserver-svc`.
`.Values.deps`:
```json
{
"aserver_host": "aserver-svc.<namespace>",
"aserver_port": 80
}
```
`.Values.svcs`:
```json
{
"aserver-svc_host": "aserver-svc.<namespace>",
"aserver-svc_port": [80]
}
```
### Middleware values
Middleware values are injected only after you declare the middleware dependency in the `middleware` section of `OlaresManifest.yaml`.
PostgreSQL and Redis are preinstalled. MongoDB, MinIO, RabbitMQ, MySQL and MariaDB must be installed separately before your app can use them.
#### MariaDB
See [Integrate with MariaDB](/developer/develop/mw-integrate-with-mariadb.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mariadb.host` | String | MariaDB host. |
| `.Values.mariadb.port` | Number | MariaDB port. |
| `.Values.mariadb.username` | String | MariaDB username. |
| `.Values.mariadb.password` | String | MariaDB password. |
| `.Values.mariadb.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mariadb.databases.app_db`. |
#### MinIO
See [Integrate with MinIO](/developer/develop/mw-integrate-with-minio.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.minio.host` | String | MinIO service host. |
| `.Values.minio.port` | Number | MinIO service port. |
| `.Values.minio.username` | String | MinIO access key. |
| `.Values.minio.password` | String | MinIO secret key. |
| `.Values.minio.buckets` | Map\<String,String> | Requested buckets, keyed by bucket name. For example, a request for `mybucket` is available at `.Values.minio.buckets.mybucket`. |
#### MongoDB
See [Integrate with MongoDB](/developer/develop/mw-integrate-with-mongodb.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mongodb.host` | String | MongoDB host. |
| `.Values.mongodb.port` | Number | MongoDB port. |
| `.Values.mongodb.username` | String | MongoDB username. |
| `.Values.mongodb.password` | String | MongoDB password. |
| `.Values.mongodb.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mongodb.databases.app_db`. |
#### MySQL
See [Integrate with MySQL](/developer/develop/mw-integrate-with-mysql.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mysql.host` | String | MySQL host. |
| `.Values.mysql.port` | Number | MySQL port. |
| `.Values.mysql.username` | String | MySQL username. |
| `.Values.mysql.password` | String | MySQL password. |
| `.Values.mysql.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mysql.databases.app_db`. |
#### PostgreSQL
See [Integrate with PostgreSQL](/developer/develop/mw-integrate-with-pg.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.postgres.host` | String | PostgreSQL host. |
| `.Values.postgres.port` | Number | PostgreSQL port. |
| `.Values.postgres.username` | String | PostgreSQL username. |
| `.Values.postgres.password` | String | PostgreSQL password. |
| `.Values.postgres.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.postgres.databases.app_db`. |
#### RabbitMQ
See [Integrate with RabbitMQ](/developer/develop/mw-integrate-with-rabbitmq.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.rabbitmq.host` | String | RabbitMQ host. |
| `.Values.rabbitmq.port` | Number | RabbitMQ port. |
| `.Values.rabbitmq.username` | String | RabbitMQ username. |
| `.Values.rabbitmq.password` | String | RabbitMQ password. |
| `.Values.rabbitmq.vhosts` | Map\<String,String> | Requested vhosts, keyed by vhost name. For example, a request for `myvhost` is available at `.Values.rabbitmq.vhosts.myvhost`. |
#### Redis
See [Integrate with Redis](/developer/develop/mw-integrate-with-redis.md) for installation and configuration details.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.redis.host` | String | Redis host. |
| `.Values.redis.port` | Number | Redis port. |
| `.Values.redis.password` | String | Redis password. |
| `.Values.redis.namespaces` | Map\<String,String> | Requested namespaces, keyed by namespace name. For example, a request for `app_ns` is available at `.Values.redis.namespaces.app_ns`. |

View File

@@ -0,0 +1,107 @@
---
outline: [2, 3]
description: Understand how application distribution works in Olares.
---
# Distribute Olares applications
Distributing applications on Olares is based on open standards and automated validation.
If your application is already packaged as an Olares Application Chart (OAC), you can publish it to Olares Market and make it available to users with minimal friction.
This guide walks you through the distribution lifecycle of an Olares application, from understanding how Market indexing works to publishing, maintaining, and promoting your app.
## Before you begin
Before distributing your application, it helps to understand a few core concepts:
- **[Olares Application Chart (OAC)](/developer/develop/package/chart.md)**
The packaging format used to describe an Olares application, including metadata, ownership, versioning, and installation configuration.
- **Application index**
A service that provides application metadata to Olares Market. Olares includes a default public index, and developers can deploy their own.
- **Terminus-Gitbot**
The automated validation system that checks application submissions and enforces distribution rules.
- **Owners file (`owners`)**
A file in the OAC root directory used to validate ownership and permissions. The file has no extension.
```text
owners:
- <your-github-username>
- <collaborator1-username>
- <collaborator2-username>
```
- **Control files**
Special empty files in the OAC root directory that control distribution status:
- `.suspend`: suspend distribution
- `.remove`: remove an app from the Market
For details, see [Manage the app lifecycle](/developer/develop/manage-apps.md#control-files).
## Ownership and collaboration
To collaborate as a team:
- Add all maintainers to the owners file (recommended). Each listed owner can independently fork the repo and submit changes for that app.
- Add teammates as collaborators to your forked repository so they can push commits to your PR branch.
## App distribution workflow
### 1. Prepare your app package
Before an app can be distributed, it must be packaged as an **Olares Application Chart (OAC)**.
At this stage, developers typically:
- Develop and test the app on an Olares host.
- Verify installation and upgrade behavior.
- Finalize chart metadata and structure.
For details, see [Olares Application Chart (OAC)](/developer/develop/package/chart.md).
### 2. Submit the app to the default index
Olares Market indexes applications from Git repositories.
To publish an app to the default public index, developers submit their OAC by opening a PR to the official repository.
During submission:
- The PR title declares the action type.
- Terminus-Gitbot validates file scope, ownership, and version rules.
- Valid PRs are merged automatically without manual review.
For details, see [Submit applications](/developer/develop/submit-apps.md).
### 3. Automated validation and indexing
After a PR is submitted, Terminus-Gitbot performs automated checks to ensure the submission follows distribution rules.
If all checks pass, the PR is merged automatically.
After a short delay, the application becomes visible in Olares Market.
### 4. Manage the application lifecycle
After an application is published, developers continue to manage its lifecycle through Pull Requests.
Lifecycle actions include:
- Releasing new versions.
- Temporarily suspending distribution.
- Permanently removing an application from the Market.
These actions are controlled using PR types and special control files in the OAC.
For details, see [Manage the app lifecycle](/developer/develop/manage-apps.md).
### 5. Optimize your Market listing
Once published, you can improve how your app is presented in Olares Market by adding icons, screenshots, and featured images.
For details, see [Promote your apps](/developer/develop/promote-apps.md).
### 6. (Optional) Publish paid applications
Olares Market also supports paid application distribution.
Paid apps require additional identity registration, pricing configuration, and license management.
For details, see [Publish paid applications](/developer/develop/paid-apps.md).

View File

@@ -27,4 +27,4 @@ To publish your application to the Olares Market, you must structure it accordin
## Step 3: Submit your application
Once your application is built and packaged, the final step is to share it with the Olares community.
* **[Submit to Market](./submit/index.md)**: Learn how to submit your application to the Olares Market for review and distribution.
* **[Submit to Market](/developer/develop/distribute-index.md)**: Learn how to submit your application to the Olares Market for review and distribution.

View File

@@ -0,0 +1,72 @@
---
outline: [2, 3]
description: Learn how to update, suspend, or remove your application from Olares Market.
---
# Manage the app lifecycle
This guide explains how to manage an application after it has been published, including updating, suspending, or removing it from Olares Market.
All actions are performed through Pull Requests (PRs) to the `main` branch. Terminus-Gitbot supports three lifecycle actions after your app is published:
- **UPDATE**: Keep your app up to date. Release new versions, fix bugs, or adjust configurations.
- **SUSPEND**: Pause distribution. Stop new discovery, downloads, and installs in Olares Market without affecting existing users.
- **REMOVE**: Retire the app. Permanently stop distribution and prevent the chart folder name from being reused.
:::tip Reduce conflicts
Before opening the PR, sync your fork and rebase your branch onto the latest `main` to reduce potential conflicts.
:::
## Control files
Control files are special empty files in the OAC root directory that manage an application's distribution status in Olares Market.
| File name | Used for | Version rule | Content needed |
|--|--|--|--|
| `.suspend` | Suspend distribution | Upgrade (>) | Empty file |
| `.remove` | Remove application | Same (=) | Empty file |
An `UPDATE` PR or a `NEW` PR must not include these files. They are only used for `SUSPEND` and `REMOVE`.
## Update an app (UPDATE)
To update an existing application, such as releasing a new version, changing configurations, or updating the owners, submit a PR with type `UPDATE`.
The PR must meet the following requirements:
- **Version bump**: The new Chart version must be greater than the current version in the repository. Any change to a chart must bump the Chart version.
- **Clean directory**: The OAC root must not contain `.suspend` or `.remove` files.
- **No conflict**: The PR branch must not conflict with `beclab/apps:main`.
:::warning No rollbacks
Olares Market does not support version rollbacks. If an issue occurs, you must submit a new version to fix it.
:::
## Suspend an app (SUSPEND)
To temporarily stop your application from being listed, downloaded, or installed, submit a PR with type `SUSPEND`.
The PR must meet the following requirements:
- **Version bump**: The Chart version must be greater than the current version in the repository.
- **Control file**: The OAC root directory contains the `.suspend` file and does not contain the `.remove` file.
- **No conflict**: The PR branch must not conflict with `beclab/apps:main`.
After the PR is merged, the application is no longer listed in Olares Market. Users who have already installed the application can continue to use it.
## Remove an app (REMOVE)
To permanently remove an application from Olares Market, submit a PR with type `REMOVE`.
The PR must meet the following requirements:
- **Same version**: The Chart version in the PR title must be the same as the current version in the repository.
- **Control file**: After the change, the `.remove` file is the only file in the OAC root directory.
- **No conflict**: The PR branch must not conflict with `beclab/apps:main`.
:::warning
Removal is irreversible.
:::
After the PR is merged:
- The chart folder name cannot be reused by the application owners.
- Users who have already installed the application can continue to use it.

View File

@@ -0,0 +1,71 @@
---
outline: [2, 3]
description: Learn how to integrate your app with Elasticsearch service in Olares.
---
# Integrate with Elasticsearch
Use Olares Elasticsearch middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install Elasticsearch service
Install the Elasticsearch service from Market.
1. Open Market from Launchpad and search for "Elasticsearch".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the Elasticsearch user.
- Use the `indexes` field to request one or more indexes. Each index name is used as the key in `.Values.elasticsearch.indexes`.
**Example**
```yaml
middleware:
elasticsearch:
username: elasticlient
indexes:
- name: aaa
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.elasticsearch.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
env:
- name: ES_HOST
value: "{{ .Values.elasticsearch.host }}"
- name: ES_PORT
value: "{{ .Values.elasticsearch.port }}"
- name: ES_USER
value: "{{ .Values.elasticsearch.username }}"
- name: ES_PASSWORD
value: "{{ .Values.elasticsearch.password }}"
# Index name
# The index name configured in OlaresManifest (for example, aaa)
- name: ES_INDEX
value: "{{ .Values.elasticsearch.indexes.aaa }}"
```
## Elasticsearch values reference
Elasticsearch values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.elasticsearch.host` | String | Elasticsearch service host. |
| `.Values.elasticsearch.port` | Number | Elasticsearch service port. |
| `.Values.elasticsearch.username` | String | Elasticsearch username. |
| `.Values.elasticsearch.password` | String | Elasticsearch password. |
| `.Values.elasticsearch.indexes` | Map\<String,String> | Requested indexes, keyed by index name. For example, a request for `aaa` is available at `.Values.elasticsearch.indexes.aaa`. |

View File

@@ -0,0 +1,70 @@
---
outline: [2, 3]
description: Learn how to integrate your app with MariaDB service in Olares.
---
# Integrate with MariaDB
Use Olares MariaDB middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install MariaDB service
Install the MariaDB service from Market.
1. Open Market from Launchpad and search for "MariaDB".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the database username.
- Use the `databases` field to request one or more databases. Each database name is used as the key in `.Values.mariadb.databases`.
**Example**
```yaml
middleware:
mariadb:
username: mariadbclient
databases:
- name: aaa
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.mariadb.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
# For MariaDB, the corresponding value is as follows
env:
- name: MDB_HOST
value: "{{ .Values.mariadb.host }}"
- name: MDB_PORT
value: "{{ .Values.mariadb.port }}"
- name: MDB_USER
value: "{{ .Values.mariadb.username }}"
- name: MDB_PASSWORD
value: "{{ .Values.mariadb.password }}"
# Database Name
# The database name configured in OlaresManifest (e.g., aaa)
- name: MDB_DB
value: "{{ .Values.mariadb.databases.aaa }}"
```
## MariaDB values reference
MariaDB values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mariadb.host` | String | MariaDB host. |
| `.Values.mariadb.port` | Number | MariaDB port. |
| `.Values.mariadb.username` | String | MariaDB username. |
| `.Values.mariadb.password` | String | MariaDB password. |
| `.Values.mariadb.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mariadb.databases.app_db`. |

View File

@@ -0,0 +1,72 @@
---
outline: [2, 3]
description: Learn how to integrate your app with MinIO service in Olares.
---
# Integrate with MinIO
Use Olares MinIO middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install MinIO service
Install the MinIO service from Market.
1. Open Market from Launchpad and search for "MinIO".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the MinIO access key.
- Use the `buckets` field to request one or more buckets. Each bucket name is used as the key in `.Values.minio.buckets`.
**Example**
```yaml
middleware:
minio:
username: miniouser
buckets:
- name: mybucket
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.minio.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
# For MinIO, the corresponding values are as follows
env:
# Construct the endpoint using host and port
- name: MINIO_ENDPOINT
value: "{{ .Values.minio.host }}:{{ .Values.minio.port }}"
- name: MINIO_PORT
value: "{{ .Values.minio.port }}"
- name: MINIO_ACCESS_KEY
value: "{{ .Values.minio.username }}"
- name: MINIO_SECRET_KEY
value: "{{ .Values.minio.password }}"
# Bucket name
# The bucket name configured in OlaresManifest (e.g., mybucket)
- name: MINIO_BUCKET
value: "{{ .Values.minio.buckets.mybucket }}"
```
## MinIO values reference
MinIO values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.minio.host` | String | MinIO service host. |
| `.Values.minio.port` | Number | MinIO service port. |
| `.Values.minio.username` | String | MinIO access key. |
| `.Values.minio.password` | String | MinIO secret key. |
| `.Values.minio.buckets` | Map\<String,String> | Requested buckets, keyed by bucket name. For example, a request for `mybucket` is available at `.Values.minio.buckets.mybucket`. |

View File

@@ -0,0 +1,76 @@
---
outline: [2, 3]
description: Learn how to integrate your app with MongoDB service in Olares.
---
# Integrate with MongoDB
Use Olares MongoDB middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install MongoDB service
Install the MongoDB service from Market.
1. Open Market from Launchpad and search for "MongoDB".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the MongoDB database user.
- Use the `databases` field to request one or more databases.
- (Optional) Use the `script` field under each database to specify initialization scripts that are executed after the database is created.
**Example**
```yaml
middleware:
mongodb:
username: chromium
databases:
- name: chromium
script:
- 'db.getSiblingDB("$databasename").myCollection.insertOne({ x: 111 });'
# Please make sure each line is a complete query.
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.mongodb.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
# For MongoDB, the corresponding values are as follows
env:
- name: MONGODB_HOST
value: "{{ .Values.mongodb.host }}"
- name: MONGODB_PORT
value: "{{ .Values.mongodb.port }}"
- name: MONGODB_USER
value: "{{ .Values.mongodb.username }}"
- name: MONGODB_PASSWORD
value: "{{ .Values.mongodb.password }}"
# Database name
# The database name configured in OlaresManifest (e.g., app_db)
- name: MONGODB_DATABASE
value: "{{ .Values.mongodb.databases.app_db }}"
```
## MongoDB values reference
MongoDB values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mongodb.host` | String | MongoDB host. |
| `.Values.mongodb.port` | Number | MongoDB port. |
| `.Values.mongodb.username` | String | MongoDB username. |
| `.Values.mongodb.password` | String | MongoDB password. |
| `.Values.mongodb.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mongodb.databases.app_db`. |

View File

@@ -0,0 +1,72 @@
---
outline: [2, 3]
description: Learn how to integrate your app with MySQL service in Olares.
---
# Integrate with MySQL
Use Olares MySQL middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install MySQL service
Install the MySQL service from Market.
1. Open Market from Launchpad and search for "MySQL".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the MySQL database user.
- Use the `databases` field to request one or more databases. Each database name is used as the key in `.Values.mysql.databases`.
**Example**
```yaml
middleware:
mysql:
username: mysqlclient
databases:
- name: aaa
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.mysql.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
# For MySQL, the corresponding values are as follows
env:
- name: MDB_HOST
value: "{{ .Values.mysql.host }}"
- name: MDB_PORT
value: "{{ .Values.mysql.port }}"
- name: MDB_USER
value: "{{ .Values.mysql.username }}"
- name: MDB_PASSWORD
value: "{{ .Values.mysql.password }}"
# Database name
# The database name configured in OlaresManifest (e.g., aaa)
- name: MDB_DB
value: "{{ .Values.mysql.databases.aaa }}"
```
## MySQL values reference
MySQL values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.mysql.host` | String | MySQL host. |
| `.Values.mysql.port` | Number | MySQL port. |
| `.Values.mysql.username` | String | MySQL username. |
| `.Values.mysql.password` | String | MySQL password. |
| `.Values.mysql.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.mysql.databases.app_db`. |

View File

@@ -0,0 +1,82 @@
---
outline: [2, 3]
description: Learn how to integrate your app with the built-in PostgreSQL service in Olares.
---
# Integrate with PostgreSQL
Use Olares PostgreSQL middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
:::info PosgreSQL installed
PostgreSQL service has been installed by default.
:::
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `scripts` field to specify scripts that should be executed after the database is created.
- Use the `extensions` field to add the corresponding extension in the database.
:::info Variable injection in scripts
The OS provides two variables, `$databasename` and `$dbusername`, which will be replaced by Olares Application Runtime when the command is executed.
:::
**Example**
```yaml
middleware:
postgres:
username: immich
databases:
- name: immich
extensions:
- vectors
- earthdistance
scripts:
- BEGIN;
- ALTER DATABASE $databasename SET search_path TO "$user", public, vectors;
- ALTER SCHEMA vectors OWNER TO $dbusername;
- COMMIT;
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.postgres.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
env:
# The database name configured in OlaresManifest, specified in middleware.postgres.databases[i].name
# NOTE: Replace <dbname> with the actual name defined in the Manifest (e.g., immich)
- name: DB_POSTGRESDB_DATABASE
value: {{ .Values.postgres.databases.<dbname> }}
# Host
- name: DB_POSTGRESDB_HOST
value: {{ .Values.postgres.host }}
# Port
- name: DB_POSTGRESDB_PORT
value: "{{ .Values.postgres.port }}"
# Username
- name: DB_POSTGRESDB_USER
value: {{ .Values.postgres.username }}
# Password
- name: DB_POSTGRESDB_PASSWORD
value: {{ .Values.postgres.password }}
```
## PostgreSQL values reference
PostgreSQL values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.postgres.host` | String | PostgreSQL host. |
| `.Values.postgres.port` | Number | PostgreSQL port. |
| `.Values.postgres.username` | String | PostgreSQL username. |
| `.Values.postgres.password` | String | PostgreSQL password. |
| `.Values.postgres.databases` | Map\<String,String> | Requested databases, keyed by database name. For example, a request for `app_db` is available at `.Values.postgres.databases.app_db`. |

View File

@@ -0,0 +1,91 @@
---
outline: [2, 3]
description: Learn how to integrate your app with RabbitMQ service in Olares.
---
# Integrate with RabbitMQ
Use Olares RabbitMQ middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
## Install RabbitMQ service
Install the RabbitMQ service from Market.
1. Open Market from Launchpad and search for "RabbitMQ".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required middleware configuration.
- Use the `username` field to specify the RabbitMQ user.
- Use the `vhosts` field to request one or more virtual hosts (vhosts). Each vhost name is used as the key in `.Values.rabbitmq.vhosts`.
**Example**
```yaml
middleware:
rabbitmq:
username: rabbitmquser
vhosts:
- name: aaa
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.rabbitmq.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
# For RabbitMQ, the corresponding values are as follows
env:
- name: RABBITMQ_HOST
value: "{{ .Values.rabbitmq.host }}"
- name: RABBITMQ_PORT
value: "{{ .Values.rabbitmq.port }}"
- name: RABBITMQ_USER
value: "{{ .Values.rabbitmq.username }}"
- name: RABBITMQ_PASSWORD
value: "{{ .Values.rabbitmq.password }}"
# Vhost
# The vhost name configured in OlaresManifest (e.g., aaa)
- name: RABBITMQ_VHOST
value: "{{ .Values.rabbitmq.vhosts.aaa }}"
```
## Construct a RabbitMQ connection URI
After configuring the environment variables, you can read them in your application code to construct the connection string.
Below is an example of constructing an AMQP URL using the environment variables:
```Go
// Read environment variables
user := os.Getenv("RABBITMQ_USER")
password := os.Getenv("RABBITMQ_PASSWORD")
vhost := os.Getenv("RABBITMQ_VHOST")
host := os.Getenv("RABBITMQ_HOST")
portMQ := os.Getenv("RABBITMQ_PORT")
// Construct AMQP connection string
// Format: amqp://user:password@host:port/vhost
url := fmt.Sprintf("amqp://%s:%s@%s:%s/%s", user, password, host, portMQ, vhost)
```
## RabbitMQ values reference
RabbitMQ values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.rabbitmq.host` | String | RabbitMQ host. |
| `.Values.rabbitmq.port` | Number | RabbitMQ port. |
| `.Values.rabbitmq.username` | String | RabbitMQ username. |
| `.Values.rabbitmq.password` | String | RabbitMQ password. |
| `.Values.rabbitmq.vhosts` | Map\<String,String> | Requested vhosts, keyed by vhost name. For example, a request for `myvhost` is available at `.Values.rabbitmq.vhosts.myvhost`. |

View File

@@ -0,0 +1,66 @@
---
outline: [2, 3]
description: Learn how to integrate your app with the built-in Redis service in Olares.
---
# Integrate with Redis
Use Olares Redis middleware by declaring it in `OlaresManifest.yaml`, then mapping the injected values to your container environment variables.
:::info Redis installed
Redis service has been installed by default.
:::
## Configure `OlaresManifest.yaml`
In `OlaresManifest.yaml`, add the required Redis middleware configuration.
- Use the `password` field to specify the Redis access password.
- Use the `namespace` field to request a Redis namespace.
**Example**
```yaml
middleware:
redis:
password: password
namespace: db0
```
## Map to environment variables
In your deployment YAML, map the injected `.Values.redis.*` fields to the container environment variables your app requires.
**Example**
```yaml
containers:
- name: my-app
env:
# Host
- name: REDIS_HOST
value: {{ .Values.redis.host }}
# Port
# Quote the value to ensure it's treated as a string
- name: REDIS_PORT
value: "{{ .Values.redis.port }}"
# Password
# Quote the value to handle special characters correctly
- name: REDIS_PASSWORD
value: "{{ .Values.redis.password }}"
# Namespace
# NOTE: Replace <namespace> with the actual namespace defined in OlaresManifest (e.g., db0)
- name: REDIS_NAMESPACE
value: {{ .Values.redis.namespaces.<namespace> }}
```
## Redis values reference
Redis values are predefined runtime values injected into `values.yaml` during deployment. They are system-managed and not user-editable.
| Value | Type | Description |
| --- | --- | --- |
| `.Values.redis.host` | String | Redis host. |
| `.Values.redis.port` | Number | Redis port. |
| `.Values.redis.password` | String | Redis password. |
| `.Values.redis.namespaces` | Map\<String,String> | Requested namespaces, keyed by namespace name. For example, a request for `app_ns` is available at `.Values.redis.namespaces.app_ns`. |

View File

@@ -0,0 +1,64 @@
---
outline: [2, 3]
description: Learn what middleware is in Olares and navigate to access and integration guides for each supported service.
---
# Middleware in Olares
Middleware refers to infrastructure services that sit between your application and the system, providing data storage, messaging, and other common capabilities.
Our middleware documentation is organized into two types of guides:
- **Access and manage data**: Connect to a running service to inspect data and troubleshoot issues.
- **App integrate**: Configure your app to use a middleware service in Olares using `OlaresManifest.yaml`.
## Document types
### Access and manage data
Access and manage data guides explain how to connect to a running middleware service for administration.
Use these guides when you want to:
- Inspect stored data or indexes.
- Run queries or commands.
- Debug application behavior.
- Verify service status.
The access method (e.g., CLI, Dashboard, or Bytebase) depends on the service.
### App integration
App integration guides explain how to connect your application to a middleware service.
Use these guides when you want your application to:
- Declare dependencies in `OlaresManifest.yaml`.
- Request service resources.
- Read system-injected connection values in your application.
Integration is declarative and handled by Olares at deployment time.
## Supported services
### Databases and caching
| Service | Access and manage data | App integration |
| --- | --- | --- |
| Elasticsearch | [Access](./mw-view-es-data.md) | [Integrate](./mw-integrate-with-es.md) |
| MariaDB | [Access](./mw-view-mariadb-data.md) | [Integrate](./mw-integrate-with-mariadb.md) |
| MongoDB | [Access](./mw-view-mongodb-data.md) | [Integrate](./mw-integrate-with-mongodb.md) |
| MySQL | [Access](./mw-view-mysql-data.md) | [Integrate](./mw-integrate-with-mysql.md) |
| PostgreSQL | [Access](./mw-view-pg-data.md) | [Integrate](./mw-integrate-with-pg.md) |
| Redis | [Access](./mw-view-redis-data.md) | [Integrate](./mw-integrate-with-redis.md) |
### Messaging and streaming
| Service | Access and manage data | App integration |
| --- | --- | --- |
| RabbitMQ | [Access](./mw-view-rabbitmq-data.md) | [Integrate](./mw-integrate-with-rabbitmq.md) |
| NATS | [Access](./mw-view-nats-data.md) | — |
### Storage and observability
| Service | Access and manage data | App integration |
| --- | --- | --- |
| MinIO | [Access](./mw-view-minio-data.md) | [Integrate](./mw-integrate-with-minio.md) |
| Grafana | [Access](./mw-view-grafana-data.md) | — |
| OpenTelemetry | [Access](./mw-view-otel-data.md) | — |

View File

@@ -0,0 +1,69 @@
---
outline: [2, 3]
description: Learn how to connect to and manage Elasticsearch data in Olares using Bytebase.
---
# View Elasticsearch data
To use Elasticsearch in Olares, install it from Market first. This guide explains how to access and manage Elasticsearch data using Bytebase.
## Install Elasticsearch service
Before connecting, install the Elasticsearch service from Market.
1. Open Market from Launchpad and search for "Elasticsearch".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Get connection information
Before connecting, obtain Elasticsearch connection details from Control Hub.
1. Open Control Hub from Launchpad.
2. In the left navigation pane, go to Middleware and select **Elasticsearch**.
3. On the Details panel, record the following information:
- **Host**: Used for Bytebase connection.
- **User**: Used for Bytebase connection.
- **Password**: Used for Bytebase connection.
![Elasticsearch details](/images/developer/develop/middleware/mw-es-details.png#bordered){width=60% style="margin-left:0"}
## Manage via Bytebase
Bytebase provides a graphical interface for database management and schema changes.
### Prerequisites
:::info MongoDB app required
Bytebase uses MongoDB to store its metadata. Install MongoDB before installing Bytebase.
:::
1. Open Market and search for "MongoDB".
2. Click **Get**, then **Install**, and wait until the service is running.
3. After MongoDB is installed, search for "Bytebase" in Market.
4. Click **Get**, then **Install**.
### First-time setup
When launching Bytebase for the first time, you must configure an administrator account.
:::tip
Remember these credentials. Only the admin account can create new database instances.
:::
1. Open Bytebase from Launchpad.
2. Follow the on-screen prompts to set up your admin account with email and password.
### Create an Elasticsearch instance
1. Log in to Bytebase with your admin account.
2. In the left navigation pane, select **Instances**, then click **+ Add Instance**.
3. Choose **Elasticsearch** as the database type.
4. Fill in the connection fields using values from Control Hub:
- **Host or Socket**: Enter the **Host** address and do not include the port.
- **Port**: Keep the default, usually `9200`.
- **Username**: Enter the **User** value from Control Hub.
- **Password**: Enter the **Password** value from Control Hub.
5. Click **Test Connection** to verify connectivity, then click **Create**.
Creating an instance in Bytebase does not create a new database. Once the instance is created, you can use the corresponding client tools to inspect and manage data.

View File

@@ -0,0 +1,67 @@
---
outline: [2, 3]
description: Learn how to visualize Prometheus metrics in Olares using Grafana dashboards.
---
# Use Grafana dashboards
To visualize system metrics in Olares, you can run Grafana and connect it to the built-in Prometheus service. This guide explains how to install Grafana, connect the data source, and import a standard dashboard.
## Install Grafana
Before using Grafana, install it from Market.
1. Open Market from Launchpad and search for "Grafana".
2. Click **Get**, then **Install**.
3. In the pop-up window, set your login credentials:
- `GF_USERNAME`: Grafana login username.
- `GF_PASSWORD`: Grafana login password.
:::tip Remember your login credentials
These are the login credentials for Grafana. You will need them if you access Grafana later.
:::
![Set login credentials](/public/images/developer/develop/middleware/mw-grafana-set-login.png#bordered){width=90% style="margin-left:0"}
4. Wait for the installation to complete.
## Access Grafana
1. Open **Grafana** from Launchpad, then click <i class="material-symbols-outlined">open_in_new</i> to open it in a new tab.
2. On the login screen, enter the `GF_USERNAME` and `GF_PASSWORD` you configured during installation.
After logging in, you will see the Grafana home page.
## Add Prometheus data source
Olares runs a built-in Prometheus service that collects system metrics.
To connect Grafana to this internal service:
1. In the Grafana left navigation pane, go to **Connections** > **Data sources**.
2. Click **Add data source**, then select **Prometheus**.
3. For the **Prometheus server URL** field, enter:
```text
http://dashboard.<olaresid>.olares.com
```
Replace `<olaresid>` with your Olares ID.
4. Click **Save & test** at the bottom of the page. If the connection is successful, you will see the prompt below.
![Successful connection](/public/images/developer/develop/middleware/mw-grafana-connect.png#bordered){width=90% style="margin-left:0"}
## Create a dashboard
This approach is suitable when you need custom metrics and visualizations and are familiar with PromQL.
1. In the left navigation pane, click **Dashboards**.
2. Click **+ Create dashboard**, then select **+ Add visualization**.
3. Select **prometheus** as the data source.
4. Configure panels, PromQL queries, and expressions as needed.
5. Click **Save dashboard** in the top-right corner for future use.
## Import a dashboard (recommended)
If you do not need to build dashboards from scratch, you can import existing dashboards.
1. Visit the [Grafana Dashboard library](https://grafana.com/grafana/dashboards/).
2. Download the required dashboard as a `JSON` file.
3. In Grafana, click <i class="material-symbols-outlined">add_2</i> in the top-right corner and select **Import dashboard**.
4. Upload the `JSON` file, and select **prometheus** as the data source.
5. Click **Import** to complete the import.
Imported dashboards provide predefined panels and queries and can be customized after import.
![Imported dashboard](/public/images/developer/develop/middleware/mw-grafana-dashboard.png#bordered){width=90%}

View File

@@ -0,0 +1,91 @@
---
outline: [2, 3]
description: Learn how to connect to and manage MariaDB data in Olares using CLI or Bytebase.
---
# View MariaDB data
To use MariaDB in Olares, install it from Market first. This guide explains how to access and manage MariaDB data using CLI or Bytebase.
## Install MariaDB service
Before connecting, install the MariaDB service from Market.
1. Open Market from Launchpad and search for "MariaDB".
2. Click **Get**, then **Install**, and wait for the installation to complete.
Once installed, the service and its connection details will appear in the Middleware list in Control Hub.
## Get connection information
Before connecting, obtain MariaDB connection details from Control Hub.
1. Open Control Hub from Launchpad.
2. In the left navigation pane, go to Middleware and select **Mariadb**.
3. On the Details panel, record the following information:
- **Host**: Used for Bytebase connection.
- **User**: Used for Bytebase connection.
- **Password**: Used for both CLI and Bytebase.
![MariaDB details](/images/developer/develop/middleware/mw-mariadb-details.png#bordered){width=60% style="margin-left:0"}
## Access via CLI
You can use the Olares terminal to access the MariaDB container for debugging or data operations.
1. In Control Hub, open the Olares terminal at the bottom of the left navigation pane.
2. Retrieve the Pod name for the middleware:
```bash
kubectl get pods -n mariadb-middleware
```
3. Record the Pod name, then enter the container:
```bash
kubectl exec -it -n mariadb-middleware <mariadb-pod> -- sh
```
4. Connect to MariaDB:
```bash
mysql -u root -p
```
5. When prompted, enter the password you retrieved from Control Hub.
## Manage via Bytebase
Bytebase provides a graphical interface for database management and schema changes.
### Prerequisites
:::info MongoDB app required
Bytebase uses MongoDB to store its metadata. Install MongoDB before installing Bytebase.
:::
1. Open Market and search for "MongoDB".
2. Click **Get**, then **Install**, and wait until the service is running.
3. After MongoDB is installed, search for "Bytebase" in Market.
4. Click **Get**, then **Install**.
### First-time setup
When launching Bytebase for the first time, you must configure an administrator account.
:::tip
Remember these credentials. Only the admin account can create new database instances.
:::
1. Open Bytebase from Launchpad.
2. Follow the on-screen prompts to set up your admin account with email and password.
### Create a MariaDB instance
1. Log in to Bytebase with your admin account.
2. In the left navigation pane, select **Instances**, then click **+ Add Instance**.
3. Choose **MariaDB** as the database type.
4. Fill in the connection fields using values from Control Hub:
- **Host or Socket**: Enter the **Host** address and do not include the port.
- **Port**: Keep the default, usually `3306`.
- **Username**: Enter the **User** value from Control Hub.
- **Password**: Enter the **Password** value from Control Hub.
5. Click **Test Connection** to verify connectivity, then click **Create**.
Creating an instance in Bytebase does not create a new database. Once the instance is created, you can use the corresponding client tools to inspect and manage data.

Some files were not shown because too many files have changed in this diff Show More