@@ -2,6 +2,7 @@ package cli
22
33import (
44 "context"
5+ "encoding/base64"
56 "errors"
67 "fmt"
78 "os"
@@ -13,14 +14,11 @@ import (
1314 "github.com/psviderski/uncloud/internal/cli/tui"
1415 "github.com/psviderski/uncloud/internal/machine/api/pb"
1516 "github.com/psviderski/uncloud/internal/sshexec"
17+ "github.com/psviderski/uncloud/scripts"
1618 "google.golang.org/protobuf/types/known/emptypb"
1719)
1820
19- const (
20- // TODO: support pinning the script version to the CLI version.
21- installScriptURL = "https://raw.githubusercontent.com/psviderski/uncloud/refs/heads/main/scripts/install.sh"
22- rootUser = "root"
23- )
21+ const rootUser = "root"
2422
2523type RemoteMachine struct {
2624 User string
@@ -30,26 +28,30 @@ type RemoteMachine struct {
3028 UseSSHGo bool // Use Go's built-in SSH library instead of the system ssh CLI command.
3129}
3230
33- func installCmd (user string , version string ) string {
31+ // installCmd returns a shell command that decodes the base64-encoded install script and pipes it
32+ // into bash, optionally via sudo and with UNCLOUD_* environment variables set.
33+ func installCmd (scriptBase64 , user , version string ) string {
3434 sudoPrefix := ""
3535 var env []string
3636
3737 // Add the SSH user (non-root) to the uncloud group to allow access to the Uncloud daemon unix socket.
3838 if user != rootUser {
39- sudoPrefix = "sudo"
39+ sudoPrefix = "sudo "
4040 env = append (env , "UNCLOUD_GROUP_ADD_USER=" + sshexec .Quote (user ))
4141 }
4242 if version != "" {
4343 env = append (env , "UNCLOUD_VERSION=" + sshexec .Quote (version ))
4444 }
4545
46- envCmd := strings .Join (env , " " )
47- curlBashCmd := fmt .Sprintf ("curl -fsSL %s | %s %s bash" , sshexec .Quote (installScriptURL ), sudoPrefix , envCmd )
46+ envPrefix := ""
47+ if len (env ) > 0 {
48+ envPrefix = strings .Join (env , " " ) + " "
49+ }
4850
49- return curlBashCmd
51+ return fmt . Sprintf ( "printf '%%s' %s | base64 -d | %s%sbash" , scriptBase64 , sudoPrefix , envPrefix )
5052}
5153
52- // provisionMachine provisions the remote machine by downloading the Uncloud install script from GitHub and running it .
54+ // provisionMachine provisions the remote machine by running the Uncloud install script embedded in the uc CLI .
5355// If version is specified, it will be passed to the install script as UNCLOUD_VERSION environment variable.
5456func provisionMachine (ctx context.Context , exec sshexec.Executor , version string ) error {
5557 user , err := exec .Run (ctx , "whoami" )
@@ -88,13 +90,10 @@ func provisionMachine(ctx context.Context, exec sshexec.Executor, version string
8890 }
8991 }
9092
91- cmd := installCmd (user , version )
92-
93- fmt .Println ("Downloading Uncloud install script:" , installScriptURL )
94-
95- cmd = sshexec .QuoteCommand ("bash" , "-c" , "set -o pipefail; " + cmd )
93+ scriptBase64 := base64 .StdEncoding .EncodeToString ([]byte (scripts .InstallScript ))
94+ cmd := sshexec .QuoteCommand ("bash" , "-c" , "set -o pipefail; " + installCmd (scriptBase64 , user , version ))
9695 if err = exec .Stream (ctx , cmd , os .Stdout , os .Stderr ); err != nil {
97- return fmt .Errorf ("download and run install script: %w" , err )
96+ return fmt .Errorf ("run install script: %w" , err )
9897 }
9998 return nil
10099}
0 commit comments