44#
55# Install OpenShell from a GitHub release.
66#
7- # Linux installs either the Debian or RPM packages from the selected release.
8- # Apple Silicon macOS installs the generated Homebrew formula, so Homebrew owns
9- # the binary layout and launchd service lifecycle.
7+ # Linux prefers the Snap path when snapd is available. Otherwise Linux installs
8+ # the Debian or RPM packages from the selected release. Apple Silicon macOS
9+ # installs the generated Homebrew formula, so Homebrew owns the binary layout
10+ # and launchd service lifecycle.
1011#
1112set -e
1213
@@ -21,6 +22,12 @@ HOMEBREW_FORMULA_NAME="openshell"
2122BREAKING_RELEASE_VERSION=" 0.0.37"
2223LINUX_PACKAGE_GLIBC_MIN_VERSION=" 2.31"
2324UPGRADE_NOTICE_ACK=" ${OPENSHELL_ACK_BREAKING_UPGRADE:- } "
25+ SNAP_PACKAGE_NAME=" openshell"
26+ SNAP_DOCKER_SLOT=" docker:docker-daemon"
27+ SNAP_DEFAULT_CHANNEL=" latest/stable"
28+ SNAP_DEV_CHANNEL=" latest/edge"
29+ LINUX_INSTALL_METHOD_SNAP=" snap"
30+ LINUX_INSTALL_METHOD_CLASSIC=" classic"
2431
2532info () {
2633 printf ' %s: %s\n' " $APP_NAME " " $* " >&2
@@ -54,13 +61,27 @@ ENVIRONMENT VARIABLES:
5461 OPENSHELL_ACK_BREAKING_UPGRADE
5562 Set to 1 only after backing up and cleaning up a
5663 pre-v0.0.37 installation.
64+ OPENSHELL_INSTALL_METHOD
65+ Linux only. Selects snap or classic. Accepted values:
66+ snap install from the Snap Store
67+ classic install via dpkg or rpm
68+ When unset, snap is used when snapd is available and
69+ running, otherwise the classic package manager is used.
70+ Set OPENSHELL_INSTALL_METHOD=classic on distros where
71+ snapd is not desired.
5772
5873NOTES:
5974 When OPENSHELL_VERSION is unset, this resolves the latest tagged release
6075 from ${GITHUB_URL} /releases/latest.
6176
62- Linux installs the Debian package on amd64/arm64 or the RPM packages on
63- x86_64/aarch64, depending on the host package manager.
77+ Linux prefers the snap method when snapd is available. The Snap channel
78+ follows OPENSHELL_VERSION: 'dev' selects ${SNAP_DEV_CHANNEL:- latest/ edge} ,
79+ tagged releases select ${SNAP_DEFAULT_CHANNEL:- latest/ stable} . snapd
80+ manages the gateway as the 'openshell.gateway' service.
81+
82+ On systems without snapd, Linux installs the Debian package on
83+ amd64/arm64 or the RPM packages on x86_64/aarch64, depending on the
84+ host package manager.
6485 macOS installs the release Homebrew formula on Apple Silicon and starts a
6586 brew services-backed local gateway.
6687EOF
@@ -477,6 +498,69 @@ linux_package_method() {
477498 fi
478499}
479500
501+ has_snapd () {
502+ if [ " ${OPENSHELL_INSTALL_SH_TEST:- 0} " = " 1" ]; then
503+ case " ${OPENSHELL_TEST_SNAPD_AVAILABLE:- 0} " in
504+ 1) return 0 ;;
505+ 0) return 1 ;;
506+ esac
507+ fi
508+
509+ command -v snap > /dev/null 2>&1 || return 1
510+ [ -S /run/snapd.socket ] || [ -S /var/run/snapd.socket ] || return 1
511+ return 0
512+ }
513+
514+ host_supports_native_package () {
515+ has_cmd dpkg || has_cmd rpm
516+ }
517+
518+ check_docker_not_installed_natively () {
519+ if ! command -v docker > /dev/null 2>&1 ; then
520+ return 0
521+ fi
522+
523+ _docker_path=" $( command -v docker) "
524+ case " $_docker_path " in
525+ /snap/bin/docker | /var/lib/snapd/snap/bin/docker)
526+ return 0
527+ ;;
528+ esac
529+
530+ error " Docker is installed via a non-snap package. The Docker snap cannot be installed alongside a native Docker installation. Please uninstall the native Docker package and try again, or install OpenShell via dpkg/rpm instead of snap."
531+ }
532+
533+ resolve_linux_install_method () {
534+ _method=" ${OPENSHELL_INSTALL_METHOD:- } "
535+ if [ -n " $_method " ]; then
536+ case " $_method " in
537+ " $LINUX_INSTALL_METHOD_SNAP " | " $LINUX_INSTALL_METHOD_CLASSIC " )
538+ echo " $_method "
539+ return 0
540+ ;;
541+ * )
542+ error " OPENSHELL_INSTALL_METHOD must be '${LINUX_INSTALL_METHOD_SNAP} ' or '${LINUX_INSTALL_METHOD_CLASSIC} ' (got: ${_method} )"
543+ ;;
544+ esac
545+ fi
546+
547+ if has_snapd; then
548+ echo " $LINUX_INSTALL_METHOD_SNAP "
549+ elif host_supports_native_package; then
550+ echo " $LINUX_INSTALL_METHOD_CLASSIC "
551+ else
552+ error " OpenShell Linux installs require either snapd or dpkg/rpm"
553+ fi
554+ }
555+
556+ resolve_snap_channel () {
557+ if [ " ${RELEASE_TAG:- } " = " dev" ]; then
558+ echo " $SNAP_DEV_CHANNEL "
559+ else
560+ echo " $SNAP_DEFAULT_CHANNEL "
561+ fi
562+ }
563+
480564set_linux_target_runtime_dir () {
481565 if [ " $( id -u) " -eq " $TARGET_UID " ] && [ -n " ${XDG_RUNTIME_DIR:- } " ]; then
482566 TARGET_RUNTIME_DIR=" $XDG_RUNTIME_DIR "
@@ -866,6 +950,44 @@ print_gateway_add_output() {
866950 done
867951}
868952
953+ install_linux_snap () {
954+ _channel=" $( resolve_snap_channel) "
955+
956+ info " installing ${APP_NAME} from the Snap Store (channel: ${_channel} )..."
957+ as_root snap install " $SNAP_PACKAGE_NAME " --channel=" $_channel "
958+
959+ # TODO: Remove this check once snapd 2.76 is released, which lifts the
960+ # restriction preventing snap packages from being installed alongside a
961+ # native Docker installation. At that point the docker snap can be
962+ # pre-installed unconditionally.
963+ check_docker_not_installed_natively
964+
965+ info " pre-installing the Docker snap..."
966+ as_root snap install docker
967+
968+ info " connecting required interfaces..."
969+ as_root snap connect " ${SNAP_PACKAGE_NAME} :docker" " $SNAP_DOCKER_SLOT " || \
970+ warn " could not connect ${SNAP_PACKAGE_NAME} :docker to ${SNAP_DOCKER_SLOT} ; the Docker driver will not work until this is fixed"
971+ for _plug in log-observe system-observe ssh-keys; do
972+ as_root snap connect " ${SNAP_PACKAGE_NAME} :${_plug} " || \
973+ warn " could not connect ${SNAP_PACKAGE_NAME} :${_plug} ; some features may be limited"
974+ done
975+
976+ info " installed ${APP_NAME} from the Snap Store (${_channel} )"
977+ info " snapd manages the OpenShell gateway as the 'openshell.gateway' service."
978+ info " "
979+ info " Next steps:"
980+ info " snap services openshell"
981+ info " openshell status"
982+ info " openshell gateway add https://127.0.0.1:17670 --local --name openshell"
983+ if ! command -v snap > /dev/null 2>&1 ; then
984+ info " "
985+ info " note: the 'openshell' binary is provided by the snap."
986+ info " Make sure snap is in your PATH, or invoke openshell with the"
987+ info " absolute path, before running the next-step commands."
988+ fi
989+ }
990+
869991install_linux_deb () {
870992 check_linux_deb_platform
871993 set_linux_target_runtime_dir
@@ -1033,16 +1155,23 @@ main() {
10331155
10341156 case " $PLATFORM " in
10351157 linux)
1036- require_linux_package_glibc
1037- case " $( linux_package_method) " in
1038- deb)
1039- install_linux_deb
1040- ;;
1041- rpm)
1042- install_linux_rpm
1158+ case " $( resolve_linux_install_method) " in
1159+ " $LINUX_INSTALL_METHOD_SNAP " )
1160+ install_linux_snap
10431161 ;;
1044- * )
1045- error " unsupported Linux package method"
1162+ " $LINUX_INSTALL_METHOD_CLASSIC " )
1163+ require_linux_package_glibc
1164+ case " $( linux_package_method) " in
1165+ deb)
1166+ install_linux_deb
1167+ ;;
1168+ rpm)
1169+ install_linux_rpm
1170+ ;;
1171+ * )
1172+ error " unsupported Linux package method"
1173+ ;;
1174+ esac
10461175 ;;
10471176 esac
10481177 ;;
0 commit comments