Compare commits

...

209 Commits

Author SHA1 Message Date
hysyeah
ff7765bcb9 fix: skip invalid expose port (#2434) 2026-01-22 12:00:32 +08:00
wiy
c98c855099 feat(olares-app): update version to v1.8.2 (#2433)
* feat(olares-app): update version to v1.8.2

* feat(olares-app): update version to v1.8.2
2026-01-22 00:06:13 +08:00
hysyeah
4ae552f33f bfl: myapps api add rawAppName (#2432)
* fix: myapps api add rawAppName field

* update bfl api image tag to v0.4.39
2026-01-22 00:05:42 +08:00
hysyeah
f2aad6d9f6 cli: feat amdgpu install (#2430) 2026-01-22 00:05:01 +08:00
dkeven
02bc4fafd5 feat(cli): collect nginx logs stored temporarily in some containers (#2429) 2026-01-22 00:04:29 +08:00
eball
8d34cc995d daemon: modify mDNS registration method (#2427)
daemon: update zeroconf dependency to v0.2.5 and modify mDNS registration method
2026-01-19 23:28:29 +08:00
Yajing
a19e81a4a0 docs: refactor local access guide (#2419)
* docs: refactor local access guide

* Apply suggestions from code review

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

* address comments

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-19 21:59:08 +08:00
hysyeah
ee3f2a7df2 tapr: add max retry for delete action (#2426)
* tapr: upgrade pod template and image for PGCluster reconciliation (#2213)

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(ci): specify working directory in github action for tapr (#2215)

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(kvrocks): update init container image and pull policy configuration (#2331)

* tapr: change kvrocks running as root by default

* fix: add max retry for delete action

* tapr: update middleware-operator image tag to 0.2.31

---------

Co-authored-by: eball <liuy102@hotmail.com>
Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2026-01-19 20:31:35 +08:00
eball
73ea65b004 hami: revert hami-core latest update (#2424) 2026-01-19 19:26:28 +08:00
wiy
4ef2e7124a feat(olares-app): update olares-app version to v1.7.7 (#2423) 2026-01-19 14:06:43 +08:00
wiy
ef46f91ec7 feat(olares-app): update new version to v1.7.6 (#2422)
fix(share): fixed the error message that appeared after exceeding the upload limit.
2026-01-16 23:57:38 +08:00
hysyeah
0f5a346d86 authelia: fix target url parse method (#2421) 2026-01-16 23:57:12 +08:00
salt
caa799e902 feat: optimize highlight segment order (#2420)
Co-authored-by: ubuntu <you@example.com>
2026-01-16 15:42:12 +08:00
Power-One-2025
2be5f6d108 docs: add lobechat tutorial (#2368)
* docs/feat/add-lobechat-tutorial

* docs/feat/fix-images

* docs/feat/lobechat-fixlink

* docs/feat/iterate-content

* docs/update/more-content

* docs/updaate/refine

* docs/feat/lobechat-refine

* docs/feat/add-lobechat-index

* docs/updates/fix-link

* Update docs/use-cases/lobechat.md

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

* Update docs/use-cases/lobechat.md

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

* Update docs/use-cases/lobechat.md

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

* Update docs/use-cases/lobechat.md

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

* docs/update/address-comments

* Apply suggestions from code review

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

* docs/update/address-comment

* docs/update/conflict

* refine edit

* docs/updates/image-size-opt

* docs/update/resize

* Apply suggestions from code review

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

* docs/update/add-faq

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-15 23:29:06 +08:00
salt
05f3c8ffdc fix: fix meaningless word highlight (#2418)
Co-authored-by: ubuntu <you@example.com>
2026-01-15 19:30:06 +08:00
berg
c0e242b05c settings: update search origin (#2417)
feat: update system frontend version
2026-01-15 19:29:07 +08:00
Power-One-2025
7929e420b1 docs: add stirling-pdf tutorial (#2369) 2026-01-15 16:10:05 +08:00
Power-One-2025
66de213f43 docs/update/image-size-opt 2026-01-15 15:56:25 +08:00
Power-One-2025
2166cec66f docs/update/fixtoc 2026-01-15 15:37:44 +08:00
Power-One-2025
1a0f9727c4 Merge branch 'main' into docs/add-stirling-pdf-tutorial 2026-01-15 11:07:46 +08:00
hysyeah
810253fe94 kubeblocks: skip check pod spec,status image (#2414)
fix: skip check pod spec,status image
2026-01-14 23:57:45 +08:00
wiy
23429a6193 olares-app, login: update version to v1.7.4 (#2413) 2026-01-14 23:57:01 +08:00
salt
49e40f316f fix: fix english highight missing (#2412)
Co-authored-by: ubuntu <you@example.com>
2026-01-14 23:56:37 +08:00
eball
1e7b655826 daemon: handle missing auth token for WebSocket connections (#2411) 2026-01-14 23:56:09 +08:00
dkeven
adea16ce7e feat(gpu): update gpu plugin version to v2.6.8 (#2410) 2026-01-14 23:55:48 +08:00
Power-One-2025
c2222859a5 docs: add PDFMathTranslate tutorial (#2378)
* docs/feat/draft

* docs/update/more-content

* docs/updates/refine

* docs/update/fix-build-conflict

* docs/update/fix-broken-link

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* docs/updates/compress-images

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* docs/update/comments

* docs/update/refine

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* Update docs/use-cases/pdfmathtranslate.md

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

* docs/update/comment

* Update docs/use-cases/pdfmathtranslate.md

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

* docs/update/fix-link

* Update docs/use-cases/pdfmathtranslate.md

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

* docs/update/comment

---------

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-14 23:17:55 +08:00
yyh
e7dde2ff51 user-service: update mtranserverv2 (#2408)
fix(user-service): update mtranserverv2
2026-01-13 23:57:31 +08:00
lovehunter9
d06c1e8a99 fix: files check disk space for upload link and copy (#2407) 2026-01-13 23:57:01 +08:00
dkeven
131faacce0 feat(cli): sync kubeconfig for the original user invoking sudo (#2406) 2026-01-13 23:56:08 +08:00
Meow33
8133704761 docs: add CLI docs for user, upgrade, and disk commands (#2383)
* docs: add CLI docs for user, upgrade, and disk commands

* docs: update based on comments

* docs: fix typo

* docs: refine formatting and add description for argument

* docs: resolve conflicts
2026-01-13 17:30:57 +08:00
Power-One-2025
09e61aecad docs/update/address-comment 2026-01-12 15:49:11 +08:00
Power-One-2025
bc5fd5fd82 Merge branch 'main' into docs/add-stirling-pdf-tutorial 2026-01-12 15:38:50 +08:00
Power-One-2025
1367355661 docs/update/address-comments 2026-01-12 15:36:38 +08:00
eball
2a506be19a ci: bump version to 1.12.5 (#2405) 2026-01-12 15:00:44 +08:00
Power-One-2025
30195f1513 Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:42:28 +08:00
Power-One-2025
88b140ccc2 Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:42:14 +08:00
Power-One-2025
39947f464c Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:41:31 +08:00
Power-One-2025
698bdf96ed docs: remove outdated environment variables (#2394) 2026-01-12 14:05:52 +08:00
wiy
69e6ac35f8 feat(olares-app): file upload add total_size parameter (#2404)
* feat(olares-app): file upload add total_size parameter

* fix: infisical update

---------

Co-authored-by: aby913 <aby913@163.com>
2026-01-12 14:01:09 +08:00
salt
f41e66b39a feat: search3 upgrade to v0.1.2 for juicefs watch (#2403)
Co-authored-by: ubuntu <you@example.com>
2026-01-12 14:00:32 +08:00
dkeven
1a36faaf6d feat(cli): add upgrader for main line version 1.12.4 (#2402) 2026-01-12 13:59:24 +08:00
Yajing
cbdd08d237 docs: add faqs and refactor help docs (#2376)
* docs: add faqs and refactor help docs

* align zh-cn
2026-01-10 12:56:33 +08:00
dkeven
2fd9d23371 feat(cli): optimize and unify pod readiness check logic (#2393) 2026-01-09 16:10:12 +08:00
hysyeah
f1714534db appservice: delay create nats conn (#2392)
* fix: failed release upgrade

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

* fix: delay create nats conn (#2391)

* set appservice image tag and add readiness probe
2026-01-09 15:59:35 +08:00
lovehunter9
9bc66369df fix: files sync reconnection error msg and upload chuck access token (#2390) 2026-01-09 15:22:31 +08:00
Meow33
ba85b0f60d docs/remove outdated env variables 2026-01-09 14:45:07 +08:00
aby913
7c2624d418 market: skip systemenv check in the cloud, add nsfw trigger in settings (#2387)
market: fix systemenv in public, add nsfw trigger in settings
2026-01-08 23:36:40 +08:00
hysyeah
7eb21516d0 authelia,lldap: distinguish error message in firstfactor authentication (#2389) 2026-01-08 23:35:52 +08:00
berg
266aef8616 system frontend: add the NSFW feature (#2388)
* market: fix sync app state on nats, add log levels

* feat: update system frontend to v1.6.42

---------

Co-authored-by: aby913 <aby913@163.com>
2026-01-08 23:35:09 +08:00
aby913
3755bede0c backup: folder set to UID 1000 (#2386)
* backup: backup folder set to UID 1000

* backup: folder set to UID 1000
2026-01-08 23:33:01 +08:00
hysyeah
cca39eed7e appservice: fix inorder nats event (#2384)
* fix: failed release upgrade

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

* fix: push all nats event to queue  (#2374)

* fix: push all nats event to queue and via one connection

* fix: wrap yaml decode error

* update appservice image tag to 0.4.74
2026-01-08 23:31:25 +08:00
dkeven
b27b90b9a8 fix(bfl): add backend cluster API handler for stats report (#2382)
* fix(bfl): add backend cluster API handler for stats report (#2381)

* chore(bfl): update image version to v0.4.38
2026-01-08 23:30:37 +08:00
eball
119ec75234 cli: enhance CUDA library handling for WSL with strace detection (#2380) 2026-01-08 23:30:05 +08:00
aby913
8739bfc040 market: fix sync app state on nats, add log levels, nsfw label (#2379)
market: fix sync app state on nats, add log levels
2026-01-08 00:54:34 +08:00
Yajing
6304739725 docs: merge 1.12.3 docs to main (#2377) 2026-01-07 19:25:30 +08:00
yajing wang
f8f452b27f fix formatting 2026-01-07 19:12:03 +08:00
yajing wang
36acf0384d fix conflicts 2026-01-07 17:09:41 +08:00
Meow33
aa5b073b5c docs: update based on comments 2026-01-07 16:58:44 +08:00
Meow33
18dfae6c87 docs: add steam guide zh cn 2026-01-07 16:58:42 +08:00
Meow33
a54445db8b docs: address comments 2026-01-07 16:58:20 +08:00
Meow33
375e2c4f63 Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
c366b56de9 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
85d90a36ed docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
172c5342d8 docs: update file search guide 2026-01-07 16:58:20 +08:00
Yajing
dcc0ab1cd2 Update docs/zh/manual/olares/wise/index.md 2026-01-07 16:58:20 +08:00
Yajing
b078f80b5a fix wording 2026-01-07 16:58:20 +08:00
Meow33
854e25096f docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
78949de2b6 docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
bd72cb8067 docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
3b9f0d33a3 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
3e782c6cea Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
28c2979db0 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
fc8ade657d docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
74c80a9c7e Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
51a06f8964 docs: update relevant docs 2026-01-07 16:58:18 +08:00
Meow33
0c50d93d77 docs: refactor guide for gpu management 2026-01-07 16:57:42 +08:00
Power-One-2025
17b8d2d96e docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
5b5e5d289c docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
b113f66c4f Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
bbbe3ecf9b docs/update/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
b7ff5db985 docs/update/comments 2026-01-07 16:57:42 +08:00
Power-One-2025
f39e359ef8 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4a80ef6148 Update docs/.vitepress/en.ts
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
c4af7a5783 docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
5c498fbe18 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4fbe32b141 docs/update/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
46fc840302 docs/update/address-comments 2026-01-07 16:57:42 +08:00
Power-One-2025
5677026de0 Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4d95152e0a Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
9560985965 Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
1b6d90c2a5 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
2c73b3b7f8 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
22c52398ed docs/update/fix-comment 2026-01-07 16:57:42 +08:00
Power-One-2025
d1e55515d4 docs/updates/fix-note-style 2026-01-07 16:57:42 +08:00
Power-One-2025
5db251520d docs/updates/fix-comments 2026-01-07 16:57:42 +08:00
Power-One-2025
d2b630c7b4 docs/update/fix-links 2026-01-07 16:57:40 +08:00
Power-One-2025
0debd332a8 docs/updates/fix-toc 2026-01-07 16:54:40 +08:00
Power-One-2025
9a2c58e3fa docs/updates/market-comments-fix 2026-01-07 16:54:38 +08:00
Meow33
b8842cfe61 docs: update based on suggestions 2026-01-07 16:54:02 +08:00
Meow33
70e170b71a docs: update larepass upgrade descriptions 2026-01-07 16:54:02 +08:00
Power-One-2025
e975e4aec8 docs/update/files-index-update 2026-01-07 16:54:02 +08:00
Power-One-2025
9d6d242625 docs/update/refine-images 2026-01-07 16:54:02 +08:00
Power-One-2025
86d7b985a2 docs/update/preview-edit-files 2026-01-07 16:54:01 +08:00
Power-One-2025
31a2b3ee28 docs/updates/add-images 2026-01-07 16:54:01 +08:00
Power-One-2025
9aa7e0b108 docs/update/add-image-share 2026-01-07 16:54:01 +08:00
Power-One-2025
9092f28458 docs/updates/files-comments-fix 2026-01-07 16:54:01 +08:00
Yajing
f925268cd4 fix typo
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:54:01 +08:00
yajing wang
e1c19f7327 update intro & screenshots 2026-01-07 16:54:01 +08:00
Yajing
5e925e0cb6 Apply suggestions
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:54:01 +08:00
yajing wang
6a0885d37d fix lint 2026-01-07 16:54:00 +08:00
yajing wang
3e46af80e1 docs: add play games directly on olares device 2026-01-07 16:53:12 +08:00
yajing wang
74c48b81fb docs: update windows use case 2026-01-07 16:52:03 +08:00
Power-One-2025
56aed6b683 Update docs/zh/manual/olares/settings/gpu-resource.md 2026-01-07 16:52:03 +08:00
Meow33
cbfcf3d3aa docs: update screenshots 2026-01-07 16:52:03 +08:00
Meow33
fd23e52723 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
b48368b934 docs: update guide for manage gpu usage 2026-01-07 16:52:03 +08:00
Meow33
ca9ce45353 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
fa148969c5 docs: update en version based on suggestions and update translation 2026-01-07 16:52:03 +08:00
Meow33
21c1884bb8 docs: update tutorials for Wise 2026-01-07 16:52:03 +08:00
Meow33
b517d08981 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
73e2cd0eb4 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
a631db1e9e docs: add guide for search under settings 2026-01-07 16:52:03 +08:00
Meow33
f3b59b9b3e docs: add larepass upgrade restart prompt 2026-01-07 16:52:03 +08:00
Power-One-2025
910bf02b48 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
dcc909a06e Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
1238ad01f1 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
77ee176f5e Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
1d9c3f7b4a Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
8a52737f89 docs/update/refine-description 2026-01-07 16:52:03 +08:00
Power-One-2025
bd7c46a663 docs/update/table-line-wrap 2026-01-07 16:52:03 +08:00
Power-One-2025
9ee4af9040 docs/update/add-faq-resume-app 2026-01-07 16:52:03 +08:00
Power-One-2025
fc86bbadc2 docs/update/image 2026-01-07 16:52:03 +08:00
Power-One-2025
52118b1126 docs/updates/clond-apps-images 2026-01-07 16:52:01 +08:00
Power-One-2025
76be9e82c0 docs/updates/resize-image 2026-01-07 16:51:21 +08:00
Power-One-2025
478d9f28c8 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
114ed5ad7b Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
c85b23d9a9 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
fbc61764ca Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
d866966531 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
d140849d7c Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
679ddb0f8d Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
0ec0a5a4ac Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
74ecf9f73d Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
028c5c7bdb Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
f3ab03becc docs/update/consistency 2026-01-07 16:51:21 +08:00
Power-One-2025
e408da75a4 docs/update/mobile-app-image-style 2026-01-07 16:51:21 +08:00
Power-One-2025
8ffbc82ebd docs/update/formatting-fix-zh 2026-01-07 16:51:21 +08:00
Power-One-2025
304dbf69c5 docs/updates/formatting-fix 2026-01-07 16:51:21 +08:00
Power-One-2025
66b0144b40 docs/update/add-restore-purchased-app 2026-01-07 16:51:21 +08:00
Power-One-2025
e91a76f92f docs/updates/dev-comments 2026-01-07 16:51:21 +08:00
Power-One-2025
45cd406cd4 docs/updates/add-images-paid-app 2026-01-07 16:51:21 +08:00
Power-One-2025
7ef7ae9335 docs/feat/purchase-paid-apps 2026-01-07 16:51:21 +08:00
Power-One-2025
f2f342a28a Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
fdca458e4f docs/update/clone-apps 2026-01-07 16:51:21 +08:00
Power-One-2025
b7141373b7 docs/updates/add-note 2026-01-07 16:51:21 +08:00
Power-One-2025
21118c8e95 docs/updates/single-source-for-sync 2026-01-07 16:51:19 +08:00
Power-One-2025
307a6bb502 docs/updates/address comments on share files 2026-01-07 16:50:00 +08:00
Power-One-2025
91ec932c95 Update docs/manual/olares/files/add-edit-download.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:50:00 +08:00
Power-One-2025
a1cb16cfe9 docs/feat/share-files 2026-01-07 16:49:57 +08:00
Power-One-2025
aec5e178b3 docs/update/add-title-level 2026-01-07 16:48:15 +08:00
Power-One-2025
2624ea5dc5 docs/updates/address comment on files sync 2026-01-07 16:48:15 +08:00
Power-One-2025
0d1bae720d Update docs/manual/olares/files/add-edit-download.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
96520a8bc3 docs/feature/sync-files-to-local 2026-01-07 16:48:15 +08:00
Power-One-2025
27b9356037 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
c289d5837c Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
e6f9922951 address comment 2026-01-07 16:48:15 +08:00
Power-One-2025
a3ad8ce78c Update market.md 2026-01-07 16:48:15 +08:00
Power-One-2025
c70587062a Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
f7306b66dc Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
325bfeb90d Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
bfc3ca0720 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:14 +08:00
Power-One-2025
ef071e43ca docs: new app clone feature to Market 2026-01-07 16:48:14 +08:00
Power-One-2025
7440e85c2e docs/update/address-comments 2026-01-07 14:23:29 +08:00
Power-One-2025
d71747928c Update docs/use-cases/stirling-pdf.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 11:31:48 +08:00
eball
473898a715 daemon: bump zeroconf dependency to v0.2.4 (#2375)
daemon: bump zeroconf dependency to v0.2.4 and increase log verbosity for server events
2026-01-07 00:10:40 +08:00
lovehunter9
637b1839f7 fix: files sync reconnection at pipe client when sending has met broken pipe (#2373) 2026-01-05 23:46:42 +08:00
wiy
1f1c1a8d3b olares-app: update vault add websocket (#2372)
wizard: update qrcode size
2026-01-05 23:46:03 +08:00
dkeven
1ddcc3bd4c fix(gpu): handle scheduler inconsistency and device stuck in unhealthy (#2371) 2026-01-05 23:44:50 +08:00
dkeven
96a2eb524a fix(cli): remove olares name when uninstalling to prepare (#2370) 2026-01-05 23:44:08 +08:00
Power-One-2025
b20d5c0876 docs/feat/stirlingpdf-refine 2026-01-05 14:39:56 +08:00
Power-One-2025
c4fc3198bb docs/feat/stirlingpdf-add-index 2026-01-05 13:42:47 +08:00
Power-One-2025
260b6154f3 docs/feat/stirlingpdf-more 2026-01-05 13:38:33 +08:00
Power-One-2025
ecfcd0d1d8 docs/feat/content-add 2026-01-04 22:29:05 +08:00
eball
be7f3b3c3f daemon: update serial filtering logic to use suffix matching (#2367) 2026-01-04 20:44:41 +08:00
hysyeah
99c6d3860d app-service: app upgrade set tailscale acl (#2362)
* fix: failed release upgrade

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

* fix: app upgrade set tailscale acl (#2357)

* fix: increase wait timeout for namespace delete

* fix: update app-service image tag to 0.4.73
2025-12-31 23:58:57 +08:00
berg
9f56cf0f05 login, system frontend: update qrcode size (#2361)
feat: update login version and system frontend version
2025-12-31 23:58:11 +08:00
Yajing
76c8e93822 docs: fix misplaced braces in studio tutorial (#2358) 2025-12-31 21:41:30 +08:00
yajing wang
d38d0d0e1d docs: fix misplaced braces in studio tutorial 2025-12-31 20:59:24 +08:00
hysyeah
65b32c7c41 kubeblocks-addon: fix kubeblocks-addon rabbitmq image pull policy (#2356)
fix: kubeblocks-addon rabbitmq image pull policy
2025-12-31 15:10:26 +08:00
wiy
f6f14e8d9a olares app: update settings create sub-accounts to block domain (#2355) 2025-12-31 15:09:33 +08:00
eball
f8653692b1 daemon: update DID gate URL handling in JWS validation and resolution (#2354) 2025-12-31 13:07:22 +08:00
eball
5264df60cc cli: update ResolveOlaresName and CheckJWS to accept gateUrl parameter (#2352) 2025-12-31 00:11:35 +08:00
berg
1a200ed17c system frontend: update market topic ids (#2351)
feat: update system frontend version
2025-12-30 21:17:53 +08:00
eball
48fdaa5481 daemon: enhance USB monitoring with serial filtering support (#2349)
* daemon: enhance USB monitoring with serial filtering support

* daemon: add check for USB devices with serial before mounting

* daemon: implement FilterBySerial function for USB device filtering
2025-12-30 21:17:15 +08:00
eball
570fe070c9 k3s: update eviction thresholds and image GC settings (#2348)
k3s: update eviction thresholds and image GC settings for improved resource management
2025-12-30 21:16:54 +08:00
lovehunter9
6b18bbd94d fix: files change usb watcher to retry and change sync reconnection to callback (#2342)
* fix: files change usb watcher to retry and change sync reconnection to callback

* fix: create folder and rsync chown to 1000
2025-12-30 21:15:34 +08:00
Yajing
c6836f9859 docs: update nav to reflect the latest changes (#2343) 2025-12-30 17:41:39 +08:00
yajing wang
288869d91d docs: update nav to reflect the latest changes 2025-12-29 20:55:06 +08:00
hysyeah
8ea8a0857e app-service: add helm upgrade timeout (#2339)
* fix: failed release upgrade

* fix: update appservice image tag to 0.4.71

* fix: helm upgrade do not use atomic param and allow upgrade failed release
2025-12-27 14:05:22 +08:00
eball
87674cc5d9 opa: update image validation to exclude alpine and mariadb images (#2337) 2025-12-27 14:04:31 +08:00
berg
11f556e9af system frontend, market backend: verify the update time when the app status is changed. (#2336)
feat: update system frontend version
2025-12-27 14:04:14 +08:00
simon
d2d3195fea download-server: modify ytdlp support domain (#2335)
download
2025-12-27 14:03:45 +08:00
hysyeah
ad3b138284 app-service: fix exposeport upgrade (#2334)
* fix: exposeport upgrade (#2333)

* update appservice tag to 0.4.70
2025-12-26 19:41:14 +08:00
eball
ff609db1aa tapr: change kvrocks to run as root by default (#2332)
* tapr: upgrade pod template and image for PGCluster reconciliation (#2213)

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(ci): specify working directory in github action for tapr (#2215)

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(kvrocks): update init container image and pull policy configuration (#2331)

* tapr: change kvrocks running as root by default

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2025-12-26 19:40:48 +08:00
dkeven
43c6bff906 feat(cli): collect more logs for K8s resources (#2330) 2025-12-26 15:36:02 +08:00
berg
b28dac652c system fronted, market backend, chart repo: add suspend app function (#2329)
feat: update market version
2025-12-26 14:46:38 +08:00
lovehunter9
fbb5c08227 fix: files sync reconnection (#2327) 2025-12-25 19:05:04 +08:00
dkeven
a04d363597 fix(daemon): update module appservice dependency to fix security issues (#2326) 2025-12-25 17:21:19 +08:00
dkeven
994d2b9b91 fix(cli): update module appservice dependency to fix security issues (#2325) 2025-12-25 17:20:47 +08:00
428 changed files with 7842 additions and 3046 deletions

View File

@@ -75,7 +75,7 @@ jobs:
steps:
- id: generate
run: |
v=1.12.4-$(echo $RANDOM$RANDOM)
v=1.12.5-$(echo $RANDOM$RANDOM)
echo "version=$v" >> "$GITHUB_OUTPUT"
upload-cli:

View File

@@ -41,7 +41,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.24.3
go-version: 1.24.11
- name: Install x86_64 cross-compiler
run: sudo apt-get update && sudo apt-get install -y build-essential

View File

@@ -42,7 +42,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.22.1
go-version: 1.24.11
- name: install udev-devel and pcap-devel
run: |

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- id: generate
run: |
v=1.12.4-$(date +"%Y%m%d")
v=1.12.5-$(date +"%Y%m%d")
echo "version=$v" >> "$GITHUB_OUTPUT"
release-id:

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.6.31
image: beclab/system-frontend:v1.8.2
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.81
image: beclab/user-service:v0.0.82
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000

View File

@@ -29,7 +29,7 @@ spec:
containers:
- name: wizard
image: beclab/wizard:v1.6.30
image: beclab/wizard:v1.6.40
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80

View File

@@ -18,7 +18,7 @@ fi
if [[ x"$VERSION" == x"" ]]; then
if [[ "$LOCAL_RELEASE" == "1" ]]; then
ts=$(date +%Y%m%d%H%M%S)
export VERSION="1.12.4-$ts"
export VERSION="1.12.5-$ts"
echo "will build and use a local release of Olares with version: $VERSION"
echo ""
else
@@ -28,7 +28,7 @@ fi
if [[ "x${VERSION}" == "x" || "x${VERSION:3}" == "xVERSION__" ]]; then
echo "error: Olares version is unspecified, please set the VERSION env var and rerun this script."
echo "for example: VERSION=1.12.4-20241124 bash $0"
echo "for example: VERSION=1.12.5-20241124 bash $0"
exit 1
fi

View File

@@ -158,7 +158,7 @@ export VERSION="#__VERSION__"
if [[ "x${VERSION}" == "x" || "x${VERSION:3}" == "xVERSION__" ]]; then
echo "error: Olares version is unspecified, please set the VERSION env var and rerun this script."
echo "for example: VERSION=1.12.4-20241124 bash $0"
echo "for example: VERSION=1.12.5-20241124 bash $0"
exit 1
fi

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuInstall() *cobra.Command {
cmd := &cobra.Command{
Use: "install",
Short: "Install AMD ROCm stack via amdgpu-install",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuInstall(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -0,0 +1,16 @@
package amdgpu
import "github.com/spf13/cobra"
func NewCmdAmdGpu() *cobra.Command {
cmd := &cobra.Command{
Use: "amdgpu",
Short: "Manage AMD GPU ROCm stack",
}
cmd.AddCommand(NewCmdAmdGpuInstall())
cmd.AddCommand(NewCmdAmdGpuUninstall())
cmd.AddCommand(NewCmdAmdGpuStatus())
return cmd
}

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuStatus() *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "Show AMD GPU driver and ROCm status",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuStatus(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuUninstall() *cobra.Command {
cmd := &cobra.Command{
Use: "uninstall",
Short: "Uninstall AMD ROCm stack via amdgpu-install",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuUninstall(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -3,19 +3,24 @@ package os
import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"log"
"net"
"os"
"os/exec"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"strings"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
ctrl "sigs.k8s.io/controller-runtime"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/spf13/cobra"
@@ -242,7 +247,6 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
if err := cmd.Run(); err != nil {
logFile.Close()
return fmt.Errorf("failed to collect logs for %s: %v", service, err)
continue
}
logFile.Close()
@@ -276,7 +280,7 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
func collectDmesgLogs(tw *tar.Writer, options *LogCollectOptions) error {
cmd := exec.Command("dmesg")
cmd := exec.Command("dmesg -T")
output, err := cmd.Output()
if err != nil {
return err
@@ -375,49 +379,153 @@ func collectKubernetesLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
}
cmd = exec.Command("kubectl", "describe", "pods", "--all-namespaces")
output, err = tryKubectlCommand(cmd, "describe pods", options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err == nil {
header := &tar.Header{
Name: "pods-describe.txt",
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
resourceTypes := []string{"node", "pod", "statefulset", "deployment", "replicaset", "service", "configmap"}
for _, res := range resourceTypes {
cmd = exec.Command("kubectl", "describe", res, "--all-namespaces")
output, err = tryKubectlCommand(cmd, fmt.Sprintf("describe %s", res), options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write pods description header: %v", err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write pods description data: %v", err)
if err == nil {
header := &tar.Header{
Name: fmt.Sprintf("%s-describe.txt", res),
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write %s description header: %v", res, err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write %s description data: %v", res, err)
}
}
}
cmd = exec.Command("kubectl", "describe", "node")
output, err = tryKubectlCommand(cmd, "describe node", options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err == nil {
header := &tar.Header{
Name: "node-describe.txt",
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write node description header: %v", err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write node description data: %v", err)
if err := collectNginxLogsFromLabeledPods(tw); err != nil {
if !options.IgnoreKubeErrors {
return fmt.Errorf("failed to collect nginx logs from labeled pods: %v", err)
}
}
return nil
}
func collectNginxLogsFromLabeledPods(tw *tar.Writer) error {
if _, err := util.GetCommand("kubectl"); err != nil {
fmt.Printf("warning: kubectl not found, skipping collecting nginx logs from labeled pods\n")
return nil
}
cfg, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get kubeconfig: %v", err)
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return fmt.Errorf("failed to create kube client: %v", err)
}
type selectorSpec struct {
LabelSelector string
ContainerName string
}
selectors := []selectorSpec{
{LabelSelector: "app=l4-bfl-proxy", ContainerName: ""},
{LabelSelector: "tier=bfl", ContainerName: "ingress"},
}
type targetPod struct {
Namespace string
Name string
ContainerName string
}
var targets []targetPod
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
for _, sel := range selectors {
podList, err := clientset.CoreV1().Pods(corev1.NamespaceAll).List(ctx, metav1.ListOptions{LabelSelector: sel.LabelSelector})
if err != nil {
return fmt.Errorf("failed to list pods by label %q: %v", sel.LabelSelector, err)
}
for _, pod := range podList.Items {
targets = append(targets, targetPod{
Namespace: pod.Namespace,
Name: pod.Name,
ContainerName: sel.ContainerName,
})
}
}
if len(targets) == 0 {
return nil
}
// simplest approach: use kubectl cp (it already implements copy via tar over exec)
tempDir, err := os.MkdirTemp("", "olares-nginx-logs-*")
if err != nil {
return fmt.Errorf("failed to create temp directory for nginx logs: %v", err)
}
defer os.RemoveAll(tempDir)
files := []string{"/var/log/nginx/access.log", "/var/log/nginx/error.log"}
for _, target := range targets {
for _, remotePath := range files {
base := filepath.Base(remotePath)
archivePath := filepath.Join("nginx", target.Namespace, target.Name, base)
dest := filepath.Join(tempDir, fmt.Sprintf("%s__%s__%s", target.Namespace, target.Name, base))
err := kubectlCopyFile(target.Namespace, target.Name, target.ContainerName, remotePath, dest)
if err != nil {
return fmt.Errorf("failed to kubectl cp %s/%s:%s: %v", target.Namespace, target.Name, remotePath, err)
}
fi, err := os.Stat(dest)
if err != nil {
return fmt.Errorf("failed to stat copied nginx log %s: %v", dest, err)
}
f, err := os.Open(dest)
if err != nil {
return fmt.Errorf("failed to open copied nginx log %s: %v", dest, err)
}
defer f.Close()
header := &tar.Header{
Name: archivePath,
Mode: 0644,
Size: fi.Size(),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write header for %s: %v", archivePath, err)
}
if _, err := io.CopyN(tw, f, header.Size); err != nil {
return fmt.Errorf("failed to write data for %s: %v", archivePath, err)
}
}
}
return nil
}
func kubectlCopyFile(namespace, pod, container, remotePath, destPath string) error {
args := []string{"-n", namespace, "cp"}
if container != "" {
args = append(args, "-c", container)
}
args = append(args, fmt.Sprintf("%s:%s", pod, remotePath), destPath)
cmd := exec.Command("kubectl", args...)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("kubectl %s failed: %v, output: %s", strings.Join(args, " "), err, strings.TrimSpace(string(out)))
}
return nil
}
func collectNetworkConfigs(tw *tar.Writer, options *LogCollectOptions) error {
if _, err := util.GetCommand("ip"); err == nil {
cmd := exec.Command("ip", "address")

View File

@@ -49,7 +49,7 @@ func NewCmdRelease() *cobra.Command {
}
if version == "" {
version = fmt.Sprintf("1.12.4-%s", time.Now().Format("20060102150405"))
version = fmt.Sprintf("1.12.5-%s", time.Now().Format("20060102150405"))
fmt.Printf("--version unspecified, using: %s\n", version)
time.Sleep(1 * time.Second)
}

View File

@@ -1,6 +1,7 @@
package ctl
import (
"github.com/beclab/Olares/cli/cmd/ctl/amdgpu"
"github.com/beclab/Olares/cli/cmd/ctl/disk"
"github.com/beclab/Olares/cli/cmd/ctl/gpu"
"github.com/beclab/Olares/cli/cmd/ctl/node"
@@ -33,6 +34,7 @@ func NewDefaultCommand() *cobra.Command {
cmds.AddCommand(os.NewOSCommands()...)
cmds.AddCommand(node.NewNodeCommand())
cmds.AddCommand(gpu.NewCmdGpu())
cmds.AddCommand(amdgpu.NewCmdAmdGpu())
cmds.AddCommand(user.NewUserCommand())
cmds.AddCommand(disk.NewDiskCommand())

View File

@@ -1,15 +1,16 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"context"
"fmt"
"log"
"strings"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation"
"log"
"strings"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"

View File

@@ -1,16 +1,17 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"fmt"
"os"
"strconv"
"time"
"github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd"
"os"
"sigs.k8s.io/controller-runtime/pkg/client"
"strconv"
"time"
)
func newUserClientFromKubeConfig(kubeconfig string) (client.Client, error) {

View File

@@ -1,27 +1,21 @@
module github.com/beclab/Olares/cli
go 1.24.2
toolchain go1.24.6
go 1.24.11
replace (
bytetrade.io/web3os/app-service => github.com/beclab/app-service v0.4.41
bytetrade.io/web3os/backups-sdk => github.com/Above-Os/backups-sdk v0.1.17
github.com/containers/image/v5 => github.com/containers/image/v5 v5.21.1
github.com/containers/storage => github.com/containers/storage v1.40.0
github.com/estesp/manifest-tool/v2 => github.com/estesp/manifest-tool/v2 v2.0.3
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.1.0
)
require (
bytetrade.io/web3os/app-service v0.0.0-00010101000000-000000000000
bytetrade.io/web3os/backups-sdk v0.0.0-00010101000000-000000000000
github.com/Masterminds/semver/v3 v3.4.0
github.com/PaesslerAG/jsonpath v0.1.1
github.com/alecthomas/assert/v2 v2.11.0
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70
github.com/beclab/api v0.0.2
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/containerd/containerd v1.7.28
github.com/containerd/containerd v1.7.29
github.com/decentralized-identity/web5-go v0.25.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
github.com/distribution/reference v0.6.0
@@ -48,10 +42,10 @@ require (
github.com/syndtr/goleveldb v1.0.0
github.com/tyler-smith/go-bip39 v1.1.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.41.0
golang.org/x/sys v0.35.0
golang.org/x/term v0.34.0
golang.org/x/text v0.28.0
golang.org/x/crypto v0.45.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.37.0
golang.org/x/text v0.31.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.18.6
@@ -94,9 +88,11 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/containers/image/v5 v5.36.1 // indirect
github.com/containers/storage v1.59.1 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
@@ -174,7 +170,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opencontainers/selinux v1.13.1 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
@@ -205,10 +201,11 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools/godoc v0.1.0-deprecated // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect

View File

@@ -43,10 +43,10 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70 h1:U3z6m0hokD1gzl788BrUdxCbDyAjdOBBXA8ilYgn6VQ=
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70/go.mod h1:D9wl7y3obLqXMqfubMROMgdxWAwInnKNrFC//d0nyIA=
github.com/beclab/api v0.0.2 h1:aD5RcMie2uqa/FZI7aQBa1F4yVEib8/x3IIZSLiHkBM=
github.com/beclab/api v0.0.2/go.mod h1:ESZLe8cf4934QFkU6cqbskKfiTyNk67i1qbv/ctS6js=
github.com/beclab/app-service v0.4.41 h1:WSIXEqHSAepHweBooPkc+pedVaGGn335RugNwixkciY=
github.com/beclab/app-service v0.4.41/go.mod h1:0vEg3rv/DbR7dYznvTlXNXyYNn+TXNMaxz03GQYRWUQ=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -68,8 +68,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c=
github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
@@ -88,13 +88,17 @@ github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRq
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containers/image/v5 v5.36.1 h1:6zpXBqR59UcAzoKpa/By5XekeqFV+htWYfr65+Cgjqo=
github.com/containers/image/v5 v5.36.1/go.mod h1:b4GMKH2z/5t6/09utbse2ZiLK/c72GuGLFdp7K69eA4=
github.com/containers/storage v1.59.1 h1:11Zu68MXsEQGBBd+GadPrHPpWeqjKS8hJDGiAHgIqDs=
github.com/containers/storage v1.59.1/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -105,16 +109,14 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
@@ -262,6 +264,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -348,6 +352,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nats-io/nats.go v1.45.0 h1:/wGPbnYXDM0pLKFjZTX+2JOw9TQPoIgTFrUaH97giwA=
@@ -368,12 +374,12 @@ github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
@@ -502,8 +508,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glB
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU=
@@ -542,8 +548,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -552,8 +558,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -564,8 +570,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -574,8 +580,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -587,14 +593,14 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -606,8 +612,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

133
cli/pkg/amdgpu/tasks.go Normal file
View File

@@ -0,0 +1,133 @@
package amdgpu
import (
"fmt"
"os/exec"
"path"
"path/filepath"
"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/Masterminds/semver/v3"
"github.com/pkg/errors"
)
// InstallAmdRocmModule installs AMD ROCm stack on supported Ubuntu if AMD GPU is present.
type InstallAmdRocmModule struct {
common.KubeModule
}
func (m *InstallAmdRocmModule) Init() {
m.Name = "InstallAMDGPU"
installAmd := &task.RemoteTask{
Name: "InstallAmdRocm",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Action: &InstallAmdRocm{
// no manifest needed
},
Parallel: false,
Retry: 1,
}
m.Tasks = []task.Interface{
installAmd,
}
}
// InstallAmdRocm installs ROCm using amdgpu-install on Ubuntu 22.04/24.04 for AMD GPUs.
type InstallAmdRocm struct {
common.KubeAction
}
func (t *InstallAmdRocm) Execute(runtime connector.Runtime) error {
si := runtime.GetSystemInfo()
if !si.IsLinux() || !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
return nil
}
amdGPUExists, err := utils.HasAmdIGPU(runtime)
if err != nil {
return err
}
// skip rocm install
if !amdGPUExists {
return nil
}
rocmV, _ := utils.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())
}
if rocmV != nil && rocmV.GreaterThan(min) {
logger.Warnf("Warning: detected ROCm version %s great than maximum tested version %s")
return nil
}
if rocmV != nil && rocmV.Equal(min) {
logger.Infof("detected ROCm version %s, skip rocm install...", min.Original())
return nil
}
// ensure python3-setuptools and python3-wheel
_, _ = runtime.GetRunner().SudoCmd("apt-get update", false, true)
checkPkgs := "dpkg -s python3-setuptools python3-wheel >/dev/null 2>&1 || DEBIAN_FRONTEND=noninteractive apt-get install -y python3-setuptools python3-wheel"
if _, err := runtime.GetRunner().SudoCmd(checkPkgs, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install python3-setuptools and python3-wheel")
}
// ensure amdgpu-install exists
if _, err := exec.LookPath("amdgpu-install"); err != nil {
var debURL string
if si.IsUbuntuVersionEqual(connector.Ubuntu2404) {
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/noble/amdgpu-install_7.1.1.70101-1_all.deb"
} else {
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/jammy/amdgpu-install_7.1.1.70101-1_all.deb"
}
tmpDeb := path.Join(runtime.GetBaseDir(), cc.PackageCacheDir, "gpu", "amdgpu-install_7.1.1.70101-1_all.deb")
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("install -d -m 0755 %s", filepath.Dir(tmpDeb)), false, true); err != nil {
return err
}
cmd := fmt.Sprintf("sh -c 'wget -O %s %s'", tmpDeb, debURL)
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to download amdgpu-install deb")
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("DEBIAN_FRONTEND=noninteractive apt-get install -y %s", tmpDeb), false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install amdgpu-install deb")
}
}
// run installer for rocm usecase
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
}
fmt.Println()
logger.Warn("Warning: To enable ROCm, please reboot your machine after installation.")
return nil
}
type AmdgpuInstallAction struct {
common.KubeAction
}
func (t *AmdgpuInstallAction) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
}
return nil
}
type AmdgpuUninstallAction struct {
common.KubeAction
}
func (t *AmdgpuUninstallAction) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install --uninstall -y", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to uninstall AMD ROCm via amdgpu-install")
}
fmt.Println()
logger.Warn("Warning: Please reboot your machine after uninstall to fully remove ROCm components.")
return nil
}

View File

@@ -81,6 +81,7 @@ func (m *RunPrechecksModule) Init() {
new(NvidiaCardArchChecker),
new(NouveauChecker),
new(CudaChecker),
new(RocmChecker),
}
runPreChecks := &task.LocalTask{
Name: "RunPrechecks",

View File

@@ -372,6 +372,48 @@ func (c *CudaChecker) Check(runtime connector.Runtime) error {
return nil
}
// RocmChecker checks AMD ROCm version for AMD GPU on Ubuntu 22.04/24.04 only.
type RocmChecker struct{}
func (r *RocmChecker) Name() string {
return "ROCm"
}
func (r *RocmChecker) Check(runtime connector.Runtime) error {
if !runtime.GetSystemInfo().IsLinux() {
return nil
}
si := runtime.GetSystemInfo()
if !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
return nil
}
// detect AMD GPU presence
amdGPUExists, err := utils.HasAmdIGPU(runtime)
if err != nil {
return err
}
// no AMD GPU found, no need to check rocm
if !amdGPUExists {
return nil
}
curV, err := utils.RocmVersion()
if err != nil && !os.IsNotExist(err) {
return err
}
if os.IsNotExist(err) {
return nil
}
min := semver.MustParse("7.1.1")
if curV.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", curV.Original(), min.Original())
}
return nil
}
//////////////////////////////////////////////
// precheck - task

View File

@@ -287,7 +287,7 @@ func (a *Argument) LoadReleaseInfo() error {
return nil
}
func (a *Argument) SaveReleaseInfo() error {
func (a *Argument) SaveReleaseInfo(withoutName bool) error {
if a.BaseDir == "" {
return errors.New("invalid: empty base directory")
}
@@ -300,15 +300,17 @@ func (a *Argument) SaveReleaseInfo() error {
ENV_OLARES_VERSION: a.OlaresVersion,
}
if a.User != nil && a.User.UserName != "" && a.User.DomainName != "" {
releaseInfoMap["OLARES_NAME"] = fmt.Sprintf("%s@%s", a.User.UserName, a.User.DomainName)
} else {
if util.IsExist(OlaresReleaseFile) {
// if the user is not set, try to load the user name from the release file
envs, err := godotenv.Read(OlaresReleaseFile)
if err == nil {
if userName, ok := envs["OLARES_NAME"]; ok {
releaseInfoMap["OLARES_NAME"] = userName
if !withoutName {
if a.User != nil && a.User.UserName != "" && a.User.DomainName != "" {
releaseInfoMap["OLARES_NAME"] = fmt.Sprintf("%s@%s", a.User.UserName, a.User.DomainName)
} else {
if util.IsExist(OlaresReleaseFile) {
// if the user is not set, try to load the user name from the release file
envs, err := godotenv.Read(OlaresReleaseFile)
if err == nil {
if userName, ok := envs["OLARES_NAME"]; ok {
releaseInfoMap["OLARES_NAME"] = userName
}
}
}
}

View File

@@ -51,10 +51,12 @@ func (d DebianVersion) String() string {
}
const (
Ubuntu20 UbuntuVersion = "20."
Ubuntu22 UbuntuVersion = "22."
Ubuntu24 UbuntuVersion = "24."
Ubuntu25 UbuntuVersion = "25."
Ubuntu20 UbuntuVersion = "20."
Ubuntu22 UbuntuVersion = "22."
Ubuntu24 UbuntuVersion = "24."
Ubuntu25 UbuntuVersion = "25."
Ubuntu2204 UbuntuVersion = "22.04"
Ubuntu2404 UbuntuVersion = "24.04"
Debian9 DebianVersion = "9"
Debian10 DebianVersion = "10"

View File

@@ -10,8 +10,8 @@ import (
"strings"
"time"
v1alpha1 "bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "bytetrade.io/web3os/app-service/pkg/utils"
v1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils"
ctrl "sigs.k8s.io/controller-runtime"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -263,6 +263,10 @@ func (t *PatchK3sDriver) Execute(runtime connector.Runtime) error {
return err
}
if _, err := runtime.GetRunner().SudoCmd("apt install -y strace", false, false); err != nil {
return err
}
if _, err := runtime.GetRunner().SudoCmd(dstName, false, false); err != nil {
return errors.Wrap(err, "failed to apply CUDA patch for WSL")
}

View File

@@ -10,17 +10,39 @@ var (
K3sCudaFixValues = template.Must(template.New("cuda_lib_fix.sh").Parse(
dedent.Dedent(`#!/bin/bash
sh_c="sh -c"
real_driver=$($sh_c "find /usr/lib/wsl/drivers/ -name libcuda.so.1.1|head -1")
real_driver=""
real_nvml=""
# Try to find the real driver path via strace
real_driver_path=$($sh_c "strace -qq -e trace=openat /usr/lib/wsl/lib/nvidia-smi 2>&1|grep '/usr/lib/wsl/drivers'|grep libnvidia-ml.so.1|awk '{print \$2}'|sed 's/[\",]//g'|sed 's/libnvidia-ml.so.1//g'")
if [[ x"$real_driver_path" != x"" ]]; then
real_driver="${real_driver_path}libcuda.so.1.1"
real_nvml="${real_driver_path}libnvidia-ml.so.1"
else
driver_path=$($sh_c "strace -qq -e trace=openat /usr/lib/wsl/lib/nvidia-smi 2>&1|grep '/usr/lib/wsl/'|grep libnvidia-ml.so.1")
if [[ x"$driver_path" != x"" ]]; then
echo "already fixed cuda libs, exit now."
exit 0
fi
fi
if [[ x"$real_driver" == x"" ]]; then
real_driver=$($sh_c "find /usr/lib/wsl/drivers/ -name libcuda.so.1.1|head -1")
real_nvml=$($sh_c "find /usr/lib/wsl/drivers/ -name libnvidia-ml.so.1|head -1")
fi
if [[ x"$real_driver" != x"" ]]; then
$sh_c "ln -s /usr/lib/wsl/lib/libcuda* /usr/lib/x86_64-linux-gnu/"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1.1"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so.1"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so.1.1"
$sh_c "ln -s $real_driver /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "ln -s $real_driver /usr/lib/x86_64-linux-gnu/libcuda.so.1.1"
$sh_c "cp -f $real_nvml /usr/lib/wsl/lib/libnvidia-ml.so.1"
$sh_c "cp -f $real_driver /usr/lib/x86_64-linux-gnu/"
$sh_c "cp -f $real_nvml /usr/lib/x86_64-linux-gnu/"
$sh_c "ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.1.1 /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.1 /usr/lib/x86_64-linux-gnu/libcuda.so"
fi`),
))

View File

@@ -36,6 +36,7 @@ import (
"github.com/beclab/Olares/cli/pkg/k3s/templates"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/registry"
"github.com/beclab/Olares/cli/pkg/storage"
)
type InstallContainerModule struct {
@@ -470,6 +471,18 @@ func (j *JoinNodesModule) Init() {
Parallel: true,
}
createSharedLibDirForWorker := &task.RemoteTask{
Name: "CreateSharedLibDir(k3s)",
Desc: "Create shared lib directory on worker",
Hosts: j.Runtime.GetHostsByRole(common.Worker),
Prepare: &prepare.PrepareCollection{
&kubernetes.NodeInCluster{Not: true},
new(common.OnlyWorker),
},
Action: new(storage.CreateSharedLibDir),
Parallel: true,
}
enableK3s := &task.RemoteTask{
Name: "EnableK3sService",
Desc: "Enable k3s service",
@@ -536,6 +549,7 @@ func (j *JoinNodesModule) Init() {
k3sService,
k3sEnv,
k3sRegistryConfig,
createSharedLibDirForWorker,
enableK3s,
copyKubeConfigForMaster,
syncKubeConfigToWorker,

View File

@@ -195,13 +195,13 @@ func (g *GenerateK3sService) Execute(runtime connector.Runtime) error {
defaultKubeletArs := map[string]string{
"kube-reserved": "cpu=200m,memory=250Mi,ephemeral-storage=1Gi",
"system-reserved": "cpu=200m,memory=250Mi,ephemeral-storage=1Gi",
"eviction-hard": "memory.available<5%,nodefs.available<10%,imagefs.available<10%",
"eviction-hard": "memory.available<5%,nodefs.available<5%,imagefs.available<5%",
"config": "/etc/rancher/k3s/kubelet.config",
"containerd": container.DefaultContainerdCRISocket,
"cgroup-driver": "systemd",
"runtime-request-timeout": "5m",
"image-gc-high-threshold": "91",
"image-gc-low-threshold": "90",
"image-gc-high-threshold": "96",
"image-gc-low-threshold": "95",
"housekeeping_interval": "5s",
}
defaultKubeProxyArgs := map[string]string{
@@ -397,53 +397,23 @@ type CopyK3sKubeConfig struct {
}
func (c *CopyK3sKubeConfig) Execute(runtime connector.Runtime) error {
createConfigDirCmd := "mkdir -p /root/.kube && mkdir -p $HOME/.kube"
getKubeConfigCmd := "cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config"
chmodKubeConfigCmd := "chmod 0600 /root/.kube/config"
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return err
}
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd, chmodKubeConfigCmd}, " && ")
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
cmds := []string{
"mkdir -p /root/.kube",
"cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config",
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("cp -f /etc/rancher/k3s/k3s.yaml %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "copy k3s kube config failed")
}
userMkdir := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
userCopyKubeConfig := "cp -f /etc/rancher/k3s/k3s.yaml $HOME/.kube/config"
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user copy /etc/rancher/k3s/k3s.yaml to $HOME/.kube/config failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config 0600 failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
}
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
}
return nil
}
@@ -493,59 +463,29 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
cluster := v.(*K3sStatus)
createConfigDirCmd := "mkdir -p /root/.kube"
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
}
oldServer := "server: https://127.0.0.1:6443"
newServer := fmt.Sprintf("server: https://%s:%d",
s.KubeConf.Cluster.ControlPlaneEndpoint.Domain,
s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newKubeConfig := strings.Replace(cluster.KubeConfig, oldServer, newServer, -1)
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config")
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config failed")
}
userConfigDirCmd := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "$HOME/.kube/config")
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
return err
}
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
cmds := []string{
"mkdir -p /root/.kube",
fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config"),
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("echo '%s' > %s", newKubeConfig, targetKubeConfigPath),
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
}
}
return nil

View File

@@ -23,6 +23,7 @@ import (
"github.com/beclab/Olares/cli/pkg/core/prepare"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/storage"
)
type StatusModule struct {
@@ -243,6 +244,18 @@ func (j *JoinNodesModule) Init() {
Retry: 5,
}
createSharedLibDirForWorker := &task.RemoteTask{
Name: "CreateSharedLibDir(k8s)",
Desc: "Create shared lib directory on worker",
Hosts: j.Runtime.GetHostsByRole(common.Worker),
Prepare: &prepare.PrepareCollection{
&NodeInCluster{Not: true},
new(common.OnlyWorker),
},
Action: new(storage.CreateSharedLibDir),
Parallel: true,
}
joinWorkerNode := &task.RemoteTask{
Name: "JoinWorkerNode(k8s)",
Desc: "Join worker node",
@@ -323,6 +336,7 @@ func (j *JoinNodesModule) Init() {
j.Tasks = []task.Interface{
generateKubeadmConfig,
joinMasterNode,
createSharedLibDirForWorker,
joinWorkerNode,
copyKubeConfig,
removeMasterTaint,

View File

@@ -417,51 +417,23 @@ type CopyKubeConfigForControlPlane struct {
}
func (c *CopyKubeConfigForControlPlane) Execute(runtime connector.Runtime) error {
createConfigDirCmd := "mkdir -p /root/.kube"
getKubeConfigCmd := "cp -f /etc/kubernetes/admin.conf /root/.kube/config"
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd}, " && ")
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return err
}
cmds := []string{
"mkdir -p /root/.kube",
"cp -f /etc/kubernetes/admin.conf /root/.kube/config",
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("cp -f /etc/kubernetes/admin.conf %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "copy kube config failed")
}
userMkdir := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
userCopyKubeConfig := "cp -f /etc/kubernetes/admin.conf $HOME/.kube/config"
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user copy /etc/kubernetes/admin.conf to $HOME/.kube/config failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
}
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
}
return nil
}
@@ -521,53 +493,23 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
cluster := v.(*KubernetesStatus)
createConfigDirCmd := "mkdir -p /root/.kube"
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
}
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config")
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
}
userConfigDirCmd := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "$HOME/.kube/config")
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
return err
}
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
cmds := []string{
"mkdir -p /root/.kube",
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config"),
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, targetKubeConfigPath),
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
}
}
return nil

View File

@@ -296,8 +296,10 @@ func GetKubeletConfiguration(runtime connector.Runtime, kubeConf *common.KubeCon
"memory": "250Mi",
},
"evictionHard": map[string]string{
"memory.available": "5%",
"pid.available": "10%",
"memory.available": "5%",
"pid.available": "10%",
"nodefs.available": "5%",
"imagefs.available": "5%",
},
"evictionSoft": map[string]string{
"memory.available": "10%",
@@ -309,8 +311,8 @@ func GetKubeletConfiguration(runtime connector.Runtime, kubeConf *common.KubeCon
"evictionPressureTransitionPeriod": "30s",
"featureGates": FeatureGatesDefaultConfiguration,
"runtimeRequestTimeout": "5m",
"imageGCHighThresholdPercent": 91,
"imageGCLowThresholdPercent": 90,
"imageGCHighThresholdPercent": 96,
"imageGCLowThresholdPercent": 95,
}
if securityEnhancement {

View File

@@ -111,6 +111,7 @@ func (p *phaseBuilder) phaseInstall() *phaseBuilder {
PhaseFile: common.TerminusStateFileInstalled,
BaseDir: p.runtime.GetBaseDir(),
},
&terminus.WriteReleaseFileModule{WithoutName: true},
)
}
return p

View File

@@ -3,8 +3,7 @@ package system
import (
"strings"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/beclab/Olares/cli/pkg/amdgpu"
"github.com/beclab/Olares/cli/pkg/bootstrap/os"
"github.com/beclab/Olares/cli/pkg/bootstrap/patch"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
@@ -12,6 +11,7 @@ import (
"github.com/beclab/Olares/cli/pkg/container"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/daemon"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/beclab/Olares/cli/pkg/images"
"github.com/beclab/Olares/cli/pkg/k3s"
"github.com/beclab/Olares/cli/pkg/manifest"
@@ -82,6 +82,7 @@ func (l *linuxPhaseBuilder) build() []module.Module {
addModule(&terminus.WriteReleaseFileModule{}).
addModule(gpuModuleBuilder(func() []module.Module {
return []module.Module{
&amdgpu.InstallAmdRocmModule{},
&gpu.InstallDriversModule{
ManifestModule: manifest.ManifestModule{
Manifest: l.manifestMap,

101
cli/pkg/pipelines/amdgpu.go Normal file
View File

@@ -0,0 +1,101 @@
package pipelines
import (
"strings"
"github.com/beclab/Olares/cli/pkg/amdgpu"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/action"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type singleTaskModule struct {
common.KubeModule
name string
act action.Action
}
func (m *singleTaskModule) Init() {
m.Name = m.name
m.Tasks = []task.Interface{
&task.LocalTask{
Name: m.name,
Action: m.act,
},
}
}
func AmdGpuInstall() error {
arg := common.NewArgument()
arg.SetConsoleLog("amdgpuinstall.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
if err != nil {
return err
}
p := &pipeline.Pipeline{
Name: "InstallAMDGPUDrivers",
Runtime: runtime,
Modules: []module.Module{
&amdgpu.InstallAmdRocmModule{},
},
}
return p.Start()
}
func AmdGpuUninstall() error {
arg := common.NewArgument()
arg.SetConsoleLog("amdgpuuninstall.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
if err != nil {
return err
}
p := &pipeline.Pipeline{
Name: "UninstallAMDGPUDrivers",
Runtime: runtime,
Modules: []module.Module{
&singleTaskModule{name: "AmdgpuUninstall", act: new(amdgpu.AmdgpuUninstallAction)},
},
}
return p.Start()
}
func AmdGpuStatus() error {
arg := common.NewArgument()
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
if err != nil {
return err
}
runtime.SetRunner(
&connector.Runner{
Host: &connector.BaseHost{
Name: common.LocalHost,
Arch: runtime.GetSystemInfo().GetOsArch(),
Os: runtime.GetSystemInfo().GetOsType(),
},
},
)
amdModel, _ := runtime.GetRunner().SudoCmd("lspci | grep -iE 'VGA|3D|Display' | grep -iE 'AMD|ATI' | head -1 || true", false, false)
drvVer, _ := runtime.GetRunner().SudoCmd("modinfo amdgpu 2>/dev/null | awk -F': ' '/^version:/{print $2}' || true", false, false)
rocmVer, _ := runtime.GetRunner().SudoCmd("cat /opt/rocm/.info/version 2>/dev/null || true", false, false)
if strings.TrimSpace(amdModel) != "" {
logger.Infof("AMD GPU: %s", strings.TrimSpace(amdModel))
} else {
logger.Info("AMD GPU: not detected")
}
if strings.TrimSpace(drvVer) != "" {
logger.Infof("AMDGPU driver %s", strings.TrimSpace(drvVer))
} else {
logger.Info("AMDGPU driver version: unknown")
}
if strings.TrimSpace(rocmVer) != "" {
logger.Infof("ROCm version: %s", strings.TrimSpace(rocmVer))
} else {
logger.Info("ROCm version: not installed")
}
return nil
}

View File

@@ -396,3 +396,17 @@ func (t *DeleteTerminusData) Execute(runtime connector.Runtime) error {
return nil
}
type CreateSharedLibDir struct {
common.KubeAction
}
func (t *CreateSharedLibDir) Execute(runtime connector.Runtime) error {
if runtime.GetSystemInfo().IsDarwin() {
return nil
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", OlaresSharedLibDir, OlaresSharedLibDir), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
}
return nil
}

View File

@@ -74,6 +74,7 @@ func (m *PreparedModule) Init() {
type WriteReleaseFileModule struct {
common.KubeModule
WithoutName bool
}
func (m *WriteReleaseFileModule) Init() {
@@ -82,7 +83,7 @@ func (m *WriteReleaseFileModule) Init() {
m.Tasks = []task.Interface{
&task.LocalTask{
Name: "WriteReleaseFile",
Action: new(WriteReleaseFile),
Action: &WriteReleaseFile{WithoutName: m.WithoutName},
},
}
}

View File

@@ -10,8 +10,8 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "bytetrade.io/web3os/app-service/pkg/utils"
"github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/storage"
@@ -38,12 +38,6 @@ type InstallOsSystem struct {
}
func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
if !runtime.GetSystemInfo().IsDarwin() {
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", storage.OlaresSharedLibDir, storage.OlaresSharedLibDir), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
}
}
config, err := ctrl.GetConfig()
if err != nil {
return err
@@ -367,6 +361,11 @@ func (m *InstallOsSystemModule) Init() {
Action: &CreateUserEnvConfigMap{},
}
createSharedLibDir := &task.LocalTask{
Name: "CreateSharedLibDir",
Action: &storage.CreateSharedLibDir{},
}
installOsSystem := &task.LocalTask{
Name: "InstallOsSystem",
Action: &InstallOsSystem{},
@@ -399,6 +398,7 @@ func (m *InstallOsSystemModule) Init() {
m.Tasks = []task.Interface{
applySystemEnv,
createUserEnvConfigMap,
createSharedLibDir,
installOsSystem,
createBackupConfigMap,
checkSystemService,

View File

@@ -97,25 +97,8 @@ func (t *CheckKeyPodsRunning) Execute(runtime connector.Runtime) error {
if !strings.HasPrefix(pod.Namespace, "user-") && !strings.HasPrefix(pod.Namespace, "os-") {
continue
}
if pod.Status.Phase != corev1.PodRunning {
return fmt.Errorf("pod %s/%s is not running", pod.Namespace, pod.Name)
}
if len(pod.Status.ContainerStatuses) != len(pod.Spec.Containers) {
return fmt.Errorf("pod %s/%s has not started all containers yet", pod.Namespace, pod.Name)
}
for _, cStatus := range pod.Status.ContainerStatuses {
if cStatus.State.Terminated != nil {
if cStatus.State.Terminated.ExitCode != 0 {
return fmt.Errorf("container %s in pod %s/%s is terminated", cStatus.Name, pod.Namespace, pod.Name)
}
continue
}
if cStatus.State.Running == nil {
return fmt.Errorf("container %s in pod %s/%s is not running", cStatus.Name, pod.Namespace, pod.Name)
}
if !cStatus.Ready {
return fmt.Errorf("container %s in pod %s/%s is not ready", cStatus.Name, pod.Namespace, pod.Name)
}
if err := utils.AssertPodReady(&pod); err != nil {
return err
}
}
return nil
@@ -126,29 +109,39 @@ type CheckPodsRunning struct {
labels map[string][]string
}
func (c *CheckPodsRunning) Execute(runtime connector.Runtime) error {
func (c *CheckPodsRunning) Execute(_ connector.Runtime) error {
if c.labels == nil {
return nil
}
kubectl, err := util.GetCommand(common.CommandKubectl)
if err != nil {
return errors.Wrap(errors.WithStack(err), "kubectl not found")
}
var ctx, cancel = context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
kubeConfig, err := ctrl.GetConfig()
if err != nil {
return errors.Wrap(err, "failed to load kubeconfig")
}
kubeClient, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
return errors.Wrap(err, "failed to create kube client")
}
for ns, labels := range c.labels {
for _, label := range labels {
var cmd = fmt.Sprintf("%s get pod -n %s -l '%s' -o jsonpath='{.items[*].status.phase}'", kubectl, ns, label)
phase, err := runtime.GetRunner().SudoCmdContext(ctx, cmd, false, false)
podList, err := kubeClient.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: label})
if err != nil {
return fmt.Errorf("pod status invalid, namespace: %s, label: %s, waiting ...", ns, label)
}
if phase != "Running" {
logger.Infof("pod in namespace: %s, label: %s, current phase: %s, waiting ...", ns, label, phase)
return fmt.Errorf("pod is %s, namespace: %s, label: %s, waiting ...", phase, ns, label)
if podList == nil || len(podList.Items) == 0 {
return fmt.Errorf("no pod found, namespace: %s, label: %s, waiting ...", ns, label)
}
for i := range podList.Items {
pod := &podList.Items[i]
if err := utils.AssertPodReady(pod); err != nil {
return err
}
}
}
}
@@ -250,13 +243,14 @@ func (t *PrepareFinished) Execute(runtime connector.Runtime) error {
type WriteReleaseFile struct {
common.KubeAction
WithoutName bool
}
func (t *WriteReleaseFile) Execute(runtime connector.Runtime) error {
if util.IsExist(common.OlaresReleaseFile) {
logger.Debugf("found existing release file: %s, overriding ...", common.OlaresReleaseFile)
}
return t.KubeConf.Arg.SaveReleaseInfo()
return t.KubeConf.Arg.SaveReleaseInfo(t.WithoutName)
}
type RemoveReleaseFile struct {

View File

@@ -9,6 +9,7 @@ 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 {
@@ -68,6 +69,15 @@ func (t *WelcomeMessage) Execute(runtime connector.Runtime) error {
logger.Infof("Username: %s", t.KubeConf.Arg.User.UserName)
logger.Infof("Password: %s", t.KubeConf.Arg.User.Password)
fmt.Printf("\n------------------------------------------------\n\n\n\n\n")
fmt.Println()
// 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 {
logger.Warnf("\x1b[31mWarning: To enable ROCm, please reboot your machine after activation.\x1b[0m")
fmt.Println()
}
}
return nil
}

View File

@@ -5,12 +5,12 @@ import (
"fmt"
"time"
v1alpha1 "bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/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"
v1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
apixclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -5,12 +5,12 @@ import (
"fmt"
"time"
v1alpha1 "bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/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"
v1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
apixclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierrors "k8s.io/apimachinery/pkg/api/errors"

View File

@@ -8,36 +8,36 @@ import (
"github.com/beclab/Olares/cli/version"
)
var version_1_12_3 = semver.MustParse("1.12.3")
var version_1_12_4 = semver.MustParse("1.12.4")
type upgrader_1_12_3 struct {
type upgrader_1_12_4 struct {
breakingUpgraderBase
}
func (u upgrader_1_12_3) Version() *semver.Version {
func (u upgrader_1_12_4) Version() *semver.Version {
cliVersion, err := semver.NewVersion(version.VERSION)
// tolerate local dev version
if err != nil {
return version_1_12_3
return version_1_12_4
}
if samePatchLevelVersion(version_1_12_3, cliVersion) && getReleaseLineOfVersion(cliVersion) == mainLine {
if samePatchLevelVersion(version_1_12_4, cliVersion) && getReleaseLineOfVersion(cliVersion) == mainLine {
return cliVersion
}
return version_1_12_3
return version_1_12_4
}
func (u upgrader_1_12_3) AddedBreakingChange() bool {
if u.Version().Equal(version_1_12_3) {
func (u upgrader_1_12_4) AddedBreakingChange() bool {
if u.Version().Equal(version_1_12_4) {
return true
}
return false
}
func (u upgrader_1_12_3) NeedRestart() bool {
func (u upgrader_1_12_4) NeedRestart() bool {
return true
}
func (u upgrader_1_12_3) PrepareForUpgrade() []task.Interface {
func (u upgrader_1_12_4) PrepareForUpgrade() []task.Interface {
tasks := make([]task.Interface, 0)
tasks = append(tasks, upgradeKsConfig()...)
@@ -57,7 +57,7 @@ func (u upgrader_1_12_3) PrepareForUpgrade() []task.Interface {
return tasks
}
func (u upgrader_1_12_3) UpgradeSystemComponents() []task.Interface {
func (u upgrader_1_12_4) UpgradeSystemComponents() []task.Interface {
pre := []task.Interface{
&task.LocalTask{
Name: "UpgradeL4BFLProxy",
@@ -69,7 +69,7 @@ func (u upgrader_1_12_3) UpgradeSystemComponents() []task.Interface {
return append(pre, u.upgraderBase.UpgradeSystemComponents()...)
}
func (u upgrader_1_12_3) UpdateOlaresVersion() []task.Interface {
func (u upgrader_1_12_4) UpdateOlaresVersion() []task.Interface {
var tasks []task.Interface
tasks = append(tasks,
&task.LocalTask{
@@ -88,5 +88,5 @@ func (u upgrader_1_12_3) UpdateOlaresVersion() []task.Interface {
}
func init() {
registerMainUpgrader(upgrader_1_12_3{})
registerMainUpgrader(upgrader_1_12_4{})
}

67
cli/pkg/utils/amdgpu.go Normal file
View File

@@ -0,0 +1,67 @@
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
}

111
cli/pkg/utils/pod.go Normal file
View File

@@ -0,0 +1,111 @@
package utils
import (
"fmt"
corev1 "k8s.io/api/core/v1"
)
func AssertPodReady(pod *corev1.Pod) error {
if pod == nil {
return fmt.Errorf("pod is nil")
}
podKey := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)
if pod.DeletionTimestamp != nil {
return fmt.Errorf("pod %s is terminating", podKey)
}
if pod.Status.Phase != corev1.PodRunning {
return fmt.Errorf("pod %s is not running (phase=%s)", podKey, pod.Status.Phase)
}
if len(pod.Spec.InitContainers) > 0 {
initStatusByName := make(map[string]corev1.ContainerStatus, len(pod.Status.InitContainerStatuses))
for i := range pod.Status.InitContainerStatuses {
s := pod.Status.InitContainerStatuses[i]
initStatusByName[s.Name] = s
}
for _, ic := range pod.Spec.InitContainers {
s, ok := initStatusByName[ic.Name]
if !ok {
return fmt.Errorf("pod %s has not started init container %s yet", podKey, ic.Name)
}
if t := s.State.Terminated; t != nil {
if t.ExitCode != 0 {
return fmt.Errorf(
"init container %s in pod %s terminated (exitCode=%d, reason=%s, message=%s)",
s.Name, podKey, t.ExitCode, t.Reason, t.Message,
)
}
continue
}
if w := s.State.Waiting; w != nil {
return fmt.Errorf(
"init container %s in pod %s is waiting (reason=%s, message=%s)",
s.Name, podKey, w.Reason, w.Message,
)
}
return fmt.Errorf("pod %s init container %s is still running", podKey, s.Name)
}
}
readyCondFound := false
for i := range pod.Status.Conditions {
cond := pod.Status.Conditions[i]
if cond.Type != corev1.PodReady {
continue
}
readyCondFound = true
if cond.Status != corev1.ConditionTrue {
if cond.Reason != "" || cond.Message != "" {
return fmt.Errorf("pod %s is not ready (reason=%s, message=%s)", podKey, cond.Reason, cond.Message)
}
return fmt.Errorf("pod %s is not ready", podKey)
}
break
}
if !readyCondFound {
return fmt.Errorf("pod %s is not ready (missing Ready condition)", podKey)
}
statusByName := make(map[string]corev1.ContainerStatus, len(pod.Status.ContainerStatuses))
for i := range pod.Status.ContainerStatuses {
s := pod.Status.ContainerStatuses[i]
statusByName[s.Name] = s
}
for _, c := range pod.Spec.Containers {
cStatus, ok := statusByName[c.Name]
if !ok {
return fmt.Errorf("pod %s has not started container %s yet", podKey, c.Name)
}
if t := cStatus.State.Terminated; t != nil {
return fmt.Errorf(
"container %s in pod %s terminated (exitCode=%d, reason=%s, message=%s)",
cStatus.Name,
podKey,
t.ExitCode,
t.Reason,
t.Message,
)
}
if cStatus.State.Running == nil {
if w := cStatus.State.Waiting; w != nil {
return fmt.Errorf(
"container %s in pod %s is waiting (reason=%s, message=%s)",
cStatus.Name,
podKey,
w.Reason,
w.Message,
)
}
return fmt.Errorf("container %s in pod %s is not running", cStatus.Name, podKey)
}
if !cStatus.Ready {
return fmt.Errorf("container %s in pod %s is not ready", cStatus.Name, podKey)
}
}
return nil
}

View File

@@ -321,3 +321,54 @@ func GetBufIOReaderOfTerminalInput() (*bufio.Reader, error) {
}
return bufio.NewReader(tty), nil
}
// ResolveSudoUserHomeAndIDs resolves the home directory, uid, and gid for the user
// who invoked sudo. If not running under sudo, it falls back to the current user.
// This is useful for commands that need to operate on the invoking user's home
// directory rather than /root when running with sudo.
func ResolveSudoUserHomeAndIDs(runtime connector.Runtime) (home, uid, gid string, err error) {
uid, err = runtime.GetRunner().Cmd("echo ${SUDO_UID:-}", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_UID failed")
}
gid, err = runtime.GetRunner().Cmd("echo ${SUDO_GID:-}", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_GID failed")
}
uid = strings.TrimSpace(uid)
gid = strings.TrimSpace(gid)
if uid == "" {
uid, err = runtime.GetRunner().Cmd("id -u", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get current uid failed")
}
gid, err = runtime.GetRunner().Cmd("id -g", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get current gid failed")
}
uid = strings.TrimSpace(uid)
gid = strings.TrimSpace(gid)
}
home, err = runtime.GetRunner().Cmd(fmt.Sprintf(`getent passwd %s | awk -F: 'NR==1{print $6; exit}'`, uid), false, false)
if err != nil {
home = ""
}
home = strings.TrimSpace(home)
if home == "" {
home, _ = runtime.GetRunner().Cmd(fmt.Sprintf(`awk -F: -v uid=%s '$3==uid {print $6; exit}' /etc/passwd 2>/dev/null`, uid), false, false)
home = strings.TrimSpace(home)
}
if home == "" {
home, err = runtime.GetRunner().Cmd("echo $HOME", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get HOME failed")
}
home = strings.TrimSpace(home)
}
if home == "" {
return "", "", "", errors.New("resolve user home failed")
}
return home, uid, gid, nil
}

View File

@@ -19,7 +19,6 @@ import (
)
var (
DIDGateURL = "https://did-gate-v3.bttcdn.com/1.0/name/"
DIDGateTimeout = 10 * time.Second
DIDCachePath = "/var/lib/olares"
)
@@ -90,7 +89,7 @@ type CheckJWSResult struct {
}
// resolveDID resolves a DID either from cache or from the DID gate
func ResolveOlaresName(olares_id string) (*didcore.ResolutionResult, error) {
func ResolveOlaresName(gateUrl, olares_id string) (*didcore.ResolutionResult, error) {
name := strings.Replace(olares_id, "@", ".", -1)
// Try to get from cache first
cached, err := getDB().Get([]byte(name), nil)
@@ -105,7 +104,7 @@ func ResolveOlaresName(olares_id string) (*didcore.ResolutionResult, error) {
client := &http.Client{
Timeout: DIDGateTimeout,
}
resp, err := client.Get(DIDGateURL + name)
resp, err := client.Get(gateUrl + name)
if err != nil {
return nil, fmt.Errorf("failed to fetch DID from gate: %w", err)
}
@@ -135,7 +134,7 @@ func ResolveOlaresName(olares_id string) (*didcore.ResolutionResult, error) {
}
// CheckJWS verifies a JWS and returns the terminus name, body and kid
func CheckJWS(jws string, duration int64) (*CheckJWSResult, error) {
func CheckJWS(gateUrl, jws string, duration int64) (*CheckJWSResult, error) {
var kid string
var name string
var timestamp int64
@@ -198,7 +197,7 @@ func CheckJWS(jws string, duration int64) (*CheckJWSResult, error) {
}
// Resolve DID
resolutionResult, err := ResolveOlaresName(name)
resolutionResult, err := ResolveOlaresName(gateUrl, name)
if err != nil {
return nil, fmt.Errorf("failed to resolve DID: %w", err)
}

View File

@@ -25,5 +25,5 @@ build-linux-in-docker:
-v $(current_dir):/olaresd \
-w /olaresd \
-e DEBIAN_FRONTEND=noninteractive \
golang:1.24 \
sh -c "apt-get -y update; apt-get -y install libudev-dev libpcap-dev; make build-linux"
golang:1.24.11 \
sh -c "apt-get -y update; apt-get -y install libudev-dev libpcap-dev; make build-linux"

View File

@@ -1,11 +1,8 @@
module github.com/beclab/Olares/daemon
go 1.24.2
toolchain go1.24.4
go 1.24.11
replace (
bytetrade.io/web3os/app-service => github.com/beclab/app-service v0.4.37
bytetrade.io/web3os/backups-sdk => github.com/Above-Os/backups-sdk v0.1.17
bytetrade.io/web3os/bfl => github.com/beclab/bfl v0.3.36
github.com/labstack/echo/v4 => github.com/eball/echo/v4 v4.13.4-patch
@@ -18,15 +15,15 @@ replace (
)
require (
bytetrade.io/web3os/app-service v0.0.0-00010101000000-000000000000
bytetrade.io/web3os/bfl v0.0.0-00010101000000-000000000000
github.com/Masterminds/semver/v3 v3.4.0
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/beclab/Olares/cli v0.0.0-20251219153848-63d422037cf9
github.com/containerd/containerd v1.7.28
github.com/beclab/Olares/cli v0.0.0-20251230161135-5264df60cc33
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70
github.com/containerd/containerd v1.7.29
github.com/distribution/distribution/v3 v3.0.0
github.com/dustin/go-humanize v1.0.1
github.com/eball/zeroconf v0.2.2
github.com/eball/zeroconf v0.2.5
github.com/godbus/dbus/v5 v5.1.0
github.com/gofiber/fiber/v2 v2.52.9
github.com/google/gopacket v1.1.19
@@ -53,9 +50,9 @@ require (
github.com/txn2/txeh v1.5.5
github.com/vishvananda/netlink v1.3.0
go.opentelemetry.io/otel/trace v1.36.0
golang.org/x/crypto v0.41.0
golang.org/x/crypto v0.45.0
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
golang.org/x/sys v0.35.0
golang.org/x/sys v0.38.0
k8s.io/api v0.34.1
k8s.io/apiextensions-apiserver v0.34.0
k8s.io/apimachinery v0.34.1
@@ -92,10 +89,11 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
@@ -147,7 +145,7 @@ require (
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runc v1.3.0 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opencontainers/selinux v1.13.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.23.0 // indirect
@@ -182,14 +180,14 @@ require (
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/term v0.34.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/tools v0.38.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect

View File

@@ -24,10 +24,10 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beclab/Olares/cli v0.0.0-20251219153848-63d422037cf9 h1:YNHfPra2FqsKJ5mAxSWNVIK6VyWygRyZiNwfPqiFxlg=
github.com/beclab/Olares/cli v0.0.0-20251219153848-63d422037cf9/go.mod h1:cYPcuju2yRSp9BQjIN/CC495dDOOvVoL42r/gvFlutk=
github.com/beclab/app-service v0.4.37 h1:gt60wQxgPWMc3oN94TNSdiQAvzqTyCv/OUP93jNSQTY=
github.com/beclab/app-service v0.4.37/go.mod h1:0vEg3rv/DbR7dYznvTlXNXyYNn+TXNMaxz03GQYRWUQ=
github.com/beclab/Olares/cli v0.0.0-20251230161135-5264df60cc33 h1:WYuUPOT/p26aCDJGJEDai1v7YM6QHiaFDusBVynnbBY=
github.com/beclab/Olares/cli v0.0.0-20251230161135-5264df60cc33/go.mod h1:ixhzBK5XIovsRB5djk44TChsOK4wum2q4y/hZxJKlNw=
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70 h1:U3z6m0hokD1gzl788BrUdxCbDyAjdOBBXA8ilYgn6VQ=
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70/go.mod h1:D9wl7y3obLqXMqfubMROMgdxWAwInnKNrFC//d0nyIA=
github.com/beclab/bfl v0.3.36 h1:PgeSPGc+XoONiwFsKq9xX8rqcL4kVM1G/ut0lYYj/js=
github.com/beclab/bfl v0.3.36/go.mod h1:A82u38MxYk1C3Lqnm4iUUK4hBeY9HHIs+xU4V93OnJk=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -45,8 +45,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c=
github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
@@ -65,6 +65,8 @@ github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRq
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -73,20 +75,20 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eball/echo/v4 v4.13.4-patch h1:5w83KQrEqrxhc1BO0BpRBHssC37vFrWualUM27Rt2sg=
github.com/eball/echo/v4 v4.13.4-patch/go.mod h1:ORgy8LWTq8knpwgaz538rAJMri7WgpoAD6H3zYccn84=
github.com/eball/zeroconf v0.2.2 h1:y23X67tLFlU+b35LyM9THXGsdC88IUz803G+mzfeSeE=
github.com/eball/zeroconf v0.2.2/go.mod h1:eIbIjGYo9sSMaKWLcveHEPRWdyblz7q9ih2R1HnNw5M=
github.com/eball/zeroconf v0.2.5 h1:RNINVvj8kbm/r4YoqYu/jWD57l5NJmvRUCfbjlIsbJg=
github.com/eball/zeroconf v0.2.5/go.mod h1:eIbIjGYo9sSMaKWLcveHEPRWdyblz7q9ih2R1HnNw5M=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
@@ -287,8 +289,8 @@ github.com/opencontainers/runc v1.3.0 h1:cvP7xbEvD0QQAs0nZKLzkVog2OPZhI/V2w3WmTm
github.com/opencontainers/runc v1.3.0/go.mod h1:9wbWt42gV+KRxKRVVugNP6D5+PQciRbenB4fLVsqGPs=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
@@ -414,8 +416,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
@@ -426,8 +428,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -440,8 +442,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -451,8 +453,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -472,16 +474,16 @@ 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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -493,8 +495,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -2,8 +2,10 @@ package handlers
import (
"net/http"
"net/url"
"github.com/beclab/Olares/cli/pkg/web5/jws"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/gofiber/fiber/v2"
"k8s.io/klog/v2"
)
@@ -14,8 +16,14 @@ func (h *Handlers) ResolveOlaresName(c *fiber.Ctx) error {
klog.Error("olaresName parameter is missing")
return h.ErrJSON(c, fiber.StatusBadRequest, "olaresName parameter is required")
}
klog.Infof("Received olaresName: %s", olaresName)
result, err := jws.ResolveOlaresName(olaresName)
didServiceURL, err := getDidGateURL()
if err != nil {
return h.ErrJSON(c, fiber.StatusInternalServerError, "Failed to get DID gate URL")
}
result, err := jws.ResolveOlaresName(didServiceURL, olaresName)
if err != nil {
klog.Errorf("Failed to resolve DID for %s: %v", olaresName, err)
return h.ErrJSON(c, fiber.StatusInternalServerError, "Failed to resolve DID")
@@ -46,7 +54,11 @@ func (h *Handlers) CheckJWS(c *fiber.Ctx) error {
body.Duration = int64(3 * 60 * 1000) // 3 minutes in milliseconds
}
result, err := jws.CheckJWS(body.JWS, body.Duration)
didServiceURL, err := getDidGateURL()
if err != nil {
return h.ErrJSON(c, fiber.StatusInternalServerError, "Failed to get DID gate URL")
}
result, err := jws.CheckJWS(didServiceURL, body.JWS, body.Duration)
if err != nil {
klog.Errorf("Failed to check JWS: %v", err)
return h.ErrJSON(c, fiber.StatusBadRequest, "Invalid JWS")
@@ -54,3 +66,12 @@ func (h *Handlers) CheckJWS(c *fiber.Ctx) error {
return h.OkJSON(c, "success", result)
}
func getDidGateURL() (string, error) {
didServiceURL, err := url.JoinPath(commands.OLARES_REMOTE_SERVICE, "/did/1.0/name/")
if err != nil {
klog.Errorf("failed to parse DID gate service URL: %v, Olares remote service: %s", err, commands.OLARES_REMOTE_SERVICE)
return "", err
}
return didServiceURL, nil
}

View File

@@ -81,7 +81,7 @@ func (s *mDNSServer) StartAll() error {
host: &DNSConfig{Domain: domain},
}
}
klog.Info("Intranet mDNS server started")
klog.V(8).Info("Intranet mDNS server started")
return nil
}

View File

@@ -84,8 +84,15 @@ func (p *proxyServer) Start() error {
clientIp = h
}
}
if c.IsWebSocket() {
ctx = context.WithValue(ctx, WSKey, true)
swp := c.Request().Header.Get("Sec-WebSocket-Protocol")
authToken := c.Request().Header.Get("X-Authorization")
if len(authToken) == 0 && len(swp) > 0 {
// handle missing auth token for websocket
c.Request().Header.Set("X-Authorization", swp)
}
}
r := c.Request().WithContext(ctx)
if clientIp != "" {
@@ -243,7 +250,7 @@ func (p *proxyServer) customDialContext(d *net.Dialer) func(ctx context.Context,
}
if isWs {
klog.Info("WebSocket connection detected, using upgraded dialer")
klog.Info("WebSocket connection detected, using upgraded dialer, ", addr)
return tlsDial(ctx, d, func(ctx context.Context, network, addr string) (net.Conn, error) {
return proxyDial(ctx, d, network, newAddr)
}, network, addr, &tls.Config{InsecureSkipVerify: true})

View File

@@ -147,6 +147,6 @@ func (s *Server) Reload(o *ServerOptions) error {
return fmt.Errorf("reload intranet server with %d errors", len(errs))
}
klog.Info("Intranet server reloaded")
klog.V(8).Info("Intranet server reloaded")
return nil
}

View File

@@ -99,7 +99,7 @@ func (s *server) Restart() error {
instanceName = hostname
}
s.server, err = zeroconf.Register(instanceName, s.serviceName, "local.", hostname, s.port, []string{""}, []net.Interface{*iface})
s.server, err = zeroconf.RegisterAll(instanceName, s.serviceName, "local.", hostname, s.port, []string{""}, []net.Interface{*iface}, false, false, false)
if err != nil {
klog.Error("create mdns server error, ", err)
return err

View File

@@ -79,7 +79,7 @@ func (w *applicationWatcher) Watch(ctx context.Context) {
klog.Error("reload intranet server config error, ", err)
return
}
klog.Info("Intranet server config reloaded")
klog.V(8).Info("Intranet server config reloaded")
} else {
// Start the intranet server
err = w.intranetServer.Start(o)

View File

@@ -20,6 +20,12 @@ func NewUsbWatcher() *usbWatcher {
return w
}
var UsbSerialKey = struct{}{}
func WithSerial(ctx context.Context, serial string) context.Context {
return context.WithValue(ctx, UsbSerialKey, serial)
}
func (w *usbWatcher) Watch(ctx context.Context) {
retry := 1
devs, err := utils.DetectdUsbDevices(ctx)
@@ -55,6 +61,16 @@ func (w *usbWatcher) Watch(ctx context.Context) {
return
}
serial := ctx.Value(UsbSerialKey).(string)
if serial != "" {
klog.Info("mount usb device with serial, ", serial)
devs = utils.FilterArray(devs, utils.FilterBySerial(serial))
if len(devs) == 0 {
klog.Info("no usb device found with serial, ", serial)
return
}
}
mountedPath, err := utils.MountUsbDevice(ctx, commands.MOUNT_BASE_DIR, devs)
if err != nil {
klog.Error("mount usb error, ", err)
@@ -80,13 +96,13 @@ func (w *umountWatcher) Watch(ctx context.Context) {
}
func NewUsbMonitor(ctx context.Context) error {
return utils.MonitorUsbDevice(ctx, func(action string) error {
return utils.MonitorUsbDevice(ctx, func(action, serial string) error {
switch action {
case "add":
delay := time.NewTimer(2 * time.Second)
go func() {
<-delay.C
NewUsbWatcher().Watch(ctx)
NewUsbWatcher().Watch(WithSerial(ctx, serial))
}()
case "remove":
NewUmountWatcher().Watch(ctx)

View File

@@ -119,7 +119,7 @@ func DetectdHddDevices(ctx context.Context) (usbDevs []storageDevice, err error)
return detectdStorageDevices(ctx, "ata")
}
func MonitorUsbDevice(ctx context.Context, cb func(action string) error) error {
func MonitorUsbDevice(ctx context.Context, cb func(action, serial string) error) error {
filter := &usbmon.ActionFilter{Action: usbmon.ActionAll}
devs, err := usbmon.ListenFiltered(ctx, filter)
if err != nil {
@@ -137,8 +137,8 @@ func MonitorUsbDevice(ctx context.Context, cb func(action string) error) error {
fmt.Println("Path: " + dev.Path())
fmt.Println("Vendor: " + dev.Vendor())
if cb != nil {
err = cb(dev.Action())
if cb != nil && dev.Serial() != "" {
err = cb(dev.Action(), dev.Serial())
if err != nil {
klog.Error("usb action callback error, ", err, ", ", dev.Action())
}
@@ -197,6 +197,12 @@ func MountedHddPath(ctx context.Context) ([]string, error) {
return getMountedPath(hdds)
}
func FilterBySerial(serial string) func(dev storageDevice) bool {
return func(dev storageDevice) bool {
return strings.HasSuffix(serial, dev.IDSerial) || strings.HasSuffix(serial, dev.IDSerialShort)
}
}
func MountUsbDevice(ctx context.Context, mountBaseDir string, dev []storageDevice) (mountedPath []string, err error) {
mounter := mountutils.New("")
mountedList, err := mounter.List()

View File

@@ -19,7 +19,7 @@ func DetectdHddDevices(ctx context.Context) (usbDevs []storageDevice, err error)
return
}
func MonitorUsbDevice(ctx context.Context, cb func(action string) error) error {
func MonitorUsbDevice(ctx context.Context, cb func(action, id string) error) error {
klog.Warning("not implement")
return nil
}
@@ -72,3 +72,9 @@ func MountedPath(ctx context.Context) ([]mountedPath, error) {
klog.Warning("not implement")
return nil, nil
}
func FilterBySerial(serial string) func(dev storageDevice) bool {
return func(dev storageDevice) bool {
return dev.IDSerial == serial || dev.IDSerialShort == serial
}
}

View File

@@ -18,15 +18,14 @@ func ValidateJWS(token string) (bool, string, error) {
klog.Errorf("failed to parse DID gate service URL: %v, Olares remote service: %s", err, commands.OLARES_REMOTE_SERVICE)
return false, "", err
}
jws.DIDGateURL = didServiceURL
// Validate the JWS token with a 20-minute expiration time
checkJWS, err := jws.CheckJWS(token, 20*60*1000)
checkJWS, err := jws.CheckJWS(didServiceURL, token, 20*60*1000)
if err != nil {
if strings.HasPrefix(err.Error(), "timestamp") {
err = fmt.Errorf("%v, server time: %s", err, time.Now().UTC().Format(time.RFC3339))
}
klog.Errorf("failed to check JWS: %v, on %s", err, jws.DIDGateURL)
klog.Errorf("failed to check JWS: %v, on %s", err, didServiceURL)
return false, "", err
}

View File

@@ -25,8 +25,8 @@ import (
"k8s.io/utils/pointer"
ctrl "sigs.k8s.io/controller-runtime"
sysv1 "bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"bytetrade.io/web3os/app-service/pkg/generated/clientset/versioned"
sysv1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/generated/clientset/versioned"
)
const (

11
daemon/pkg/utils/utils.go Normal file
View File

@@ -0,0 +1,11 @@
package utils
func FilterArray[T any](items []T, fn func(T) bool) []T {
var filtered []T
for _, item := range items {
if fn(item) {
filtered = append(filtered, item)
}
}
return filtered
}

View File

@@ -6,19 +6,34 @@ const side = {
text: "What is Olares",
link: "/manual/overview",
items: [
{ text: "Compare Olares and NAS", link: "/manual/olares-vs-nas" },
{ text: "Help and support", link: "/manual/help/request-technical-support"}
// collapsed: true,
// items: [
// { text: "FAQs", link: "/manual/help/faqs" },
// {
// text: "Request support",
// link: "/manual/help/request-technical-support",
// },
//{
// text: "Troubleshooting Guide",
// link: "/manual/help/troubleshooting-guide",
// },
// { text: "Compare Olares and NAS", link: "/manual/olares-vs-nas" },
{
text: "FAQs",
// link: "/manual/help/faqs",
collapsed: true,
items: [
{
text: "Olares FAQs",
link: "/manual/help/olares",
},
{
text: "Installation FAQs",
link: "/manual/help/installation",
},
{
text: "Usage FAQs",
link: "/manual/help/usage",
},
// {
// text: "Request support",
// link: "/manual/help/request-technical-support",
// },
// {
// text: "Troubleshooting",
// link: "/manual/help/troubleshooting",
// },
],
},
],
},
{
@@ -109,7 +124,7 @@ const side = {
link: "/manual/larepass/back-up-mnemonics"
},
{
text: "Access Olares locally",
text: "Access Olares securely",
link: "/manual/get-started/local-access",
},
{
@@ -127,39 +142,39 @@ const side = {
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: "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: "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: "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 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: "Autofill passwords", link: "/manual/larepass/autofill" },
{ text: "Generate 2FA codes", link: "/manual/larepass/two-factor-verification" },
],
},
{
/*{
text: "Manage knowledge",
link: "/manual/larepass/manage-knowledge",
},
},*/
],
},
{
@@ -168,7 +183,24 @@ const side = {
link: "/manual/olares/",
items: [
{ text: "Desktop", link: "/manual/olares/desktop", },
{ text: "Market", link: "/manual/olares/market", },
{
text: "Market",
collapsed: true,
items: [
{
text: "Basic operations",
link: "/manual/olares/market/market",
},
{
text: "Clone applications",
link: "/manual/olares/market/clone-apps",
},
{
text: "Manage paid applications",
link: "/manual/olares/market/purchase-paid-apps",
},
],
},
{
text: "Files",
collapsed: true,
@@ -178,18 +210,26 @@ const side = {
text: "Basic file operations",
link: "/manual/olares/files/add-edit-download",
},
// {
// text: "Sync and share",
// link: "/manual/larepass/sync-share",
// },
// {
// text: "Sync and share",
// link: "/manual/larepass/sync-share",
// },
{
text: "Share files",
link: "/manual/olares/files/share-files",
},
{
text: "Sync files to local",
link: "/manual/olares/files/sync-files",
},
{
text: "Mount SMB",
link: "/manual/olares/files/mount-SMB",
},
{
text: "Mount cloud storage",
link: "/manual/olares/files/mount-cloud-storage",
},
{
text: "Mount cloud storage",
link: "/manual/olares/files/mount-cloud-storage",
},
],
},
{
@@ -224,17 +264,32 @@ const side = {
text: "Basic operations",
link: "/manual/olares/wise/basics",
},
{
/*{
text: "Get recommendation engine",
link: "/manual/olares/wise/recommend",
},
},*/
{
text: "Manage your feeds",
link: "/manual/olares/wise/subscribe",
},
{
text: "Organize your knowledge",
text: "Manage cookies",
link: "/manual/olares/wise/manage-cookies",
},
{
text: "Organize with filters",
link: "/manual/olares/wise/filter",
collapsed: true,
items: [
{
text: "Filter syntax",
link: "/manual/olares/wise/filter-syntax-guide",
},
{
text: "Filter example",
link: "/manual/olares/wise/filter-examples",
},
],
},
],
},
@@ -305,16 +360,16 @@ const side = {
link: "/manual/olares/settings/manage-app-env",
},
],
},
},
{
text: "Manage integrations",
link:"/manual/olares/settings/integrations",
},
{
link: "/manual/olares/settings/integrations",
},
{
text: "Customize appearance",
link:"/manual/olares/settings/language-appearance",
},
{text: "Manage VPN", link: "/manual/olares/settings/remote-access",},
link: "/manual/olares/settings/language-appearance",
},
{ text: "Manage VPN", link: "/manual/olares/settings/remote-access", },
{
text: "Configure network",
collapsed: true,
@@ -325,54 +380,59 @@ const side = {
},
{
text: "Set up hosts file",
link:"/manual/olares/settings/set-up-hosts",
link: "/manual/olares/settings/set-up-hosts",
},
],
},
{text: "Manage GPU", link: "/manual/olares/settings/gpu-resource"},
{text: "Set video playback", link: "/manual/olares/settings/video"},
},
{ text: "Manage GPU", link: "/manual/olares/settings/gpu-resource" },
{ text: "Set video playback", link: "/manual/olares/settings/video" },
{ text: "Manage search rules", link: "/manual/olares/settings/search" },
{
text: "Backup and restore",
collapsed: true,
items: [
{text: "Backup", link: "/manual/olares/settings/backup"},
{text: "Restore", link: "/manual/olares/settings/restore"},
{ text: "Backup", link: "/manual/olares/settings/backup" },
{ text: "Restore", link: "/manual/olares/settings/restore" },
],
},
{text: "Developer resources", link: "/manual/olares/settings/developer"},
]
},
{text: "Dashboard", link: "/manual/olares/resources-usage"},
{text: "Profile", link: "/manual/olares/profile"},
],
{ text: "Developer resources", link: "/manual/olares/settings/developer" },
]
},
{ text: "Dashboard", link: "/manual/olares/resources-usage" },
{ text: "Profile", link: "/manual/olares/profile" },
],
},
{
text: "Best practices",
link: "/manual/best-practices/",
collapsed: true,
items: [
{
text: "Set up custom domain",
link: "/manual/best-practices/set-custom-domain",
},
{
text: "Manage knowledge with Wise",
link: "/manual/best-practices/organize-content",
},
{
text: "Install a multi-node Olares cluster",
link: "/manual/best-practices/install-olares-multi-node",
},
{
text: "Install Olares on PVE with GPU Passthrough",
link: "/manual/best-practices/install-olares-gpu-passthrough",
},
{
text: "Expand storage in Olares",
{
text: "Tutorials",
link: "/manual/best-practices/",
collapsed: true,
items: [
{
text: "Set up custom domain",
link: "/manual/best-practices/set-custom-domain",
},
{
text: "Manage knowledge with Wise",
link: "/manual/best-practices/organize-content",
},
{
text: "Install a multi-node Olares cluster",
link: "/manual/best-practices/install-olares-multi-node",
},
{
text: "Install Olares on PVE with GPU Passthrough",
link: "/manual/best-practices/install-olares-gpu-passthrough",
},
{
text: "Expand storage in Olares",
link: "/manual/best-practices/expand-storage-in-olares",
},
],
},
{
text: "Access Olares locally",
link: "/manual/best-practices/local-access",
},
],
},
{ text: "Glossary", link: "/manual/glossary" },
],
"/space/": [
@@ -421,83 +481,106 @@ const side = {
},
],
"/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",
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: "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",
{
text: "Olares ID",
link: "/developer/concepts/olares-id",
collapsed: true,
items: [
@@ -534,7 +617,7 @@ const side = {
{ text: "Secrets", link: "/developer/concepts/secrets" },
],
},
{
{
text: "Installation deep-dive",
link: "/developer/install/",
items: [
@@ -559,74 +642,55 @@ const side = {
link: "/developer/install/cli/olares-cli",
collapsed: true,
items: [
{ text: "gpu", link: "/developer/install/cli/gpu" },
{ text: "osinfo", link: "/developer/install/cli/osinfo" },
{ text: "node", link: "/developer/install/cli/node" },
{
text: "backups",
link: "/developer/install/cli/backups",
collapsed: true,
items: [
{text: "download", link: "/developer/install/cli/backups-download"},
{text: "region", link: "/developer/install/cli/backups-region"},
{text: "backup", link: "/developer/install/cli/backups-backup"},
{text: "restore", link: "/developer/install/cli/backups-restore"},
{text: "snapshots", link: "/developer/install/cli/backups-snapshots"},
],
},
{ 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: "change-ip",
link: "/developer/install/cli/change-ip",
},
{
text: "download",
link: "/developer/install/cli/download",
},
{ text: "info", link: "/developer/install/cli/info" },
{
text: "install",
link: "/developer/install/cli/install",
},
{
text: "user activate",
link: "/developer/install/cli/user-activate",
},
{
text: "logs",
link: "/developer/install/cli/logs",
},
{
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: "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: "Olares versioning",
link: "/developer/install/versioning",
},
],
},
{
text: "Develop Olares apps",
link: "/developer/develop/",
@@ -682,43 +746,43 @@ const side = {
// items: [
// {
// text: "terminus-info",
// link: "/developer/develop/advanced/terminus-info",
// link: "/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service provider",
// link: "/developer/develop/advanced/provider",
// link: "/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/developer/develop/advanced/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",
// link: "/developer/develop/advanced/account",
// },
// {
// text: "Market",
// link: "/developer/develop/advanced/market",
// link: "/developer/develop/advanced/market",
// },
// {
// text: "Websocket",
// link: "/developer/develop/advanced/websocket",
// link: "/developer/develop/advanced/websocket",
// },
// {
// text: "File upload",
// link: "/developer/develop/advanced/file-upload",
// link: "/developer/develop/advanced/file-upload",
// },
// {
// text: "Secret",
// link: "/developer/develop/advanced/secret",
// link: "/developer/develop/advanced/secret",
// },
// {
// text: "Kubesphere",
// link: "/developer/develop/advanced/kubesphere",
// link: "/developer/develop/advanced/kubesphere",
// },
// ],
// ],
// },
{
text: "Submit application",
@@ -756,86 +820,86 @@ const side = {
},
],
},
{
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",
},
],
},
],
},
{
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",
},
],
},
],
},
],
},
],
@@ -856,4 +920,4 @@ export const en = defineConfig({
sidebar: side,
},
});
});

View File

@@ -0,0 +1,9 @@
<script setup lang="ts">
const targetUrl = 'https://www.olares.cn/larepass'
</script>
<template>
<a :href="targetUrl" target="_blank" rel="noreferrer" class="app-link">
<slot>LarePass 下载页面</slot>
</a>
</template>

View File

@@ -0,0 +1,9 @@
<script setup lang="ts">
const targetUrl = 'https://www.olares.com/larepass'
</script>
<template>
<a :href="targetUrl" target="_blank" rel="noreferrer" class="app-link">
<slot>LarePass Download page</slot>
</a>
</template>

View File

@@ -14,6 +14,9 @@ import OSTabs from "./components/OStabs.vue";
import VersionSwitcher from "./components/VersionSwitcher.vue";
import _ from "lodash";
import { redirects } from './redirects';
import AppLinkGlobal from './components/AppLinkGlobal.vue'
import AppLinkCN from './components/AppLinkCN.vue'
const LANGUAGE_LOCAL_KEY = "language";
let isMenuChange = false;
@@ -27,6 +30,8 @@ enhanceApp({ app, router }: { app: App; router: Router }) {
app.component("FilterableList", FilterableList);
app.component("OSTabs", OSTabs);
app.component("VersionSwitcher", VersionSwitcher);
app.component('AppLinkGlobal', AppLinkGlobal)
app.component('AppLinkCN', AppLinkCN)
router.onBeforeRouteChange = (to: string) => {
const path = to.replace(/\.html$/i, ''),
@@ -142,4 +147,4 @@ enhanceApp({ app, router }: { app: App; router: Router }) {
}
);
},
};
};

View File

@@ -6,23 +6,36 @@ const side = {
text: "Olares 是什么?",
link: "/zh/manual/overview",
items: [
// { text: "应用场景", link: "/zh/manual/why-olares" },
//{ text: "功能对比", link: "/zh/manual/feature-overview" },
{ text: "比较 Olares 和 NAS", link: "/zh/manual/olares-vs-nas" },
{text: "帮助与支持", link: "/zh/manual/help/request-technical-support",}
// collapsed: true,
// items: [
// { text: "常见问题", link: "/zh/manual/help/faqs" },
// {
// text: "技术支持",
// link: "/zh/manual/help/request-technical-support",
// },
// { text: "比较 Olares 和 NAS", link: "/zh/manual/olares-vs-nas" },
{
text: "常见问题",
// link: "/zh/manual/help/faqs",
collapsed: true,
items: [
{
text: "产品",
link: "/zh/manual/help/olares",
},
{
text: "安装激活",
link: "/zh/manual/help/installation",
},
{
text: "使用",
link: "/zh/manual/help/usage",
},
// {
// text: "技术支持",
// link: "/zh/manual/help/request-technical-support",
// },
// {
// text: "Troubleshooting Guide",
// link: "/zh/manual/help/troubleshooting-guide",
// },
],
},
],
},
{
text: "快速开始",
collapsed: false,
@@ -110,7 +123,7 @@ const side = {
link: "/zh/manual/larepass/back-up-mnemonics",
},
{
text: "内网访问 Olares",
text: "安全访问 Olares",
link: "zh/manual/get-started/local-access",
},
{
@@ -128,39 +141,39 @@ const side = {
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/create-account" },
{ text: "备份助记词", link: "/zh/manual/larepass/back-up-mnemonics" },
{ text: "管理集成", link: "/zh/manual/larepass/integrations" },
],
},
{text: "使用专用网络", link:"/zh/manual/larepass/private-network"},
{ 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: "激活 Olares", link: "/zh/manual/larepass/activate-olares" },
{ text: "管理 Olares", link: "/zh/manual/larepass/manage-olares" },
],
},
{text: "管理文件", link:"/zh/manual/larepass/manage-files"},
// collapsed: true,
{ 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/autofill" },
{ text: "双重验证", link: "/zh/manual/larepass/two-factor-verification" },
],
},
{
/*{
text: "管理内容",
link: "/zh/manual/larepass/manage-knowledge",
},
},*/
],
},
{
@@ -169,7 +182,24 @@ const side = {
"link": "/zh/manual/olares/",
"items": [
{ "text": "桌面", "link": "/zh/manual/olares/desktop" },
{ "text": "应用市场", "link": "/zh/manual/olares/market" },
{
"text": "应用市场",
"collapsed": true,
"items": [
{
"text": "基本操作",
"link": "/zh/manual/olares/market/market"
},
{
"text": "管理付费应用",
"link": "/zh/manual/olares/market/purchase-paid-apps"
},
{
"text": "克隆应用",
"link": "/zh/manual/olares/market/clone-apps"
},
],
},
{
"text": "文件管理器",
"collapsed": true,
@@ -181,8 +211,16 @@ const side = {
},
//{
// "text": "同步与共享",
// "link": "/zh/manual/larepass/sync-share"
// "link": "/zh/manual/larepass/sync-share"
// },
{
"text": "分享文件",
"link": "/zh/manual/olares/files/share-files"
},
{
"text": "同步文件至本地",
"link": "/zh/manual/olares/files/sync-files"
},
{
"text": "挂载 SMB",
"link": "/zh/manual/olares/files/mount-SMB"
@@ -225,19 +263,34 @@ const side = {
"text": "基本操作",
"link": "/zh/manual/olares/wise/basics"
},
{
/*{
"text": "获取推荐引擎",
"link": "/zh/manual/olares/wise/recommend"
},
},*/
{
"text": "管理订阅",
"link": "/zh/manual/olares/wise/subscribe"
},
{
"text": "整理知识",
"link": "/zh/manual/olares/wise/filter"
}
]
text: "管理 Cookie",
link: "/zh/manual/olares/wise/manage-cookies",
},
{
"text": "管理知识",
"link": "/zh/manual/olares/wise/filter",
collapsed: true,
items: [
{
"text": "过滤语法参考",
"link": "/zh/manual/olares/wise/filter-syntax-guide"
},
{
"text": "过滤视图示例",
"link": "/zh/manual/olares/wise/filter-examples"
}
],
},
],
},
{
"text": "控制面板",
@@ -271,7 +324,7 @@ const side = {
"collapsed": true,
"link": "/zh/manual/olares/settings/",
"items": [
{"text": "我的 Olares", link: "/zh/manual/olares/settings/my-olares"},
{ "text": "我的 Olares", link: "/zh/manual/olares/settings/my-olares" },
{
"text": "管理用户",
"collapsed": true,
@@ -303,16 +356,16 @@ const side = {
link: "/zh/manual/olares/settings/manage-app-env",
},
],
},
},
{
"text": "管理集成",
"link":"/zh/manual/olares/settings/integrations",
},
{
"link": "/zh/manual/olares/settings/integrations",
},
{
"text": "自定义外观",
"link":"/zh/manual/olares/settings/language-appearance",
},
{text: "管理 VPN", link: "/zh/manual/olares/settings/remote-access",},
"link": "/zh/manual/olares/settings/language-appearance",
},
{ text: "管理 VPN", link: "/zh/manual/olares/settings/remote-access", },
{
"text": "配置网络",
"collapsed": true,
@@ -323,29 +376,30 @@ const side = {
},
{
"text": "设置 hosts 文件",
"link":"/zh/manual/olares/settings/set-up-hosts",
"link": "/zh/manual/olares/settings/set-up-hosts",
},
],
},
{text: "管理 GPU", link: "/zh/manual/olares/settings/gpu-resource"},
{text: "视频设置", link: "/zh/manual/olares/settings/video"},
},
{ text: "管理 GPU", link: "/zh/manual/olares/settings/gpu-resource" },
{ text: "视频设置", link: "/zh/manual/olares/settings/video" },
{ text: "文件搜索", link: "/zh/manual/olares/settings/search" },
{
"text": "备份与恢复",
"collapsed": true,
"items": [
{text: "备份", link: "/zh/manual/olares/settings/backup"},
{text: "恢复", link: "/zh/manual/olares/settings/restore"},
{ text: "备份", link: "/zh/manual/olares/settings/backup" },
{ 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" },
{ "text": "Profile", "link": "/zh/manual/olares/profile" }
]
},
{
text: "Olares 进阶",
text: "教程",
collapsed: true,
link: "/zh/manual/best-practices/",
items: [
@@ -368,11 +422,15 @@ const side = {
{
text: "在启用显卡直通的 PVE 上安装 Olares",
link: "/zh/manual/best-practices/install-olares-gpu-passthrough",
},
{
},
{
text: "在 Olares 中扩展存储空间",
link: "/zh/manual/best-practices/expand-storage-in-olares",
},
{
text: "本地访问 Olares",
link: "/manual/best-practices/local-access",
},
],
},
{ text: "术语", link: "/zh/manual/glossary" },
@@ -425,7 +483,7 @@ const side = {
],
"/zh/use-cases/": [
{
text: "Tutorials & use cases",
text: "应用示例",
link: "/zh/use-cases/",
items: [
{
@@ -469,12 +527,22 @@ const side = {
},
{
text: "Steam",
link: "/zh/use-cases/stream-game",
},
{
text: "Redroid",
link: "/zh/use-cases/host-cloud-android",
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",
// },
],
},
],
@@ -484,7 +552,8 @@ const side = {
link: "/zh/developer/concepts/",
items: [
{ text: "系统架构", link: "/zh/developer/concepts/system-architecture" },
{ text: "Olares ID",
{
text: "Olares ID",
link: "/zh/developer/concepts/olares-id",
collapsed: true,
items: [
@@ -543,76 +612,56 @@ const side = {
},
{
text: "Olares CLI",
collapsed: true,
link: "/zh/developer/install/cli/olares-cli",
collapsed: true,
items: [
{text: "gpu", link: "/zh/developer/install/cli/gpu"},
{text: "osinfo", link: "/zh/developer/install/cli/osinfo"},
{text: "node", link: "/zh/developer/install/cli/node"},
{
text: "backups",
link: "/zh/developer/install/cli/backups",
collapsed: true,
items: [
{text: "download", link: "/zh/developer/install/cli/backups-download"},
{text: "region", link: "/zh/developer/install/cli/backups-region"},
{text: "backup", link: "/zh/developer/install/cli/backups-backup"},
{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: "download",
link: "/zh/developer/install/cli/download",
},
{ text: "info", link: "/zh/developer/install/cli/info" },
{
text: "install",
link: "/zh/developer/install/cli/install",
},
{
text: "user activate",
link: "/zh/developer/install/cli/user-activate",
},
{
text: "logs",
link: "/zh/developer/install/cli/logs",
},
{
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: "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: "版本说明",
link: "/zh/developer/install/versioning",
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",
},
],
},
{
@@ -654,7 +703,7 @@ const side = {
text: "OlaresManifest",
link: "/zh/developer/develop/package/manifest",
},
/*/{
/*{
text: "推荐算法",
link: "/zh/developer/develop/package/recommend",
},*/
@@ -664,66 +713,66 @@ const side = {
},
],
},
// {
// {
// text: "进阶",
// collapsed: true,
// items: [
// {
// text: "terminus-info",
// link: "/zh/developer/develop/advanced/terminus-info",
// link: "/zh/developer/develop/advanced/terminus-info",
// },
// {
// text: "Service Provider",
// link: "/zh/developer/develop/advanced/provider",
// link: "/zh/developer/develop/advanced/provider",
// },
// {
// text: "AI",
// link: "/zh/developer/develop/advanced/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",
// link: "/zh/developer/develop/advanced/account",
// },
// {
// text: "应用市场",
// link: "/zh/developer/develop/advanced/market",
// link: "/zh/developer/develop/advanced/market",
// },
// {
// text: "Analytic",
// link: "/zh/developer/develop/advanced/analytic",
// },
// {
// text: "Analytic",
// link: "/zh/developer/develop/advanced/analytic",
// },
// {
// text: "Websocket",
// link: "/zh/developer/develop/advanced/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",
// 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: "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,
@@ -842,8 +891,8 @@ const side = {
},
],
},
],
};
],
};
export const zh = defineConfig({
lang: "zh",
@@ -860,4 +909,4 @@ export const zh = defineConfig({
sidebar: side,
},
});
});

View File

@@ -122,7 +122,7 @@ The mechanism consists of three procedures
- User
[Manage apps in Market](../../manual/olares/market.md)<br>
[Manage apps in Market](../../manual/olares/market/market.md)<br>
- Developer

View File

@@ -17,7 +17,7 @@ outline: [2, 3]
### 1. Develop and test your application
Before submitting an application, please ensure that it has been thoroughly tested on your Olares.
- Use Studio's dev-container to test and debug your application in a real online environment. [Learn more about Studio](../tutorial/).
- Use Studio's dev-container to test and debug your application in a real online environment. [Learn more about Studio](../tutorial/develop.md).
- Use the [custom installation](../tutorial/package-upload.md) in the Market app for user testing.
### 2. Submit an application

View File

@@ -92,13 +92,13 @@ This example demonstrates creating a basic web page manually.
```
5. Create a file named `index.js` in `/root/` with the following content:
```js
// Ensure the port matches what you defined
const express = require('express');
const app = express();
app.use(express.static('public/'));
app.listen(8080), function() {
console.log('Server is running on port 8080');
};
// Ensure the port matches what you defined
const express = require('express');
const app = express();
app.use(express.static('public/'));
app.listen(8080, function() {
console.log('Server is running on port 8080');
});
```
6. Create a `public` directory in `/root/` and add an `index.html` file:
```html
@@ -204,15 +204,15 @@ Once deployed, go to **Services** > **Ports**. You can see your new port listed
const express = require('express');
const app = express();
app.use(express.static('public/'));
app.listen(8080), function() {
console.log('Server is running on port 8080');
};
app.listen(8080, function() {
console.log('Server is running on port 8080');
});
// Add the following
const app_new = express();
app_new.use(express.static('new/'));
app_new.listen(8081), function() {
console.log('Server is running on port 8081');
};
app_new.listen(8081, function() {
console.log('Server is running on port 8081');
});
```
2. Create a `new` directory in `/root/` and add an `index.html` file:
```html

View File

@@ -65,7 +65,7 @@ These options apply to all backends:
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
```
## Example
## Examples
```bash
# Backup to Tencent COS
olares-cli backups backup cos --path /data --repo-name my_repo \

View File

@@ -12,7 +12,7 @@ olares-cli backups download [options]
|--------------------|-----------|--------------------------------------------------------|-------------------------|--------------------|
| `--download-cdn-url`| | Specifies the CDN URL for downloading the Restic tool. | No | System default URL |
| `--help` | `-h` | Displays help information. | No | N/A |
## Example
## Examples
```bash d
# Download Restic using a custom CDN URL
olares-cli backups download --download-cdn-url https://custom-cdn.example.com/restic

View File

@@ -17,7 +17,7 @@ olares-cli backups region space [options]
1. To retrieve the access token and Olares DID, inspect the payload of the network requests made by the Olares Space web interface after logging in. The `token` field corresponds to the access token, and the `userid` field corresponds to the Olares DID.
## Example
## Examples
```bash
# Query cloud name and region ID
olares-cli backups region space \

View File

@@ -69,7 +69,7 @@ These options apply to all backends:
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
```
## Example
## Examples
```bash
# Restore the data from Tencent COS
olares-cli backups restore cos --path /data_restore --repo-name my_repo \

View File

@@ -61,7 +61,7 @@ These options apply to all backends:
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
```
## Example
## Examples
```bash
# List snapshots for Tencent COS
olares-cli backups snapshots cos --repo-name my_repo \

View File

@@ -0,0 +1,33 @@
# `disk`
## Synopsis
The `disk` command provides a set of tools to manage storage resources in the Olares system. It is specifically used for managing LVM-based storage configurations.
```bash
olares-cli disk <subcommand>
```
## Subcommands
| Subcommand | Description |
|--|--|
| `extend` | Extends Olares storage capacity on LVM-based installations. |
| `list-unmounted` | Lists unmounted disks. |
## Options
| Name | Shorthand | Usage |
|--|--|--|
| `--help` | `-h` | Displays help information.|
## Examples
```bash
# List all disks that are connected but not mounted
olares-cli disk list-unmounted
# Extend Olares storage by adding newly detected unmounted disks
olares-cli disk extend
```

View File

@@ -32,7 +32,7 @@ olares-cli gpu <subcommand> [options]
| `--version`| `-v` | Specifies the Olares version for GPU drivers and components. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
| `--help` | `-h` | Displays help information. | No | N/A |
## Example
## Examples
```bash
# Install GPU drivers and dependencies to a specific directory

View File

@@ -7,7 +7,7 @@ The `info` command displays general information about the installed Olares versi
olares-cli info
```
## Flag
## Options
| Name | Shorthand | Usage |
|----------|-----------|---------------------------|

View File

@@ -28,7 +28,7 @@ olares-cli logs [option]
| `--output-dir` | | Saves logs to the specified directory. Creates the directory if it does not exist. | No | `./olares-logs` |
| `--since` | | Fetches logs newer than a specified relative duration (e.g., `5s`, `2m`, `3h`). | No | `7d` |
## Example
## Examples
```bash
# Collect all logs with default settings
olares-cli logs

View File

@@ -29,7 +29,7 @@ olares-cli node <subcommand> [options]
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
| `--help` | `-h` | Displays help information. | No | N/A | |
## Example
## Examples
```bash
# Retrieve system information from a master node at IP 192.168.1.15

View File

@@ -28,12 +28,13 @@ wsl -d Ubuntu
## Syntax
The Olares CLI uses the following syntax:
> `olares-cli command [subcommand] [option]`
> `olares-cli command [subcommand] [argument] [options] `
where
- `command`: Specifies the main operation you want to perform. For example, `olares-cli install`.
- `subcommand`: Further specifies the task for commands that support additional operations. For example, `wizard` or `component`.
- `option`: Optional arguments that modify the behavior of the `command`. Options include flags and options with arguments.
- `argument`: Specifies the target resource or input data for the command, typically an ID, name, or file path. For example, in `olares-cli user activate <Olares ID> [options]`, `<Olares ID>` is the argument.
- `options`: Optional arguments that modify the behavior of the `command`. Options include flags and options with arguments.
Olares CLI allows you to temporarily override certain Olares default settings. Each option applies only to the command in which it is used.
@@ -43,21 +44,23 @@ To get detailed help for any command, run `olares-cli help`.
## Available CLI commands
| Operation | Syntax | Description |
|--------------------|----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `gpu` | `olares-cli gpu <subcommand> [option]` | Manages GPU-related operations. |
| `info` | `olares-cli info <subcommand> [option]` | Displays general information about the operating system of the current device. |
| `node` | `olares-cli node <subcommand> [option]` | Manages node-related operations. |
| `backups` | `olares-cli backups <subcommand> [option]` | Manages backup-related operations. |
| `change-ip` | `olares-cli change-ip [option]` | Changes the IP address of the Olares OS. |
| `download` | `olares-cli download <subcommand> [option]` | Downloads specific resources. |
| `info` | `olares-cli info [option]` | Displays general information about the downloaded Olares OS. |
| `install` | `olares-cli install [option]` | Deploys system-level and user-level components of Olares. |
| `logs` | `olares-cli logs [option]` | Collects logs from Olares system components for debugging and troubleshooting. |
| `precheck` | `olares-cli precheck [option]` | Verifies whether the system environment meets all requirements for Olares installation. |
| `prepare` | `olares-cli prepare [option]` | Prepares the environment for the installation process, including setting up essential services and configurations of Olares. |
| `release` | `olares-cli release [option]` | Packages Olares installation resources for distribution or deployment. |
| `start` | `olares-cli start [option]` | Starts Olares services and components. |
| `stop` | `olares-cli stop [option]` | Stops Olares services and components. |
| `uninstall` | `olares-cli uninstall [option]` | Uninstalls Olares completely, or roll back the installation to a specific phase. |
| Operation | Syntax | Description |
|--|--|--|
| `backups` | `olares-cli backups <subcommand> [options]` | Manages backup-related operations. |
| `change-ip` | `olares-cli change-ip [options]` | Changes the IP address of the Olares OS. |
| `disk` | `olares-cli disk <subcommand>` | Manages storage resources in the Olares system. |
| `download` | `olares-cli download <subcommand> [options]` | Downloads specific resources. |
| `gpu` | `olares-cli gpu <subcommand> [options]` | Manages GPU-related operations. |
| `info` | `olares-cli info [options]` | Displays general information about the downloaded Olares OS. |
| `install` | `olares-cli install [options]` | Deploys system-level and user-level components of Olares. |
| `logs` | `olares-cli logs [options]` | Collects logs from Olares system components for debugging and troubleshooting. |
| `node` | `olares-cli node <subcommand> [options]` | Manages node-related operations. |
| `osinfo` | `olares-cli osinfo <subcommand> [options]` | Displays general information about the operating system of the current device. |
| `precheck` | `olares-cli precheck [options]` | Verifies whether the system environment meets all requirements for Olares installation. |
| `prepare` | `olares-cli prepare [options]` | Prepares the environment for the installation process, including setting up essential services and configurations of Olares. |
| `release` | `olares-cli release [options]` | Packages Olares installation resources for distribution or deployment. |
| `start` | `olares-cli start [options]` | Starts Olares services and components. |
| `stop` | `olares-cli stop [options]` | Stops Olares services and components. |
| `uninstall` | `olares-cli uninstall [options]` | Uninstalls Olares completely, or roll back the installation to a specific phase. |
| `upgrade` | `olares-cli upgrade <subcommand> [options]` | Upgrades Olares and checks upgrade readiness and compatibility.|
| `user` | `olares-cli user <subcommand> [options]`| Manages users in the Olares system |

View File

@@ -8,13 +8,13 @@ The `osinfo` command provides detailed information about the operating system of
olares-cli osinfo <subcommand> [options]
```
## Subcommand
## Subcommands
| Subcommand | Description |
|------------|----------------------------------------------------------------------|
| `show` | Prints information about the operating system of the current device. |
## Flag
## Options
| Name | Short | Description |
|--------------|-------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

View File

@@ -18,7 +18,7 @@ olares-cli prepare [option]
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
## Example
## Examples
```bash
# Uses JuiceFS as the root filesystem
olares-cli prepare --with-juicefs=true

View File

@@ -12,7 +12,7 @@ olares-cli start [option]
After executing this command, allow 5-8 minutes for all Olares components to restart. You can verify the status of all pods by running `kubectl get pods -A` or by simply trying to access your Olares desktop.
:::
## Option
## Options
| Name | Shorthand | Usage |
|------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

View File

@@ -15,7 +15,7 @@ olares-cli stop [option]
| `--help` | `-h` | Displays help information. | No | N/A |
| `--timeout` | | Sets the maximum time to wait for a graceful shutdown before using SIGKILL (e.g., `5s`, `2m`, `3h`). | No | `1m` |
## Example
## Examples
```bash
# Stop the Olares system
olares-cli stop

View File

@@ -0,0 +1,53 @@
# `upgrade`
## Synopsis
The `upgrade` command provides a set of tools for upgrading Olares and checking upgrade readiness and compatibility.
```bash
olares-cli upgrade <subcommand> [options]
```
## Subcommands
| Subcommand | Aliases | Description |
|--|--|--|
| `precheck` | | Prechecks Olares for upgrade. |
| `spec` | `current-spec` | Gets the upgrade spec of the current CLI version. |
| `viable` | | Determines whether upgrade can be directly performed upon a base version. |
## Global options
These options apply to the main `upgrade` command and are inherited by its subcommands where applicable.
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--base-dir` | `-b` | Sets the base directory for Olares packages. | No | `$HOME/.olares` |
| `--help` | `-h` | Displays help information. | No | N/A |
| `--version` | `-v` | Sets the target Olares version to upgrade to. For example, `1.10.0`, `1.10.0-20241109`. | No | N/A |
## Options for `viable`
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--base` | `-b` | Base version to check. | No | Current Olares system version |
:::warning Option conflict
The `-b` shorthand is used by the parent command for `--base-dir`. However, when running `upgrade viable`, `-b` specifically refers to `--base`.
:::
## Examples
```bash
# Check whether the current system can be upgraded directly
olares-cli upgrade viable
# Check upgrade viability from a specific base version
olares-cli upgrade viable --base 1.9.0
# Run pre-upgrade checks
olares-cli upgrade precheck
# View the upgrade spec of the current CLI
olares-cli upgrade spec
```

View File

@@ -1,8 +1,9 @@
# `user activate`
# `activate`
## Synopsis
The `user activate` command activates an existing Olares account. It requires the user's Olares ID, password, and 12-word mnemonic phrase to complete the activation. This command typically requires administrator privileges (`sudo`).
The `activate` subcommand activates an existing Olares account. It requires the user's Olares ID, password, and 12-word mnemonic phrase to complete the activation.
```bash
olares-cli user activate <Olares ID> [options]
@@ -12,31 +13,32 @@ olares-cli user activate <Olares ID> [options]
| Argument | Description | Required|
|--|--|--|
| `<Olares ID>` | Specifies the unique identifier for the Olares user account to be activated. <br>Similar to an email address(e.g., `alice123@olares.com`).| **Yes** |
| `<Olares ID>` | Specifies the unique identifier for the Olares user account <br>to be activated. <br>Similar to an email address like `alice123@olares.com`.| Yes |
## Options
| Option | Shorthand | Usage | Required | Default |
| Option | Short| Usage | Required | Default |
|--|--|--|--|--|
| `--bfl` | | Specifies the Backend For Launcher (BFL) service URL (e.g., `https://example.com`). | No | `http://127.0.0.1:30180` |
| `--bfl` | | Specifies the Backend For Launcher (BFL) service URL, such as `https://example.com`. | No | `http://127.0.0.1:30180` |
| `--enable-tunnel` | | Enables or disables tunnel mode for activation. | No | `false` |
| `--help` | `-h` | Displays help information. | No | N/A |
| `--host` | | Specifies the Fast Reverse Proxy (FRP) host. <br>Only used when the `--enable-tunnel` option is set to `true`. | No | N/A |
| `--jws` | | Specifies the FRP JWS token.<br>Only used when the `--enable-tunnel` option is set to `true`.| No | N/A |
| `--host` | | Specifies the Fast Reverse Proxy (FRP) host. Only used when `--enable-tunnel` option is set to `true`. | No | N/A |
| `--jws` | | Specifies the FRP JWS token. Only used when `--enable-tunnel` option is set to `true`.| No | N/A |
| `--language` | | Sets the system language. | No | `en-US` |
| `--location` | | Sets the timezone location. | No | `Asia/Shanghai` |
| `--mnemonic` | | Specifies the 12-word mnemonic phrase required for activation. | **Yes** | N/A |
| `--password` | `-p` | Specifies the Olares login password for authentication. | **Yes** | N/A |
| `--vault` | | Specifies the Vault service URL (e.g., `https://example.com`). | No | `http://127.0.0.1:30181` |
| `--mnemonic` | | Specifies the 12-word mnemonic phrase required for activation. | Yes | N/A |
| `--password` | `-p` | Specifies the Olares login password for authentication. | Yes | N/A |
| `--reset-password` | | Specifies the new password to set during password reset. This option is required only when performing a password reset. | No | N/A |
| `--vault` | | Specifies the Vault service URL, such as `https://example.com`. | No | `http://127.0.0.1:30180` |
## Example
## Examples
```bash
# Activate an Olares user account
sudo olares-cli user activate alice@olares.com -p "HerPassWord" --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
olares-cli user activate alic123e@olares.com -p "HerPassWord" --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
# Activate an Olares user account with tunnel mode enabled
sudo olares-cli user activate david@olares.com -p "HisPassWord" --enable-tunnel --host "frp-gateway.olares.com" --jws "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo.signature" --bfl http://127.0.0.1:30180 --vault http://127.0.0.1:30180/server --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
olares-cli user activate david456@olares.com -p "HisPassWord" --enable-tunnel --host "frp-gateway.olares.com" --jws "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo.signature" --bfl http://127.0.0.1:30180 --vault http://127.0.0.1:30180/server --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
# Activate an Olares user account with specific language and timezone settings
sudo olares-cli user activate carol@olares.com -p "AnotherPassWord" --mnemonic "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu" --language "en-US" --location "America/New_York"
olares-cli user activate carol789@olares.com -p "AnotherPassWord" --mnemonic "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu" --language "en-US" --location "America/New_York"
```

View File

@@ -0,0 +1,46 @@
# `create`
## Synopsis
The `create` subcommand creates a new user account in the Olares system. It allows administrators to define initial settings such as the username, password, role permissions, and resource limits.
**Aliases**: `create`, `add`, `new`
```bash
olares-cli user create <name> [options]
```
## Arguments
| Argument | Description | Required|
|--|--|--|
| `<name>` | Specifies the username for the new account. <br>It is typically the part before the `@` symbol in an Olares ID. <br>For example, `alice123` for `alice123@olares.com`.| Yes |
## Options
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--cpu-limit` | `-c` | Sets the CPU limit for the user environment. | No | `1` |
| `--description` | | Adds a description for the user account. | No | N/A |
| `--display-name` | | Sets the display name for the user. | No | N/A |
| `--domain` | | Specifies the domain for the Olares ID. | No | Olares system's domain |
| `--help` | `-h` | Displays help information. | No | N/A |
| `--kubeconfig` | | Specifies the path to a kubeconfig file. | No | N/A |
| `--memory-limit` | `-m` | Sets the memory limit for the user environment. | No | `3G` |
| `--password` | `-p` | Sets the initial login password for the user. | No | N/A |
| `--role` | `-r` | Sets the user role.<br>Valid values: `owner`, `admin`, `normal`. | No | `normal` |
## Examples
```bash
# Create a basic user with default settings
olares-cli user create alice123
# Create a user with a specified password and role
olares-cli user create blake123 -p "StrongPassword123" -r admin
# Create a user with custom resource limits (2 CPU cores, 4 GB memory)
olares-cli user create carol123 --cpu-limit 2 --memory-limit 4G
# Create a user with display name and description
olares-cli user create david123 --display-name "David Smith" --description "Data platform administrator"
```

View File

@@ -0,0 +1,30 @@
# `delete`
## Synopsis
The `delete` subcommand permanently removes an existing user account from the Olares system.
**Aliases**: `delete`, `d`, `del`, `rm`, `remove`
```bash
olares-cli user delete <name> [options]
```
## Arguments
| Argument | Description | Required|
|--|--|--|
| `<name>` | Specifies the username of the account to be deleted. <br>It is typically the part before the `@` symbol in an Olares ID. <br>For example, `alice123` for `alice123@olares.com`.| Yes |
## Options
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--help` | `-h` | Displays help information. | No | N/A |
| `--kubeconfig` | | Specifies the path to a kubeconfig file. | No | N/A |
## Examples
```bash
# Delete a user named alice123
olares-cli user delete alice123
```

View File

@@ -0,0 +1,33 @@
# `get`
## Synopsis
The `get` subcommand retrieves detailed information about a specific Olares user account. The output can be formatted as a table or JSON.
```bash
olares-cli user get <name> [options]
```
## Arguments
| Argument | Description | Required|
|--|--|--|
| `<name>` | Specifies the username of the account to retrieve. <br>It is typically the part before the `@` symbol in an Olares ID. <br>For example, `alice123` for `alice123@olares.com`.| Yes |
## Options
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--help` | `-h` | Displays help information. | No | N/A |
| `--kubeconfig` | | Specifies the path to a kubeconfig file. | No | N/A |
| `--no-headers` | | Disables the header row in the output. | No | N/A |
| `--output` | `-o` | Specifies the output format. Valid values: `table`, `json`. | No | `table` |
## Examples
```bash
# Get details for user named alice123 in default table format
olares-cli user get alice123
# Get details for user named blake123 in JSON format
olares-cli user get blake123 -o json
```

View File

@@ -0,0 +1,34 @@
# `list`
## Synopsis
The `list` subcommand displays a list of all registered users in the Olares system. You can sort, filter, and format the output to suit your needs.
**Aliases**: `list`, `ls`, `l`
```bash
olares-cli user list [options]
```
## Options
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
| `--help` | `-h` | Displays help information. | No | N/A |
| `--kubeconfig` | | Specifies the path to a kubeconfig file. | No | N/A |
| `--no-headers` | | Disables the header row in the output. | No | N/A |
| `--output` | `-o`| Specifies the output format. Valid values: `table`, `json`.| No | `table` |
| `--reverse` | `-r` | Reverses the sort order of the output. | No | N/A |
| `--sort` | | Sorts the output by a specific field.<br> Valid values: `name`, `role`, `create-time`, `memory`, `cpu` | No | N/A |
## Examples
```bash
# List all users in a table format
olares-cli user list
# List all users in JSON format
olares-cli user list -o json
# List users sorted by role
olares-cli user list --sort role
```

View File

@@ -0,0 +1,29 @@
# `reset-password`
## Synopsis
The `reset-password` subcommand forcefully resets the login password for a specific user via the authentication provider.
```bash
olares-cli user reset-password <username> [options]
```
## Arguments
| Argument | Description | Required|
|--|--|--|
| `<username>` | Specifies the username of the account to reset. <br>It is typically the part before the `@` symbol in an Olares ID. <br>For example, `alice123` for `alice123@olares.com`.| Yes |
## Options
| Option | Shorthand | Usage | Required | Default |
|--|--|--|--|--|
`--help` | `-h` | Displays help information. | No | N/A |
| `--kubeconfig` | | Specifies the path to a kubeconfig file. | No | N/A |
| `--password` | `-p` | Specifies the new password for the user. | Yes | N/A |
## Examples
```bash
# Reset password for user named alice123
olares-cli user reset-password alice123 -p "NewSecurePassword456!"
```

View File

@@ -0,0 +1,13 @@
# `user`
The `user` command provides a set of tools to manage users in the Olares system. It allows administrators to create, activate, query, and remove users, as well as reset user passwords.
## Subcommands
| Subcommand | Description |
|--|--|
| `activate` | Activates an existing Olares account. |
| `create` | Creates a new user. |
| `delete` | Deletes an existing user. |
| `get` | Retrieves details of a specific user. |
| `list` | Lists all users within the Olares cluster. |
| `reset-password` | Forcefully resets a user's password via the authentication provider. |

View File

@@ -34,20 +34,6 @@ Specifies whether to enable the Cloudflare proxy.
- `1` (enable)
- **Default**: `0`
### `DID_GATE_URL`
Specifies the endpoint for the DID gateway.
- **Valid values**:
- `https://did-gate-v3.bttcdn.com`
- `https://did-gate-v3.api.jointerminus.cn/` (recommended for better connectivity in mainland China)
- **Default**: `https://did-gate-v3.bttcdn.com`
### `FIREBASE_PUSH_URL`
Specifies the endpoint for Firebase push services.
- **Valid values**:
- `https://firebase-push-test.bttcdn.com/v1/api/push`
- `https://firebase-push-test.api.jointerminus.cn/v1/api/push` (recommended for better connectivity in mainland China)
- **Default**: `https://firebase-push-test.bttcdn.com/v1/api/push`
### `FRP_AUTH_METHOD`
Sets the FRP authentication method.
- **Valid values**:
@@ -68,13 +54,6 @@ Specifies whether to enable FRP for internal network tunneling. Requires additio
- `1` (enable)
- **Default**: `0`
### `FRP_LIST_URL`
Specifies the endpoint for the Olares FRP information service.
- **Valid values**:
- `https://terminus-frp.snowinning.com`
- `https://terminus-frp.api.jointerminus.cn` (recommended for better connectivity in mainland China)
- **Default**: `https://terminus-frp.snowinning.com`
### `FRP_PORT`
Specifies the FRP server's listening port.
- **Valid values**: An integer in the range `165535`
@@ -106,13 +85,6 @@ Specifies whether to enable GPU sharing. Applies only if GPU is enabled.
- `1` (enable)
- **Default**: `0`
### `MARKET_PROVIDER`
Specifies the backend domain used by the application marketplace (Market).
- **Valid values**:
- `appstore-server-prod.bttcdn.com`
- `appstore-china-server-prod.api.jointerminus.cn` (recommended for better connectivity in mainland China)
- **Default**: `appstore-server-prod.bttcdn.com`
### `NVIDIA_CONTAINER_REPO_MIRROR`
Specifies the APT repository mirror for installing NVIDIA Container Toolkit.
- **Valid values**:
@@ -120,13 +92,6 @@ Specifies the APT repository mirror for installing NVIDIA Container Toolkit.
- `mirrors.ustc.edu.cn` (recommended for better connectivity in mainland China)
- **Default**: `nvidia.github.io`
### `OLARES_SPACE_URL`
Specifies the endpoint for the Olares Space service.
- **Valid values**:
- `https://cloud-api.bttcdn.com/`
- `https://cloud-api.api.jointerminus.cn/` (recommended for better connectivity in mainland China)
- **Default**: `https://cloud-api.bttcdn.com/`
### `PREINSTALL`
Runs only the pre-installation phase (system dependency setup) without proceeding to the full Olares installation.
- **Valid values**: `1`
@@ -145,27 +110,6 @@ Specifies a custom Docker registry mirror for faster image pulls.
- **Valid values**: `https://mirrors.olares.com` or any other valid URL
- **Default**: `https://registry-1.docker.io`
### `TAILSCALE_CONTROLPLANE_URL`
Specifies the endpoint for the Olares Tailscale control-plane service.
- **Valid values**:
- `https://controlplane.snowinning.com`
- `https://controlplane.api.jointerminus.cn` (recommended for better connectivity in mainland China)
- **Default**: `https://controlplane.snowinning.com`
### `TERMINUS_CERT_SERVICE_API`
Specifies the endpoint for the Olares HTTPS certificate service.
- **Valid values**:
- `https://terminus-cert.snowinning.com`
- `https://terminus-cert.api.jointerminus.cn` (recommended for better connectivity in mainland China)
- **Default**: `https://terminus-cert.snowinning.com`
### `TERMINUS_DNS_SERVICE_API`
Specifies the endpoint for the Olares DNS service.
- **Valid values**:
- `https://terminus-dnsop.snowinning.com`
- `https://terminus-dnsop.api.jointerminus.cn` (recommended for better connectivity in mainland China)
- **Default**: `https://terminus-dnsop.snowinning.com`
### `TERMINUS_IS_CLOUD_VERSION`
Marks the machine explicitly as a cloud instance.
- **Valid values**: `true`

View File

@@ -1,12 +1,13 @@
---
description: In-depth guides and proven best practices to help you get the most out of Olares.
---
# Beyond the basics: Olares best practices and advanced guides
# Tutorials
This section offers in-depth guides and proven best practices to help you get the most out of Olares. Whether you're optimizing performance, securing your environment, or customizing advanced features, these resources go beyond initial setup to support real-world scenarios and power-user workflows.
This section offers in-depth guides and proven best practices to help you get the most out of Olares.
- [Configure a custom domain for your Olares](set-custom-domain.md)
- [Install a multi-node Olares cluster](install-olares-multi-node.md)
- [Build your knowledge hub with Wise](organize-content.md)
- [Install Olares on PVE via ISO with GPU Passthrough](install-olares-gpu-passthrough.md)
- [Expand Olares storage capacity](expand-storage-in-olares.md)
- [Access Olares services locally](local-access.md)

View File

@@ -0,0 +1,250 @@
---
outline: [2,3]
description: Learn the different methods to access Olares services locally for improved speed and offline capability.
---
# Access Olares services locally
Olares is designed to provide seamless access to your self-hosted services anytime, anywhere.
However, accessing your devices locally provides several advantages:
- **Maximum performance**: Transfer files at full speed without the latency and potential bottlenecks of the internet.
- **Enhanced privacy**: Keep your traffic contained within your home network for added security.
- **Offline independence**: Access your data and apps even when your internet service is unavailable.
## Objectives
By the end of this tutorial, you will learn how to:
- Establish a secure, high-speed local connection using the LarePass VPN.
- Access Olares services using `.local` domains.
- Configure local DNS to allow standard URLs to resolve locally across your entire network.
- Manually map hosts files to ensure access on specific machines without internet.
## Choose a connection method
There are four ways to establish a local connection:
* **[Method 1: Enable LarePass VPN](#method-1-enable-larepass-vpn)**<br/>
Uses LarePass VPN to automatically detect your local network and optimize the connection speed without changing settings.
* **[Method 2: Use `.local` domain](#method-2-use-local-domain)**<br/>
Access the device via a specific local URL format. No installation required.
* **[Method 3: Configure local DNS](#method-3-configure-local-dns)**<br/>
Updates your router or computer's DNS settings to map the standard Olares URL to the local IP address.
* **[Method 4: Modify hosts files](#method-4-modify-hosts-files)**<br/>
Manually maps the standard Olares URL to the local IP on a single computer.
## Method 1: Enable LarePass VPN
The LarePass VPN is designed to secure your connection while optimizing performance. When enabled, LarePass detects if you are on the same network as your device and switches to **Intranet** mode.
:::tip Always enable VPN for remote access
Keep LarePass VPN enabled. It automatically prioritizes the fastest available route to ensure you always get the best speed possible without manual switching.
:::
:::info iOS and macOS setup
On iOS or macOS, you may be prompted to add a VPN Configuration to your system settings the first time you enable the feature. Allow this to complete the setup.
:::
Enable the LarePass VPN directly on the device you are currently using to access Olares.
<tabs>
<template #On-LarePass-mobile-client>
1. Open the LarePass app, and go to **Settings**.
2. In the **My Olares** card, toggle on the VPN switch.
![Enable LarePass VPN on mobile](/images/manual/get-started/larepass-vpn-mobile.png#bordered)
</template>
<template #On-LarePass-desktop-client>
1. Open the LarePass app, and click your avatar in the top-left corner to open the user menu.
2. Toggle on the switch for **VPN connection**.
![Enable LarePass VPN on desktop](/images/manual/get-started/larepass-vpn-desktop.png#bordered)
</template>
</tabs>
Once enabled, check the status indicator in LarePass to verify the connection type:
| Status | Description |
|:-------------|:---------------------------------------------------------|
| **Intranet** | Direct connection via your local LAN IP. Fastest speeds. |
| **P2P** | Direct encrypted tunnel between devices. High speed. |
| **DERP** | Routed via a secure relay server. Used as a fallback. |
## Method 2: Use `.local` domain
If you prefer not to install additional apps, you can access services using the `.local` domain. There are two domain formats available depending on your operating system.
:::info Use HTTP protocol
The `.local` domain does not support HTTPS. You must explicitly use `http://` at the beginning of the URL.
:::
### Single-level domain (All operating systems)
:::warning Supported for community apps only
Olares system apps such as Desktop and Files do not support this URL format and will not load correctly.
:::
This format uses a single-level domain by connecting the entrance ID and the username with hyphens (`-`).
- **Default URL**:
```plain
https://<entrance_id>.<username>.olares.com
```
- **Local-access URL**:
```plain
http://<entrance_id>-<username>-olares.local
```
### Multi-level domain (macOS and iOS only)
Apple devices support local service discovery via [Bonjour](https://developer.apple.com/bonjour/) (zeroconfiguration networking), which can resolve multilabel domains under `.local` on macOS and iOS. This allows a local URL format that mirrors the remote address.
- **Default URL**:
```plain
https://<entrance_id>.<username>.olares.com
```
- **Local-access URL**:
```plain
http://<entrance_id>.<username>.olares.local
```
![Multi-level local domain](/images/manual/get-started/multilevel-local-domain-mac.png#bordered)
## Method 3: Configure local DNS
For a seamless experience where standard URLs resolve to your local IP address automatically, you can configure your network DNS. This configuration ensures consistent access across all devices on the network without requiring individual client setup.
### Find the internal IP for Olares device
To configure DNS, first you need to find the internal IP for your Olares device.
<tabs>
<template #Check-via-the-LarePass-mobile-client>
If your phone and Olares device are on the same network:
1. Open the LarePass app, and go to **Settings** > **System** to navigate to the **Olares management** page
![Tap the System card](/images/manual/get-started/larepass-system.png#bordered)
2. Tap on the device card.
![Tap the device card](/images/manual/get-started/larepass-device-card.png#bordered)
3. Scroll down to the **Network** section. You can find the **Intranet IP** there.
![Find Network section](/images/manual/get-started/larepass-network.png#bordered)
</template>
<template #Check-via-Olares-Terminal>
Control Hub provides a built-in terminal that allows you to run system commands directly from the browser, without needing an external SSH client.
1. Open the Control Hub app, and under **Terminal**, select **Olares** in the left navigation bar.
![Find internal IP from Control Hub](/images/manual/get-started/find-internal-ip-from-controlhub.png#bordered)
2. Type `ifconfig` in the terminal and press **Enter**.
3. Look for your active connection, typically named `enp3s0` (wired) or `wlo1` (wireless). The IP address follows `inet`.
Example output:
```bash
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.116 netmask 255.255.255.0 broadcast 192.168.50.255
inet6 fe80::4194:4045:c35e:7b32 prefixlen 64 scopeid 0x20<link>
ether d8:43:ae:54:ce:fc txqueuelen 1000 (Ethernet)
RX packets 80655321 bytes 71481515308 (71.4 GB)
RX errors 0 dropped 136 overruns 0 frame 0
TX packets 51867817 bytes 15924740708 (15.9 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
```
In this example, `192.168.50.116` is the internal IP.
</template>
</tabs>
### Configure DNS
With the internal IP address identified, you must now configure your DNS settings to route traffic correctly. You can apply this configuration to a single computer for individual access, or update your router to enable seamless local resolution for all devices on your network.
<tabs>
<template #Configure-for-local-device>
Update the DNS settings on your specific computer. For example, on macOS:
1. Open Apple menu and go to **System Settings**.
2. Select **Wi-Fi**, then click **Details** on your connected network.
3. Select **DNS** and update the server list:
a. Click the **+** button under **DNS Servers** to add your Olares device's internal IP (e.g., `192.168.x.x`).
b. Ensure the Olares IP is listed at the top. Add your original DNS (or `1.1.1.1`) below it as a fallback. <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
4. Click **OK** to save changes.
</template>
<template #Configure-for-all-devices>
Update the DNS on your router to apply changes to every device in your network.
1. Log in to your router's admin panel.
2. Navigate to **DHCP / DNS Settings**.
3. Set **Primary DNS** to your Olares device's internal IP (e.g., `192.168.x.x`).
4. Set **Secondary DNS** to your current Primary DNS (or a public provider like `1.1.1.1`). <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
5. Save and reconnect your devices to refresh the DNS cache.
</template>
</tabs>
Once configured, you can access Olares using both your standard public address and your local address.
:::tip
You can install AdGuard Home from the Olares Market to monitor traffic and manage DNS mappings graphically.
:::
## Method 4: Modify hosts files
If you cannot change router settings and need immediate offline access on a specific computer, you can manually map the domains in your hosts file.
1. Locate your hosts file:
- **Windows**: `C:\Windows\System32\drivers\etc\hosts`
- **macOS/Linux**: `/etc/hosts`
2. Open the file with a text editor, which requires Administrator privileges.
3. Add the mapping lines:
```plain
# Replace with the actual internal IP and the username
# Olares apps
192.168.31.208 desktop.<username>.olares.com
192.168.31.208 auth.<username>.olares.com
192.168.31.208 files.<username>.olares.com
192.168.31.208 market.<username>.olares.com
192.168.31.208 settings.<username>.olares.com
192.168.31.208 dashboard.<username>.olares.com
192.168.31.208 control-hub.<username>.olares.com
192.168.31.208 profile.<username>.olares.com
192.168.31.208 vault.<username>.olares.com
# Add other community apps as needed
192.168.31.208 <entrance_id>.<username>.olares.com
```
4. Save the file to apply changes and ensure local access without an internet connection.
Verify the changes by checking the URL for quick loading or using the terminal:
```bash
ping desktop.<username>.olares.com
```
If the IP address starts with `192.168`, it indicates successful configuration.
## FAQs
### Why doesn't LarePass VPN work on my Mac anymore?
If you successfully enabled the VPN previously, but it has stopped working, you might need to reset the system extension.
:::info
Depending on your macOS version, the UI might look slightly different.
:::
1. Open **System Settings**, search for "Extension", and select **Login Items & Extensions**.
2. Scroll to the **Network Extensions** section and click the info icon (ⓘ) to view loaded extensions.
3. Find LarePass, click the three dots (...), and select **Delete Extension**.
4. Confirm the uninstallation.
5. Restart your Mac and re-enable the VPN in the LarePass desktop client.
### Why can't I enable LarePass VPN on Windows?
Third-party antivirus software might mistakenly flag the LarePass desktop client as suspicious, preventing it from launching the VPN service.
If prompted by your antivirus when opening LarePass for the first time, allow the application to continue.
If the VPN still fails to enable:
1. Open your security software and check if LarePass was blocked.
2. Add the main LarePass executable to the allowlist or exclusions of your antivirus.
3. Restart LarePass and enable the VPN.
### Why the `.local` domain does not work in Chrome (macOS)?
Chrome may fail to access local URLs if macOS blocks local network permissions.
To enable access:
1. Open Apple menu and go to **System Settings**.
2. Go to **Privacy & Security** > **Local Network**.
3. Find Google Chrome and Google Chrome Helper in the list and enable the toggles.
![Enable local network](/images/manual/larepass/mac-chrome-local-access.png#bordered){width=400}
4. Restart Chrome and try accessing the local URL again.
### Why does the application fail to load in an iFrame when using a `.local` domain on Chrome (macOS)?
Chrome might default to HTTPS when using local domains, and you might see a "connection not secure" warning.
![Incorrect local address](/images/manual/get-started/incorrect-local-address.png#bordered)
To address this, explicitly add the HTTP protocol (`http://`) to the beginning of the URL. This tells Chrome it's a local, non-encrypted connection, which is expected on your home network.

View File

@@ -9,7 +9,33 @@ You can use Docker to install and run Olares in a containerized environment. Thi
For best performance and stability, we recommend [installing Olares on Linux via script](/manual/get-started/install-olares.md).
:::
<!--@include: ./reusables.md{52,65}-->
## System requirements
Make sure your device meets the following requirements.
### Required specifications
- **CPU**: At least 4 cores.
- **RAM**: At least 8 GB of available memory.
- **Storage**: At least 150 GB of available SSD storage.
:::warning SSD required
The installation will fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
- **Supported systems**:
- Ubuntu 22.04-25.04 LTS
- Debian 12 or 13
:::info Version compatibility
While these specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
:::
### Optional hardware
A GPU is not required to install Olares, but is necessary for AI applications.
- **GPU (NVIDIA only)**:
- **Architecture**: Turing or newer (e.g., GTX 16 series, RTX 20 series).
- **Verification**: Run `lspci | grep -i nvidia` and check the [compatible GPU table](https://github.com/NVIDIA/open-gpu-kernel-modules?tab=readme-ov-file#compatible-gpus).
## Before you begin
Before you begin, ensure the following:

View File

@@ -1,4 +1,5 @@
---
outline: [2, 3]
description: Install Olares on a physical machine using the official ISO image, including system requirements, installation steps, and activation process.
---
@@ -10,6 +11,7 @@ This guide explains how to install Olares on a physical machine using the offici
## Prerequisites
### Required
- **Host requirements**:
- **CPU**: Minimum 4 cores with **x86-64 architecture** (Intel or AMD). ARM-based processors are not currently supported for this method.
- **Memory**: At least 8 GB of available RAM.
@@ -19,7 +21,15 @@ This guide explains how to install Olares on a physical machine using the offici
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
- **Other**: A USB flash drive with at least **8 GB** capacity.
- **USB flash drive**: **8 GB** capacity or larger.
### Optional
A GPU is not required to install Olares, but is necessary for AI applications.
- **GPU (NVIDIA only)**:
- **Architecture**: Turing or newer (e.g., GTX 16 series, RTX 20 series).
- **Verification**: Run `lspci | grep -i nvidia` and check the [compatible GPU table](https://github.com/NVIDIA/open-gpu-kernel-modules?tab=readme-ov-file#compatible-gpus).
## Create a bootable USB drive

View File

@@ -1,4 +1,5 @@
---
outline: [2, 3]
description: Detailed instructions for installing Olares on Linux systems including Ubuntu and Debian. Covers system requirements, installation steps, and activation process.
---
# Install Olares on Linux via the script
@@ -6,7 +7,33 @@ This guide explains how to install Olares on Linux using the provided installati
<!--@include: ./reusables.md{44,51}-->
<!--@include: ./reusables.md{52,65}-->
## System requirements
Make sure your device meets the following requirements.
### Required specifications
- **CPU**: At least 4 cores.
- **RAM**: At least 8 GB of available memory.
- **Storage**: At least 150 GB of available SSD storage.
:::warning SSD required
The installation will fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
- **Supported systems**:
- Ubuntu 22.04-25.04 LTS
- Debian 12 or 13
:::info Version compatibility
While these specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
:::
### Optional hardware
A GPU is not required to install Olares, but is necessary for AI applications.
- **GPU (NVIDIA only)**:
- **Architecture**: Turing or newer (e.g., GTX 16 series, RTX 20 series).
- **Verification**: Run `lspci | grep -i nvidia` and check the [compatible GPU table](https://github.com/NVIDIA/open-gpu-kernel-modules?tab=readme-ov-file#compatible-gpus).
## Install Olares

View File

@@ -12,21 +12,31 @@ Currently, Olares on LXC has certain limitations. We recommend using it only for
## System requirements
Make sure your device meets the following requirements.
### Required specifications
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 150GB of available SSD storage.
- RAM: At least 8 GB of available memory
- Storage: At least 150 GB of available SSD storage.
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
- Supported systems:
- PVE 8.2.2
- Linux container: Debian 12 (for existing LXC containers on PVE)
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
:::info Version compatibility
While the specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
:::
### Optional hardware
A GPU is not required to install Olares, but is necessary for AI applications.
- GPU (NVIDIA only):
- Architecture: Turing or newer (e.g., GTX 16 series, RTX 20 series, and later).
- Verification: Run `lspci | grep -i nvidia` in the PVE host shell to confirm the card is detected.
- Setup: To utilize the GPU, you must configure LXC device passthrough. Please refer to [Configure GPU passthrough in PVE](/manual/best-practices/install-olares-gpu-passthrough.md#configure-gpu-passthrough-in-pve) for detailed instructions.
## Prerequisites
- Working directories for storing images and packages on the PVE host. You can set it using the following command:

View File

@@ -20,11 +20,14 @@ Make sure your device meets the following requirements.
- Architecture: AMD64 or ARM64
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 150GB of available SSD storage.
- RAM: At least 8 GB of available memory
- Storage: At least 150 GB of available SSD storage.
::: warning SSD required
The installation will fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
::: info GPU limitation
Olares GPU acceleration currently supports NVIDIA GPUs only. Consequently, GPU resources cannot be managed or utilized for AI workloads on macOS devices.
:::
## Before you begin
Before you begin, ensure the following:

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