Compare commits
43 Commits
module-osn
...
l4/fix/rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5de7ea01bc | ||
|
|
ff7765bcb9 | ||
|
|
c98c855099 | ||
|
|
4ae552f33f | ||
|
|
f2aad6d9f6 | ||
|
|
02bc4fafd5 | ||
|
|
8d34cc995d | ||
|
|
a19e81a4a0 | ||
|
|
ee3f2a7df2 | ||
|
|
73ea65b004 | ||
|
|
4ef2e7124a | ||
|
|
ef46f91ec7 | ||
|
|
0f5a346d86 | ||
|
|
caa799e902 | ||
|
|
2be5f6d108 | ||
|
|
05f3c8ffdc | ||
|
|
c0e242b05c | ||
|
|
7929e420b1 | ||
|
|
66de213f43 | ||
|
|
2166cec66f | ||
|
|
1a0f9727c4 | ||
|
|
810253fe94 | ||
|
|
23429a6193 | ||
|
|
49e40f316f | ||
|
|
1e7b655826 | ||
|
|
adea16ce7e | ||
|
|
c2222859a5 | ||
|
|
e7dde2ff51 | ||
|
|
d06c1e8a99 | ||
|
|
131faacce0 | ||
|
|
8133704761 | ||
|
|
09e61aecad | ||
|
|
bc5fd5fd82 | ||
|
|
1367355661 | ||
|
|
30195f1513 | ||
|
|
88b140ccc2 | ||
|
|
39947f464c | ||
|
|
7440e85c2e | ||
|
|
d71747928c | ||
|
|
b20d5c0876 | ||
|
|
c4fc3198bb | ||
|
|
260b6154f3 | ||
|
|
ecfcd0d1d8 |
@@ -317,7 +317,7 @@ spec:
|
||||
chown -R 1000:1000 /uploadstemp && \
|
||||
chown -R 1000:1000 /appdata
|
||||
- name: olares-app-init
|
||||
image: beclab/system-frontend:v1.7.1
|
||||
image: beclab/system-frontend:v1.8.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
@@ -439,7 +439,7 @@ spec:
|
||||
- name: NATS_SUBJECT_VAULT
|
||||
value: os.vault.{{ .Values.bfl.username}}
|
||||
- name: user-service
|
||||
image: beclab/user-service:v0.0.81
|
||||
image: beclab/user-service:v0.0.82
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
|
||||
21
cli/cmd/ctl/amdgpu/install.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package amdgpu
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/pipelines"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewCmdAmdGpuInstall() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "install",
|
||||
Short: "Install AMD ROCm stack via amdgpu-install",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := pipelines.AmdGpuInstall(); err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
16
cli/cmd/ctl/amdgpu/root.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package amdgpu
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func NewCmdAmdGpu() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "amdgpu",
|
||||
Short: "Manage AMD GPU ROCm stack",
|
||||
}
|
||||
cmd.AddCommand(NewCmdAmdGpuInstall())
|
||||
cmd.AddCommand(NewCmdAmdGpuUninstall())
|
||||
cmd.AddCommand(NewCmdAmdGpuStatus())
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
||||
21
cli/cmd/ctl/amdgpu/status.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package amdgpu
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/pipelines"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewCmdAmdGpuStatus() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Show AMD GPU driver and ROCm status",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := pipelines.AmdGpuStatus(); err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
21
cli/cmd/ctl/amdgpu/uninstall.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package amdgpu
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/pipelines"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewCmdAmdGpuUninstall() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "uninstall",
|
||||
Short: "Uninstall AMD ROCm stack via amdgpu-install",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := pipelines.AmdGpuUninstall(); err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package os
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -13,6 +14,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
@@ -276,7 +280,7 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
|
||||
}
|
||||
|
||||
func collectDmesgLogs(tw *tar.Writer, options *LogCollectOptions) error {
|
||||
cmd := exec.Command("dmesg")
|
||||
cmd := exec.Command("dmesg -T")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -399,6 +403,126 @@ func collectKubernetesLogs(tw *tar.Writer, options *LogCollectOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := collectNginxLogsFromLabeledPods(tw); err != nil {
|
||||
if !options.IgnoreKubeErrors {
|
||||
return fmt.Errorf("failed to collect nginx logs from labeled pods: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectNginxLogsFromLabeledPods(tw *tar.Writer) error {
|
||||
if _, err := util.GetCommand("kubectl"); err != nil {
|
||||
fmt.Printf("warning: kubectl not found, skipping collecting nginx logs from labeled pods\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get kubeconfig: %v", err)
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create kube client: %v", err)
|
||||
}
|
||||
|
||||
type selectorSpec struct {
|
||||
LabelSelector string
|
||||
ContainerName string
|
||||
}
|
||||
selectors := []selectorSpec{
|
||||
{LabelSelector: "app=l4-bfl-proxy", ContainerName: ""},
|
||||
{LabelSelector: "tier=bfl", ContainerName: "ingress"},
|
||||
}
|
||||
|
||||
type targetPod struct {
|
||||
Namespace string
|
||||
Name string
|
||||
ContainerName string
|
||||
}
|
||||
var targets []targetPod
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
for _, sel := range selectors {
|
||||
podList, err := clientset.CoreV1().Pods(corev1.NamespaceAll).List(ctx, metav1.ListOptions{LabelSelector: sel.LabelSelector})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list pods by label %q: %v", sel.LabelSelector, err)
|
||||
}
|
||||
for _, pod := range podList.Items {
|
||||
targets = append(targets, targetPod{
|
||||
Namespace: pod.Namespace,
|
||||
Name: pod.Name,
|
||||
ContainerName: sel.ContainerName,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(targets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// simplest approach: use kubectl cp (it already implements copy via tar over exec)
|
||||
tempDir, err := os.MkdirTemp("", "olares-nginx-logs-*")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp directory for nginx logs: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
files := []string{"/var/log/nginx/access.log", "/var/log/nginx/error.log"}
|
||||
for _, target := range targets {
|
||||
for _, remotePath := range files {
|
||||
base := filepath.Base(remotePath)
|
||||
archivePath := filepath.Join("nginx", target.Namespace, target.Name, base)
|
||||
|
||||
dest := filepath.Join(tempDir, fmt.Sprintf("%s__%s__%s", target.Namespace, target.Name, base))
|
||||
|
||||
err := kubectlCopyFile(target.Namespace, target.Name, target.ContainerName, remotePath, dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to kubectl cp %s/%s:%s: %v", target.Namespace, target.Name, remotePath, err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stat copied nginx log %s: %v", dest, err)
|
||||
}
|
||||
|
||||
f, err := os.Open(dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open copied nginx log %s: %v", dest, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
header := &tar.Header{
|
||||
Name: archivePath,
|
||||
Mode: 0644,
|
||||
Size: fi.Size(),
|
||||
ModTime: time.Now(),
|
||||
}
|
||||
if err := tw.WriteHeader(header); err != nil {
|
||||
return fmt.Errorf("failed to write header for %s: %v", archivePath, err)
|
||||
}
|
||||
if _, err := io.CopyN(tw, f, header.Size); err != nil {
|
||||
return fmt.Errorf("failed to write data for %s: %v", archivePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func kubectlCopyFile(namespace, pod, container, remotePath, destPath string) error {
|
||||
args := []string{"-n", namespace, "cp"}
|
||||
if container != "" {
|
||||
args = append(args, "-c", container)
|
||||
}
|
||||
args = append(args, fmt.Sprintf("%s:%s", pod, remotePath), destPath)
|
||||
|
||||
cmd := exec.Command("kubectl", args...)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("kubectl %s failed: %v, output: %s", strings.Join(args, " "), err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ctl
|
||||
|
||||
import (
|
||||
"github.com/beclab/Olares/cli/cmd/ctl/amdgpu"
|
||||
"github.com/beclab/Olares/cli/cmd/ctl/disk"
|
||||
"github.com/beclab/Olares/cli/cmd/ctl/gpu"
|
||||
"github.com/beclab/Olares/cli/cmd/ctl/node"
|
||||
@@ -33,6 +34,7 @@ func NewDefaultCommand() *cobra.Command {
|
||||
cmds.AddCommand(os.NewOSCommands()...)
|
||||
cmds.AddCommand(node.NewNodeCommand())
|
||||
cmds.AddCommand(gpu.NewCmdGpu())
|
||||
cmds.AddCommand(amdgpu.NewCmdAmdGpu())
|
||||
cmds.AddCommand(user.NewUserCommand())
|
||||
cmds.AddCommand(disk.NewDiskCommand())
|
||||
|
||||
|
||||
133
cli/pkg/amdgpu/tasks.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package amdgpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
cc "github.com/beclab/Olares/cli/pkg/core/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/utils"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InstallAmdRocmModule installs AMD ROCm stack on supported Ubuntu if AMD GPU is present.
|
||||
type InstallAmdRocmModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
|
||||
func (m *InstallAmdRocmModule) Init() {
|
||||
m.Name = "InstallAMDGPU"
|
||||
|
||||
installAmd := &task.RemoteTask{
|
||||
Name: "InstallAmdRocm",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Action: &InstallAmdRocm{
|
||||
// no manifest needed
|
||||
},
|
||||
Parallel: false,
|
||||
Retry: 1,
|
||||
}
|
||||
|
||||
m.Tasks = []task.Interface{
|
||||
installAmd,
|
||||
}
|
||||
}
|
||||
|
||||
// InstallAmdRocm installs ROCm using amdgpu-install on Ubuntu 22.04/24.04 for AMD GPUs.
|
||||
type InstallAmdRocm struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *InstallAmdRocm) Execute(runtime connector.Runtime) error {
|
||||
si := runtime.GetSystemInfo()
|
||||
if !si.IsLinux() || !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
amdGPUExists, err := utils.HasAmdIGPU(runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// skip rocm install
|
||||
if !amdGPUExists {
|
||||
return nil
|
||||
}
|
||||
rocmV, _ := utils.RocmVersion()
|
||||
min := semver.MustParse("7.1.1")
|
||||
if rocmV != nil && rocmV.LessThan(min) {
|
||||
return fmt.Errorf("detected ROCm version %s, which is lower than required %s; please uninstall existing ROCm/AMDGPU components before installation with command: olares-cli amdgpu uninstall", rocmV.Original(), min.Original())
|
||||
}
|
||||
if rocmV != nil && rocmV.GreaterThan(min) {
|
||||
logger.Warnf("Warning: detected ROCm version %s great than maximum tested version %s")
|
||||
return nil
|
||||
}
|
||||
if rocmV != nil && rocmV.Equal(min) {
|
||||
logger.Infof("detected ROCm version %s, skip rocm install...", min.Original())
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensure python3-setuptools and python3-wheel
|
||||
_, _ = runtime.GetRunner().SudoCmd("apt-get update", false, true)
|
||||
checkPkgs := "dpkg -s python3-setuptools python3-wheel >/dev/null 2>&1 || DEBIAN_FRONTEND=noninteractive apt-get install -y python3-setuptools python3-wheel"
|
||||
if _, err := runtime.GetRunner().SudoCmd(checkPkgs, false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to install python3-setuptools and python3-wheel")
|
||||
}
|
||||
// ensure amdgpu-install exists
|
||||
if _, err := exec.LookPath("amdgpu-install"); err != nil {
|
||||
var debURL string
|
||||
if si.IsUbuntuVersionEqual(connector.Ubuntu2404) {
|
||||
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/noble/amdgpu-install_7.1.1.70101-1_all.deb"
|
||||
} else {
|
||||
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/jammy/amdgpu-install_7.1.1.70101-1_all.deb"
|
||||
}
|
||||
tmpDeb := path.Join(runtime.GetBaseDir(), cc.PackageCacheDir, "gpu", "amdgpu-install_7.1.1.70101-1_all.deb")
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("install -d -m 0755 %s", filepath.Dir(tmpDeb)), false, true); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := fmt.Sprintf("sh -c 'wget -O %s %s'", tmpDeb, debURL)
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to download amdgpu-install deb")
|
||||
}
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("DEBIAN_FRONTEND=noninteractive apt-get install -y %s", tmpDeb), false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to install amdgpu-install deb")
|
||||
}
|
||||
}
|
||||
// run installer for rocm usecase
|
||||
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
|
||||
}
|
||||
fmt.Println()
|
||||
logger.Warn("Warning: To enable ROCm, please reboot your machine after installation.")
|
||||
return nil
|
||||
}
|
||||
|
||||
type AmdgpuInstallAction struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *AmdgpuInstallAction) Execute(runtime connector.Runtime) error {
|
||||
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AmdgpuUninstallAction struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *AmdgpuUninstallAction) Execute(runtime connector.Runtime) error {
|
||||
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install --uninstall -y", false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to uninstall AMD ROCm via amdgpu-install")
|
||||
}
|
||||
fmt.Println()
|
||||
logger.Warn("Warning: Please reboot your machine after uninstall to fully remove ROCm components.")
|
||||
return nil
|
||||
}
|
||||
@@ -81,6 +81,7 @@ func (m *RunPrechecksModule) Init() {
|
||||
new(NvidiaCardArchChecker),
|
||||
new(NouveauChecker),
|
||||
new(CudaChecker),
|
||||
new(RocmChecker),
|
||||
}
|
||||
runPreChecks := &task.LocalTask{
|
||||
Name: "RunPrechecks",
|
||||
|
||||
@@ -372,6 +372,48 @@ func (c *CudaChecker) Check(runtime connector.Runtime) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RocmChecker checks AMD ROCm version for AMD GPU on Ubuntu 22.04/24.04 only.
|
||||
type RocmChecker struct{}
|
||||
|
||||
func (r *RocmChecker) Name() string {
|
||||
return "ROCm"
|
||||
}
|
||||
|
||||
func (r *RocmChecker) Check(runtime connector.Runtime) error {
|
||||
if !runtime.GetSystemInfo().IsLinux() {
|
||||
return nil
|
||||
}
|
||||
si := runtime.GetSystemInfo()
|
||||
if !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// detect AMD GPU presence
|
||||
amdGPUExists, err := utils.HasAmdIGPU(runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// no AMD GPU found, no need to check rocm
|
||||
if !amdGPUExists {
|
||||
return nil
|
||||
}
|
||||
|
||||
curV, err := utils.RocmVersion()
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
min := semver.MustParse("7.1.1")
|
||||
if curV.LessThan(min) {
|
||||
return fmt.Errorf("detected ROCm version %s, which is lower than required %s; please uninstall existing ROCm/AMDGPU components before installation with command: olares-cli amdgpu uninstall", curV.Original(), min.Original())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// precheck - task
|
||||
|
||||
|
||||
@@ -51,10 +51,12 @@ func (d DebianVersion) String() string {
|
||||
}
|
||||
|
||||
const (
|
||||
Ubuntu20 UbuntuVersion = "20."
|
||||
Ubuntu22 UbuntuVersion = "22."
|
||||
Ubuntu24 UbuntuVersion = "24."
|
||||
Ubuntu25 UbuntuVersion = "25."
|
||||
Ubuntu20 UbuntuVersion = "20."
|
||||
Ubuntu22 UbuntuVersion = "22."
|
||||
Ubuntu24 UbuntuVersion = "24."
|
||||
Ubuntu25 UbuntuVersion = "25."
|
||||
Ubuntu2204 UbuntuVersion = "22.04"
|
||||
Ubuntu2404 UbuntuVersion = "24.04"
|
||||
|
||||
Debian9 DebianVersion = "9"
|
||||
Debian10 DebianVersion = "10"
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
"github.com/beclab/Olares/cli/pkg/k3s/templates"
|
||||
"github.com/beclab/Olares/cli/pkg/manifest"
|
||||
"github.com/beclab/Olares/cli/pkg/registry"
|
||||
"github.com/beclab/Olares/cli/pkg/storage"
|
||||
)
|
||||
|
||||
type InstallContainerModule struct {
|
||||
@@ -470,6 +471,18 @@ func (j *JoinNodesModule) Init() {
|
||||
Parallel: true,
|
||||
}
|
||||
|
||||
createSharedLibDirForWorker := &task.RemoteTask{
|
||||
Name: "CreateSharedLibDir(k3s)",
|
||||
Desc: "Create shared lib directory on worker",
|
||||
Hosts: j.Runtime.GetHostsByRole(common.Worker),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
&kubernetes.NodeInCluster{Not: true},
|
||||
new(common.OnlyWorker),
|
||||
},
|
||||
Action: new(storage.CreateSharedLibDir),
|
||||
Parallel: true,
|
||||
}
|
||||
|
||||
enableK3s := &task.RemoteTask{
|
||||
Name: "EnableK3sService",
|
||||
Desc: "Enable k3s service",
|
||||
@@ -536,6 +549,7 @@ func (j *JoinNodesModule) Init() {
|
||||
k3sService,
|
||||
k3sEnv,
|
||||
k3sRegistryConfig,
|
||||
createSharedLibDirForWorker,
|
||||
enableK3s,
|
||||
copyKubeConfigForMaster,
|
||||
syncKubeConfigToWorker,
|
||||
|
||||
@@ -397,53 +397,23 @@ type CopyK3sKubeConfig struct {
|
||||
}
|
||||
|
||||
func (c *CopyK3sKubeConfig) Execute(runtime connector.Runtime) error {
|
||||
createConfigDirCmd := "mkdir -p /root/.kube && mkdir -p $HOME/.kube"
|
||||
getKubeConfigCmd := "cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config"
|
||||
chmodKubeConfigCmd := "chmod 0600 /root/.kube/config"
|
||||
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd, chmodKubeConfigCmd}, " && ")
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
|
||||
cmds := []string{
|
||||
"mkdir -p /root/.kube",
|
||||
"cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config",
|
||||
"chmod 0600 /root/.kube/config",
|
||||
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
|
||||
fmt.Sprintf("cp -f /etc/rancher/k3s/k3s.yaml %s", filepath.Join(targetHome, ".kube", "config")),
|
||||
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
|
||||
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
|
||||
}
|
||||
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "copy k3s kube config failed")
|
||||
}
|
||||
|
||||
userMkdir := "mkdir -p $HOME/.kube"
|
||||
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
|
||||
}
|
||||
|
||||
userCopyKubeConfig := "cp -f /etc/rancher/k3s/k3s.yaml $HOME/.kube/config"
|
||||
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user copy /etc/rancher/k3s/k3s.yaml to $HOME/.kube/config failed")
|
||||
}
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config 0600 failed")
|
||||
}
|
||||
|
||||
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
// }
|
||||
|
||||
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
// }
|
||||
|
||||
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
}
|
||||
|
||||
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
}
|
||||
|
||||
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
|
||||
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -493,59 +463,29 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
|
||||
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
|
||||
cluster := v.(*K3sStatus)
|
||||
|
||||
createConfigDirCmd := "mkdir -p /root/.kube"
|
||||
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
|
||||
}
|
||||
|
||||
oldServer := "server: https://127.0.0.1:6443"
|
||||
newServer := fmt.Sprintf("server: https://%s:%d",
|
||||
s.KubeConf.Cluster.ControlPlaneEndpoint.Domain,
|
||||
s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
|
||||
newKubeConfig := strings.Replace(cluster.KubeConfig, oldServer, newServer, -1)
|
||||
|
||||
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config")
|
||||
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
|
||||
}
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config failed")
|
||||
}
|
||||
|
||||
userConfigDirCmd := "mkdir -p $HOME/.kube"
|
||||
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
|
||||
}
|
||||
|
||||
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "$HOME/.kube/config")
|
||||
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
|
||||
}
|
||||
|
||||
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
// }
|
||||
|
||||
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
// }
|
||||
|
||||
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
|
||||
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
return err
|
||||
}
|
||||
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
|
||||
|
||||
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
cmds := []string{
|
||||
"mkdir -p /root/.kube",
|
||||
fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config"),
|
||||
"chmod 0600 /root/.kube/config",
|
||||
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
|
||||
fmt.Sprintf("echo '%s' > %s", newKubeConfig, targetKubeConfigPath),
|
||||
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
|
||||
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
|
||||
}
|
||||
|
||||
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
|
||||
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
|
||||
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/beclab/Olares/cli/pkg/core/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/manifest"
|
||||
"github.com/beclab/Olares/cli/pkg/storage"
|
||||
)
|
||||
|
||||
type StatusModule struct {
|
||||
@@ -243,6 +244,18 @@ func (j *JoinNodesModule) Init() {
|
||||
Retry: 5,
|
||||
}
|
||||
|
||||
createSharedLibDirForWorker := &task.RemoteTask{
|
||||
Name: "CreateSharedLibDir(k8s)",
|
||||
Desc: "Create shared lib directory on worker",
|
||||
Hosts: j.Runtime.GetHostsByRole(common.Worker),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
&NodeInCluster{Not: true},
|
||||
new(common.OnlyWorker),
|
||||
},
|
||||
Action: new(storage.CreateSharedLibDir),
|
||||
Parallel: true,
|
||||
}
|
||||
|
||||
joinWorkerNode := &task.RemoteTask{
|
||||
Name: "JoinWorkerNode(k8s)",
|
||||
Desc: "Join worker node",
|
||||
@@ -323,6 +336,7 @@ func (j *JoinNodesModule) Init() {
|
||||
j.Tasks = []task.Interface{
|
||||
generateKubeadmConfig,
|
||||
joinMasterNode,
|
||||
createSharedLibDirForWorker,
|
||||
joinWorkerNode,
|
||||
copyKubeConfig,
|
||||
removeMasterTaint,
|
||||
|
||||
@@ -417,51 +417,23 @@ type CopyKubeConfigForControlPlane struct {
|
||||
}
|
||||
|
||||
func (c *CopyKubeConfigForControlPlane) Execute(runtime connector.Runtime) error {
|
||||
createConfigDirCmd := "mkdir -p /root/.kube"
|
||||
getKubeConfigCmd := "cp -f /etc/kubernetes/admin.conf /root/.kube/config"
|
||||
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd}, " && ")
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
|
||||
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmds := []string{
|
||||
"mkdir -p /root/.kube",
|
||||
"cp -f /etc/kubernetes/admin.conf /root/.kube/config",
|
||||
"chmod 0600 /root/.kube/config",
|
||||
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
|
||||
fmt.Sprintf("cp -f /etc/kubernetes/admin.conf %s", filepath.Join(targetHome, ".kube", "config")),
|
||||
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
|
||||
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
|
||||
}
|
||||
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "copy kube config failed")
|
||||
}
|
||||
|
||||
userMkdir := "mkdir -p $HOME/.kube"
|
||||
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
|
||||
}
|
||||
|
||||
userCopyKubeConfig := "cp -f /etc/kubernetes/admin.conf $HOME/.kube/config"
|
||||
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user copy /etc/kubernetes/admin.conf to $HOME/.kube/config failed")
|
||||
}
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
|
||||
}
|
||||
|
||||
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
// }
|
||||
|
||||
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
// }
|
||||
|
||||
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
}
|
||||
|
||||
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
}
|
||||
|
||||
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
|
||||
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -521,53 +493,23 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
|
||||
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
|
||||
cluster := v.(*KubernetesStatus)
|
||||
|
||||
createConfigDirCmd := "mkdir -p /root/.kube"
|
||||
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
|
||||
}
|
||||
|
||||
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config")
|
||||
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
|
||||
}
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
|
||||
}
|
||||
|
||||
userConfigDirCmd := "mkdir -p $HOME/.kube"
|
||||
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
|
||||
}
|
||||
|
||||
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "$HOME/.kube/config")
|
||||
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
|
||||
}
|
||||
|
||||
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
// }
|
||||
|
||||
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
// }
|
||||
|
||||
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
|
||||
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user id failed")
|
||||
return err
|
||||
}
|
||||
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
|
||||
|
||||
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "get user group id failed")
|
||||
cmds := []string{
|
||||
"mkdir -p /root/.kube",
|
||||
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config"),
|
||||
"chmod 0600 /root/.kube/config",
|
||||
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
|
||||
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, targetKubeConfigPath),
|
||||
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
|
||||
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
|
||||
}
|
||||
|
||||
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
|
||||
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
|
||||
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -3,8 +3,7 @@ package system
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/gpu"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/amdgpu"
|
||||
"github.com/beclab/Olares/cli/pkg/bootstrap/os"
|
||||
"github.com/beclab/Olares/cli/pkg/bootstrap/patch"
|
||||
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
|
||||
@@ -12,6 +11,7 @@ import (
|
||||
"github.com/beclab/Olares/cli/pkg/container"
|
||||
"github.com/beclab/Olares/cli/pkg/core/module"
|
||||
"github.com/beclab/Olares/cli/pkg/daemon"
|
||||
"github.com/beclab/Olares/cli/pkg/gpu"
|
||||
"github.com/beclab/Olares/cli/pkg/images"
|
||||
"github.com/beclab/Olares/cli/pkg/k3s"
|
||||
"github.com/beclab/Olares/cli/pkg/manifest"
|
||||
@@ -82,6 +82,7 @@ func (l *linuxPhaseBuilder) build() []module.Module {
|
||||
addModule(&terminus.WriteReleaseFileModule{}).
|
||||
addModule(gpuModuleBuilder(func() []module.Module {
|
||||
return []module.Module{
|
||||
&amdgpu.InstallAmdRocmModule{},
|
||||
&gpu.InstallDriversModule{
|
||||
ManifestModule: manifest.ManifestModule{
|
||||
Manifest: l.manifestMap,
|
||||
|
||||
101
cli/pkg/pipelines/amdgpu.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package pipelines
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/amdgpu"
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/action"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/core/module"
|
||||
"github.com/beclab/Olares/cli/pkg/core/pipeline"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
)
|
||||
|
||||
type singleTaskModule struct {
|
||||
common.KubeModule
|
||||
name string
|
||||
act action.Action
|
||||
}
|
||||
|
||||
func (m *singleTaskModule) Init() {
|
||||
m.Name = m.name
|
||||
m.Tasks = []task.Interface{
|
||||
&task.LocalTask{
|
||||
Name: m.name,
|
||||
Action: m.act,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AmdGpuInstall() error {
|
||||
arg := common.NewArgument()
|
||||
arg.SetConsoleLog("amdgpuinstall.log", true)
|
||||
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := &pipeline.Pipeline{
|
||||
Name: "InstallAMDGPUDrivers",
|
||||
Runtime: runtime,
|
||||
Modules: []module.Module{
|
||||
&amdgpu.InstallAmdRocmModule{},
|
||||
},
|
||||
}
|
||||
return p.Start()
|
||||
}
|
||||
|
||||
func AmdGpuUninstall() error {
|
||||
arg := common.NewArgument()
|
||||
arg.SetConsoleLog("amdgpuuninstall.log", true)
|
||||
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := &pipeline.Pipeline{
|
||||
Name: "UninstallAMDGPUDrivers",
|
||||
Runtime: runtime,
|
||||
Modules: []module.Module{
|
||||
&singleTaskModule{name: "AmdgpuUninstall", act: new(amdgpu.AmdgpuUninstallAction)},
|
||||
},
|
||||
}
|
||||
return p.Start()
|
||||
}
|
||||
|
||||
func AmdGpuStatus() error {
|
||||
arg := common.NewArgument()
|
||||
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.SetRunner(
|
||||
&connector.Runner{
|
||||
Host: &connector.BaseHost{
|
||||
Name: common.LocalHost,
|
||||
Arch: runtime.GetSystemInfo().GetOsArch(),
|
||||
Os: runtime.GetSystemInfo().GetOsType(),
|
||||
},
|
||||
},
|
||||
)
|
||||
amdModel, _ := runtime.GetRunner().SudoCmd("lspci | grep -iE 'VGA|3D|Display' | grep -iE 'AMD|ATI' | head -1 || true", false, false)
|
||||
drvVer, _ := runtime.GetRunner().SudoCmd("modinfo amdgpu 2>/dev/null | awk -F': ' '/^version:/{print $2}' || true", false, false)
|
||||
rocmVer, _ := runtime.GetRunner().SudoCmd("cat /opt/rocm/.info/version 2>/dev/null || true", false, false)
|
||||
|
||||
if strings.TrimSpace(amdModel) != "" {
|
||||
logger.Infof("AMD GPU: %s", strings.TrimSpace(amdModel))
|
||||
} else {
|
||||
logger.Info("AMD GPU: not detected")
|
||||
}
|
||||
if strings.TrimSpace(drvVer) != "" {
|
||||
logger.Infof("AMDGPU driver %s", strings.TrimSpace(drvVer))
|
||||
} else {
|
||||
logger.Info("AMDGPU driver version: unknown")
|
||||
}
|
||||
if strings.TrimSpace(rocmVer) != "" {
|
||||
logger.Infof("ROCm version: %s", strings.TrimSpace(rocmVer))
|
||||
} else {
|
||||
logger.Info("ROCm version: not installed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -396,3 +396,17 @@ func (t *DeleteTerminusData) Execute(runtime connector.Runtime) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateSharedLibDir struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *CreateSharedLibDir) Execute(runtime connector.Runtime) error {
|
||||
if runtime.GetSystemInfo().IsDarwin() {
|
||||
return nil
|
||||
}
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", OlaresSharedLibDir, OlaresSharedLibDir), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,12 +38,6 @@ type InstallOsSystem struct {
|
||||
}
|
||||
|
||||
func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
|
||||
if !runtime.GetSystemInfo().IsDarwin() {
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", storage.OlaresSharedLibDir, storage.OlaresSharedLibDir), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
|
||||
}
|
||||
}
|
||||
|
||||
config, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -367,6 +361,11 @@ func (m *InstallOsSystemModule) Init() {
|
||||
Action: &CreateUserEnvConfigMap{},
|
||||
}
|
||||
|
||||
createSharedLibDir := &task.LocalTask{
|
||||
Name: "CreateSharedLibDir",
|
||||
Action: &storage.CreateSharedLibDir{},
|
||||
}
|
||||
|
||||
installOsSystem := &task.LocalTask{
|
||||
Name: "InstallOsSystem",
|
||||
Action: &InstallOsSystem{},
|
||||
@@ -399,6 +398,7 @@ func (m *InstallOsSystemModule) Init() {
|
||||
m.Tasks = []task.Interface{
|
||||
applySystemEnv,
|
||||
createUserEnvConfigMap,
|
||||
createSharedLibDir,
|
||||
installOsSystem,
|
||||
createBackupConfigMap,
|
||||
checkSystemService,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/utils"
|
||||
)
|
||||
|
||||
type WelcomeMessage struct {
|
||||
@@ -68,6 +69,15 @@ func (t *WelcomeMessage) Execute(runtime connector.Runtime) error {
|
||||
logger.Infof("Username: %s", t.KubeConf.Arg.User.UserName)
|
||||
logger.Infof("Password: %s", t.KubeConf.Arg.User.Password)
|
||||
fmt.Printf("\n------------------------------------------------\n\n\n\n\n")
|
||||
fmt.Println()
|
||||
|
||||
// If AMD GPU on Ubuntu 22.04/24.04, print warning about reboot for ROCm
|
||||
if si := runtime.GetSystemInfo(); si.IsUbuntu() && (si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
|
||||
if hasAmd, _ := utils.HasAmdIGPU(runtime); hasAmd {
|
||||
logger.Warnf("\x1b[31mWarning: To enable ROCm, please reboot your machine after activation.\x1b[0m")
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
67
cli/pkg/utils/amdgpu.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
)
|
||||
|
||||
func HasAmdIGPU(execRuntime connector.Runtime) (bool, error) {
|
||||
// Detect by CPU model names that bundle AMD AI NPU/graphics
|
||||
targets := []string{
|
||||
"AMD Ryzen AI Max+ 395",
|
||||
"AMD Ryzen AI Max 390",
|
||||
"AMD Ryzen AI Max 385",
|
||||
"AMD Ryzen AI 9 HX 375",
|
||||
"AMD Ryzen AI 9 HX 370",
|
||||
"AMD Ryzen AI 9 365",
|
||||
}
|
||||
// try lscpu first: extract 'Model name' field
|
||||
out, err := execRuntime.GetRunner().SudoCmd("lscpu 2>/dev/null | awk -F': *' '/^Model name/{print $2; exit}' || true", false, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if out != "" {
|
||||
lo := strings.ToLower(strings.TrimSpace(out))
|
||||
for _, t := range targets {
|
||||
if strings.Contains(lo, strings.ToLower(t)) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// fallback to /proc/cpuinfo
|
||||
out, err = execRuntime.GetRunner().SudoCmd("awk -F': *' '/^model name/{print $2; exit}' /proc/cpuinfo 2>/dev/null || true", false, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if out != "" {
|
||||
lo := strings.ToLower(strings.TrimSpace(out))
|
||||
for _, t := range targets {
|
||||
if strings.Contains(lo, strings.ToLower(t)) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func RocmVersion() (*semver.Version, error) {
|
||||
const rocmVersionFile = "/opt/rocm/.info/version"
|
||||
data, err := os.ReadFile(rocmVersionFile)
|
||||
if err != nil {
|
||||
// no ROCm installed, nothing to check
|
||||
if os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
curStr := strings.TrimSpace(string(data))
|
||||
cur, err := semver.NewVersion(curStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid rocm version: %s", curStr)
|
||||
}
|
||||
return cur, nil
|
||||
}
|
||||
@@ -321,3 +321,54 @@ func GetBufIOReaderOfTerminalInput() (*bufio.Reader, error) {
|
||||
}
|
||||
return bufio.NewReader(tty), nil
|
||||
}
|
||||
|
||||
// ResolveSudoUserHomeAndIDs resolves the home directory, uid, and gid for the user
|
||||
// who invoked sudo. If not running under sudo, it falls back to the current user.
|
||||
// This is useful for commands that need to operate on the invoking user's home
|
||||
// directory rather than /root when running with sudo.
|
||||
func ResolveSudoUserHomeAndIDs(runtime connector.Runtime) (home, uid, gid string, err error) {
|
||||
uid, err = runtime.GetRunner().Cmd("echo ${SUDO_UID:-}", false, false)
|
||||
if err != nil {
|
||||
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_UID failed")
|
||||
}
|
||||
gid, err = runtime.GetRunner().Cmd("echo ${SUDO_GID:-}", false, false)
|
||||
if err != nil {
|
||||
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_GID failed")
|
||||
}
|
||||
uid = strings.TrimSpace(uid)
|
||||
gid = strings.TrimSpace(gid)
|
||||
|
||||
if uid == "" {
|
||||
uid, err = runtime.GetRunner().Cmd("id -u", false, false)
|
||||
if err != nil {
|
||||
return "", "", "", errors.Wrap(errors.WithStack(err), "get current uid failed")
|
||||
}
|
||||
gid, err = runtime.GetRunner().Cmd("id -g", false, false)
|
||||
if err != nil {
|
||||
return "", "", "", errors.Wrap(errors.WithStack(err), "get current gid failed")
|
||||
}
|
||||
uid = strings.TrimSpace(uid)
|
||||
gid = strings.TrimSpace(gid)
|
||||
}
|
||||
|
||||
home, err = runtime.GetRunner().Cmd(fmt.Sprintf(`getent passwd %s | awk -F: 'NR==1{print $6; exit}'`, uid), false, false)
|
||||
if err != nil {
|
||||
home = ""
|
||||
}
|
||||
home = strings.TrimSpace(home)
|
||||
if home == "" {
|
||||
home, _ = runtime.GetRunner().Cmd(fmt.Sprintf(`awk -F: -v uid=%s '$3==uid {print $6; exit}' /etc/passwd 2>/dev/null`, uid), false, false)
|
||||
home = strings.TrimSpace(home)
|
||||
}
|
||||
if home == "" {
|
||||
home, err = runtime.GetRunner().Cmd("echo $HOME", false, false)
|
||||
if err != nil {
|
||||
return "", "", "", errors.Wrap(errors.WithStack(err), "get HOME failed")
|
||||
}
|
||||
home = strings.TrimSpace(home)
|
||||
}
|
||||
if home == "" {
|
||||
return "", "", "", errors.New("resolve user home failed")
|
||||
}
|
||||
return home, uid, gid, nil
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ require (
|
||||
github.com/containerd/containerd v1.7.29
|
||||
github.com/distribution/distribution/v3 v3.0.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/eball/zeroconf v0.2.4
|
||||
github.com/eball/zeroconf v0.2.5
|
||||
github.com/godbus/dbus/v5 v5.1.0
|
||||
github.com/gofiber/fiber/v2 v2.52.9
|
||||
github.com/google/gopacket v1.1.19
|
||||
|
||||
@@ -87,8 +87,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eball/echo/v4 v4.13.4-patch h1:5w83KQrEqrxhc1BO0BpRBHssC37vFrWualUM27Rt2sg=
|
||||
github.com/eball/echo/v4 v4.13.4-patch/go.mod h1:ORgy8LWTq8knpwgaz538rAJMri7WgpoAD6H3zYccn84=
|
||||
github.com/eball/zeroconf v0.2.4 h1:S5nUHLu2zhpA8YuR/Ue/vXPiY6ynPECkpDXjYV+Ckj4=
|
||||
github.com/eball/zeroconf v0.2.4/go.mod h1:eIbIjGYo9sSMaKWLcveHEPRWdyblz7q9ih2R1HnNw5M=
|
||||
github.com/eball/zeroconf v0.2.5 h1:RNINVvj8kbm/r4YoqYu/jWD57l5NJmvRUCfbjlIsbJg=
|
||||
github.com/eball/zeroconf v0.2.5/go.mod h1:eIbIjGYo9sSMaKWLcveHEPRWdyblz7q9ih2R1HnNw5M=
|
||||
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
|
||||
|
||||
@@ -84,8 +84,15 @@ func (p *proxyServer) Start() error {
|
||||
clientIp = h
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsWebSocket() {
|
||||
ctx = context.WithValue(ctx, WSKey, true)
|
||||
swp := c.Request().Header.Get("Sec-WebSocket-Protocol")
|
||||
authToken := c.Request().Header.Get("X-Authorization")
|
||||
if len(authToken) == 0 && len(swp) > 0 {
|
||||
// handle missing auth token for websocket
|
||||
c.Request().Header.Set("X-Authorization", swp)
|
||||
}
|
||||
}
|
||||
r := c.Request().WithContext(ctx)
|
||||
if clientIp != "" {
|
||||
@@ -243,7 +250,7 @@ func (p *proxyServer) customDialContext(d *net.Dialer) func(ctx context.Context,
|
||||
}
|
||||
|
||||
if isWs {
|
||||
klog.Info("WebSocket connection detected, using upgraded dialer")
|
||||
klog.Info("WebSocket connection detected, using upgraded dialer, ", addr)
|
||||
return tlsDial(ctx, d, func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return proxyDial(ctx, d, network, newAddr)
|
||||
}, network, addr, &tls.Config{InsecureSkipVerify: true})
|
||||
|
||||
@@ -99,7 +99,7 @@ func (s *server) Restart() error {
|
||||
instanceName = hostname
|
||||
}
|
||||
|
||||
s.server, err = zeroconf.Register(instanceName, s.serviceName, "local.", hostname, s.port, []string{""}, []net.Interface{*iface})
|
||||
s.server, err = zeroconf.RegisterAll(instanceName, s.serviceName, "local.", hostname, s.port, []string{""}, []net.Interface{*iface}, false, false, false)
|
||||
if err != nil {
|
||||
klog.Error("create mdns server error, ", err)
|
||||
return err
|
||||
|
||||
@@ -124,7 +124,7 @@ const side = {
|
||||
link: "/manual/larepass/back-up-mnemonics"
|
||||
},
|
||||
{
|
||||
text: "Access Olares locally",
|
||||
text: "Access Olares securely",
|
||||
link: "/manual/get-started/local-access",
|
||||
},
|
||||
{
|
||||
@@ -403,7 +403,7 @@ const side = {
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Best practices",
|
||||
text: "Tutorials",
|
||||
link: "/manual/best-practices/",
|
||||
collapsed: true,
|
||||
items: [
|
||||
@@ -427,6 +427,10 @@ const side = {
|
||||
text: "Expand storage in Olares",
|
||||
link: "/manual/best-practices/expand-storage-in-olares",
|
||||
},
|
||||
{
|
||||
text: "Access Olares locally",
|
||||
link: "/manual/best-practices/local-access",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ text: "Glossary", link: "/manual/glossary" },
|
||||
@@ -554,6 +558,18 @@ const side = {
|
||||
text: "ACE-Step",
|
||||
link: "/use-cases/ace-step",
|
||||
},
|
||||
{
|
||||
text: "Stirling PDF",
|
||||
link: "/use-cases/stirling-pdf",
|
||||
},
|
||||
{
|
||||
text: "PDFMathTranslate",
|
||||
link: "/use-cases/pdfmathtranslate",
|
||||
},
|
||||
{
|
||||
text: "LobeChat",
|
||||
link: "/use-cases/lobechat",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -626,65 +642,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" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -923,4 +920,4 @@ export const en = defineConfig({
|
||||
|
||||
sidebar: side,
|
||||
},
|
||||
});
|
||||
});
|
||||
9
docs/.vitepress/theme/components/AppLinkCN.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
const targetUrl = 'https://www.olares.cn/larepass'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a :href="targetUrl" target="_blank" rel="noreferrer" class="app-link">
|
||||
<slot>LarePass 下载页面</slot>
|
||||
</a>
|
||||
</template>
|
||||
9
docs/.vitepress/theme/components/AppLinkGlobal.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
const targetUrl = 'https://www.olares.com/larepass'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a :href="targetUrl" target="_blank" rel="noreferrer" class="app-link">
|
||||
<slot>LarePass Download page</slot>
|
||||
</a>
|
||||
</template>
|
||||
@@ -14,6 +14,9 @@ import OSTabs from "./components/OStabs.vue";
|
||||
import VersionSwitcher from "./components/VersionSwitcher.vue";
|
||||
import _ from "lodash";
|
||||
import { redirects } from './redirects';
|
||||
import AppLinkGlobal from './components/AppLinkGlobal.vue'
|
||||
import AppLinkCN from './components/AppLinkCN.vue'
|
||||
|
||||
|
||||
const LANGUAGE_LOCAL_KEY = "language";
|
||||
let isMenuChange = false;
|
||||
@@ -27,6 +30,8 @@ enhanceApp({ app, router }: { app: App; router: Router }) {
|
||||
app.component("FilterableList", FilterableList);
|
||||
app.component("OSTabs", OSTabs);
|
||||
app.component("VersionSwitcher", VersionSwitcher);
|
||||
app.component('AppLinkGlobal', AppLinkGlobal)
|
||||
app.component('AppLinkCN', AppLinkCN)
|
||||
|
||||
router.onBeforeRouteChange = (to: string) => {
|
||||
const path = to.replace(/\.html$/i, ''),
|
||||
@@ -142,4 +147,4 @@ enhanceApp({ app, router }: { app: App; router: Router }) {
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -123,7 +123,7 @@ const side = {
|
||||
link: "/zh/manual/larepass/back-up-mnemonics",
|
||||
},
|
||||
{
|
||||
text: "内网访问 Olares",
|
||||
text: "安全访问 Olares",
|
||||
link: "zh/manual/get-started/local-access",
|
||||
},
|
||||
{
|
||||
@@ -399,7 +399,7 @@ const side = {
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Olares 进阶",
|
||||
text: "教程",
|
||||
collapsed: true,
|
||||
link: "/zh/manual/best-practices/",
|
||||
items: [
|
||||
@@ -427,6 +427,10 @@ const side = {
|
||||
text: "在 Olares 中扩展存储空间",
|
||||
link: "/zh/manual/best-practices/expand-storage-in-olares",
|
||||
},
|
||||
{
|
||||
text: "本地访问 Olares",
|
||||
link: "/manual/best-practices/local-access",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ text: "术语", link: "/zh/manual/glossary" },
|
||||
@@ -608,72 +612,52 @@ 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: "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: "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: "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: "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: "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",
|
||||
@@ -719,7 +703,7 @@ const side = {
|
||||
text: "OlaresManifest",
|
||||
link: "/zh/developer/develop/package/manifest",
|
||||
},
|
||||
/*/{
|
||||
/*{
|
||||
text: "推荐算法",
|
||||
link: "/zh/developer/develop/package/recommend",
|
||||
},*/
|
||||
@@ -925,4 +909,4 @@ export const zh = defineConfig({
|
||||
|
||||
sidebar: side,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
33
docs/developer/install/cli/disk.md
Normal 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
|
||||
```
|
||||
@@ -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
|
||||
|
||||
@@ -7,7 +7,7 @@ The `info` command displays general information about the installed Olares versi
|
||||
olares-cli info
|
||||
```
|
||||
|
||||
## Flag
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------|-----------|---------------------------|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
@@ -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 |
|
||||
|--------------|-------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|
||||
@@ -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
|
||||
|
||||
53
docs/developer/install/cli/upgrade.md
Normal 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
|
||||
```
|
||||
@@ -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"
|
||||
```
|
||||
46
docs/developer/install/cli/user-create.md
Normal 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"
|
||||
```
|
||||
30
docs/developer/install/cli/user-delete.md
Normal 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
|
||||
```
|
||||
33
docs/developer/install/cli/user-get.md
Normal 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
|
||||
```
|
||||
34
docs/developer/install/cli/user-list.md
Normal 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
|
||||
```
|
||||
29
docs/developer/install/cli/user-reset-password.md
Normal 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!"
|
||||
```
|
||||
13
docs/developer/install/cli/user.md
Normal 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. |
|
||||
@@ -1,12 +1,13 @@
|
||||
---
|
||||
description: In-depth guides and proven best practices to help you get the most out of Olares.
|
||||
---
|
||||
# Beyond the basics: Olares best practices and advanced guides
|
||||
# Tutorials
|
||||
|
||||
This section offers in-depth guides and proven best practices to help you get the most out of Olares. Whether you're optimizing performance, securing your environment, or customizing advanced features, these resources go beyond initial setup to support real-world scenarios and power-user workflows.
|
||||
This section offers in-depth guides and proven best practices to help you get the most out of Olares.
|
||||
|
||||
- [Configure a custom domain for your Olares](set-custom-domain.md)
|
||||
- [Install a multi-node Olares cluster](install-olares-multi-node.md)
|
||||
- [Build your knowledge hub with Wise](organize-content.md)
|
||||
- [Install Olares on PVE via ISO with GPU Passthrough](install-olares-gpu-passthrough.md)
|
||||
- [Expand Olares storage capacity](expand-storage-in-olares.md)
|
||||
- [Access Olares services locally](local-access.md)
|
||||
250
docs/manual/best-practices/local-access.md
Normal file
@@ -0,0 +1,250 @@
|
||||
---
|
||||
outline: [2,3]
|
||||
description: Learn the different methods to access Olares services locally for improved speed and offline capability.
|
||||
---
|
||||
# Access Olares services locally
|
||||
Olares is designed to provide seamless access to your self-hosted services anytime, anywhere.
|
||||
|
||||
However, accessing your devices locally provides several advantages:
|
||||
- **Maximum performance**: Transfer files at full speed without the latency and potential bottlenecks of the internet.
|
||||
- **Enhanced privacy**: Keep your traffic contained within your home network for added security.
|
||||
- **Offline independence**: Access your data and apps even when your internet service is unavailable.
|
||||
|
||||
## Objectives
|
||||
|
||||
By the end of this tutorial, you will learn how to:
|
||||
|
||||
- Establish a secure, high-speed local connection using the LarePass VPN.
|
||||
- Access Olares services using `.local` domains.
|
||||
- Configure local DNS to allow standard URLs to resolve locally across your entire network.
|
||||
- Manually map hosts files to ensure access on specific machines without internet.
|
||||
|
||||
## Choose a connection method
|
||||
There are four ways to establish a local connection:
|
||||
|
||||
* **[Method 1: Enable LarePass VPN](#method-1-enable-larepass-vpn)**<br/>
|
||||
Uses LarePass VPN to automatically detect your local network and optimize the connection speed without changing settings.
|
||||
* **[Method 2: Use `.local` domain](#method-2-use-local-domain)**<br/>
|
||||
Access the device via a specific local URL format. No installation required.
|
||||
* **[Method 3: Configure local DNS](#method-3-configure-local-dns)**<br/>
|
||||
Updates your router or computer's DNS settings to map the standard Olares URL to the local IP address.
|
||||
* **[Method 4: Modify hosts files](#method-4-modify-hosts-files)**<br/>
|
||||
Manually maps the standard Olares URL to the local IP on a single computer.
|
||||
|
||||
## Method 1: Enable LarePass VPN
|
||||
The LarePass VPN is designed to secure your connection while optimizing performance. When enabled, LarePass detects if you are on the same network as your device and switches to **Intranet** mode.
|
||||
|
||||
:::tip Always enable VPN for remote access
|
||||
Keep LarePass VPN enabled. It automatically prioritizes the fastest available route to ensure you always get the best speed possible without manual switching.
|
||||
:::
|
||||
:::info iOS and macOS setup
|
||||
On iOS or macOS, you may be prompted to add a VPN Configuration to your system settings the first time you enable the feature. Allow this to complete the setup.
|
||||
:::
|
||||
|
||||
Enable the LarePass VPN directly on the device you are currently using to access Olares.
|
||||
|
||||
<tabs>
|
||||
<template #On-LarePass-mobile-client>
|
||||
|
||||
1. Open the LarePass app, and go to **Settings**.
|
||||
2. In the **My Olares** card, toggle on the VPN switch.
|
||||
|
||||

|
||||
</template>
|
||||
<template #On-LarePass-desktop-client>
|
||||
|
||||
1. Open the LarePass app, and click your avatar in the top-left corner to open the user menu.
|
||||
2. Toggle on the switch for **VPN connection**.
|
||||
|
||||

|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
Once enabled, check the status indicator in LarePass to verify the connection type:
|
||||
|
||||
| Status | Description |
|
||||
|:-------------|:---------------------------------------------------------|
|
||||
| **Intranet** | Direct connection via your local LAN IP. Fastest speeds. |
|
||||
| **P2P** | Direct encrypted tunnel between devices. High speed. |
|
||||
| **DERP** | Routed via a secure relay server. Used as a fallback. |
|
||||
|
||||
## Method 2: Use `.local` domain
|
||||
If you prefer not to install additional apps, you can access services using the `.local` domain. There are two domain formats available depending on your operating system.
|
||||
|
||||
:::info Use HTTP protocol
|
||||
The `.local` domain does not support HTTPS. You must explicitly use `http://` at the beginning of the URL.
|
||||
:::
|
||||
|
||||
### Single-level domain (All operating systems)
|
||||
:::warning Supported for community apps only
|
||||
Olares system apps such as Desktop and Files do not support this URL format and will not load correctly.
|
||||
:::
|
||||
This format uses a single-level domain by connecting the entrance ID and the username with hyphens (`-`).
|
||||
- **Default URL**:
|
||||
```plain
|
||||
https://<entrance_id>.<username>.olares.com
|
||||
```
|
||||
- **Local-access URL**:
|
||||
```plain
|
||||
http://<entrance_id>-<username>-olares.local
|
||||
```
|
||||
|
||||
### Multi-level domain (macOS and iOS only)
|
||||
Apple devices support local service discovery via [Bonjour](https://developer.apple.com/bonjour/) (zero‑configuration networking), which can resolve multi‑label domains under `.local` on macOS and iOS. This allows a local URL format that mirrors the remote address.
|
||||
|
||||
- **Default URL**:
|
||||
```plain
|
||||
https://<entrance_id>.<username>.olares.com
|
||||
```
|
||||
- **Local-access URL**:
|
||||
```plain
|
||||
http://<entrance_id>.<username>.olares.local
|
||||
```
|
||||

|
||||
|
||||
## Method 3: Configure local DNS
|
||||
For a seamless experience where standard URLs resolve to your local IP address automatically, you can configure your network DNS. This configuration ensures consistent access across all devices on the network without requiring individual client setup.
|
||||
|
||||
### Find the internal IP for Olares device
|
||||
To configure DNS, first you need to find the internal IP for your Olares device.
|
||||
<tabs>
|
||||
<template #Check-via-the-LarePass-mobile-client>
|
||||
|
||||
If your phone and Olares device are on the same network:
|
||||
1. Open the LarePass app, and go to **Settings** > **System** to navigate to the **Olares management** page
|
||||

|
||||
|
||||
2. Tap on the device card.
|
||||

|
||||
|
||||
3. Scroll down to the **Network** section. You can find the **Intranet IP** there.
|
||||

|
||||
|
||||
</template>
|
||||
<template #Check-via-Olares-Terminal>
|
||||
|
||||
Control Hub provides a built-in terminal that allows you to run system commands directly from the browser, without needing an external SSH client.
|
||||
1. Open the Control Hub app, and under **Terminal**, select **Olares** in the left navigation bar.
|
||||

|
||||
|
||||
2. Type `ifconfig` in the terminal and press **Enter**.
|
||||
3. Look for your active connection, typically named `enp3s0` (wired) or `wlo1` (wireless). The IP address follows `inet`.
|
||||
|
||||
Example output:
|
||||
```bash
|
||||
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.50.116 netmask 255.255.255.0 broadcast 192.168.50.255
|
||||
inet6 fe80::4194:4045:c35e:7b32 prefixlen 64 scopeid 0x20<link>
|
||||
ether d8:43:ae:54:ce:fc txqueuelen 1000 (Ethernet)
|
||||
RX packets 80655321 bytes 71481515308 (71.4 GB)
|
||||
RX errors 0 dropped 136 overruns 0 frame 0
|
||||
TX packets 51867817 bytes 15924740708 (15.9 GB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
In this example, `192.168.50.116` is the internal IP.
|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
### Configure DNS
|
||||
With the internal IP address identified, you must now configure your DNS settings to route traffic correctly. You can apply this configuration to a single computer for individual access, or update your router to enable seamless local resolution for all devices on your network.
|
||||
<tabs>
|
||||
<template #Configure-for-local-device>
|
||||
|
||||
Update the DNS settings on your specific computer. For example, on macOS:
|
||||
1. Open Apple menu and go to **System Settings**.
|
||||
2. Select **Wi-Fi**, then click **Details** on your connected network.
|
||||
3. Select **DNS** and update the server list:
|
||||
|
||||
a. Click the **+** button under **DNS Servers** to add your Olares device's internal IP (e.g., `192.168.x.x`).
|
||||
|
||||
b. Ensure the Olares IP is listed at the top. Add your original DNS (or `1.1.1.1`) below it as a fallback. <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
|
||||
|
||||
4. Click **OK** to save changes.
|
||||
|
||||
</template>
|
||||
|
||||
<template #Configure-for-all-devices>
|
||||
|
||||
Update the DNS on your router to apply changes to every device in your network.
|
||||
|
||||
1. Log in to your router's admin panel.
|
||||
2. Navigate to **DHCP / DNS Settings**.
|
||||
3. Set **Primary DNS** to your Olares device's internal IP (e.g., `192.168.x.x`).
|
||||
4. Set **Secondary DNS** to your current Primary DNS (or a public provider like `1.1.1.1`). <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
|
||||
5. Save and reconnect your devices to refresh the DNS cache.
|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
Once configured, you can access Olares using both your standard public address and your local address.
|
||||
:::tip
|
||||
You can install AdGuard Home from the Olares Market to monitor traffic and manage DNS mappings graphically.
|
||||
:::
|
||||
## Method 4: Modify hosts files
|
||||
If you cannot change router settings and need immediate offline access on a specific computer, you can manually map the domains in your hosts file.
|
||||
|
||||
1. Locate your hosts file:
|
||||
- **Windows**: `C:\Windows\System32\drivers\etc\hosts`
|
||||
- **macOS/Linux**: `/etc/hosts`
|
||||
2. Open the file with a text editor, which requires Administrator privileges.
|
||||
3. Add the mapping lines:
|
||||
```plain
|
||||
# Replace with the actual internal IP and the username
|
||||
# Olares apps
|
||||
192.168.31.208 desktop.<username>.olares.com
|
||||
192.168.31.208 auth.<username>.olares.com
|
||||
192.168.31.208 files.<username>.olares.com
|
||||
192.168.31.208 market.<username>.olares.com
|
||||
192.168.31.208 settings.<username>.olares.com
|
||||
192.168.31.208 dashboard.<username>.olares.com
|
||||
192.168.31.208 control-hub.<username>.olares.com
|
||||
192.168.31.208 profile.<username>.olares.com
|
||||
192.168.31.208 vault.<username>.olares.com
|
||||
# Add other community apps as needed
|
||||
192.168.31.208 <entrance_id>.<username>.olares.com
|
||||
```
|
||||
4. Save the file to apply changes and ensure local access without an internet connection.
|
||||
|
||||
Verify the changes by checking the URL for quick loading or using the terminal:
|
||||
```bash
|
||||
ping desktop.<username>.olares.com
|
||||
```
|
||||
If the IP address starts with `192.168`, it indicates successful configuration.
|
||||
|
||||
|
||||
## FAQs
|
||||
### Why doesn't LarePass VPN work on my Mac anymore?
|
||||
If you successfully enabled the VPN previously, but it has stopped working, you might need to reset the system extension.
|
||||
:::info
|
||||
Depending on your macOS version, the UI might look slightly different.
|
||||
:::
|
||||
1. Open **System Settings**, search for "Extension", and select **Login Items & Extensions**.
|
||||
2. Scroll to the **Network Extensions** section and click the info icon (ⓘ) to view loaded extensions.
|
||||
3. Find LarePass, click the three dots (...), and select **Delete Extension**.
|
||||
4. Confirm the uninstallation.
|
||||
5. Restart your Mac and re-enable the VPN in the LarePass desktop client.
|
||||
|
||||
### Why can't I enable LarePass VPN on Windows?
|
||||
Third-party antivirus software might mistakenly flag the LarePass desktop client as suspicious, preventing it from launching the VPN service.
|
||||
|
||||
If prompted by your antivirus when opening LarePass for the first time, allow the application to continue.
|
||||
|
||||
If the VPN still fails to enable:
|
||||
1. Open your security software and check if LarePass was blocked.
|
||||
2. Add the main LarePass executable to the allowlist or exclusions of your antivirus.
|
||||
3. Restart LarePass and enable the VPN.
|
||||
|
||||
### Why the `.local` domain does not work in Chrome (macOS)?
|
||||
Chrome may fail to access local URLs if macOS blocks local network permissions.
|
||||
To enable access:
|
||||
1. Open Apple menu and go to **System Settings**.
|
||||
2. Go to **Privacy & Security** > **Local Network**.
|
||||
3. Find Google Chrome and Google Chrome Helper in the list and enable the toggles.
|
||||
{width=400}
|
||||
|
||||
4. Restart Chrome and try accessing the local URL again.
|
||||
|
||||
### Why does the application fail to load in an iFrame when using a `.local` domain on Chrome (macOS)?
|
||||
Chrome might default to HTTPS when using local domains, and you might see a "connection not secure" warning.
|
||||

|
||||
|
||||
To address this, explicitly add the HTTP protocol (`http://`) to the beginning of the URL. This tells Chrome it's a local, non-encrypted connection, which is expected on your home network.
|
||||
@@ -1,24 +1,25 @@
|
||||
---
|
||||
outline: [2,3]
|
||||
description: Learn how to access Olares apps and services directly via your local network (LAN) for maximum speed, privacy, and offline reliability.
|
||||
description: Learn how to access your Olares services securely using the LarePass VPN.
|
||||
---
|
||||
# Access Olares services locally
|
||||
# Access Olares services securely using LarePass VPN
|
||||
|
||||
Typically, you access Olares services through a browser using a URL like `https://desktop.<username>.olares.com`. This way, you can reach your services from any device at any time.
|
||||
|
||||
However, accessing your devices directly over your Local Area Network (LAN) provides several advantages:
|
||||
- **Maximum performance**: Transfer files at full speed without the latency and potential bottlenecks of the internet.
|
||||
- **Enhanced privacy**: Keep your traffic contained within your home network for added security.
|
||||
- **Offline independence**: Access your data and apps even when your internet service is unavailable.
|
||||
While this address works from anywhere, it's recommended to enable the LarePass VPN to ensure your connection is always secure and efficient. The client automatically detects your network environment and selects the best connection method:
|
||||
- **At home**: It establishes a direct **Intranet** connection to allow faster file transfers on your local network.
|
||||
- **From remote**: It switches to a secure encrypted tunnel to ensure you remain connected safely when accessing remotely.
|
||||
|
||||
This guide covers several methods to establish a local connection:
|
||||
- [Enable LarePass VPN (Recommended)](#method-1-enable-larepass-vpn)<br/>This method is the easiest solution, as it automatically establishes the fastest connection without manual configuration.
|
||||
- [Use `.local` domain](#method-2-use-local-domain)<br/>This method requires no installation, though you must use specific URL formats based on your operating system.
|
||||
- [Configure local DNS (Advanced)](#method-3-configure-local-dns)<br/>This method allows standard URLs to work locally by updating DNS settings on your router or individual computer.
|
||||
- [Modify host files (Fallback)](#method-4-modify-host-files)<br/>This method manually maps standard URLs to your local IP on a single computer, ensuring access even without an internet connection.
|
||||
## Download LarePass
|
||||
To use the secure VPN connection, the LarePass client must be installed on the device you are using.
|
||||
- **Mobile**: Use the LarePass app installed during the Olares ID creation process.
|
||||
- **Desktop**: Download and install the LarePass desktop client.
|
||||
|
||||
## Method 1: Enable LarePass VPN
|
||||
The most robust way to connect, whether you are sitting next to the device or traveling, is using the LarePass VPN. It intelligently detects when you are on the same network and switches to a direct **Intranet** mode for maximum speed.
|
||||
1. Visit <AppLinkGlobal />.
|
||||
2. Download the version compatible with your operating system.
|
||||
|
||||
## Enable LarePass VPN
|
||||
Once installed, enable the VPN directly on the device you are using to access Olares.
|
||||
|
||||
:::tip Always enable VPN for remote access
|
||||
Keep LarePass VPN enabled. It automatically prioritizes the fastest available route to ensure you always get the best speed possible without manual switching.
|
||||
@@ -27,25 +28,24 @@ Keep LarePass VPN enabled. It automatically prioritizes the fastest available ro
|
||||
On iOS or macOS, you may be prompted to add a VPN Configuration to your system settings the first time you enable the feature. Allow this to complete the setup.
|
||||
:::
|
||||
|
||||
Enable the LarePass VPN directly on the device you are currently using to access Olares.
|
||||
|
||||
<tabs>
|
||||
<template #On-LarePass-mobile-client>
|
||||
|
||||
1. Open the LarePass app, and go to **Settings**.
|
||||
1. Open the LarePass app and go to **Settings**.
|
||||
2. In the **My Olares** card, toggle on the VPN switch.
|
||||
|
||||

|
||||
</template>
|
||||
<template #On-LarePass-desktop-client>
|
||||
|
||||
1. Open the LarePass app, and click your avatar in the top-left corner to open the user menu.
|
||||
1. Open the LarePass app and click your avatar in the top-left corner to open the user menu.
|
||||
2. Toggle on the switch for **VPN connection**.
|
||||
|
||||

|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
## Verify the connection type
|
||||
Once enabled, check the status indicator in LarePass to verify the connection type:
|
||||
|
||||
| Status | Description |
|
||||
@@ -54,148 +54,6 @@ Once enabled, check the status indicator in LarePass to verify the connection ty
|
||||
| **P2P** | Direct encrypted tunnel between devices. High speed. |
|
||||
| **DERP** | Routed via a secure relay server. Used as a fallback. |
|
||||
|
||||
## Method 2: Use `.local` domain
|
||||
If you prefer not to use a VPN, you can access services using the `.local` domain. There are two domain formats available depending on your compatibility needs.
|
||||
|
||||
### Single-level domain (All operating systems)
|
||||
:::warning Supported for community apps only
|
||||
Olares system apps such as Desktop and Files do not support this URL format and will not load correctly.
|
||||
:::
|
||||
This format uses a single-level domain by connecting the entrance ID and the username with hyphens (`-`).
|
||||
- **Default URL**:
|
||||
```plain
|
||||
https://<entrance_id>.<username>.olares.com
|
||||
```
|
||||
- **Local-access URL**:
|
||||
```plain
|
||||
http://<entrance_id>-<username>-olares.local
|
||||
```
|
||||
|
||||
### Multi-level domain (macOS and iOS only)
|
||||
Apple devices support local service discovery via [Bonjour](https://developer.apple.com/bonjour/) (zero‑configuration networking), which can resolve multi‑label domains under `.local` on macOS and iOS. This allows a local URL format that mirrors the remote address.
|
||||
|
||||
- **Default URL**:
|
||||
```plain
|
||||
https://<entrance_id>.<username>.olares.com
|
||||
```
|
||||
- **Local-access URL**:
|
||||
```plain
|
||||
http://<entrance_id>.<username>.olares.local
|
||||
```
|
||||

|
||||
|
||||
## Method 3: Configure local DNS
|
||||
For a seamless experience where standard URLs resolve to your local IP address automatically, you can configure your network DNS. This configuration ensures consistent access across all devices on the network without requiring individual client setup.
|
||||
|
||||
### Find the internal IP for Olares device
|
||||
To configure DNS, first you need to find the internal IP for your Olares device.
|
||||
<tabs>
|
||||
<template #Check-via-the-LarePass-mobile-client>
|
||||
|
||||
If your phone and Olares device are on the same network:
|
||||
1. Open the LarePass app, and go to **Settings** > **System** to navigate to the **Olares management** page
|
||||

|
||||
|
||||
2. Tap on the device card.
|
||||

|
||||
|
||||
3. Scroll down to the **Network** section. You can find the **Intranet IP** there.
|
||||

|
||||
|
||||
</template>
|
||||
<template #Check-via-Olares-Terminal>
|
||||
|
||||
Control Hub provides a built-in terminal that allows you to run system commands directly from the browser, without needing an external SSH client.
|
||||
1. Open the Control Hub app, and under **Terminal**, select **Olares**in the left navigation bar.
|
||||

|
||||
|
||||
2. Type `ifconfig` in the terminal and press **Enter**.
|
||||
3. Look for your active connection, typically named `enp3s0` (wired) or `wlo1` (wireless). The IP address follows `inet`.
|
||||
|
||||
Example output:
|
||||
```bash
|
||||
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.50.116 netmask 255.255.255.0 broadcast 192.168.50.255
|
||||
inet6 fe80::4194:4045:c35e:7b32 prefixlen 64 scopeid 0x20<link>
|
||||
ether d8:43:ae:54:ce:fc txqueuelen 1000 (Ethernet)
|
||||
RX packets 80655321 bytes 71481515308 (71.4 GB)
|
||||
RX errors 0 dropped 136 overruns 0 frame 0
|
||||
TX packets 51867817 bytes 15924740708 (15.9 GB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
In this example, `192.168.50.116` is the internal IP.
|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
### Configure DNS
|
||||
With the internal IP address identified, you must now configure your DNS settings to route traffic correctly. You can apply this configuration to a single computer for individual access, or update your router to enable seamless local resolution for all devices on your network.
|
||||
<tabs>
|
||||
<template #Configure-for-local-device>
|
||||
|
||||
Update the DNS settings on your specific computer. For example, on macOS:
|
||||
1. Open Apple menu and go to **System Settings**.
|
||||
2. Select **Wi-Fi**, then click **Details** on your connected network.
|
||||
3. Select **DNS** and update the server list:
|
||||
|
||||
a. Click the **+** button under **DNS Servers** to add your Olares device's internal IP (e.g., `192.168.x.x`).
|
||||
|
||||
b. Ensure the Olares IP is listed at the top. Add your original DNS (or `1.1.1.1`) below it as a fallback. <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
|
||||
|
||||
4. Click **OK** to save changes.
|
||||
|
||||
</template>
|
||||
|
||||
<template #Configure-for-all-devices>
|
||||
|
||||
Update the DNS on your router to apply changes to every device in your network.
|
||||
|
||||
1. Log in to your router's admin panel.
|
||||
2. Navigate to **DHCP / DNS Settings**.
|
||||
3. Set **Primary DNS** to your Olares device's internal IP (e.g., `192.168.x.x`).
|
||||
4. Set **Secondary DNS** to your current Primary DNS (or a public provider like `1.1.1.1`). <br/>This ensures that if your Olares device shuts down, the router will automatically switch to the secondary DNS, keeping your internet connection alive.
|
||||
5. Save and reconnect your devices to refresh the DNS cache.
|
||||
</template>
|
||||
</tabs>
|
||||
|
||||
Once configured, you can access Olares using both your standard public address and your local address.
|
||||
:::tip
|
||||
You can install AdGuard Home from the Olares Market to monitor traffic and manage DNS mappings graphically.
|
||||
:::
|
||||
## Method 4: Modify host files
|
||||
If you cannot change router settings and need immediate offline access on a specific computer, you can manually map the domains in your hosts file.
|
||||
|
||||
1. Locate your hosts file:
|
||||
- **Windows:** `C:\Windows\System32\drivers\etc\hosts`
|
||||
- **macOS/Linux:** `/etc/hosts`
|
||||
2. Open the file with a text editor, which requires Administrator privileges.
|
||||
3. Add the mapping lines:
|
||||
```plain
|
||||
# Replace with the actual internal IP and the username
|
||||
# Olares apps
|
||||
192.168.31.208 desktop.<username>.olares.com
|
||||
192.168.31.208 auth.<username>.olares.com
|
||||
192.168.31.208 files.<username>.olares.com
|
||||
192.168.31.208 market.<username>.olares.com
|
||||
192.168.31.208 settings.<username>.olares.com
|
||||
192.168.31.208 dashboard.<username>.olares.com
|
||||
192.168.31.208 control-hub.<username>.olares.com
|
||||
192.168.31.208 profile.<username>.olares.com
|
||||
192.168.31.208 vault.<username>.olares.com
|
||||
# Add other community apps as needed
|
||||
192.168.31.208 <entrance_id>.<username>.olares.com
|
||||
```
|
||||
4. Save the file to apply changes and ensure local access without an internet connection.
|
||||
|
||||
Verify the changes by checking the URL for quick loading or using the terminal:
|
||||
```bash
|
||||
ping desktop.<username>.olares.com
|
||||
```
|
||||
If the IP address starts with `192.168`, it indicates successful configuration.
|
||||
|
||||
## Learn more
|
||||
- [Access Olares services remotely via LarePass VPN](../../manual/larepass/private-network.md): Understand how to use LarePass VPN.
|
||||
- [Network](../../developer/concepts/network.md): Learn about the different entry points in Olares.
|
||||
|
||||
## FAQs
|
||||
### Why doesn't LarePass VPN work on my Mac anymore?
|
||||
If you successfully enabled the VPN previously, but it has stopped working, you might need to reset the system extension.
|
||||
@@ -208,28 +66,16 @@ Depending on your macOS version, the UI might look slightly different.
|
||||
4. Confirm the uninstallation.
|
||||
5. Restart your Mac and re-enable the VPN in the LarePass desktop client.
|
||||
|
||||
### Why I cannot enable LarePass VPN on Windows?
|
||||
### Why can't I enable LarePass VPN on Windows?
|
||||
Third-party antivirus software might mistakenly flag the LarePass desktop client as suspicious, preventing it from launching the VPN service.
|
||||
|
||||
If prompted by your antivirus when opening LarePass for the first time, allow the application to continue.
|
||||
|
||||
If the VPN still fails to enable:
|
||||
1. Open your security software and check if LarePass was blocked.
|
||||
2. Add the main LarePass executable to the allowlist** or exclusions of your antivirus.
|
||||
2. Add the main LarePass executable to the allowlist or exclusions of your antivirus.
|
||||
3. Restart LarePass and enable the VPN.
|
||||
|
||||
### Why the `.local` domain does not work in Chrome (macOS)?
|
||||
Chrome may fail to access local URLs if macOS blocks local network permissions.
|
||||
To enable access:
|
||||
1. Open Apple menu and go to **System Settings**.
|
||||
2. Go to **Privacy & Security** > **Local Network**.
|
||||
3. Find Google Chrome and Google Chrome Helper in the list and enable the toggles.
|
||||
{width=400}
|
||||
|
||||
4. Restart Chrome and try accessing the local URL again.
|
||||
|
||||
### Why does the application fail to load in an iFrame when using a `.local` domain on Chrome (macOS)?
|
||||
Chrome might default to HTTPS when using local domains, and you might see a "connection not secure" warning.
|
||||

|
||||
|
||||
To address this, explicitly add the HTTP protocol (`http://`) to the beginning of the URL. This tells Chrome it's a local, non-encrypted connection, which is expected on your home network.
|
||||
## Learn more
|
||||
- [Access Olares locally](../best-practices/local-access.md): Explore detailed instructions for all available local network connection methods.
|
||||
- [Network](../../developer/concepts/network.md): Learn about the different entry points in Olares.
|
||||
BIN
docs/public/images/manual/use-cases/access-translated-files.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/public/images/manual/use-cases/add-pdf.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
docs/public/images/manual/use-cases/batch-rotate.png
Normal file
|
After Width: | Height: | Size: 239 KiB |
BIN
docs/public/images/manual/use-cases/box-draw-redaction.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
docs/public/images/manual/use-cases/color-picker-icon.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/public/images/manual/use-cases/copy-localhost-address.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
docs/public/images/manual/use-cases/delete-single-page.png
Normal file
|
After Width: | Height: | Size: 270 KiB |
BIN
docs/public/images/manual/use-cases/dev-bot-result.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
docs/public/images/manual/use-cases/download-in-files.png
Normal file
|
After Width: | Height: | Size: 647 KiB |
BIN
docs/public/images/manual/use-cases/download-in-lobechat.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
BIN
docs/public/images/manual/use-cases/draw-line.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
docs/public/images/manual/use-cases/export-all-page.png
Normal file
|
After Width: | Height: | Size: 390 KiB |
BIN
docs/public/images/manual/use-cases/export-pdf.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/public/images/manual/use-cases/export-selected-page.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
docs/public/images/manual/use-cases/find-lobechat.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
docs/public/images/manual/use-cases/green-check-icon.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/public/images/manual/use-cases/install-pdfmathtranslate.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 221 KiB |
BIN
docs/public/images/manual/use-cases/install-stirling-pdf.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
docs/public/images/manual/use-cases/install-website-crawler.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 244 KiB |
BIN
docs/public/images/manual/use-cases/lobechat-pin.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
docs/public/images/manual/use-cases/lobechat-plugin-enable.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
docs/public/images/manual/use-cases/lobechat-plugin-install.png
Normal file
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 160 KiB |
BIN
docs/public/images/manual/use-cases/lobechat-settings-menu.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
docs/public/images/manual/use-cases/local-model-setup.png
Normal file
|
After Width: | Height: | Size: 718 KiB |
BIN
docs/public/images/manual/use-cases/manual-redaction.png
Normal file
|
After Width: | Height: | Size: 316 KiB |
BIN
docs/public/images/manual/use-cases/merge-pdf.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
docs/public/images/manual/use-cases/obtain-ollama-hosturl.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/public/images/manual/use-cases/ollama-model-checkpass.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
docs/public/images/manual/use-cases/open-chat-settings.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
docs/public/images/manual/use-cases/open-file.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
docs/public/images/manual/use-cases/open-pdfmathtranslate.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
docs/public/images/manual/use-cases/page-based-redaction.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/public/images/manual/use-cases/page-select.png
Normal file
|
After Width: | Height: | Size: 239 KiB |
BIN
docs/public/images/manual/use-cases/pdf-multi-tool.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
docs/public/images/manual/use-cases/pin-daily-tech-digest.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
BIN
docs/public/images/manual/use-cases/pin-dev-bot.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
docs/public/images/manual/use-cases/pin-writing-bot.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/public/images/manual/use-cases/pipeline-menu.png
Normal file
|
After Width: | Height: | Size: 95 KiB |