github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/install/install_unix.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  //go:build linux || freebsd || netbsd || openbsd
     5  // +build linux freebsd netbsd openbsd
     6  
     7  package install
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"path"
    13  	"time"
    14  
    15  	"github.com/keybase/client/go/libkb"
    16  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    17  )
    18  
    19  // Similar to the Brew install on OSX, the Unix install happens in two steps.
    20  // First, the system package manager installs all the binaries as root. Second,
    21  // an autostart file needs to be written to the user's home dir, so that
    22  // Keybase launches when that user logs in. The second step is done the first
    23  // time the user starts Keybase.
    24  //
    25  // ".desktop" files and the ~/.config/autostart directory are part of the
    26  // freedesktop.org set of standards, which the popular desktop environments
    27  // like Gnome and KDE all support. See
    28  // http://standards.freedesktop.org/desktop-entry-spec/latest/.
    29  
    30  const backtick = "`"
    31  
    32  const autostartFileText = `# This file is generated by Keybase, along with a sentinel
    33  # file at ~/.config/keybase/autostart_created. As long as the sentinel exists,
    34  # this file won't be changed automatically, so you can edit it or delete it
    35  # as you like.
    36  
    37  # To toggle autostart on, run
    38  # ` + backtick + `keybase ctl autostart --enable` + backtick + `
    39  # or to toggle off,
    40  # ` + backtick + `keybase ctl autostart --disable` + backtick + `.
    41  # Note that this will overwrite any changes you have made.
    42  
    43  [Desktop Entry]
    44  Name=Keybase
    45  Comment=Keybase Filesystem Service and GUI
    46  Type=Application
    47  Exec=env KEYBASE_AUTOSTART=1 run_keybase
    48  `
    49  
    50  const disabledAutostartFileText = autostartFileText + `
    51  Hidden=true
    52  X-GNOME-Autostart-enabled=false
    53  `
    54  
    55  const sentinelFileText = `This file is created the first time Keybase starts, along with
    56  ~/.config/autostart/keybase_autostart.desktop. As long as this
    57  file exists, the autostart file won't be automatically recreated.
    58  `
    59  
    60  func autostartDir(context Context) string {
    61  	// strip off the "keybase" folder on the end of the config dir
    62  	return path.Join(context.GetConfigDir(), "..", "autostart")
    63  }
    64  
    65  func autostartFilePath(context Context) string {
    66  	return path.Join(autostartDir(context), "keybase_autostart.desktop")
    67  }
    68  
    69  func sentinelFilePath(context Context) string {
    70  	return path.Join(context.GetConfigDir(), "autostart_created")
    71  }
    72  
    73  func ToggleAutostart(context Context, on bool, forAutoinstall bool) error {
    74  	if forAutoinstall {
    75  		_, err := os.Stat(sentinelFilePath(context))
    76  		if err == nil {
    77  			// The sentinel exists. Don't recreate the autostart file.
    78  			return nil
    79  		} else if !os.IsNotExist(err) {
    80  			// The error is something unexpected. Return it.
    81  			return err
    82  		}
    83  		// The sentinel doesn't exist. Create the autostart file, and then create
    84  		// the sentinel. This might stomp on old user edits one time, but we need
    85  		// to do that to add in the KEYBASE_AUTOSTART variable.
    86  	}
    87  
    88  	err := os.MkdirAll(autostartDir(context), 0755)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	var text string
    94  	if on {
    95  		text = autostartFileText
    96  	} else {
    97  		text = disabledAutostartFileText
    98  	}
    99  
   100  	if forAutoinstall {
   101  		fmt.Println(`Installing autostart file. Manage autostart settings with ` + backtick + `keybase ctl autostart` + backtick + `.`)
   102  	}
   103  
   104  	err = os.WriteFile(autostartFilePath(context), []byte(text), 0644)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	if forAutoinstall {
   110  		err = os.WriteFile(sentinelFilePath(context), []byte(sentinelFileText), 0644)
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  
   116  	return nil
   117  }
   118  
   119  func GetAutostart(context Context) keybase1.OnLoginStartupStatus {
   120  	bs, _ := os.ReadFile(autostartFilePath(context))
   121  	switch string(bs) {
   122  	case autostartFileText:
   123  		return keybase1.OnLoginStartupStatus_ENABLED
   124  	case disabledAutostartFileText:
   125  		return keybase1.OnLoginStartupStatus_DISABLED
   126  	}
   127  	return keybase1.OnLoginStartupStatus_UNKNOWN
   128  }
   129  
   130  // AutoInstall installs auto start on unix
   131  func AutoInstall(context Context, _ string, _ bool, timeout time.Duration, log Log) (newProc bool, err error) {
   132  	err = os.MkdirAll(context.GetConfigDir(), 0755)
   133  	if err != nil {
   134  		return false, err
   135  	}
   136  
   137  	err = ToggleAutostart(context, true, true)
   138  	if err != nil {
   139  		// Ignore if we couldn't write to autostart
   140  		log.Errorf("Autoinstall failed: %s.", err)
   141  	}
   142  
   143  	return false, nil
   144  }
   145  
   146  // CheckIfValidLocation is not used on unix
   147  func CheckIfValidLocation() error {
   148  	return nil
   149  }
   150  
   151  // KBFSBinPath returns the path to the KBFS executable
   152  func KBFSBinPath(runMode libkb.RunMode, binPath string) (string, error) {
   153  	return kbfsBinPathDefault(runMode, binPath)
   154  }
   155  
   156  // kbfsBinName returns the name for the KBFS executable
   157  func kbfsBinName() string {
   158  	return "kbfsfuse"
   159  }
   160  
   161  func updaterBinName() (string, error) {
   162  	return "", fmt.Errorf("Updater isn't supported on unix")
   163  }
   164  
   165  // RunApp starts the app
   166  func RunApp(context Context, log Log) error {
   167  	// TODO: Start app, see run_keybase: /opt/keybase/Keybase
   168  	return nil
   169  }
   170  
   171  func InstallLogPath() (string, error) {
   172  	return "", nil
   173  }
   174  
   175  // WatchdogLogPath doesn't exist on linux as an independent log file
   176  func WatchdogLogPath(string) (string, error) {
   177  	return "", nil
   178  }
   179  
   180  func SystemLogPath() string {
   181  	return ""
   182  }