Compare commits

...

19 Commits

Author SHA1 Message Date
lovehunter9
b8981f9b75 fix: files check disk space for upload link and copy 2026-01-13 21:30:12 +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
eball
2a506be19a ci: bump version to 1.12.5 (#2405) 2026-01-12 15:00:44 +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
93 changed files with 1855 additions and 1031 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

@@ -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.40
image: beclab/system-frontend:v1.7.1
imagePullPolicy: IfNotPresent
command:
- /bin/sh

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

@@ -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

@@ -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

@@ -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
}
}
}
}

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{})
}

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

@@ -7,18 +7,33 @@ const side = {
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: "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",
// },
],
},
],
},
{
@@ -132,7 +147,7 @@ const side = {
{ 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,
@@ -176,7 +191,7 @@ const side = {
text: "Basic operations",
link: "/manual/olares/market/market",
},
{
{
text: "Clone applications",
link: "/manual/olares/market/clone-apps",
},
@@ -265,16 +280,16 @@ const side = {
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",
},
],
items: [
{
text: "Filter syntax",
link: "/manual/olares/wise/filter-syntax-guide",
},
{
text: "Filter example",
link: "/manual/olares/wise/filter-examples",
},
],
},
],
},
@@ -368,10 +383,10 @@ const side = {
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 search rules", link: "/manual/olares/settings/search"},
},
{ 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,
@@ -380,12 +395,12 @@ const side = {
{ 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",
@@ -519,10 +534,10 @@ const side = {
}
]
},
// {
// text: "Redroid",
// link: "/use-cases/host-cloud-android",
// },
// {
// text: "Redroid",
// link: "/use-cases/host-cloud-android",
// },
{
text: "Windows",
link: "/use-cases/windows",
@@ -611,65 +626,46 @@ 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: "backup", link: "/developer/install/cli/backups-backup" },
{ 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: "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" },
],
},
],
},

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: "常见问题",
// 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,
@@ -128,33 +141,33 @@ 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" },
],
},
/*{
@@ -198,7 +211,7 @@ const side = {
},
//{
// "text": "同步与共享",
// "link": "/zh/manual/larepass/sync-share"
// "link": "/zh/manual/larepass/sync-share"
// },
{
"text": "分享文件",
@@ -266,17 +279,17 @@ const side = {
"text": "管理知识",
"link": "/zh/manual/olares/wise/filter",
collapsed: true,
items:[
{
"text": "过滤语法参考",
"link": "/zh/manual/olares/wise/filter-syntax-guide"
items: [
{
"text": "过滤语法参考",
"link": "/zh/manual/olares/wise/filter-syntax-guide"
},
{
"text": "过滤视图示例",
"link": "/zh/manual/olares/wise/filter-examples"
}
],
},
{
"text": "过滤视图示例",
"link": "/zh/manual/olares/wise/filter-examples"
}
],
},
],
},
{
@@ -311,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,
@@ -343,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,
@@ -363,24 +376,24 @@ 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: "文件搜索", link: "/zh/manual/olares/settings/search"},
},
{ 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" }
]
@@ -409,8 +422,8 @@ 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",
},
@@ -535,7 +548,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: [
@@ -594,76 +608,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",
},
],
},
{
@@ -705,7 +699,7 @@ const side = {
text: "OlaresManifest",
link: "/zh/developer/develop/package/manifest",
},
/*/{
/*{
text: "推荐算法",
link: "/zh/developer/develop/package/recommend",
},*/
@@ -715,66 +709,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,
@@ -893,8 +887,8 @@ const side = {
},
],
},
],
};
],
};
export const zh = defineConfig({
lang: "zh",

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,105 +1,2 @@
---
description: Find answers to common questions about Olares.
---
# FAQs
## What license is Olares using?
Olares consists of a series of projects using a hierarchical authorization approach. The basic principles are:
- Projects running on blockchain use Apache 2.0, such as [Snowinning Protocol](https://github.com/beclab/terminusdid-contract-system).
- Projects related to protocols use Apache 2.0, such as [r4](https://github.com/beclab/r4).
- Projects around Olares and LarePass use the [Olares License](https://github.com/beclab/Olares/blob/main/LICENSE.md).
- For third-party applications running on Olares, it is up to the developer to decide whether they want them open source or not and choose the license accordingly.
For more details, visit our projects on [GitHub](https://github.com/beclab).
## Is the Olares License an open source license?
Olares's choice of license for its major projects is inspired by [fair code](https://faircode.io/). The [Olares License](https://github.com/beclab/Olares/blob/main/LICENSE.md) also follows these principles:
> - Is generally free to use and can be distributed by anybody
> - Has its source code openly available
> - Can be extended by anybody in public and private communities
> - Is commercially restricted by its authors
## Why can't I restore my account if the mnemonics goes missing?
From 1Passwords MasterKey to crypto wallets mnemonic phrase, for more than ten years, the problem of mnemonic storage has not been well solved.
The mnemonic phrase of Olares will be encrypted and stored on all devices that install LarePass. Generally, you only lose the mnemonic phrase if you lose all the devices with LarePass installed at the same time.
Safety is the most important principle in designing our system. We will continue to improve it in the future to provide you with a better solution that balances convenience and safety.
## Is there a difference between Olares and the current operating systems running on NAS?
At the inception of Olares (formerly Terminus), the market already had excellent NAS operating systems such as [Synology](https://www.synology.com/en-global/dsm/packages), [CasaOS](https://github.com/IceWhaleTech/CasaOS), and [Umbrel](https://github.com/getumbrel/umbrel). They have indeed inspired us.
But we do think the operating system running on Edge should be able to:
- Orchestrate resources for multiple hardware
- Manage applications in sandboxes
This is difficult to achieve with the above-mentioned NAS operating systems built on Docker Compose.
Meanwhile, Olares aims to provide a one-stop self-hosted solution, which goes beyond the scope of general NAS operating systems.
## Do I need to pay for Olares?
When you're self-hosting, you can essentially use Olares for free.
But for the following two features, we may introduce reasonable charges due to the cost (currently both are provided for free):
- **Backup**
We provide 10G of free backup space for each Olares ID on Olares Space. When the archive size exceeds this limit, we will charge you a certain fee to cover the cloud provider fee.
- **Fast Reverse Proxy (FRP)**
Accessing Olares locally or via VPN is essentially free. However, if youre providing external services like hosting a blog, traffic will be forwarded to a Fast Reverse Proxy (FRP) server before reaching Olares. In this case:
- If you use your own FRP service, Olares does not impose any charges.
- If you opt to use the default FRP service from Olares, we offer a free monthly traffic allowance of 2GB. This is usually sufficient for users who do not provide external services through Olares. Additional charges may apply if your usage exceeds this limit.
## When are other languages available?
Right now we only support English and Simplified Chinese.
In fact, we have completed i18n replacement in all front-end projects. However, we lack the experience in maintaining translation resources for a fast iterating project through the open source community. We are still learning.
## What are the differences among the different "passwords"?
Olares does have various passwords to ensure its security, including:
- Private key
- The password of LarePass:
- On mobile phones, biometrics can be used for login
- On computers and browser plug-ins, manual input is required
- Password for first activation of Olares
- Password for Olares login
- Second verification code when logging in to Olares
Don't panic! For daily use, what you need to enter is the two-step verification code when logging in to Olares.
## How to deploy multi-user applications?
It depends on whether you want to provide external service or simply let internal Olares users use it.
- To provide services to the public, you can select the Entrance to access the application as **Public**. This allows the application to manage its own user registration and authentication.
- To provide internal access only, you can deploy the Cluster-scoped version of such products on Olares.
For Gitlab, we provide two versions of porting: [Gitlab Pure](https://github.com/beclab/apps/tree/main/gitlabpure) and [Gitlab Fusion](https://github.com/RLovelett/gitlab-fusion).
## How can I reactivate Olares with the same Olares ID?
If you've reinstalled Olares, the Olares instance you originally activated will no longer be accessible. To reactivate Olares using the same Olares ID:
::: tip Install with the same Olares ID
During the Olares installation, ensure that you have entered the exact same domain and Olares ID that you used previously.
:::
![Reactivate](/images/manual/help/reactivate.png)
1. Open LarePass on your phone and enter your previous account. You should see a red prompt on the top saying "No active Olares found".
2. Tap **Learn more** > **Reactivate** to enter the QR scan screen.
3. Tap **Scan QR code** to scan the QR code on the wizard page and activate Olares.
This section summarizes frequently asked questions about Olares.

View File

@@ -0,0 +1,78 @@
---
outline: [2, 3]
description: Find answers to common questions during the installation and activation of Olares.
---
# Olares installation and activation FAQs
This page lists the FAQs about installing, configuring, and activating Olares on your hardware.
## Installation
### What platforms does Olares support?
You can install Olares on Linux (Ubuntu or Debian) for best performance.
For product evaluation, you can also install Olares on the following platforms:
* Proxmox VE
* Raspberry Pi
* macOS
* Windows
### What is the minimum hardware requirements for installing Olares?
The requirements vary by platform. Generally:
* **CPU**: Minimum 4 cores with x86-64 architecture (Intel or AMD).
* **Memory**: At least 8 GB of available RAM.
* **Storage**: Minimum 150 GB SSD.
For detailed requirements, refer to the [installation docs](../get-started/install-olares.md).
### Can I use a mechanical hard drive to install Olares?
No. You must use an SSD. The installation will likely fail if a mechanical hard drive is used due to slower read and write speeds, which can cause timeouts during the system initialization.
### Does the system support NVIDIA GPUs?
Yes. Olares is fully optimized for NVIDIA hardware. It automatically handles driver installation, allowing you to get immediate AI and gaming performance.
It also supports multiple GPUs on a single motherboard (currently NVIDIA only), allowing users with custom hardware to leverage all available compute power for AI workloads.
### How do I manually install NVIDIA drivers if the automatic setup fails?
The Olares installer usually detects and installs drivers automatically. However, if your system previously had NVIDIA drivers installed, the process might be skipped or fail due to conflicts.
In this case, you should:
1. Reboot the machine after the Olares installation to ensure any old driver components are fully cleared.
2. Manually trigger the driver installation using the command `olares-cli gpu install`.
After installation, you can confirm that the drivers are installed and your GPU is recognized by running `nvidia-smi`.
### Why does installation fail with `failed to build Kubernetes objects` or `Ensure CRDs are installed first`?
While these error messages suggest a problem with Custom Resource Definitions (CRDs), they are often a symptom of poor disk performance.
Olares relies on etcd, the backing database for Kubernetes. etcd is very sensitive to storage speed. If you are installing Olares on a slow disk, such as a traditional HDD, etcd cannot respond fast enough. This causes the API server to time out while attempting to apply CRDs.
Installing Olares on SSD storage should fix this issue.
### My Olares installation timed out and didn't show a password, but the system seems to be running. How can I find the password?
This typically occurs when the installation times out due to insufficient system resources, especially in a virtual machine (VM). You can retrieve the password from the installation log file with the following command:
```bash
# Replace v1.12.2 with your specific Olares version number.
grep password $HOME/.olares/versions/v1.12.2/logs/install.log
```
An installation timeout often means some services failed to start correctly. After finding your password, run `kubectl get pod -A` to check the status of all services.
## Activation
### Is it possible to activate Olares with a non-local network?
Yes. Before activation, users typically access the activation wizard using the local IP address, which generally requires both parties to be on the same network. However, if Olares is assigned a public IP, such as on a public cloud, this local network limitation no longer applies.
Note that IP access is only used during activation. Once activated, devices can be accessed via domain names on both internal and external networks.
### My Olares is powered on and connected to LAN, but I can't find it in LarePass. What should I do?
Ensure both your phone and Olares device are on the same network. If they are not, LarePass cannot discover Olares automatically.
In situations where you cannot connect via Wi-Fi, you can use the Bluetooth network setup in the LarePass app to connect Olares to the same network as your phone.
For details, see [Activate Olares using Bluetooth](../../manual/larepass/activate-olares.md#activate-olares-using-bluetooth).

125
docs/manual/help/olares.md Normal file
View File

@@ -0,0 +1,125 @@
---
outline: [2, 3]
description: Find answers to common questions about the Olares platform.
---
# Olares FAQs
This page lists most frequently asked questions about Olares.
## General information
### What is Olares?
Olares is an open-source personal cloud operating system based on Kubernetes designed to empower users to own and manage their digital assets locally.
It features native resource orchestration, application sandboxing, and production-grade infrastructure for edge computing. The goal of Olares is to provide a one-stop personal cloud solution that runs powerful local alternatives to public cloud services such as large language models and automation workflows. It is suitable for use cases ranging from personal media servers and AI development to decentralized identity management.
### What is "personal cloud"?
A personal cloud is a private infrastructure that replicates the utility of public cloud services such as anywhere-access to files and computing power but runs entirely on your own hardware to ensure data sovereignty.
### Who is Olares for?
Olares is designed for anyone who wants to use powerful AI tools locally without dealing with complex technical setups.
* **For general users**: You can deploy complex applications like ComfyUI or Perplexica from the Market with a single click.
* **For developers**: Olares functions as an efficient local development environment. You can leverage the sandboxing and agent infrastructure to build and test applications directly on your Olares device, saving time on environment configuration.
### How is Olares different from NAS operating systems?
Olares is designed fundamentally as a Personal AI Cloud rather than a storage server. Traditional NAS systems like Synology DSM or CasaOS are optimized primarily for storing files and hosting lightweight containers.
Olares distinguishes itself by focusing on high-performance computing:
* **Orchestrating resources**: It natively manages hardware resources such as GPUs to power local AI workloads.
* **Sandboxing**: It enforces strict application isolation, providing a security model that goes beyond standard file servers.
For detailed comparisons, refer to [Compare Olares and NAS](https://blog.olares.com/compare-olares-and-nas/).
### Why is an Olares ID required?
The Olares ID is currently required to automate secure remote access for your device. It allows the system to configure a reverse proxy, register a subdomain, and manage HTTPS certificates on your behalf. Without this, you would need to manually handle complex network configurations such as port forwarding and DNS management to access your device from outside your home.
Unlike a centralized cloud account, the Olares ID is owned entirely by you. We never see your credentials, and we cannot recover your data if you lose your mnemonic phrase.
We understand the community's preference for flexibility. In the upcoming March update, we plan to introduce new activation options that will make the Olares ID optional if you prefer to configure your own network access.
### Can I use Olares offline or without internet?
Yes, we support local-first usage, though the initial activation currently requires internet access.
For users prioritizing strict local control, we offer these options:
* **VPN-Only mode**: You can restrict your Olares so it is only accessible remotely via VPN.
* **Local-Only access**: You can access Olares services via `.local` domains even if the router has no internet access.
For detailed local access options, refer to [Access Olares services locally](../get-started/local-access.md).
Note that we are also working on an option to allow full device activation in a completely offline environment.
### What is LarePass and why is it required?
LarePass is the official client for Olares. It acts as a secure bridge to enable seamless access, file synchronization across devices, etc. Currently, it is required to handle the device activation.
### Can I use Olares without the LarePass app?
We understand this is a core requirement for advanced users. We are working on decoupling these functions:
* **CLI activation**: We plan to move activation logic into the `olares-cli`, allowing for a terminal-based setup without the app.
* **Standalone components**: We aim to provide standalone deployment options for components like the Reverse Proxy, DID service, and Market repo in future updates.
### Can I use my own domain name?
Yes. You can use your own custom domain instead of the default `olares.com` domain. Note that setting this up currently requires the LarePass app.
For details, refer to [Set up a custom domain for your Olares](../best-practices/set-custom-domain.md).
### Do I need to pay for Olares?
Olares OS itself is free and open source for self-hosting. If you purchase Olares One, it is a one-time hardware cost.
We offer two optional cloud-assisted services for convenience, but free alternatives are available so you are never locked in:
* **Cloud backup**: You can subscribe to Olares Space for integrated cloud backups. The free alternative is to back up to your own external storage or S3-compatible service.
* **Remote access (FRP)**: For easy remote access, we offer a built-in FRP (Fast Reverse Proxy) service with 2 GB of free monthly traffic, with paid options for higher usage. The completely free alternative is to access Olares services via LarePass VPN, or to configure and use your own FRP server.
### How often does Olares update?
We aim for a major release approximately every 2 months. You can view specific changes in our [changelog](https://www.olares.com/changelog).
## License
### Is Olares open source?
Yes. The Olares OS software is open source, ensuring transparency and community collaboration. The project consists of a family of repositories licensed under appropriate models:
* **Olares and LarePass**: Licensed under AGPL-3.0. You can view our [GitHub organization](https://github.com/beclab).
* **Protocol projects**: Projects like the Smart contract system for Olares ID use Apache 2.0.
* **Third-party apps**: Developers adopt any license they choose.
### Can I build Olares from source code?
The short answer is yes, but it is currently complex.
Olares is a massive project spanning over 90 repositories. Because our architecture is evolving quickly, we currently lack a fully integrated local build system that provides a simple "what you see is what you get" experience.
We are actively working to streamline the build process and documentation. We expect to improve the local build experience and release standalone deployment guides for core services such as reverse proxy in 2026. Our goal is to refine the foundation first, then invite broader community collaboration.
## Security and privacy
### Does Olares collect my data?
No. Olares is built to reclaim your data ownership. All storage, computation, and AI processing happen locally on your hardware. Olares does not collect or transmit your private data to any centralized service.
### Does Olares support backup?
Yes. Data safety is user-controlled and private. Olares includes a [built-in backup feature](../olares/settings/backup.md) that allows you to save specific file directories and set automatic schedules.
Critically, every backup file is end-to-end encrypted. This allows you to store the backup file on any medium including external drive or third-party cloud with full confidence that the data remains inaccessible to others.
### What is app sandboxing?
Sandboxing is a security standard used to prevent a single malicious app from compromising the entire system. In Olares, every app runs in its own secure, isolated environment. If an app malfunctions, it is completely contained and cannot access or damage your other applications or personal data.
### Does the system support multi-user environments?
Yes. Olares supports sub-accounts with a built-in roles and permissions system including Super Admin, Admin, and Member.
This allows a team to access shared tools on a single server. For example, you can share files within the same Olares cluster or install a large AI model once for everyone to use.

49
docs/manual/help/usage.md Normal file
View File

@@ -0,0 +1,49 @@
---
outline: [2, 3]
description: Find answers to common questions about using Olares and community apps.
---
# Usage FAQs
Find answers to common questions about daily usage, applications, and system management.
## Applications
### What apps can I run in Olares?
The [Olares Market](https://market.olares.com/) maintains popular open-source apps like Ollama, ComfyUI, and Open WebUI.
If you have Docker experience, you can manually [deploy apps](../../developer/develop/tutorial/index.md) not listed in the Olares Market in a testing environment.
### Can I play games on my Olares device?
Yes. The Steam Headless app transforms your Olares device into a gaming server.
* [**Streaming**](../../use-cases/stream-game.md): You can run games locally on Olares and stream them to devices like phones and tablets.
* [**Direct play**](../../use-cases/play-games-directly.md): You can connect a monitor, keyboard, and mouse directly to the Olares device to play games without streaming.
### How do I access the Windows environment in Olares?
You can run a Windows VM from the Olares Market and access it using any standard RDP client.
For detailed instructions, refer to [Run a Windows VM on your Olares device](../../use-cases/windows.md).
### Can I develop apps on Olares?
Yes. You can install [Studio](../../developer/develop/tutorial/index.md) to code directly in your browser or connect your local VS Code to the device. This provides a development experience similar to your local machine but leverages the greater power of your server hardware.
## Storage
### If I add new disks to a running Olares machine, will Olares use them automatically?
It depends on the type of drive:
* **USB drives**: Yes, these are automatically mounted and will appear immediately in the Files app.
* **Internal drives**: No, internal HDDs or SSDs are not automatically added to the storage pool. You must configure them manually.
* **SMB shares**: Network storage can be added via **External** > **Connect to server** in Files.
For detailed instructions, see [Expand storage in Olares](../best-practices/expand-storage-in-olares.md).
## Multi-node clusters
### How do I add more machines to my cluster?
By default, Olares installs as a single-node cluster. However, you can install Olares as a master node and then add worker nodes to create a scalable, multi-node cluster.
Note that this is currently an Alpha feature and works on Linux only. For detailed steps, refer to [Install a multi-node Olares cluster](../best-practices/install-olares-multi-node.md).

View File

@@ -0,0 +1,32 @@
# `disk`
## 命令说明
`disk`命令提供了一组用于管理 Olares 系统存储资源的工具,主要用于基于 LVM 的存储配置管理。
```bash
olares-cli disk <subcommand>
```
## 子命令
| 子命令 | 描述 |
|--|--|
| `extend` | 在基于 LVM 的安装环境中扩展 Olares 的存储容量。 |
| `list-unmounted` | 列出未挂载的磁盘。 |
## 参数标记
| 名称 | 简写 | 说明 |
|--|--|--|
| `--help` | `-h` | 显示帮助信息。 |
## 使用示例
```bash
# 列出未挂载的磁盘
olares-cli disk list-unmounted
# 添加新检测到的未挂载磁盘来扩展 Olares 存储
olares-cli disk extend
```

View File

@@ -28,11 +28,12 @@ wsl -d Ubuntu
## 语法
Olares 命令行工具使用如下语法:
> `olares-cli 命令 [子命令] [选项]`
> `olares-cli 命令 [子命令] [参数] [选项]`
其中:
- `命令`:指定要执行的主要操作,例如 `olares-cli install`
- `子命令`:进一步指定命令的具体任务,适用于支持子操作的命令。例如 `wizard``component`
- `参数`:指定命令的目标资源或输入数据,通常是 ID、名称或文件路径。例如`olares-cli user activate <Olares ID> [选项]` 中,`<Olares ID>` 就是该命令的参数。
- `选项`可选参数用于修改命令的行为。包括标志flags和带参数的选项。
通过 Olares 命令行工具,你可以临时覆盖某些 Olares 默认设置。每个选项仅对当前执行的命令生效。
@@ -43,21 +44,23 @@ Olares 命令行工具使用如下语法:
## 可用命令列表
| 操作 | 语法 | 说明 |
|--------------------|-----------------------------------------|--------------------------------|
| `gpu` | `olares-cli gpu <子命令> [选项]` | 管理 GPU 相关操作。 |
| `info` | `olares-cli info <子命令> [选项]` | 显示当前设备的操作系统信息。 |
| `node` | `olares-cli node <子命令> [选项]` | 管理节点相关的操作。 |
| `backups` | `olares-cli backups <子命令> [选项]` | 管理备份相关操作。 |
| `change-ip` | `olares-cli change-ip [选项]` | 修改 Olares OS 的 IP 地址。 |
| `download` | `olares-cli download <子命令> [选项]` | 下载指定资源。 |
| `info` | `olares-cli info [选项]` | 显示已下载的 Olares OS 的常规信息。 |
| `install` | `olares-cli install [选项]` | 部署 Olares 系统级和用户级组件。 |
| `logs` | `olares-cli logs [选项]` | 收集 Olares 系统组件的日志,用于调试和故障排查。 |
| `precheck` | `olares-cli precheck [选项]` | 检查系统环境是否满足 Olares 安装要求。 |
| `prepare` | `olares-cli prepare [选项]` | 为安装过程准备环境,包括设置 Olares 的基础服务和配置 |
| `release` | `olares-cli release [选项]` | 打包 Olares 安装资源以供分发或部署。 |
| `start` | `olares-cli start [选项]` | 启动 Olares 服务和组件。 |
| `stop` | `olares-cli stop [选项]` | 停止 Olares 服务和组件。 |
| `uninstall` | `olares-cli uninstall [选项]` | 完全卸载 Olares或将安装回滚到特定阶段。 |
| 操作 | 语法 | 说明 |
|--|--|--|
| `backups` | `olares-cli backups <子命令> [选项]` | 管理备份相关操作。 |
| `change-ip` | `olares-cli change-ip [选项]` | 修改 Olares OS 的 IP 地址。 |
| `disk` | `olares-cli disk <子命令>` | 管理 Olares 系统存储资源。 |
| `download` | `olares-cli download <子命令> [选项]` | 下载指定资源。 |
| `gpu` | `olares-cli gpu <子命令> [选项]` | 管理 GPU 相关的操作。 |
| `info` | `olares-cli info [选项]` | 显示已下载的 Olares OS 的常规信息。|
| `install` | `olares-cli install [选项]` | 部署 Olares 的系统级和用户级组件。|
| `logs` | `olares-cli logs [选项]` | 收集 Olares 系统组件的日志,用于调试和故障排查。 |
| `node` | `olares-cli node <子命令> [选项]` | 管理节点相关的操作。 |
| `osinfo` | `olares-cli osinfo <子命令> [选项]` | 显示当前设备的操作系统信息。 |
| `precheck`| `olares-cli precheck [选项]` | 检查系统环境是否满足 Olares 安装要求。|
| `prepare` | `olares-cli prepare [选项]` | 为安装过程准备环境,包括设置 Olares 的基础服务和配置。 |
| `release` | `olares-cli release [选项]` | 打包 Olares 安装资源以供分发或部署。|
| `start` | `olares-cli start [选项]` | 启动 Olares 服务和组件。 |
| `stop` | `olares-cli stop [选项]` | 停止 Olares 服务和组件。 |
| `uninstall` | `olares-cli uninstall [选项]` | 完全卸载 Olares或将安装回滚到特定阶段。 |
| `upgrade` | `olares-cli upgrade <子命令> [选项]` | 升级 Olares检查升级准备情况与兼容性。 |
| `user` | `olares-cli user <子命令> [选项]`| 管理 Olares 用户。 |

View File

@@ -0,0 +1,53 @@
# `upgrade`
## 命令说明
`upgrade`命令提供一组用于升级 Olares检查升级准备情况与兼容性的工具。
```bash
olares-cli upgrade <子命令> [选项]
```
## 子命令
| 子命令 | 描述 |
|--|--|
| `precheck` | 对 Olares 执行升级前检查。 |
| `spec` | 获取当前 CLI 版本对应的升级规格。 |
| `viable` | 判断是否可以基于指定基础版本直接执行升级。 |
## 全局选项
以下选项适用于`upgrade`主命令,需要时可被子命令继承。
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--base-dir` | `-b` | 设置 Olares 安装包的基本目录。 | 否 | `$HOME/.olares` |
| `--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--version` | `-v` | 设置要升级到的目标 Olares 版本,例如`1.10.0``1.10.0-20241109`。 | 否 | 无 |
## `viable` 专属选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--base` | `-b` | 要检查的基础版本。 | 否 | 当前 Olares 系统版本 |
:::warning 选项冲突
主命令使用`-b`作为`--base-dir`的简写。但在执行`upgrade viable`时,`-b`指代的是`--base`
:::
## 使用示例
```bash
# 检查当前系统是否可以直接升级
sudo olares-cli upgrade viable
# 检查从指定基础版本开始是否可直接升级
sudo olares-cli upgrade viable --base 1.9.0
# 执行升级前检查
sudo olares-cli upgrade precheck
# 查看当前 CLI 对应的升级规格
sudo olares-cli upgrade spec
```

View File

@@ -1,8 +1,8 @@
# `user activate`
# `activate`
## 命令说明
`user activate`命令用于激活已有的 Olares 账户,你需要至少提供 Olares ID、登录密码和助记词短语才能完成激活。该命令通常需要使用管理员权限(`sudo`)执行。
`activate`命令用于激活已有的 Olares 账户,你需要至少提供 Olares ID、登录密码和助记词短语才能完成激活。
```bash
olares-cli user activate <Olares ID> [选项]
@@ -11,7 +11,7 @@ olares-cli user activate <Olares ID> [选项]
| 参数 | 描述 | 是否必需 |
|--|--|--|
| `<Olares ID>` | 指定待激活的 Olares 用户账户的唯一标识符。<br>格式类似电子邮件地址例如:`alice123@olares.com`| **是** |
| `<Olares ID>` | 指定待激活的 Olares 用户账户的唯一标识符。<br>格式类似电子邮件地址例如:`alice123@olares.com`| |
## 选项
@@ -24,19 +24,20 @@ olares-cli user activate <Olares ID> [选项]
| `--jws` | | 指定指定 FRP 的 JWSJSON Web Signature令牌。<br>仅当`--enable-tunnel`设置为`true`时使用。| 否 | 无 |
| `--language` | | 设置系统语言。| 否 | `en-US` |
| `--location` | | 设置系统时区位置。 | 否 | `Asia/Shanghai` |
| `--mnemonic` | | 指定用于激活的 12 词助记词短语。 | **是** | 无 |
| `--password` | `-p` | 指定待激活 Olares 账户的登录密码。 | **是** | 无 |
| `--mnemonic` | | 指定用于激活的 12 词助记词短语。 | | 无 |
| `--password` | `-p` | 指定待激活 Olares 账户的登录密码。 | | 无 |
| `--reset-password` | | 指定用于密码重置的新密码。<br>仅在执行密码重置时需要。| 否 | 无 |
| `--vault` | | 指定 Vault 服务的 URL。<br>例如:`https://example.com` | 否 | `http://127.0.0.1:30181` |
## 使用示例
```bash
# 激活 Olares 账户
sudo olares-cli user activate alice@olares.cn -p "HerPassWord" --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
olares-cli user activate alice123@olares.cn -p "HerPassWord" --mnemonic "apple banana cherry door eagle forest grape house island jacket kite lemon"
# 启用隧道模式激活 Olares 账户
sudo olares-cli user activate david@olares.cn -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.cn -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 账户
sudo olares-cli user activate carol@olares.cn -p "AnotherPassWord" --mnemonic "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu" --language "cn-ZH" --location "Asia/Shanghai"
olares-cli user activate carol789@olares.cn -p "AnotherPassWord" --mnemonic "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu" --language "cn-ZH" --location "Asia/Shanghai"
```

View File

@@ -0,0 +1,46 @@
# `create`
## 命令说明
`create`子命令用于在 Olares 中创建一个新的用户。管理员可以在创建时设置用户名、初始密码、角色权限以及资源限制等初始配置。
**别名**`create``add``new`
```bash
olares-cli user create <用户名> [选项]
```
## 参数
| 参数 | 说明 | 是否必需|
|--|--|--|
| `<用户名>` | 指定新用户的用户名。通常为 Olares ID 中`@`符号之前的部分。<br>例如`alice123@olares.com`中的`alice123`。| 是 |
## 选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--cpu-limit` | `-c` | 设置用户环境的 CPU 限制。 | 否 | `1` |
| `--description` | | 为用户账号添加描述信息。 | 否 | 无 |
| `--display-name` | | 设置用户的显示名称。 | 否 | 无 |
| `--domain` | | 指定 Olares ID 使用的域名。 | 否 | 系统默认域名 |
| `--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--kubeconfig` | | 指定 kubeconfig 文件路径。 | 否 | 无 |
| `--memory-limit` | `-m` | 设置用户环境的内存限制。 | 否 | `3G` |
| `--password` | `-p` | 设置用户的初始登录密码。 | 否 | 无 |
| `--role` | `-r` | 设置用户角色。<br>可选值:`owner``admin``normal`。 | 否 | `normal` |
## 使用示例
```bash
# 使用默认设置创建用户
olares-cli user create alice123
# 创建用户并指定密码和角色
olares-cli user create blake123 -p "StrongPassword123" -r admin
# 创建用户并设置资源限制2 个 CPU 核心4 GB 内存)
olares-cli user create carol123 --cpu-limit 2 --memory-limit 4G
# 创建用户并设置显示名称和描述
olares-cli user create david123 --display-name "David Smith" --description "Data platform administrator"
```

View File

@@ -0,0 +1,30 @@
# `delete`
## 命令说明
`delete`子命令用于从 Olares 系统中永久删除一个已有的用户账号。
**别名**`delete``d``del``rm``remove`
```bash
olares-cli user delete <用户名> [选项]
```
## 参数
| 参数 | 说明 | 是否必需|
|--|--|--|
| `<用户名>` | 指定要删除的用户名。通常为 Olares ID 中`@`符号之前的部分。<br>例如 `alice123@olares.com`中的`alice123`。| 是 |
## 选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--kubeconfig` | | 指定 kubeconfig 文件路径。 | 否 | 无 |
## 使用示例
```bash
# 删除名为 alice123 的用户
olares-cli user delete alice123
```

View File

@@ -0,0 +1,33 @@
# `get`
## 命令说明
`get`子命令用于获取 Olares 指定用户的详细信息。输出结果以表格或 JSON 格式显示。
```bash
olares-cli user get <用户名> [选项]
```
## 参数
| 参数 | 说明 | 是否必需|
|--|--|--|
| `<用户名>` | 指定要查询的用户名。通常为 Olares ID 中`@`符号之前的部分。<br>例如 `alice123@olares.com`中的`alice123`。| 是 |
## 选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--kubeconfig` | | 指定 kubeconfig 文件路径。 | 否 | 无 |
| `--no-headers` | | 输出结果不显示表头。 | 否 | 无 |
| `--output` | `-o` | 指定输出格式。<br>可选值:`table``json`。 | 否 | `table` |
## 使用示例
```bash
# 以默认表格格式查看用户 alice123 的信息
olares-cli user get alice123
# 以 JSON 格式查看用户 blake123 的信息
olares-cli user get blake123 -o json
```

View File

@@ -0,0 +1,34 @@
# `list`
## 命令说明
`list`子命令用于显示 Olares 系统中所有注册用户列表。你可以根据需要筛选用户并排序,以表格或 JSON 格式显示结果。
**别名**`list``ls``l`
```bash
olares-cli user list [选项]
```
## 选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
| `--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--kubeconfig` | | 指定 kubeconfig 文件路径。 | 否 | 无 |
| `--no-headers` | | 输出结果不显示表头。 | 否 | 无 |
| `--output` | `-o`| 指定输出格式。<br>可选值:`table``json`。| 否 | `table` |
| `--reverse` | `-r` | 倒序排列输出结果。 | 否 | 无 |
| `--sort` | | 按指定字段对结果进行排序。<br>可选值:`name``role``create-time``memory``cpu`。 | 否 | 无 |
## 使用示例
```bash
# 以表格格式列出所有用户
olares-cli user list
# 以 JSON 格式列出所有用户
olares-cli user list -o json
# 按角色排序列出用户
olares-cli user list --sort role
```

View File

@@ -0,0 +1,29 @@
# `reset-password`
## 命令说明
`reset-password`子命令用于通过认证服务强制重置指定用户的登录密码。
```bash
olares-cli user reset-password <用户名> [选项]
```
## 参数
| 参数 | 说明 | 是否必需 |
|--|--|--|
| `<用户名>` | 指定要重置密码的用户名。通常为 Olares ID 中`@`符号之前的<br>部分。例如`alice123@olares.com`中的`alice123`。| 是 |
## 选项
| 选项 | 简写 | 用途 | 是否必需 | 默认值 |
|--|--|--|--|--|
`--help` | `-h` | 显示帮助信息。 | 否 | 无 |
| `--kubeconfig` | | 指定 kubeconfig 文件路径。 | 否 | 无 |
| `--password` | `-p` | 指定为该用户设置的新密码。 | 是 | 无 |
## 使用示例
```bash
# 重置用户 alice123 的密码
olares-cli user reset-password alice123 -p "NewSecurePassword456!"
```

View File

@@ -0,0 +1,13 @@
# `user`
`user`命令提供了一组用户管理工具,可用于创建、激活、查询和删除 Olares 用户,并支持通过已配置的认证提供方重置用户密码。
## 子命令
| 子命令 | 描述 |
|--|--|
| `activate` | 激活已有的 Olares 账户。 |
| `create` | 创建新用户。 |
| `delete` | 删除已有用户。 |
| `get` | 获取指定用户的详细信息。 |
| `list` | 列出 Olares 中的所有用户。 |
| `reset-password` | 通过认证提供方强制重置指定用户的密码。|

View File

@@ -36,15 +36,7 @@ export FRP_ENABLE=1 \
JUICEFS=0 \
FRP_AUTH_METHOD="jws" \
REGISTRY_MIRRORS="https://mirrors.olares.cn" \
DOWNLOAD_CDN_URL="https://cdn.olares.cn" \
MARKET_PROVIDER="appstore-china-server-prod.api.jointerminus.cn" \
TERMINUS_CERT_SERVICE_API="https://terminus-cert.api.jointerminus.cn" \
TERMINUS_DNS_SERVICE_API="https://terminus-dnsop.api.jointerminus.cn" \
DID_GATE_URL="https://did-gate-v3.api.jointerminus.cn/" \
OLARES_SPACE_URL="https://cloud-api.api.jointerminus.cn/" \
FIREBASE_PUSH_URL="https://firebase-push-test.api.jointerminus.cn/v1/api/push" \
FRP_LIST_URL="https://terminus-frp.api.jointerminus.cn/" \
TAILSCALE_CONTROLPLANE_URL="https://controlplane.api.jointerminus.cn"
DOWNLOAD_CDN_URL="https://cdn.olares.cn"
curl -sSfL https://olares.sh | bash
```
@@ -60,20 +52,6 @@ curl -sSfL https://olares.sh | bash
- `1`(启用)
- **默认值**`0`(禁用)
### `DID_GATE_URL`
指定 DID 网关服务的地址。
- **可选值**
- `https://did-gate-v3.bttcdn.com`
- `https://did-gate-v3.api.jointerminus.cn/`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://did-gate-v3.bttcdn.com/`
### `FIREBASE_PUSH_URL`
指定 Firebase 推送服务的地址。
- **可选值**
- `https://firebase-push-test.bttcdn.com/v1/api/push`
- `https://firebase-push-test.api.jointerminus.cn/v1/api/push`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://firebase-push-test.bttcdn.com/v1/api/push`
### `FRP_AUTH_METHOD`
设置 FRP 的认证方式。
- **可选值**
@@ -94,13 +72,6 @@ curl -sSfL https://olares.sh | bash
- `1`(启用)
- **默认值**`0`(禁用)
### `FRP_LIST_URL`
指定 Olares FRP 信息服务的地址。
- **可选值**
- `https://terminus-frp.snowinning.com`
- `https://terminus-frp.api.jointerminus.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://terminus-frp.snowinning.com`
### `FRP_PORT`
设置 FRP 服务端监听端口。
- **可选值**:整数范围 `165535`
@@ -132,13 +103,6 @@ curl -sSfL https://olares.sh | bash
- `1`(启用)
- **默认值**`0`(禁用)
### `MARKET_PROVIDER`
指定应用市场Market后端服务所使用的域名可根据网络环境选择合适的域名以优化访问速度。
- **可选值**
- `appstore-server-prod.bttcdn.com`
- `appstore-china-server-prod.api.jointerminus.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`appstore-server-prod.bttcdn.com`
### `NVIDIA_CONTAINER_REPO_MIRROR`
配置 `nvidia-container-toolkit` 的 APT 安装镜像源。
- **可选值**
@@ -146,13 +110,6 @@ curl -sSfL https://olares.sh | bash
- `mirrors.ustc.edu.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`nvidia.github.io`
### `OLARES_SPACE_URL`
指定 Olares Space 服务的地址。
- **可选值**
- `https://cloud-api.bttcdn.com/`
- `https://cloud-api.api.jointerminus.cn/`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://cloud-api.bttcdn.com/`
### `PREINSTALL`
仅执行预安装阶段(系统依赖配置),不进行完整的 Olares 安装。
- **可选值**`1`
@@ -170,27 +127,6 @@ curl -sSfL https://olares.sh | bash
- **可选值**`https://mirrors.olares.cn` 或其他镜像源地址
- **默认值**`https://registry-1.docker.io`
### `TAILSCALE_CONTROLPLANE_URL`
指定 Olares Tailscale 控制平面control-plane服务的地址。
- **可选值**
- `https://controlplane.snowinning.com`
- `https://controlplane.api.jointerminus.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://controlplane.snowinning.com`
### `TERMINUS_CERT_SERVICE_API`
指定 Olares HTTPS 证书服务的地址。
- **可选值**
- `https://terminus-cert.snowinning.com`
- `https://terminus-cert.api.jointerminus.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://terminus-cert.snowinning.com`
### `TERMINUS_DNS_SERVICE_API`
指定 Olares DNS 服务的地址。
- **可选值**
- `https://terminus-dnsop.snowinning.com`
- `https://terminus-dnsop.api.jointerminus.cn`(推荐中国大陆用户使用,连接性更好)
- **默认值**`https://terminus-dnsop.snowinning.com`
### `TERMINUS_IS_CLOUD_VERSION`
明确将此机器标记为云端实例cloud instance
- **可选值**`true`

View File

@@ -1,105 +1,2 @@
---
description: 获取关于 Olares 的常见问题解答。
---
# 常见问题
## Olares 采用了什么协议?
Olares 由一系列项目组成,采用了分层授权的方式,基本原则是:
- 区块链上运行的项目,采用 Apache 2.0,例如 [Snowinning Protocol](https://github.com/beclab/olaresdid-contract-system)。
- 协议相关的项目,采用 Apache 2.0,例如 [r4](https://github.com/beclab/r4)。
- Olares 和 LarePass 相关的项目,采用 Olares License。
- 在 Olares 上运行的第三方应用,由开发者自己决定开源与否与协议选择。
- 每个项目具体的情况,可以在 [GitHub](https://github.com/beclab) 上查询。
## Olares 许可证是开源许可证吗?
Olares 主要项目的许可证选择受到了 [fair code](https://faircode.io/) 的启发。[Olares 许可证](https://github.com/beclab/Olares/blob/main/LICENSE.md)同样遵循以下原则:
> - 可供任何人免费使用和分发
> - 源代码公开可见
> - 任何人都可以在公共和私有社区中进行扩展
> - 作者对商业使用有所限制
## 如果助记词丢失了为什么不能恢复账号?
从 1Password 的主密钥到加密钱包的助记词,十多年来助记词存储这个问题一直没有很好的解决方案。
Olares 的助记词会被加密存储在所有安装了 LarePass 的设备上。通常情况下,只有当所有安装了 LarePass 的设备同时丢失时,才会失去助记词。
安全性是我们系统设计中最重要的原则。我们会在未来继续改进,为大家提供一个在便利性和安全性之间更好平衡的解决方案。
## Olares 和目前运行在 NAS 上的操作系统有什么区别?
在 Olares前身是 Terminus诞生之初市面上已经有很优秀的 NAS 操作系统,如 [Synology](https://www.synology.com/en-global/dsm/packages)、[CasaOS](https://github.com/IceWhaleTech/CasaOS) 和 [Umbrel](https://github.com/getumbrel/umbrel)。它们确实给了我们很多启发。
但我们认为运行在边缘端的操作系统应该能够:
- 为多个硬件编排资源
- 在沙箱中管理应用
这些功能很难通过上述基于 Docker Compose 构建的 NAS 操作系统实现。
同时Olares 致力于提供一站式自托管解决方案,这已经超出了普通 NAS 操作系统的范畴。
## 使用 Olares 需要付费吗?
在自托管场景下,基本上可以免费使用 Olares。
但对于以下两个功能,由于成本因素,我们可能会引入合理的收费(目前都是免费提供):
- **备份**
我们为每个 Olares ID 在 Olares Space 上提供 10G 的免费备份空间。当存档大小超过这个限制时,我们会收取一定费用来支付云服务商的费用。
- **快速反向代理FRP**
通过本地访问 Olares 或使用 Olares VPN 基本是免费的。然而,如果你通过 Olares 提供外部服务(例如博客),流量会先转发到 FRP 服务器再到达 Olares。此种情况下
- 如果你使用自己的 FRP 服务Olares 不会收取任何费用。
- 如果你选择使用 Olares 默认的 FRP 服务,我们每月提供 2GB 的免费流量额度。对于不通过 Olares 提供外部服务的用户,这些流量通常是足够的。如果使用超出此限额,可能会产生额外费用。
## 什么时候支持其他语言?
目前我们只支持英语和简体中文。
实际上,我们已经在所有前端项目中完成了 i18n 的替换工作。但我们缺乏通过开源社区维护快速迭代项目的翻译资源的经验,这方面我们还在学习中。
## 各种“密码”之间有什么区别?
为了保证安全性Olares 确实有多种密码,包括:
- 私钥
- LarePass 的密码:
- 手机上可以使用生物识别登录
- 电脑和浏览器插件需要手动输入
- Olares 首次激活使用的一次性密码
- Olares 的登录密码
- Olares 登录时的二次验证码
不用慌!日常使用时,需要输入的只是登录 Olares 时的二次验证码。
## 如何部署多用户应用?
这取决于是要对外提供服务,还是仅供内部 Olares 用户使用。
- 如果要对外提供服务,可以选择“**公开**”作为应用的访问入口。这样应用就可以自行管理用户注册和认证。
- 如果只提供内部访问,可以在 Olares 上部署这类产品的集群版本。
对于 Gitlab我们提供了两个移植版本[Gitlab Pure](https://github.com/beclab/apps/tree/main/gitlabpure) 和 [Gitlab Fusion](https://github.com/RLovelett/gitlab-fusion)。
## 如何使用相同的 Olares ID 重新激活 Olares?
如果你在同一台设备上重新安装了 Olares你之前激活的 Olares 实例将无法再访问。你可以使用同一个 Olares ID 重新激活 Olares
:::tip 使用相同的 Olares ID 安装
请确保在安装过程中输入了与之前完全相同的域名和 Olares ID。
:::
![重新激活](/images/zh/manual/help/reactivate.png)
1. 在手机上打开 LarePass 并进入之前的账户。你应该会在顶部看到一个红色状态提示:“未发现运行中的 Olares”。
2. 点击**了解更多**>**重新激活**,进入二维码扫描界面。
3. 点击**扫描二维码**来扫描向导页面上的二维码并激活 Olares。
# FAQs
This section summarizes frequently asked questions about Olares.

View File

@@ -1,3 +1,3 @@
# Help and support
# 帮助与支持
Text

View File

@@ -0,0 +1,79 @@
---
outline: [2, 3]
description: 查找有关 Olares 安装与激活过程中的常见问题解答。
---
# Olares 安装与激活常见问题
本文汇总了关于在硬件上安装、配置及激活 Olares 的常见问题。
## 安装
### Olares 支持哪些平台?
为了获得最佳性能,建议在 Linux (Ubuntu 或 Debian) 上安装 Olares。
若仅用于产品体验,也可以在以下平台安装:
* Proxmox VE
* Raspberry Pi
* macOS
* Windows
### 安装 Olares 的最低硬件要求是什么?
具体要求因平台而异。通常建议配置如下:
* **CPU**:至少 4 核x86-64 架构 (Intel 或 AMD)。
* **内存**:至少 8 GB 可用内存。
* **存储**:至少 150 GB SSD。
详细要求参见[安装文档](../get-started/install-olares.md)。
### 可以使用机械硬盘安装 Olares 吗?
不可以。必须使用 SSD。由于机械硬盘读写速度较慢极易导致系统初始化超时从而造成安装失败。
### 系统支持 NVIDIA 显卡吗?
支持。Olares 针对 NVIDIA 硬件进行了深度优化。系统会自动处理驱动安装,让你即刻获得 AI 和游戏性能加速。
系统还支持单主板多 GPU 配置 (目前仅限 NVIDIA),允许自定义硬件用户利用所有可用算力处理 AI 负载。
### 如果自动设置失败,如何手动安装 NVIDIA 驱动?
Olares 安装程序通常会自动检测并安装驱动。但如果系统中此前已安装过 NVIDIA 驱动,可能会因冲突导致安装过程跳过或失败。
此时,按以下步骤操作:
1. Olares 安装完成后重启机器,确保旧的驱动组件被完全清理。
2. 使用命令 `olares-cli gpu install` 手动触发驱动安装。
安装完成后,运行 `nvidia-smi` 确认驱动已安装且 GPU 被正确识别。
### 为什么安装时报错 `failed to build Kubernetes objects` 或 `Ensure CRDs are installed first`
虽然报错信息指向 Custom Resource Definitions (CRD) 问题,但这通常是磁盘性能不足的表现。
Olares 依赖 Kubernetes 的后端数据库 etcd。etcd 对存储速度非常敏感。如果在传统 HDD 等低速硬盘上安装etcd 无法及时响应,从而导致 API Server 在尝试应用 CRD 时超时。
更换为 SSD 存储通常能解决此问题。
### Olares 安装超时未显示密码,但系统似乎在运行。如何找回密码?
这通常是由于系统资源不足导致安装超时,特别是在虚拟机环境中。你可以通过以下命令从安装日志中获取密码:
```bash
# 将 v1.12.2 替换为你的具体 Olares 版本号
grep password $HOME/.olares/versions/v1.12.2/logs/install.log
```
安装超时通常意味着部分服务启动失败。找回密码后,运行 `kubectl get pod -A` 检查所有服务的状态。
## 激活
### 可以在非局域网环境下激活 Olares 吗?
可以。通常情况下,用户通过局域网 IP 访问激活向导,这要求双方在同一网络下。但如果 Olares 被分配了公网 IP (如在公有云上),则不受此局域网限制。
注意IP 访问仅用于激活过程。激活完成后,无论在内网还是外网,均通过域名访问设备。
### Olares 已开机并连接局域网,但 LarePass 搜不到设备。怎么办?
确保手机和 Olares 设备处于同一网络。如果不在同一网络LarePass 无法自动发现 Olares。
如果无法通过 Wi-Fi 连接,你可以利用 LarePass 应用中的蓝牙配网功能,将 Olares 连接到与手机相同的网络中。
详见[使用蓝牙激活 Olares](../larepass/activate-olares.md#通过蓝牙激活)。

View File

@@ -0,0 +1,125 @@
---
outline: [2, 3]
description: 查找关于 Olares 平台的常见问题解答。
---
# Olares 常见问题
本文汇总了关于 Olares 的常见问题。
## 基础介绍
### 什么是 Olares
Olares 是一款基于 Kubernetes 构建的开源个人云操作系统。它致力于帮助用户在本地私有环境中,实现对数字资产的完全掌控与管理。
系统原生集成了资源编排、应用沙箱以及面向边缘计算的企业级基础设施。Olares 的目标是打造一站式的个人云方案,让你能够运行大语言模型、自动化工作流等高性能应用,从而在本地替代公有云服务。无论是搭建个人媒体服务器、进行 AI 开发还是管理去中心化身份Olares 都能提供强有力的支持。
### 什么是"个人云"
个人云是一种私有化的基础设施。它既具备公有云的便利性,例如随时随地访问文件和算力,又完全运行在你自己的硬件设备上,从而确保数据主权。
### Olares 适合谁?
Olares 旨在降低本地 AI 工具的使用门槛,适合不希望折腾复杂技术配置的用户。
* **普通用户**:可以在应用市场中一键部署 ComfyUI、Perplexica 等复杂的应用程序。
* **开发者**Olares 是一个高效的本地开发环境。你可以利用内置的沙箱和 Agent infra直接在设备上构建和测试应用省去繁琐的环境配置时间。
### Olares 与 NAS 操作系统有何不同?
Olares 的定位是个人 AI 云,而非单纯的存储服务器。传统的 NAS 系统如 Synology DSM 或 CasaOS 主要针对文件存储和轻量级容器托管进行了优化。
Olares 的核心差异在于对高性能计算的支持:
* **资源编排**:原生调度 GPU 等硬件资源,以此驱动本地 AI 任务。
* **沙箱机制**:实施严格的应用隔离策略,提供比标准文件服务器更高级别的安全防护。
详细对比参见 [Olares 与 NAS 的对比](../olares-vs-nas.md)。
### 为什么需要 Olares ID
Olares ID 是目前实现自动化安全远程访问的关键。系统通过它为你自动配置反向代理、注册子域名并管理 HTTPS 证书。如果没有 Olares ID你需要手动处理端口映射、DNS 解析等复杂的网络设置,才能实现外网访问。
与中心化云账户不同Olares ID 完全归你所有。我们无法获知你的凭证信息,如果你丢失了助记词,我们也无法协助恢复数据。
为了提供更多灵活性,我们计划在 3 月的更新中推出新的激活选项:如果你倾向于自行配置网络,可以将 Olares ID 设为非必选项。
### 可以在离线或断网环境下使用 Olares 吗?
可以。虽然目前的首次激活需要联网,但我们支持"本地优先"的运行模式。
针对有严格本地控制需求的用户,我们提供以下方案:
* **仅 VPN 模式**:限制设备仅允许通过 VPN 进行远程访问。
* **仅本地访问**:即使路由器断网,也可以通过 `.local` 域名在局域网内访问服务。
详细配置参见[在本地访问 Olares 服务](../get-started/local-access.md)。
我们正在开发完全离线环境下的设备激活功能。
### 什么是 LarePass为什么要用它
LarePass 是 Olares 的官方客户端,充当连接设备的安全桥梁。它内置 VPN 功能,可实现无缝远程访问和跨设备文件同步。目前,设备激活流程必须通过 LarePass 完成。
### 可以不使用 LarePass 应用吗?
我们理解这是高级用户的核心诉求,因此正在推进功能解耦:
* **CLI 激活**:计划将激活逻辑集成到 `olares-cli` 中,支持纯终端环境下的设置,不再依赖 App。
* **组件独立化**未来将支持独立部署反向代理、DID 服务和应用市场仓库等核心组件。
### 可以使用自定义域名吗?
可以。你可以使用自己的域名来替代默认的 `olares.com` 域名。注意,目前的自定义域名配置仍需通过 LarePass 应用进行。
详情参见[为 Olares 设置自定义域名](../best-practices/set-custom-domain.md)。
### 使用 Olares 需要付费吗?
Olares 操作系统本身完全开源免费,可供自托管使用。购买 Olares One 仅涉及一次性的硬件费用。
为了提升体验,我们提供两项可选的云辅助服务(均有免费替代方案,确保避免厂商锁定):
* **云备份**:可订阅 Olares Space 进行集成备份。免费方案是将数据备份到本地外部存储或兼容 S3 协议的服务中。
* **远程访问 (FRP)**:内置 FRP 服务提供每月 2 GB 免费流量,超出部分可选付费。免费方案是通过 LarePass VPN 访问,或自行搭建 FRP 服务器。
### Olares 的更新频率如何?
我们的目标是每两个月发布一个主要版本。具体变动参见[变更日志](https://www.olares.com/changelog)。
## 许可协议
### Olares 是开源的吗?
是的。Olares OS 软件坚持开源,以确保透明度并促进社区协作。项目代码库采用了以下许可模式:
* **Olares 和 LarePass**:采用 AGPL-3.0 许可。欢迎访问我们的 [GitHub 组织](https://github.com/beclab)。
* **协议项目**:如 Olares ID 智能合约系统,采用 Apache 2.0 许可。
* **第三方应用**:由开发者自行选择许可证。
### 可以从源码构建 Olares 吗?
可以,但目前的流程较为繁琐。
Olares 是一个包含 90 多个代码库的庞大项目。由于架构迭代迅速,我们目前尚未提供"一键式"的本地构建系统。
我们正在积极优化构建流程和文档。预计在 2026 年,我们将完善本地构建体验,并发布反向代理等核心服务的独立部署指南。我们的策略是先夯实基础,再逐步开放更广泛的社区协作。
## 安全与隐私
### Olares 会收集我的数据吗?
不会。Olares 的初衷就是帮你重掌数据主权。所有的存储、计算和 AI 处理均在你的本地硬件上完成。系统不会收集你的私有数据,也不会将其传输至任何中心化服务器。
### Olares 支持备份吗?
支持。数据安全完全由你掌控。Olares 内置了[备份功能](../olares/settings/backup.md),支持指定文件目录备份并设置自动计划。
关键在于,每个备份文件都经过端到端加密处理。这意味着你可以放心地将备份存放在外部硬盘或第三方云盘上,无需担心数据被他人读取。
### 什么是应用沙箱?
沙箱是一种安全隔离机制,用于防止单个应用的故障或恶意行为波及整个系统。在 Olares 中,每个应用都在独立、安全的环境中运行。即便某个应用崩溃,其影响范围也会被严格限制,无法访问或破坏其他应用及个人数据。
### 系统支持多用户环境吗?
支持。Olares 内置了完善的子账户体系,包含超级管理员、管理员和普通成员等角色权限。
这一机制非常适合团队协作。例如,你可以让团队成员访问同一台 Olares 服务器,共享文件资源或共用一个大型 AI 模型。

View File

@@ -0,0 +1,47 @@
---
outline: [2, 3]
description: 查找关于 Olares 使用及社区应用的常见问题解答。
---
# 使用常见问题
本文汇总了关于 Olares 日常使用、应用及系统管理的常见问题。
## 应用
### Olares 支持运行哪些应用?
[Olares 应用市场](https://market.olares.com/)提供了 Ollama、ComfyUI 和 Open WebUI 等热门开源应用。
如果你有 Docker 使用经验,也可以在测试环境中[手动部署](../../developer/develop/tutorial/index.md)应用市场未收录的应用。
### 我可以在 Olares 设备上玩游戏吗?
可以。通过 Steam Headless 应用,你可以将 Olares 设备转变为游戏服务器。
* [**串流**](../../use-cases/stream-game.md):你可以在 Olares 上本地运行游戏,并将其画面串流到手机或平板等设备上。
* [**直接游玩**](../../use-cases/play-games-directly.md):你可以将显示器、键盘和鼠标直接连接到 Olares 设备,无需串流即可游玩。
### 如何在 Olares 中使用 Windows 环境?
你可以从应用市场运行 Windows 虚拟机,并使用任意标准 RDP 客户端进行连接。
### 可以在 Olares 上开发应用吗?
可以。安装 [Studio](../../developer/develop/tutorial/index.md) 后,你既可以直接在浏览器中编写代码,也可以将本地 VS Code 连接到设备。这能提供与本地机器相似的开发体验,同时利用服务器硬件更强大的算力。
## 存储
### 如果在运行中的 Olares 机器上添加新硬盘,系统会自动使用吗?
这取决于硬盘类型:
* **USB 驱动器**:是的,系统会自动挂载,并立即显示在文件管理器中。
* **内置硬盘**:不会。内置 HDD 或 SSD 不会自动加入存储池,你需要手动配置。
* **SMB 共享**:网络存储可以通过文件管理器中的**外部设备** > **连接服务器**进行添加。
详细步骤参见[扩展 Olares 存储](../best-practices/expand-storage-in-olares.md)。
## 多节点集群
### 如何向集群添加更多机器?
默认情况下Olares 安装为单节点集群。不过,你可以将 Olares 安装为 Master 节点,然后添加 Worker 节点,从而构建可扩展的多节点集群。
注意,多节点目前为实验性功能,仅支持 Linux 系统。详细步骤参见[安装 Olares 多节点集群](../best-practices/install-olares-multi-node.md)。

View File

@@ -30,7 +30,7 @@ Olares 通过 **Olares ID** 与 **LarePass 移动应用**提供安全且流畅
<!--@include: ../get-started/install-and-activate-olares.md{9,23}-->
### 通过蓝牙激活
## 通过蓝牙激活
如果 LarePass 找不到你的 Olares 设备,可以使用蓝牙激活。这通常发生在 Olares 没有连接有线网络,或者你的手机和 Olares 处于不同网络的情况下。
通过蓝牙,你可以将 Olares 直接连接到你手机当前的 Wi-Fi 网络,以便继续操作。

View File

@@ -170,8 +170,16 @@ spec:
priorityClassName: "system-cluster-critical"
containers:
- name: app-service
image: beclab/app-service:0.4.73
image: beclab/app-service:0.4.75
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6755
readinessProbe:
failureThreshold: 5
initialDelaySeconds: 10
periodSeconds: 5
tcpSocket:
port: 6755
securityContext:
runAsUser: 0
env:

View File

@@ -138,10 +138,16 @@ func main() {
setupLog.Error(err, "Unable to create controller", "controller", "Security")
os.Exit(1)
}
appEventQueue := appevent.NewAppEventQueue(ictx)
appEventQueue := appevent.NewAppEventQueue(ictx, nil)
appevent.SetAppEventQueue(appEventQueue)
go appEventQueue.Run()
defer func() {
if nc := appEventQueue.GetNatsConn(); nc != nil {
nc.Drain()
}
}()
if err = (&controllers.ApplicationManagerController{
Client: mgr.GetClient(),
KubeConfig: config,
@@ -198,6 +204,7 @@ func main() {
if err = (&controllers.NodeAlertController{
Client: mgr.GetClient(),
KubeConfig: config,
NatsConn: nil,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "Unable to create controller", "controller", "NodeAlert")
os.Exit(1)

View File

@@ -6,13 +6,13 @@ import (
"strconv"
"time"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
appv1alpha1 "github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
sysv1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
coordinationv1 "k8s.io/api/coordination/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -218,20 +218,10 @@ func (r *AppEnvController) triggerApplyEnv(ctx context.Context, appEnv *sysv1alp
UpdateTime: &now,
}
am, err := apputils.UpdateAppMgrStatus(targetAppMgr.Name, status)
_, err = apputils.UpdateAppMgrStatus(targetAppMgr.Name, status)
if err != nil {
return fmt.Errorf("failed to update ApplicationManager Status: %v", err)
}
utils.PublishAppEvent(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(am.Status.OpType),
OpID: opID,
State: appv1alpha1.ApplyingEnv.String(),
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
})
klog.Infof("Successfully triggered ApplyEnv for app: %s owner: %s", appEnv.AppName, appEnv.AppOwner)
return nil

View File

@@ -7,7 +7,10 @@ import (
appv1alpha1 "github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
appevent "github.com/beclab/Olares/framework/app-service/pkg/event"
"github.com/beclab/Olares/framework/app-service/pkg/images"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/rest"
@@ -167,6 +170,11 @@ func (r *ApplicationManagerController) preEnqueueCheckForUpdate(old, new client.
if curAppMgr.Spec.Type != appv1alpha1.App && curAppMgr.Spec.Type != appv1alpha1.Middleware {
return false
}
if oldAppMgr.Status.State != curAppMgr.Status.State {
r.publishStateChangeEvent(curAppMgr)
}
if curAppMgr.Status.OpGeneration <= oldAppMgr.Status.OpGeneration {
return false
}
@@ -174,6 +182,22 @@ func (r *ApplicationManagerController) preEnqueueCheckForUpdate(old, new client.
return true
}
func (r *ApplicationManagerController) publishStateChangeEvent(am *appv1alpha1.ApplicationManager) {
appevent.PublishAppEventToQueue(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(am.Status.OpType),
OpID: am.Status.OpID,
State: am.Status.State.String(),
Progress: am.Status.Progress,
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
Reason: am.Status.Reason,
Message: am.Status.Message,
})
}
func (r *ApplicationManagerController) loadStatefulAppAndReconcile(ctx context.Context, name string) (appstate.StatefulApp, error) {
statefulApp, err := LoadStatefulApp(ctx, r, name)
if err != nil {

View File

@@ -8,6 +8,7 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/utils"
"github.com/nats-io/nats.go"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
@@ -54,6 +55,8 @@ type NodeAlertController struct {
// lastPressureState tracks the last known pressure state for each node and pressure type
lastPressureState map[string]bool
mutex sync.RWMutex
NatsConn *nats.Conn
natsConnMux sync.Mutex
}
// SetupWithManager sets up the controller with the Manager.
@@ -245,5 +248,31 @@ func (r *NodeAlertController) sendNodeAlert(nodeName string, pressureType NodePr
// publishToNats publishes a message to the specified NATS subject
func (r *NodeAlertController) publishToNats(subject string, data interface{}) error {
return utils.PublishToNats(subject, data)
if err := r.ensureNatsConnected(); err != nil {
return fmt.Errorf("failed to ensure NATS connection: %w", err)
}
return utils.PublishEvent(r.NatsConn, subject, data)
}
func (r *NodeAlertController) ensureNatsConnected() error {
r.natsConnMux.Lock()
defer r.natsConnMux.Unlock()
if r.NatsConn != nil && r.NatsConn.IsConnected() {
return nil
}
if r.NatsConn != nil {
r.NatsConn.Close()
}
klog.Info("NATS connection not established in NodeAlertController, attempting to connect...")
nc, err := utils.NewNatsConn()
if err != nil {
klog.Errorf("NodeAlertController failed to connect to NATS: %v", err)
return err
}
r.NatsConn = nc
klog.Info("NodeAlertController successfully connected to NATS")
return nil
}

View File

@@ -9,7 +9,6 @@ import (
appv1alpha1 "github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
corev1 "k8s.io/api/core/v1"
@@ -236,20 +235,6 @@ func (r *PodAbnormalSuspendAppController) trySuspendApp(ctx context.Context, own
if _, err := apputils.UpdateAppMgrStatus(name, status); err != nil {
return false, err
}
utils.PublishAppEvent(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(status.OpType),
OpID: opID,
State: appv1alpha1.Stopping.String(),
Progress: message,
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
Reason: reason,
Message: message,
})
klog.Infof("suspend requested for app=%s owner=%s, reason=%s", am.Spec.AppName, am.Spec.AppOwner, message)
return true, nil
}

View File

@@ -8,6 +8,7 @@ import (
"strconv"
"time"
natsevent "github.com/beclab/Olares/framework/app-service/pkg/event"
"github.com/beclab/Olares/framework/app-service/pkg/users"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace/v1"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
@@ -165,7 +166,7 @@ func (r *UserController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
klog.Infof("update user failed %v", updateErr)
return ctrl.Result{}, updateErr
}
utils.PublishUserEvent("Delete", user.Name, user.Annotations[users.AnnotationUserDeleter])
r.publish("Delete", user.Name, user.Annotations[users.AnnotationUserDeleter])
}
return ctrl.Result{}, nil
}
@@ -299,11 +300,15 @@ func (r *UserController) handleUserCreation(ctx context.Context, user *iamv1alph
klog.Errorf("failed to update user status to Created %v", updateErr)
} else {
klog.Infof("publish user creation event.....")
utils.PublishUserEvent("Create", user.Name, user.Annotations[users.AnnotationUserCreator])
r.publish("Create", user.Name, user.Annotations[users.AnnotationUserCreator])
}
return ctrl.Result{}, updateErr
}
func (r *UserController) publish(topic, user, operator string) {
natsevent.PublishUserEventToQueue(topic, user, operator)
}
func (r *UserController) checkResource(user *iamv1alpha2.User) error {
metrics, _, err := apputils.GetClusterResource("")
if err != nil {

View File

@@ -9,7 +9,6 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/apiserver/api"
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/emicklei/go-restful/v3"
@@ -74,21 +73,11 @@ func (h *Handler) appApplyEnv(req *restful.Request, resp *restful.Response) {
UpdateTime: &now,
}
am, err := apputils.UpdateAppMgrStatus(appMgrName, status)
_, err = apputils.UpdateAppMgrStatus(appMgrName, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(am.Status.OpType),
OpID: opID,
State: appv1alpha1.ApplyingEnv.String(),
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
})
resp.WriteEntity(api.Response{Code: 200})
}

View File

@@ -9,8 +9,8 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/apiserver/api"
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/emicklei/go-restful/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@@ -82,21 +82,11 @@ func (h *Handler) cancel(req *restful.Request, resp *restful.Response) {
api.HandleError(resp, req, err)
return
}
a, err := apputils.UpdateAppMgrStatus(name, status)
_, err = apputils.UpdateAppMgrStatus(name, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: a.Spec.AppOwner,
Name: a.Spec.AppName,
OpType: string(a.Status.OpType),
OpID: opID,
State: cancelState.String(),
RawAppName: a.Spec.RawAppName,
Type: a.Spec.Type.String(),
Title: apputils.AppTitle(a.Spec.Config),
})
resp.WriteAsJson(api.InstallationResponse{
Response: api.Response{Code: 200},

View File

@@ -9,8 +9,6 @@ import (
"slices"
"strconv"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace"
"github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
sysv1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/apiserver/api"
@@ -19,6 +17,7 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/generated/clientset/versioned"
"github.com/beclab/Olares/framework/app-service/pkg/kubesphere"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/beclab/Olares/framework/app-service/pkg/utils/config"
@@ -611,23 +610,12 @@ func (h *installHandlerHelper) applyApplicationManager(marketSource string) (opI
UpdateTime: &now,
OpTime: &now,
}
a, err = apputils.UpdateAppMgrStatus(name, status)
_, err = apputils.UpdateAppMgrStatus(name, status)
if err != nil {
api.HandleError(h.resp, h.req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: a.Spec.AppOwner,
Name: a.Spec.AppName,
OpType: string(a.Status.OpType),
OpID: opID,
State: v1alpha1.Pending.String(),
RawAppName: a.Spec.RawAppName,
Type: a.Spec.Type.String(),
Title: apputils.AppTitle(a.Spec.Config),
})
return
}

View File

@@ -11,8 +11,8 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/appstate"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/emicklei/go-restful/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@@ -94,21 +94,11 @@ func (h *Handler) uninstall(req *restful.Request, resp *restful.Response) {
UpdateTime: &now,
}
a, err := apputils.UpdateAppMgrStatus(name, status)
_, err = apputils.UpdateAppMgrStatus(name, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: a.Spec.AppOwner,
Name: a.Spec.AppName,
OpType: string(a.Status.OpType),
OpID: opID,
State: v1alpha1.Uninstalling.String(),
RawAppName: a.Spec.RawAppName,
Type: a.Spec.Type.String(),
Title: apputils.AppTitle(a.Spec.Config),
})
resp.WriteEntity(api.InstallationResponse{
Response: api.Response{Code: 200},

View File

@@ -384,21 +384,11 @@ func (h *Handler) appUpgrade(req *restful.Request, resp *restful.Response) {
UpdateTime: &now,
}
am, err := apputils.UpdateAppMgrStatus(appMgrName, status)
_, err = apputils.UpdateAppMgrStatus(appMgrName, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(am.Status.OpType),
OpID: opID,
State: appv1alpha1.Upgrading.String(),
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
})
resp.WriteEntity(api.InstallationResponse{
Response: api.Response{Code: 200},

View File

@@ -150,7 +150,6 @@ func (h *Handler) installMiddleware(req *restful.Request, resp *restful.Response
if err != nil {
klog.Errorf("Failed to uninstall middleware err=%v", err)
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.InstallOp), opID, v1alpha1.InstallFailed.String(), "", nil, "")
}
}
}()
@@ -172,7 +171,6 @@ func (h *Handler) installMiddleware(req *restful.Request, resp *restful.Response
api.HandleError(resp, req, err)
return
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.InstallOp), opID, v1alpha1.Installing.String(), "", nil, "")
klog.Infof("Start to install middleware name=%v", middlewareConfig.MiddlewareName)
err = middlewareinstaller.Install(req.Request.Context(), h.kubeConfig, middlewareConfig)
@@ -226,7 +224,7 @@ func (h *Handler) installMiddleware(req *restful.Request, resp *restful.Response
klog.Infof("Failed to update status err=%v", err)
return
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.CancelOp), opID, v1alpha1.InstallingCanceled.String(), "", nil, "")
return
}
klog.Infof("ticker get middleware status")
@@ -245,8 +243,6 @@ func (h *Handler) installMiddleware(req *restful.Request, resp *restful.Response
e := apputils.UpdateStatus(a, opRecord.Status, &opRecord, opRecord.Message)
if e != nil {
klog.Error(e)
} else {
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.InstallOp), opID, opRecord.Status.String(), "", nil, "")
}
delete(middlewareManager, name)
return
@@ -309,7 +305,6 @@ func (h *Handler) uninstallMiddleware(req *restful.Request, resp *restful.Respon
api.HandleError(resp, req, err)
return
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.UninstallOp), opID, v1alpha1.Uninstalling.String(), "", nil, "")
now = metav1.Now()
opRecord := v1alpha1.OpRecord{
@@ -327,8 +322,6 @@ func (h *Handler) uninstallMiddleware(req *restful.Request, resp *restful.Respon
e := apputils.UpdateStatus(mgr, v1alpha1.UninstallFailed, &opRecord, opRecord.Message)
if e != nil {
klog.Errorf("Failed to update applicationmanager status in uninstall middleware name=%s err=%v", mgr.Name, e)
} else {
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.UninstallOp), opID, v1alpha1.UninstallFailed.String(), "", nil, "")
}
}
}()
@@ -344,7 +337,6 @@ func (h *Handler) uninstallMiddleware(req *restful.Request, resp *restful.Respon
api.HandleError(resp, req, err)
return
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.Uninstalled), opID, v1alpha1.Uninstalled.String(), "", nil, "")
resp.WriteEntity(api.InstallationResponse{
Response: api.Response{Code: 200},
@@ -390,7 +382,6 @@ func (h *Handler) cancelMiddleware(req *restful.Request, resp *restful.Response)
api.HandleError(resp, req, err)
return
}
utils.PublishMiddlewareEvent(owner, app, string(v1alpha1.CancelOp), opID, v1alpha1.InstallingCanceling.String(), "", nil, "")
resp.WriteAsJson(api.InstallationResponse{
Response: api.Response{Code: 200},

View File

@@ -19,7 +19,6 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/kubesphere"
"github.com/beclab/Olares/framework/app-service/pkg/provider"
"github.com/beclab/Olares/framework/app-service/pkg/tapr"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/emicklei/go-restful/v3"
@@ -264,22 +263,11 @@ func (h *Handler) setupAppEntranceDomain(req *restful.Request, resp *restful.Res
UpdateTime: &now,
}
am, err := apputils.UpdateAppMgrStatus(appMgr.Name, status)
_, err = apputils.UpdateAppMgrStatus(appMgr.Name, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: am.Spec.AppOwner,
Name: am.Spec.AppName,
OpType: string(am.Status.OpType),
OpID: opID,
State: v1alpha1.Upgrading.String(),
RawAppName: am.Spec.RawAppName,
Type: am.Spec.Type.String(),
Title: apputils.AppTitle(am.Spec.Config),
Message: fmt.Sprintf("app %s was upgrade via setup domain by user %s", am.Spec.AppName, am.Spec.AppOwner),
})
}
resp.WriteAsJson(appUpdated.Spec.Settings)
}

View File

@@ -8,8 +8,6 @@ import (
"strconv"
"time"
"k8s.io/klog/v2"
"github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/apiserver/api"
"github.com/beclab/Olares/framework/app-service/pkg/appcfg"
@@ -17,12 +15,12 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/kubesphere"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
"github.com/emicklei/go-restful/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
)
func (h *Handler) suspend(req *restful.Request, resp *restful.Response) {
@@ -77,23 +75,11 @@ func (h *Handler) suspend(req *restful.Request, resp *restful.Response) {
StatusTime: &now,
UpdateTime: &now,
}
a, err := apputils.UpdateAppMgrStatus(name, status)
_, err = apputils.UpdateAppMgrStatus(name, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: a.Spec.AppOwner,
Name: a.Spec.AppName,
OpType: string(a.Status.OpType),
OpID: opID,
State: v1alpha1.Stopping.String(),
RawAppName: a.Spec.RawAppName,
Type: a.Spec.Type.String(),
Title: apputils.AppTitle(a.Spec.Config),
Reason: constants.AppStopByUser,
Message: fmt.Sprintf("app %s was stop by user %s", a.Spec.AppName, a.Spec.AppOwner),
})
resp.WriteEntity(api.InstallationResponse{
Response: api.Response{Code: 200},
@@ -185,22 +171,11 @@ func (h *Handler) resume(req *restful.Request, resp *restful.Response) {
StatusTime: &now,
UpdateTime: &now,
}
a, err := apputils.UpdateAppMgrStatus(name, status)
_, err = apputils.UpdateAppMgrStatus(name, status)
if err != nil {
api.HandleError(resp, req, err)
return
}
utils.PublishAppEvent(utils.EventParams{
Owner: a.Spec.AppOwner,
Name: a.Spec.AppName,
OpType: string(a.Status.OpType),
OpID: opID,
State: v1alpha1.Resuming.String(),
RawAppName: a.Spec.RawAppName,
Type: a.Spec.Type.String(),
Title: apputils.AppTitle(a.Spec.Config),
Message: fmt.Sprintf("app %s was resume by user %s", a.Spec.AppName, a.Spec.AppOwner),
})
resp.WriteEntity(api.InstallationResponse{
Response: api.Response{Code: 200},

View File

@@ -15,7 +15,6 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/constants"
"github.com/beclab/Olares/framework/app-service/pkg/kubesphere"
"github.com/beclab/Olares/framework/app-service/pkg/provider"
"github.com/beclab/Olares/framework/app-service/pkg/users"
"github.com/beclab/Olares/framework/app-service/pkg/users/userspace"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
@@ -1088,14 +1087,13 @@ func (h *Handler) applicationManagerMutate(req *restful.Request, resp *restful.R
if !ok {
return
}
var pam *v1alpha1.ApplicationManager
var admissionReq, admissionResp admissionv1.AdmissionReview
proxyUUID := uuid.New()
if _, _, err := webhook.Deserializer.Decode(admissionRequestBody, nil, &admissionReq); err != nil {
klog.Errorf("Failed to decode admission request body err=%v", err)
admissionResp.Response = h.sidecarWebhook.AdmissionError("", err)
} else {
admissionResp.Response, pam = h.applicationManagerInject(req.Request.Context(), admissionReq.Request, proxyUUID)
admissionResp.Response, _ = h.applicationManagerInject(req.Request.Context(), admissionReq.Request, proxyUUID)
}
admissionResp.TypeMeta = admissionReq.TypeMeta
admissionResp.Kind = admissionReq.Kind
@@ -1109,18 +1107,6 @@ func (h *Handler) applicationManagerMutate(req *restful.Request, resp *restful.R
klog.Errorf("Failed to write response[application-manager inject] admin review in namespace=%s err=%v", requestForNamespace, err)
return
}
if pam != nil {
utils.PublishAppEvent(utils.EventParams{
Owner: pam.Spec.AppOwner,
Name: pam.Spec.AppName,
OpType: string(pam.Spec.OpType),
OpID: pam.Status.OpID,
State: pam.Status.State.String(),
RawAppName: pam.Spec.RawAppName,
Type: pam.Spec.Type.String(),
Title: apputils.AppTitle(pam.Spec.Config),
})
}
klog.Infof("Done[application-manager inject] with uuid=%s in namespace=%s", proxyUUID, requestForNamespace)
}

View File

@@ -130,15 +130,6 @@ func (p *InstallingApp) Exec(ctx context.Context) (StatefulInProgressApp, error)
return
} // end of err != nil
p.finally = func() {
klog.Infof("app %s install successfully, update app state to initializing", p.manager.Spec.AppName)
updateErr := p.updateStatus(context.TODO(), p.manager, appsv1.Initializing, nil, appsv1.Initializing.String(), "")
if updateErr != nil {
klog.Errorf("update status failed %v", updateErr)
return
}
}
if p.manager.Spec.Type == appsv1.Middleware {
ok, err := ops.WaitForLaunch()
if !ok {
@@ -165,6 +156,16 @@ func (p *InstallingApp) Exec(ctx context.Context) (StatefulInProgressApp, error)
return
}
}
} else {
p.finally = func() {
klog.Infof("app %s install successfully, update app state to initializing", p.manager.Spec.AppName)
updateErr := p.updateStatus(context.TODO(), p.manager, appsv1.Initializing, nil, appsv1.Initializing.String(), "")
if updateErr != nil {
klog.Errorf("update status failed %v", updateErr)
return
}
}
}
}()

View File

@@ -6,7 +6,6 @@ import (
appsv1 "github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
appevent "github.com/beclab/Olares/framework/app-service/pkg/event"
"github.com/beclab/Olares/framework/app-service/pkg/helm"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
@@ -100,17 +99,6 @@ func (p *PendingApp) Exec(ctx context.Context) (StatefulInProgressApp, error) {
klog.Error("update app manager status error, ", err, ", ", p.manager.Name)
return err
}
appevent.PublishAppEventToQueue(utils.EventParams{
Owner: p.manager.Spec.AppOwner,
Name: p.manager.Spec.AppName,
OpType: string(p.manager.Spec.OpType),
OpID: p.manager.Status.OpID,
State: appsv1.Downloading.String(),
RawAppName: p.manager.Spec.RawAppName,
Type: p.manager.Spec.Type.String(),
Title: apputils.AppTitle(p.manager.Spec.Config),
})
return nil
},
); err != nil {

View File

@@ -11,9 +11,7 @@ import (
"github.com/beclab/Olares/framework/app-service/pkg/appcfg"
"github.com/beclab/Olares/framework/app-service/pkg/appinstaller"
"github.com/beclab/Olares/framework/app-service/pkg/appinstaller/versioned"
appevent "github.com/beclab/Olares/framework/app-service/pkg/event"
"github.com/beclab/Olares/framework/app-service/pkg/middlewareinstaller"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils/app"
corev1 "k8s.io/api/core/v1"
@@ -82,19 +80,6 @@ func (b *baseStatefulApp) updateStatus(ctx context.Context, am *appsv1.Applicati
klog.Errorf("patch appmgr's %s status failed %v", am.Name, err)
return err
}
appevent.PublishAppEventToQueue(utils.EventParams{
Owner: b.manager.Spec.AppOwner,
Name: b.manager.Spec.AppName,
OpType: string(b.manager.Spec.OpType),
OpID: b.manager.Status.OpID,
State: state.String(),
RawAppName: b.manager.Spec.RawAppName,
Type: b.manager.Spec.Type.String(),
Title: apputils.AppTitle(b.manager.Spec.Config),
Reason: reason,
Message: message,
})
return nil
}

View File

@@ -3,10 +3,12 @@ package event
import (
"context"
"fmt"
"sync"
"time"
"github.com/beclab/Olares/framework/app-service/pkg/utils"
"github.com/nats-io/nats.go"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/workqueue"
@@ -16,8 +18,10 @@ import (
var AppEventQueue *QueuedEventController
type QueuedEventController struct {
wq workqueue.RateLimitingInterface
ctx context.Context
wq workqueue.RateLimitingInterface
ctx context.Context
nc *nats.Conn
ncMux sync.Mutex
}
type QueueEvent struct {
@@ -25,6 +29,17 @@ type QueueEvent struct {
Data interface{}
}
type UserEvent struct {
Topic string `json:"topic"`
Payload Payload `json:"payload"`
}
type Payload struct {
User string `json:"user"`
Operator string `json:"operator"`
Timestamp time.Time `json:"timestamp"`
}
func (qe *QueuedEventController) processNextWorkItem() bool {
obj, shutdown := qe.wq.Get()
if shutdown {
@@ -41,11 +56,19 @@ func (qe *QueuedEventController) process(obj interface{}) {
if !ok {
return
}
err := utils.PublishToNats(eobj.Subject, eobj.Data)
if err != nil {
klog.Errorf("async publish subject %s,data %v, failed %v", eobj.Subject, eobj.Data, err)
} else {
klog.Infof("publish event success data: %#v", eobj.Data)
for {
err := qe.publish(eobj.Subject, eobj.Data)
if err == nil {
klog.Infof("publish event success data: %#v", eobj.Data)
return
}
klog.Errorf("publish subject %s, data %v failed: %v", eobj.Subject, eobj.Data, err)
select {
case <-qe.ctx.Done():
return
case <-time.After(time.Second):
}
}
}
@@ -68,9 +91,46 @@ func (qe *QueuedEventController) enqueue(obj interface{}) {
qe.wq.Add(obj)
}
func NewAppEventQueue(ctx context.Context) *QueuedEventController {
func (qe *QueuedEventController) publish(subject string, data interface{}) error {
if err := qe.ensureNatsConnected(); err != nil {
return fmt.Errorf("failed to ensure NATS connection: %w", err)
}
return utils.PublishEvent(qe.nc, subject, data)
}
func (qe *QueuedEventController) ensureNatsConnected() error {
qe.ncMux.Lock()
defer qe.ncMux.Unlock()
if qe.nc != nil && qe.nc.IsConnected() {
return nil
}
if qe.nc != nil {
qe.nc.Close()
}
klog.Info("NATS connection not established, attempting to connect...")
nc, err := utils.NewNatsConn()
if err != nil {
klog.Errorf("Failed to connect to NATS: %v", err)
return err
}
qe.nc = nc
klog.Info("Successfully connected to NATS")
return nil
}
func (qe *QueuedEventController) GetNatsConn() *nats.Conn {
qe.ncMux.Lock()
defer qe.ncMux.Unlock()
return qe.nc
}
func NewAppEventQueue(ctx context.Context, nc *nats.Conn) *QueuedEventController {
return &QueuedEventController{
ctx: ctx,
nc: nc,
wq: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "app-event-queue"),
}
}
@@ -110,3 +170,16 @@ func PublishAppEventToQueue(p utils.EventParams) {
AppEventQueue.enqueue(&QueueEvent{Subject: subject, Data: data})
}
func PublishUserEventToQueue(topic, user, operator string) {
subject := "os.users"
data := UserEvent{
Topic: topic,
Payload: Payload{
User: user,
Operator: operator,
Timestamp: time.Now(),
},
}
AppEventQueue.enqueue(&QueueEvent{Subject: subject, Data: data})
}

View File

@@ -3,7 +3,6 @@ package utils
import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"os"
@@ -12,6 +11,7 @@ import (
"github.com/beclab/Olares/framework/app-service/api/app.bytetrade.io/v1alpha1"
"github.com/beclab/Olares/framework/app-service/pkg/constants"
refdocker "github.com/containerd/containerd/reference/docker"
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
helmLoader "helm.sh/helm/v3/pkg/chart/loader"
@@ -182,7 +182,7 @@ func GetResourceListFromChart(chartPath string, values map[string]interface{}) (
if err == io.EOF {
return resources, nil
}
return nil, fmt.Errorf("error parsing")
return nil, errors.Wrap(err, "error parsing")
}
ext.Raw = bytes.TrimSpace(ext.Raw)
if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) {

View File

@@ -47,96 +47,13 @@ type EventParams struct {
SharedEntrances []v1alpha1.Entrance
}
type UserEvent struct {
Topic string `json:"topic"`
Payload Payload `json:"payload"`
func PublishEvent(nc *nats.Conn, subject string, data interface{}) error {
return publish(nc, subject, data)
}
type Payload struct {
User string `json:"user"`
Operator string `json:"operator"`
Timestamp time.Time `json:"timestamp"`
}
func PublishUserEvent(topic, user, operator string) {
subject := "os.users"
data := UserEvent{
Topic: topic,
Payload: Payload{
User: user,
Operator: operator,
Timestamp: time.Now(),
},
}
if err := publish(subject, data); err != nil {
klog.Errorf("async publish subject %s,data %v, failed %v", subject, data, err)
} else {
t, _ := json.Marshal(data)
klog.Infof("publish user event success. data: %v", string(t))
}
}
func PublishAppEvent(p EventParams) {
subject := fmt.Sprintf("os.application.%s", p.Owner)
now := time.Now()
data := Event{
EventID: fmt.Sprintf("%s-%s-%d", p.Owner, p.Name, now.UnixMilli()),
CreateTime: now,
Name: p.Name,
Type: func() string {
if p.Type == "" {
return "app"
}
return p.Type
}(),
OpType: p.OpType,
OpID: p.OpID,
State: p.State,
Progress: p.Progress,
User: p.Owner,
RawAppName: func() string {
if p.RawAppName == "" {
return p.Name
}
return p.RawAppName
}(),
Title: p.Title,
Reason: p.Reason,
Message: p.Message,
}
if len(p.EntranceStatuses) > 0 {
data.EntranceStatuses = p.EntranceStatuses
}
if err := publish(subject, data); err != nil {
klog.Errorf("async publish subject %s,data %v, failed %v", subject, data, err)
} else {
klog.Infof("publish event success data: %#v", data)
}
}
func PublishToNats(subject string, data interface{}) error {
return publish(subject, data)
}
func publish(subject string, data interface{}) error {
natsHost := os.Getenv("NATS_HOST")
natsPort := os.Getenv("NATS_PORT")
username := os.Getenv("NATS_USERNAME")
password := os.Getenv("NATS_PASSWORD")
natsURL := fmt.Sprintf("nats://%s:%s", natsHost, natsPort)
nc, err := nats.Connect(natsURL, nats.UserInfo(username, password))
if err != nil {
klog.Infof("connect error: err=%v", err)
return err
}
defer nc.Drain()
func publish(nc *nats.Conn, subject string, data interface{}) error {
d, err := json.Marshal(data)
if err != nil {
klog.Errorf("marshal failed: %v", err)
return err
}
err = nc.Publish(subject, d)
@@ -147,34 +64,38 @@ func publish(subject string, data interface{}) error {
return nil
}
func PublishMiddlewareEvent(owner, name, opType, opID, state, progress string, entranceStatuses []v1alpha1.EntranceStatus, rawAppName string) {
subject := fmt.Sprintf("os.application.%s", owner)
func NewNatsConn() (*nats.Conn, error) {
natsHost := os.Getenv("NATS_HOST")
natsPort := os.Getenv("NATS_PORT")
username := os.Getenv("NATS_USERNAME")
password := os.Getenv("NATS_PASSWORD")
now := time.Now()
data := Event{
EventID: fmt.Sprintf("%s-%s-%d", owner, name, now.UnixMilli()),
CreateTime: now,
Name: name,
Type: "middleware",
OpType: opType,
OpID: opID,
State: state,
Progress: progress,
User: owner,
RawAppName: func() string {
if rawAppName == "" {
return name
natsURL := fmt.Sprintf("nats://%s:%s", natsHost, natsPort)
opts := []nats.Option{
nats.UserInfo(username, password),
nats.MaxReconnects(-1),
nats.ReconnectWait(2 * time.Second),
nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
if err != nil {
klog.Warningf("NATS disconnected: %v, will attempt to reconnect", err)
} else {
klog.Infof("NATS disconnected, will attempt to reconnect")
}
return rawAppName
}(),
}
if len(entranceStatuses) > 0 {
data.EntranceStatuses = entranceStatuses
}),
nats.ReconnectHandler(func(nc *nats.Conn) {
klog.Infof("NATS reconnected to %s", nc.ConnectedUrl())
}),
nats.ClosedHandler(func(nc *nats.Conn) {
klog.Errorf("NATS connection closed permanently: %v", nc.LastError())
}),
}
if err := publish(subject, data); err != nil {
klog.Errorf("async publish subject %s,data %v, failed %v", subject, data, err)
} else {
klog.Infof("publish event success data: %#v", data)
nc, err := nats.Connect(natsURL, opts...)
if err != nil {
klog.Errorf("failed to connect to NATS: %v", err)
return nil, err
}
klog.Infof("connected to NATS at %s", natsURL)
return nc, nil
}

View File

@@ -431,7 +431,7 @@ spec:
privileged: true
containers:
- name: authelia
image: beclab/auth:0.2.43
image: beclab/auth:0.2.44
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9091

View File

@@ -1,6 +1,6 @@
{{ $backupVersion := "0.3.60" }}
{{ $backupVersion := "0.3.61" }}
{{ $backup_server_rootpath := printf "%s%s" .Values.rootPath "/rootfs/backup-server" }}
{{- $backup_nats_secret := (lookup "v1" "Secret" .Release.Namespace "backup-nats-secret") -}}

View File

@@ -16,7 +16,7 @@ replace (
k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8
k8s.io/kubectl => k8s.io/kubectl v0.24.2
k8s.io/utils => k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
olares.com/backups-sdk => github.com/Above-Os/backups-sdk v0.1.38
olares.com/backups-sdk => github.com/Above-Os/backups-sdk v0.1.39
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.12.2
sigs.k8s.io/json => sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2
sigs.k8s.io/kustomize/api => sigs.k8s.io/kustomize/api v0.11.4

View File

@@ -31,8 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Above-Os/backups-sdk v0.1.38 h1:GUq/sV7Tra0mDCgm9KXfVqsJV8m5rQtIpf7Zx7FFZVg=
github.com/Above-Os/backups-sdk v0.1.38/go.mod h1:55igUShkfGaJZrWJ0z/jlkgkYniZEN/Qoav6njwyvbs=
github.com/Above-Os/backups-sdk v0.1.39 h1:myTSIJ8tiaQPCCOQAxSgx9/VHwOJSgbwvGpzUc3ytsQ=
github.com/Above-Os/backups-sdk v0.1.39/go.mod h1:55igUShkfGaJZrWJ0z/jlkgkYniZEN/Qoav6njwyvbs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=

View File

@@ -266,7 +266,7 @@ spec:
containers:
- name: api
image: beclab/bfl:v0.4.37
image: beclab/bfl:v0.4.38
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 1000

View File

@@ -2,6 +2,7 @@ package v1
import (
"fmt"
"math"
"strconv"
"time"
@@ -9,7 +10,9 @@ import (
"bytetrade.io/web3os/bfl/pkg/api"
"bytetrade.io/web3os/bfl/pkg/api/response"
"bytetrade.io/web3os/bfl/pkg/apis"
"bytetrade.io/web3os/bfl/pkg/apis/backend/v1/metrics"
"bytetrade.io/web3os/bfl/pkg/apis/iam/v1alpha1/operator"
monitov1alpha1 "bytetrade.io/web3os/bfl/pkg/apis/monitor/v1alpha1"
"bytetrade.io/web3os/bfl/pkg/apiserver/runtime"
"bytetrade.io/web3os/bfl/pkg/app_service/v1"
"bytetrade.io/web3os/bfl/pkg/client/clientset/v1alpha1"
@@ -371,3 +374,68 @@ func (h *Handler) myapps(req *restful.Request, resp *restful.Response) {
response.Success(resp, api.NewListResult(list))
}
func (h *Handler) getClusterMetric(req *restful.Request, resp *restful.Response) {
prome, err := metrics.NewPrometheus(metrics.PrometheusEndpoint)
if err != nil {
response.HandleError(resp, err)
return
}
opts := metrics.QueryOptions{
Level: metrics.LevelCluster,
}
metricsResult := prome.GetNamedMetrics(req.Request.Context(), []string{
"cluster_cpu_usage",
"cluster_cpu_total",
"cluster_disk_size_usage",
"cluster_disk_size_capacity",
"cluster_memory_total",
"cluster_memory_usage_wo_cache",
"cluster_net_bytes_transmitted",
"cluster_net_bytes_received",
}, time.Now(), opts)
var clusterMetrics monitov1alpha1.ClusterMetrics
for _, m := range metricsResult {
switch m.MetricName {
case "cluster_cpu_usage":
clusterMetrics.CPU.Usage = metrics.GetValue(&m)
case "cluster_cpu_total":
clusterMetrics.CPU.Total = metrics.GetValue(&m)
case "cluster_disk_size_usage":
clusterMetrics.Disk.Usage = metrics.GetValue(&m)
case "cluster_disk_size_capacity":
clusterMetrics.Disk.Total = metrics.GetValue(&m)
case "cluster_memory_total":
clusterMetrics.Memory.Total = metrics.GetValue(&m)
case "cluster_memory_usage_wo_cache":
clusterMetrics.Memory.Usage = metrics.GetValue(&m)
case "cluster_net_bytes_transmitted":
clusterMetrics.Net.Transmitted = metrics.GetValue(&m)
case "cluster_net_bytes_received":
clusterMetrics.Net.Received = metrics.GetValue(&m)
}
}
roundToGB := func(v float64) float64 { return math.Round((v/1000000000.00)*100.00) / 100.00 }
fmtMetricsValue(&clusterMetrics.CPU, "Cores", func(v float64) float64 { return v })
fmtMetricsValue(&clusterMetrics.Memory, "GB", roundToGB)
fmtMetricsValue(&clusterMetrics.Disk, "GB", roundToGB)
response.Success(resp, clusterMetrics)
}
func fmtMetricsValue(v *monitov1alpha1.MetricV, unit string, unitFunc func(float64) float64) {
v.Unit = unit
v.Usage = unitFunc(v.Usage)
v.Total = unitFunc(v.Total)
v.Ratio = math.Round((v.Usage / v.Total) * 100)
}

View File

@@ -52,6 +52,12 @@ func AddContainer(c *restful.Container) error {
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(http.StatusOK, "", response.Response{}))
ws.Route(ws.GET("/cluster").
To(handler.getClusterMetric).
Doc("get the cluster current metrics ( cpu, memory, disk ).").
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(http.StatusOK, "", response.Response{}))
ws.Route(ws.GET("/config-system").
To(handler.HandleGetSysConfig).
Doc("get user locale.").

View File

@@ -210,7 +210,7 @@ spec:
command:
- /samba_share
- name: files
image: beclab/files-server:v0.2.145
image: beclab/files-server:v0.2.148
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: true
@@ -314,8 +314,8 @@ spec:
value: os.users
- name: NATS_SUBJECT_SYSTEM_GROUPS
value: os.groups
- name: RESERVED_SPACE
value: '1000'
- name: RESERVED_SPACE_PERCENT
value: '1.00'
- name: OLARES_VERSION
value: '1.12'
- name: FILE_CACHE_DIR

View File

@@ -181,7 +181,7 @@ spec:
value: "postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@citus-0.citus-headless.os-platform/$(POSTGRES_DB)?sslmode=disable"
containers:
- name: infisical
image: "beclab/infisical:0.1.1"
image: "beclab/infisical:0.1.2"
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:

View File

@@ -140,7 +140,7 @@ spec:
name: check-chart-repo
containers:
- name: appstore-backend
image: beclab/market-backend:v0.6.16
image: beclab/market-backend:v0.6.17
imagePullPolicy: IfNotPresent
ports:
- containerPort: 81

View File

@@ -240,7 +240,7 @@ spec:
value: os_framework_search3
containers:
- name: search3
image: beclab/search3:v0.1.0
image: beclab/search3:v0.1.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
@@ -301,7 +301,7 @@ spec:
priorityClassName: "system-cluster-critical"
containers:
- name: search3monitor
image: beclab/search3monitor:v0.1.0
image: beclab/search3monitor:v0.1.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8081

View File

@@ -64,7 +64,7 @@ spec:
operator: Exists
containers:
- name: search3-validation
image: beclab/search3validation:v0.1.0
image: beclab/search3validation:v0.1.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8443

View File

@@ -202,7 +202,7 @@ spec:
- name: NATS_SUBJECT_SYSTEM_GROUPS
value: "os.groups"
image: beclab/lldap:0.0.16
image: beclab/lldap:0.0.17
imagePullPolicy: IfNotPresent
name: lldap
ports: