refactor bootstrap for local-first beOS Pro

This commit is contained in:
2026-03-09 09:01:35 +01:00
parent 11e627dc1f
commit fe630a89ca
11 changed files with 167 additions and 64 deletions

View File

@@ -1,6 +1,6 @@
<div align="center">
# Olares: An Open-Source Personal Cloud to </br>Reclaim Your Data<!-- omit in toc -->
# beOS Pro: A Self-Hosted Server Platform You Control<!-- omit in toc -->
[![Mission](https://img.shields.io/badge/Mission-Let%20people%20own%20their%20data%20again-purple)](#)<br/>
[![Last Commit](https://img.shields.io/github/last-commit/beclab/Olares)](https://github.com/beclab/olares/commits/main)
@@ -8,7 +8,7 @@
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/beclab/Olares)](https://github.com/beclab/olares/releases)
[![GitHub Repo stars](https://img.shields.io/github/stars/beclab/Olares?style=social)](https://github.com/beclab/Olares/stargazers)
[![Discord](https://img.shields.io/badge/Discord-7289DA?logo=discord&logoColor=white)](https://discord.gg/olares)
[![License](https://img.shields.io/badge/License-AGPL--3.0-blue)](https://github.com/beclab/olares/blob/main/LICENSE)
[![License](https://img.shields.io/badge/License-AGPL--3.0-blue)](./LICENSE)
<a href="https://trendshift.io/repositories/15376" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15376" alt="beclab%2FOlares | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
@@ -21,31 +21,28 @@
</div>
<p align="center">
<a href="https://olares.com">Website</a> ·
<a href="https://docs.olares.com">Documentation</a> ·
<a href="https://www.olares.com/larepass">Download LarePass</a> ·
<a href="https://github.com/beclab/apps">Olares Apps</a> ·
<a href="https://space.olares.com">Olares Space</a>
<a href="./README.md">Overview</a> ·
<a href="./docs">Docs Source</a> ·
<a href="./apps">Applications</a> ·
<a href="./cli">CLI</a> ·
<a href="./daemon">Daemon</a>
</p>
>*The modern internet built on public clouds is increasingly threatening your personal data privacy. As reliance on services like ChatGPT, Midjourney, and Facebook grows, so does the risk to your digital autonomy. Your data lives on their servers, subject to their terms, tracking, and potential censorship.*
>
>*It's time for a change.*
![Personal Cloud](https://app.cdn.olares.com/github/olares/public-cloud-to-personal-cloud.jpg)
We believe you have a fundamental right to control your digital life. The most effective way to uphold this right is by hosting your data locally, on your own hardware.
beOS Pro is a local-first server platform for running your own applications, storage, AI workloads, and internal services on hardware you control.
Olares is an **open-source personal cloud operating system** designed to empower you to own and manage your digital assets locally. Instead of relying on public cloud services, you can deploy powerful open-source alternatives locally on Olares, such as Ollama for hosting LLMs, ComfyUI for image generation, and Perplexica for private, AI-driven search and reasoning. Imagine the power of the cloud, but with you in complete command.
This fork is being refactored to remove mandatory dependency on vendor-managed activation, DNS, CDN, and remote control-plane services. The goal is straightforward: install on bare metal or on top of an existing Linux server, finish setup locally, and operate it without connecting to any external beOS-operated infrastructure unless you explicitly configure optional providers.
> 🌟 *Star us to receive instant notifications about new releases and updates.*
## Architecture
Just as Public clouds offer IaaS, PaaS, and SaaS layers, Olares provides open-source alternatives to each of these layers.
beOS Pro is structured as a host bootstrap layer, a Kubernetes orchestration layer, and a containerized platform/application layer.
![Tech Stacks](https://app.cdn.olares.com/github/olares/olares-architecture.jpg)
For detailed description of each component, refer to [Olares architecture](https://docs.olares.com/developer/concepts/system-architecture.html).
For the current architecture source, start with `docs/developer/concepts/system-architecture.md`.
> 🔍 **How is Olares different from traditional NAS?**
>

View File

@@ -66,14 +66,14 @@ if ! command_exists tar; then
exit 1
fi
export BASE_DIR="$HOME/.olares"
export BASE_DIR="${BEOS_BASE_DIR:-$HOME/.beos-pro}"
if [ ! -d $BASE_DIR ]; then
mkdir -p $BASE_DIR
fi
cdn_url=${OLARES_SYSTEM_CDN_SERVICE}
cdn_url=${BEOS_SYSTEM_CDN_SERVICE}
if [ -z ${cdn_url} ]; then
cdn_url="https://cdn.olares.com"
cdn_url=${OLARES_SYSTEM_CDN_SERVICE}
fi
RELEASE_ID="#__RELEASE_ID__"
@@ -87,52 +87,64 @@ if [[ x"$os_type" == x"Darwin" ]]; then
CLI_FILE="olares-cli-v${VERSION}_darwin_${ARCH}${RELEASE_ID_SUFFIX}.tar.gz"
fi
if [[ "$LOCAL_RELEASE" != "1" && -z "${cdn_url}" ]]; then
echo "error: no beOS Pro package mirror configured. Set BEOS_SYSTEM_CDN_SERVICE (or OLARES_SYSTEM_CDN_SERVICE for compatibility), or use LOCAL_RELEASE=1."
exit 1
fi
if [[ "$LOCAL_RELEASE" == "1" ]]; then
if ! command_exists olares-cli ; then
echo "error: LOCAL_RELEASE specified but olares-cli not found"
if command_exists beos-cli ; then
INSTALL_OLARES_CLI=$(which beos-cli)
elif command_exists olares-cli ; then
INSTALL_OLARES_CLI=$(which olares-cli)
else
echo "error: LOCAL_RELEASE specified but neither beos-cli nor olares-cli was found"
exit 1
fi
INSTALL_OLARES_CLI=$(which olares-cli)
else
expected_vendor="main"
if [[ "$(basename "$REPO_PATH")" == "olares-one" ]]; then
expected_vendor="OlaresOne"
fi
if command_exists olares-cli && [[ "$(olares-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(olares-cli --vendor)" == "$expected_vendor" ]]; then
if command_exists beos-cli && [[ "$(beos-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(beos-cli --vendor)" == "$expected_vendor" ]]; then
INSTALL_OLARES_CLI=$(which beos-cli)
echo "beos-cli already installed and is the expected version"
echo ""
elif command_exists olares-cli && [[ "$(olares-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(olares-cli --vendor)" == "$expected_vendor" ]]; then
INSTALL_OLARES_CLI=$(which olares-cli)
echo "olares-cli already installed and is the expected version"
echo "compatible legacy olares-cli already installed and is the expected version"
echo ""
else
if [[ ! -f ${CLI_FILE} ]]; then
CLI_URL="${cdn_url}${REPO_PATH}${CLI_FILE}"
echo "downloading Olares installer from ${CLI_URL} ..."
echo "downloading beOS Pro installer from ${CLI_URL} ..."
echo ""
curl -Lo ${CLI_FILE} ${CLI_URL}
if [[ $? -ne 0 ]]; then
echo "error: failed to download Olares installer"
echo "error: failed to download beOS Pro installer"
exit 1
else
echo "Olares installer ${VERSION} download complete!"
echo "beOS Pro installer ${VERSION} download complete!"
echo ""
fi
fi
INSTALL_OLARES_CLI="/usr/local/bin/olares-cli"
INSTALL_OLARES_CLI="/usr/local/bin/beos-cli"
echo "unpacking Olares installer to $INSTALL_OLARES_CLI..."
echo ""
tar -zxf ${CLI_FILE} olares-cli && chmod +x olares-cli
if [[ x"$os_type" == x"Darwin" ]]; then
if [ ! -f "/usr/local/Cellar/olares" ]; then
if [ ! -f "/usr/local/Cellar/beos" ]; then
current_user=$(whoami)
$sh_c "sudo mkdir -p /usr/local/Cellar/olares && sudo chown ${current_user}:staff /usr/local/Cellar/olares"
$sh_c "sudo mkdir -p /usr/local/Cellar/beos && sudo chown ${current_user}:staff /usr/local/Cellar/beos"
fi
$sh_c "mv olares-cli /usr/local/Cellar/olares/olares-cli && \
sudo rm -rf /usr/local/bin/olares-cli && \
sudo ln -s /usr/local/Cellar/olares/olares-cli $INSTALL_OLARES_CLI"
$sh_c "mv olares-cli /usr/local/Cellar/beos/beos-cli && \
sudo rm -rf /usr/local/bin/beos-cli && \
sudo ln -s /usr/local/Cellar/beos/beos-cli $INSTALL_OLARES_CLI"
else
$sh_c "mv olares-cli $INSTALL_OLARES_CLI"
$sh_c "mv olares-cli $INSTALL_OLARES_CLI"
fi
if [[ $? -ne 0 ]]; then
@@ -214,7 +226,7 @@ else
fi
echo "installing Olares..."
echo "installing beOS Pro..."
echo ""
$sh_c "$INSTALL_OLARES_CLI install"

View File

@@ -162,14 +162,19 @@ if [[ "x${VERSION}" == "x" || "x${VERSION:3}" == "xVERSION__" ]]; then
exit 1
fi
BASE_DIR="$HOME/.olares"
BASE_DIR="${BEOS_BASE_DIR:-$HOME/.beos-pro}"
if [ ! -d $BASE_DIR ]; then
mkdir -p $BASE_DIR
fi
cdn_url=${OLARES_SYSTEM_CDN_SERVICE}
cdn_url=${BEOS_SYSTEM_CDN_SERVICE}
if [[ -z "${cdn_url}" ]]; then
cdn_url="https://cdn.olares.com"
cdn_url=${OLARES_SYSTEM_CDN_SERVICE}
fi
if [[ -z "${cdn_url}" ]]; then
echo "error: no beOS Pro package mirror configured. Set BEOS_SYSTEM_CDN_SERVICE (or OLARES_SYSTEM_CDN_SERVICE for compatibility)."
exit 1
fi
set_master_host_ssh_options
@@ -185,27 +190,31 @@ expected_vendor="main"
if [[ "$(basename "$REPO_PATH")" == "olares-one" ]]; then
expected_vendor="OlaresOne"
fi
if command_exists olares-cli && [[ "$(olares-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(olares-cli --vendor)" == "$expected_vendor" ]]; then
if command_exists beos-cli && [[ "$(beos-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(beos-cli --vendor)" == "$expected_vendor" ]]; then
INSTALL_OLARES_CLI=$(which beos-cli)
echo "beos-cli already installed and is the expected version"
echo ""
elif command_exists olares-cli && [[ "$(olares-cli -v | awk '{print $3}')" == "$VERSION" ]] && [[ "$(olares-cli --vendor)" == "$expected_vendor" ]]; then
INSTALL_OLARES_CLI=$(which olares-cli)
echo "olares-cli already installed and is the expected version"
echo "compatible legacy olares-cli already installed and is the expected version"
echo ""
else
if [[ ! -f ${CLI_FILE} ]]; then
CLI_URL="${cdn_url}${REPO_PATH}${CLI_FILE}"
echo "downloading Olares installer from ${CLI_URL} ..."
echo "downloading beOS Pro installer from ${CLI_URL} ..."
echo ""
curl -Lo ${CLI_FILE} ${CLI_URL}
if [[ $? -ne 0 ]]; then
echo "error: failed to download Olares installer"
echo "error: failed to download beOS Pro installer"
exit 1
else
echo "Olares installer ${VERSION} download complete!"
echo "beOS Pro installer ${VERSION} download complete!"
echo ""
fi
fi
INSTALL_OLARES_CLI="/usr/local/bin/olares-cli"
INSTALL_OLARES_CLI="/usr/local/bin/beos-cli"
echo "unpacking Olares installer to $INSTALL_OLARES_CLI..."
echo ""
tar -zxf ${CLI_FILE} olares-cli && chmod +x olares-cli
@@ -230,7 +239,7 @@ CDN="--cdn-service ${cdn_url}"
if [[ -f $BASE_DIR/.prepared ]]; then
echo "file $BASE_DIR/.prepared detected, skip preparing phase"
echo ""
echo "please make sure the prepared Olares version is the same as the master, or there might be compatibility issues"
echo "please make sure the prepared beOS Pro version is the same as the master, or there might be compatibility issues"
echo ""
else
echo "running system prechecks ..."

View File

@@ -11,16 +11,16 @@ systemEnvs:
# TERMINUS_CERT_SERVICE_API,
# TERMINUS_DNS_SERVICE_API
- envName: OLARES_SYSTEM_REMOTE_SERVICE
default: "https://api.olares.com"
default: ""
type: url
editable: true
required: true
required: false
# the legacy DOWNLOAD_CDN_URL
- envName: OLARES_SYSTEM_CDN_SERVICE
default: "https://cdn.olares.com"
default: ""
type: url
editable: true
required: true
required: false
# docker hub mirror endpoint for docker.io registry
- envName: OLARES_SYSTEM_DOCKERHUB_SERVICE
type: url

View File

@@ -22,8 +22,8 @@ func NewDefaultCommand() *cobra.Command {
config.Init()
})
cmds := &cobra.Command{
Use: "olares-cli",
Short: "Olares Installer",
Use: "beos-cli",
Short: "beOS Pro Installer",
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: version.VERSION,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
@@ -40,7 +40,7 @@ func NewDefaultCommand() *cobra.Command {
return
},
}
cmds.Flags().BoolVar(&showVendor, "vendor", false, "show the vendor type of olares-cli")
cmds.Flags().BoolVar(&showVendor, "vendor", false, "show the vendor type of beos-cli")
cmds.AddCommand(osinfo.NewCmdInfo())
cmds.AddCommand(os.NewOSCommands()...)

View File

@@ -38,8 +38,8 @@ const (
DeployDir = "deploy"
OlaresDir = "olares"
DefaultBaseDir = ".olares"
DefaultDomainName = "olares.com"
DefaultBaseDir = ".beos-pro"
DefaultDomainName = "beos.local"
ManifestImage = "images.mf"
ManifestImageNode = "images.node.mf"
@@ -92,8 +92,8 @@ const (
)
const (
DefaultOlaresCDNService = "https://cdn.olares.com"
DefaultBashUrl = "olares.sh"
DefaultOlaresCDNService = ""
DefaultBashUrl = "beos.sh"
)
const (

View File

@@ -291,11 +291,11 @@ func (o *UserOperator) GetDenyAllPolicy(user *iamV1alpha2.User) string {
func (o *UserOperator) GetDomain() (string, error) {
terminus, err := o.terminusClient.Get(o.ctx, "terminus", metav1.GetOptions{})
if err != nil {
return "", err
return constants.DefaultLocalDomain(), nil
}
if name, ok := terminus.Spec.Settings[users.SettingsDomainNameKey]; !ok {
return "", errors.New("olares domain name not found")
return constants.DefaultLocalDomain(), nil
} else {
return name, nil
}

View File

@@ -126,16 +126,15 @@ func (h *Handler) handleBindingUserZone(req *restful.Request, resp *restful.Resp
}
if v, ok := user.Annotations[constants.UserTerminusWizardStatus]; ok {
if v != string(constants.WaitActivateVault) {
if constants.HasRemoteService() && v != string(constants.WaitActivateVault) {
response.HandleError(resp, errors.Errorf("user '%s' wizard status err, %s", user.Name, v))
return
}
}
domain, err := op.GetDomain()
if err != nil {
response.HandleError(resp, errors.Errorf("user '%s' get olares domain error, %v", user.Name, err))
return
if err != nil || domain == "" {
domain = constants.DefaultLocalDomain()
}
userPatches := []func(*iamV1alpha2.User){
@@ -189,8 +188,24 @@ func (h *Handler) handleActivate(req *restful.Request, resp *restful.Response) {
terminusName = userOp.GetTerminusName(user)
if terminusName == "" {
response.HandleError(resp, errors.New("activate system: no olares name, please ensure olares name is bound first"))
return
domain, domainErr := userOp.GetDomain()
if domainErr != nil || domain == "" {
domain = constants.DefaultLocalDomain()
}
terminusName = string(constants.NewTerminusName(user.Name, domain))
if err = userOp.UpdateUser(user, []func(*iamV1alpha2.User){
func(u *iamV1alpha2.User) {
if u.Annotations == nil {
u.Annotations = map[string]string{}
}
u.Annotations[constants.UserAnnotationTerminusNameKey] = terminusName
},
}); err != nil {
err = fmt.Errorf("activate system: failed to assign local beOS domain: %v", err)
klog.Error(err)
response.HandleError(resp, err)
return
}
}
if userOp.GetUserAnnotation(user, constants.UserAnnotationZoneKey) != "" || userOp.GetUserAnnotation(user, constants.UserTerminusWizardStatus) == string(constants.NetworkActivating) {
// already activated, or already in the process of activating, return success idempotently
@@ -254,6 +269,8 @@ func (h *Handler) handleActivate(req *restful.Request, resp *restful.Response) {
reverseProxyConf.EnableFRP = true
reverseProxyConf.FRPServer = payload.FRP.Host
reverseProxyConf.FRPAuthMethod = FRPAuthMethodJWS
} else if !constants.HasRemoteService() {
reverseProxyConf.ExternalNetworkOff = true
}
} else {
ownerUser, ownerErr := userOp.GetOwnerUser()
@@ -283,6 +300,29 @@ func (h *Handler) handleActivate(req *restful.Request, resp *restful.Response) {
return
}
if !constants.HasRemoteService() {
zone := constants.TerminusName(terminusName).UserZone()
if err = userOp.UpdateUser(user, []func(*iamV1alpha2.User){
func(u *iamV1alpha2.User) {
if u.Annotations == nil {
u.Annotations = map[string]string{}
}
u.Annotations[constants.UserAnnotationZoneKey] = zone
u.Annotations[constants.UserAnnotationIsEphemeral] = "false"
u.Annotations[constants.UserTerminusWizardStatus] = string(constants.WaitResetPassword)
u.Annotations[constants.UserTerminusWizardError] = ""
},
}); err != nil {
err = fmt.Errorf("activate system: failed to finalize local beOS setup: %v", err)
klog.Error(err)
response.HandleError(resp, err)
return
}
response.SuccessNoData(resp)
return
}
// all settings persisted, mark the status as activating
// to trigger the activation watcher
if err = userOp.UpdateUser(user, []func(*iamV1alpha2.User){

View File

@@ -3,6 +3,7 @@ package constants
import (
"fmt"
"net/url"
"os"
"strings"
)
@@ -75,7 +76,7 @@ var (
)
var (
OlaresRemoteService = "https://api.olares.com"
OlaresRemoteService = ""
APIPrefixCertService string
@@ -105,11 +106,15 @@ var (
)
const (
EnvBeOSSystemRemoteService = "BEOS_SYSTEM_REMOTE_SERVICE"
EnvBeOSDefaultDomain = "BEOS_DEFAULT_DOMAIN"
EnvOlaresSystemRemoteService = "OLARES_SYSTEM_REMOTE_SERVICE"
UserAuthorizationTokenKey = "X-Authorization"
HeaderBflUserKey = "X-BFL-USER"
)
const DefaultLocalDomainName = "beos.local"
var (
AnnotationGroup = "bytetrade.io"
@@ -312,6 +317,31 @@ const (
)
func ReloadEnvDependantVars() error {
remoteService := strings.TrimSpace(OlaresRemoteService)
if remoteService == "" {
if envRemote := strings.TrimSpace(os.Getenv(EnvBeOSSystemRemoteService)); envRemote != "" {
remoteService = envRemote
} else if envRemote := strings.TrimSpace(os.Getenv(EnvOlaresSystemRemoteService)); envRemote != "" {
remoteService = envRemote
}
}
OlaresRemoteService = remoteService
if remoteService == "" {
APIPrefixCertService = ""
APIPrefixDNSOPService = ""
APIFormatCertGenerateRequest = ""
APIFormatCertGenerateStatus = ""
APIFormatCertDownload = ""
APIDNSAddRecord = ""
APIFormatDNSDeleteRecord = ""
APIDNSAddCustomDomain = ""
APIDNSCheckCustomDomainCname = ""
APIDNSSetCloudFlareTunnel = ""
APIMyExternalIP = ""
return nil
}
APIPrefixCertService, err := url.JoinPath(OlaresRemoteService, "/cert")
if err != nil {
return err
@@ -345,6 +375,17 @@ func ReloadEnvDependantVars() error {
return nil
}
func HasRemoteService() bool {
return strings.TrimSpace(OlaresRemoteService) != ""
}
func DefaultLocalDomain() string {
if domain := strings.TrimSpace(os.Getenv(EnvBeOSDefaultDomain)); domain != "" {
return domain
}
return DefaultLocalDomainName
}
func init() {
ReloadEnvDependantVars()
}

View File

@@ -93,6 +93,10 @@ func (s *Subscriber) Do(ctx context.Context, obj interface{}, _ watchers.Action)
return s.markFailed(ctx, current, "no terminus name found")
}
if !constants.HasRemoteService() {
return s.markSuccess(ctx, current, constants.TerminusName(terminusName).UserZone())
}
if err := s.ensureL4ProxyDeployment(ctx); err != nil {
return err
}

View File

@@ -1,3 +1,3 @@
package constants
var OlaresRemoteService = "https://api.olares.com"
var OlaresRemoteService = ""