Skip to content

Instantly share code, notes, and snippets.

@reubenmiller
Last active March 2, 2023 17:39
Show Gist options
  • Save reubenmiller/d933886b2e85c55c10236cba15cce8a6 to your computer and use it in GitHub Desktop.
Save reubenmiller/d933886b2e85c55c10236cba15cce8a6 to your computer and use it in GitHub Desktop.
thin-edge.io install/bootstrapping script
#!/bin/sh
set -e
# TODO:
# * Run stop_services if there is an actual update (e.g. check if apt-get will actually do something or not)
# * Look at using a nicer command console progresss bar: printf "\033c";
# * Sometimes restart some services is required to get everything to work, e.g.
# * systemctl restart tedge-mapper-c8y
# * systemctl restart tedge-agent
# * systemctl restart c8y-log-plugin
# * Does it makes sense to preserve the certificate, and only prompt for passwords if the connection fails? e.g. to check if the certificate is trusted or not
# Support installing via gh command?
install_via_github_workflow() {
debian-packages-aarch64-unknown-linux-musl
RUN_ID=$(gh run list -R thin-edge/thin-edge.io --branch main --limit 1 --workflow build-workflow --json databaseId --jq '.[].databaseId')
gh run download "$RUN_ID" --pattern "debian-packages-aarch64-unknown-linux-musl" -R thin-edge/thin-edge.io
}
show_usage() {
echo "
DESCRIPTION:
Install and bootstrap thin-edge.io.
USAGE:
$0 [VERSION]
FLAGS:
WORKFLOW FLAGS
--clean/--no-clean Clean the device of any existing tedge installations before installing/connecting. Default False
--install/--no-install Install thin-edge.io. Default True
--connect/--no-connect Connect the mapper. Provide the type of mapper via '--mapper <name>'. Default True
--mapper <name> Name of the mapper to use when connecting (if user has specified the --connect option).
Defaults to 'c8y'
DEVICE FLAGS
--device-id <name> Use a specific device-id. A prefix will be added to the device id
--random Use a random device-id. This will override the --device-id flag value
--prefix <prefix> Device id prefix to add to the device-id or random device id. Defaults to 'tedge_'
INSTALLATION FLAGS
--version <version> Thin-edge.io version to install. Only applies for apt/script installation methods
--channel <release|main> Which channel, e.g. release or main to install thin-edge.io from
--install-method <apt|script|local> Type of method to use to install thin.edge.io. Checkout the 'Install method' section for more info
--install-sourcedir <path> Path where to look for local deb files to install
CUMULOCITY FLAGS
--c8y-url <host> Cumulocity url, e.g. 'mydomain.c8y.example.io'
--c8y-user <username> Cumulocity username (required when a new device certificate is created)
--c8y-password <password> Cumulocity password (required when a new device certificate is created)
INSTALL METHODS
local - Install the thin-edge.io .deb packages found locally on the disk under '--install-sourcedir <path>'
apt - Install using public APT repository
script - Install using the get-thin-edge_io.sh script from GitHub
EXAMPLES:
sudo -E $0
# Install and bootstrap thin-edge.io using the default settings
sudo -E $0 --device-id mydevice --bootstrap
# Install latest version and force bootstrapping using a given device id
sudo -E $0 --device-id mydevice --bootstrap --prefix ''
# Install latest version, and bootstrap with a device name without the default prefix
sudo -E $0 --random --bootstrap
# Install latest version and force bootstrapping using a random device id
sudo -E $0 --clean
# Clean the device before installing, then install and bootstrap
sudo -E $0 ./deb/
# Install and bootstrap using locally found tedge debian files under ./deb/ folder
sudo -E $0 --channel main
# Install the latest available version from the main repository. It will includes the latest version built from main
sudo -E $0 --channel release
# Install the latest available version from the release repository
sudo -E $0 --install-method script
# Install the latest version using the GitHub install script
"
}
fail () { echo "$1" >&2; exit 1; }
warning () { echo "$1" >&2; }
command_exists() { command -v "$1" >/dev/null 2>&1; }
uses_old_package_name() {
version="$1"
echo "$version" | grep --silent "^0\.[0-8]\."
}
uses_new_package_name() {
version="$1"
echo "$version" | grep --silent -e "^0\.[9]\." -e "^0\.[1-9][0-9]" -e "^[1-9]"
}
parse_domain() {
echo "$1" | sed -E 's|^.*://||g' | sed -E 's|/$||g'
}
banner() {
echo
echo "----------------------------------------------------------"
echo "$1"
echo "----------------------------------------------------------"
}
# Defaults
DEVICE_ID=${DEVICE_ID:-}
BOOTSTRAP=${BOOTSTRAP:-}
CONNECT=${CONNECT:-1}
INSTALL=${INSTALL:-1}
CLEAN=${CLEAN:-0}
VERSION=${VERSION:-}
INSTALL_METHOD="${INSTALL_METHOD:-}"
INSTALL_SOURCEDIR=${INSTALL_SOURCEDIR:-.}
MAX_CONNECT_ATTEMPTS=${MAX_CONNECT_ATTEMPTS:-2}
TEDGE_MAPPER=${TEDGE_MAPPER:-c8y}
ARCH=${ARCH:-}
USE_RANDOM_ID=${USE_RANDOM_ID:-0}
SHOULD_PROMPT=${SHOULD_PROMPT:-1}
CAN_PROMPT=0
UPLOAD_CERT_WAIT=${UPLOAD_CERT_WAIT:-1}
TEST_USER=${TEST_USER:-}
PREFIX=${PREFIX:-tedge_}
REPO_CHANNEL=${REPO_CHANNEL:-main}
C8Y_BASEURL=${C8Y_BASEURL:-}
get_debian_arch() {
arch=
if command_exists dpkg; then
arch=$(dpkg --print-architecture)
else
arch=$(uname -m)
case "$arch" in
armv7l|armv6l)
arch="armhf"
;;
aarch64)
arch="armhf"
;;
x86_64)
arch="amd64"
;;
*)
fail "Unsupported architecture. arch=$arch. This script only supports: [armv6l, armv7l, aarch64, x86_64]"
;;
esac
fi
echo "$arch"
}
generate_device_id() {
#
# Generate a device id
# Either use a raond device, or the device's hostname
#
if [ "$USE_RANDOM_ID" = "1" ]; then
if [ -n "$DEVICE_ID" ]; then
echo "Overriding the non-empty DEVICE_ID variable with a random name" >&2
fi
RANDOM_ID=
if [ -e /dev/urandom ]; then
RANDOM_ID=$(head -c 128 /dev/urandom | md5sum | head -c 10)
elif [ -e /dev/random ]; then
RANDOM_ID=$(head -c 128 /dev/random | md5sum | head -c 10)
fi
if [ -n "$RANDOM_ID" ]; then
DEVICE_ID="${PREFIX}${RANDOM_ID}"
else
warning "Could not generate a random id. Check if /dev/random is available or not"
fi
fi
if [ -n "$DEVICE_ID" ]; then
echo "$DEVICE_ID"
return
fi
if [ -n "$HOSTNAME" ]; then
echo "${PREFIX}${HOSTNAME}"
return
fi
if [ -n "$HOST" ]; then
echo "${PREFIX}${HOST}"
return
fi
echo "${PREFIX}unknown-device"
}
check_sudo() {
if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root or using sudo"
show_usage
exit 1
fi
}
# ---------------------------------------
# Argument parsing
# ---------------------------------------
while [ $# -gt 0 ]
do
case "$1" in
# ----------------------
# Clean
# ----------------------
# Should the device be cleaned prior to installation/bootstrapping
--clean)
CLEAN=1
BOOTSTRAP=1
;;
--no-clean)
CLEAN=0
;;
# ----------------------
# Install thin-edge.io
# ----------------------
--install)
INSTALL=1
;;
--no-install)
INSTALL=0
;;
# Which channel, e.g. release or main to install thin-edge.io from
--channel)
REPO_CHANNEL="$2"
shift
;;
# Tedge install options
--install-method)
# Either "apt", "script" or "local". Unknown options will use "script"
INSTALL_METHOD="$2"
shift
;;
--install-sourcedir)
# Source install directory if install method "local" is used. Location of the .deb files
INSTALL_SOURCEDIR="$2"
shift
;;
# ----------------------
# Bootstrap
# ----------------------
# Device id options
--device-id)
DEVICE_ID="$2"
shift
;;
--prefix)
PREFIX="$2"
shift
;;
--random)
USE_RANDOM_ID=1
;;
--bootstrap)
BOOTSTRAP=1
;;
--no-bootstrap)
BOOTSTRAP=0
;;
# ----------------------
# Connect mapper
# ----------------------
--connect)
CONNECT=1
;;
--no-connect)
CONNECT=0
;;
# Preferred mapper
--mapper)
TEDGE_MAPPER="$2"
shift
;;
# Cumulocity settings
--c8y-user)
C8Y_USER="$2"
shift
;;
--c8y-password)
C8Y_PASSWORD="$2"
shift
;;
--c8y-url)
C8Y_BASEURL="$2"
shift
;;
# ----------------------
# Misc
# ----------------------
# Should prompt for use if information is missing?
--prompt)
SHOULD_PROMPT=1
;;
--no-prompt)
SHOULD_PROMPT=0
;;
--help|-h)
show_usage
exit 0
;;
*)
POSITIONAL_ARGS="$1"
;;
esac
shift
done
set -- "$POSITIONAL_ARGS"
# ---------------------------------------
# Initializing
# ---------------------------------------
banner "Initializing"
# Try guessing the positional arguments
# If it looks like a directory, then use the as the install directory
# else use it has a version. But in both ca
while [ $# -gt 0 ]; do
if [ -d "$1" ] && [ -z "$INSTALL_SOURCEDIR" ]; then
echo "Detected install-sourcedir from positional argument. install-sourcedir=$1"
INSTALL_SOURCEDIR="$1"
elif [ -z "$VERSION" ]; then
echo "Detected version from positional argument. version=$1"
VERSION="$1"
else
fail "Unexpected positional arguments. Check the usage by provide '--help' for examples"
fi
shift
done
if [ -z "$REPO_CHANNEL" ]; then
if [ -z "$VERSION" ]; then
REPO_CHANNEL="release"
else
# Check if the user is requestion an official version or not
if echo "$VERSION" | grep --silent "^[0-9]\+.[0-9]\+.[0-9]\+$"; then
REPO_CHANNEL="release"
else
REPO_CHANNEL="main"
fi
fi
fi
#
# Detect settings
if command_exists tedge; then
if [ -z "$C8Y_BASEURL" ]; then
C8Y_BASEURL=$( tedge config list | grep "^c8y.url=" | sed 's/^c8y.url=//' )
fi
if [ -z "$DEVICE_ID" ]; then
DEVICE_ID=$( tedge config list | grep "^device.id=" | sed 's/^device.id=//' )
fi
# Detect if bootstrapping is required or not?
if [ -z "$BOOTSTRAP" ]; then
# If connection already exists, then assume bootstrapping does not need to occur again
# If already connected, then stick with using the same certificate
if tedge connect "$TEDGE_MAPPER" --test >/dev/null 2>&1; then
echo "No need for bootstrapping as $TEDGE_MAPPER mapper is already connected. You can force bootstrapping using either --bootstrap or --clean flags"
BOOTSTRAP=0
fi
fi
fi
if [ -z "$DEVICE_ID" ] || [ "$CLEAN" = 1 ]; then
DEVICE_ID=$(generate_device_id)
fi
if [ -z "$BOOTSTRAP" ]; then
BOOTSTRAP=1
fi
#
# Detect if the shell is running in interactive mode or not
if [ -t 0 ]; then
CAN_PROMPT=1
else
CAN_PROMPT=0
fi
#
# Auto detect the install method by checking the local install folder
#
# Only the script install method supports installing from older versions
if [ -z "$INSTALL_METHOD" ]; then
if [ -n "$(find "$INSTALL_SOURCEDIR" -type f -name "tedge_[0-9]*.deb")" ]; then
echo "Using local dpkg install method as local .deb files were found in folder: $INSTALL_SOURCEDIR"
INSTALL_METHOD=local
else
echo "Using apt install method as no local .deb files found in folder: $INSTALL_SOURCEDIR"
INSTALL_METHOD=apt
fi
else
if [ "$INSTALL_METHOD" != "apt" ] && [ "$INSTALL_METHOD" != "local" ] && [ "$INSTALL_METHOD" != "script" ]; then
fail "Invalid install method [$INSTALL_METHOD]. Only 'apt', 'local' or 'script' values are supported"
fi
fi
# ---------------------------------------
# Install helpers
# ---------------------------------------
configure_repos() {
LINUX_ARCH=$(uname -m)
REPO=""
REPO_SUFFIX=
case "$LINUX_ARCH" in
armv6l)
# armv6 need their own repo as the debian arch (armhf) collides with that of armv7 (which is also armhf)
REPO_SUFFIX="-armv6"
;;
esac
case "$REPO_CHANNEL" in
main|release)
REPO="tedge-${REPO_CHANNEL}${REPO_SUFFIX}"
;;
*)
fail "Invalid channel"
;;
esac
# Remove any other repos
DELETED_REPOS=$(sudo find /etc/apt/sources.list.d/ -type f \( -name "thinedge-*.list" -a ! -name "thinedge-${REPO}.list" -a ! -name "thinedge-community.list" \) -delete -print0)
if [ -n "$DELETED_REPOS" ]; then
echo "Cleaning other repos. $DELETED_REPOS"
sudo apt-get clean -y
# When changing repository channel the package needs to be removed but keep files
remove_tedge
fi
if command_exists bash; then
if [ ! -f "/etc/apt/sources.list.d/thinedge-${REPO}.list" ]; then
# Use a fixed distribution string to avoid guess work, and it does not really matter anyway
curl -1sLf \
"https://dl.cloudsmith.io/public/thinedge/${REPO}/setup.deb.sh" \
| distro=raspbian version=11 codename=bullseye sudo -E bash
else
echo "Repo (channel=${REPO_CHANNEL}) is already configured"
fi
COMMUNITY_REPO="community"
if [ ! -f "/etc/apt/sources.list.d/thinedge-${COMMUNITY_REPO}.list" ]; then
# Use a fixed distribution string to avoid guess work, and it does not really matter anyway
curl -1sLf \
"https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.deb.sh" \
| distro=raspbian version=11 codename=bullseye sudo -E bash
else
echo "Community Repo is already configured"
fi
else
# TODO: Support non-bash environments (but the cloudsmith script only supports bash)
fail "Bash is missing. Currently this script requires bash to setup the apt repos"
# deb [signed-by=/usr/share/keyrings/thinedge-tedge-release-archive-keyring.gpg] https://dl.cloudsmith.io/public/thinedge/tedge-release/deb/raspbian bullseye main
fi
}
install_via_apt() {
sudo apt-get update
if ! command -v mosquitto >/dev/null 2>&1; then
sudo apt-get install -y mosquitto
fi
if [ -n "$VERSION" ]; then
echo "Installing specific version: $VERSION"
sudo apt-get install -y --allow-downgrades \
tedge="$VERSION" \
tedge-mapper="$VERSION" \
tedge-agent="$VERSION" \
tedge-apt-plugin="$VERSION" \
c8y-configuration-plugin="$VERSION" \
c8y-log-plugin="$VERSION" \
c8y-remote-access-plugin="$VERSION"
# tedge-watchdog="$VERSION"
else
echo "Installing latest available version"
sudo apt-get install -y --allow-downgrades \
tedge \
tedge-mapper \
tedge-agent \
tedge-apt-plugin \
c8y-configuration-plugin \
c8y-log-plugin \
c8y-remote-access-plugin
# tedge-watchdog
fi
}
install_via_script() {
apt-get update
if [ -n "$VERSION" ]; then
echo "Installing specific version: $VERSION"
curl -fsSL https://raw.githubusercontent.com/thin-edge/thin-edge.io/main/get-thin-edge_io.sh | sudo sh -s "$VERSION"
else
echo "Installing latest official version"
curl -fsSL https://raw.githubusercontent.com/thin-edge/thin-edge.io/main/get-thin-edge_io.sh | sudo sh -s
fi
}
find_then_install_deb() {
SOURCE_DIR="$1"
PATTERN="$2"
find "$SOURCE_DIR" -type f -name "$PATTERN" -print0 \
| sort -r -V \
| head -z -n 1 \
| xargs -r0 sudo dpkg -i
}
install_via_local_files() {
if ! command_exists mosquitto; then
apt-get update
apt-get install -y mosquitto
fi
ARCH=$(get_debian_arch)
# Install tedge packages in same order as the get-thin-edge_io.sh script
find_then_install_deb "$INSTALL_SOURCEDIR" "tedge_[0-9]*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "tedge[_-]mapper_*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "tedge[_-]agent_*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "tedge[_-]apt[_-]plugin_*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "c8y[_-]configuration[_-]plugin_*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "c8y[_-]log[_-]plugin_*_$ARCH.deb"
find_then_install_deb "$INSTALL_SOURCEDIR" "tedge[_-]watchdog_*_$ARCH.deb"
}
clean_files() {
echo "Cleaning up tedge files"
sudo rm -f /etc/tedge/tedge.toml
sudo rm -f /etc/tedge/system.toml
sudo rm -f /var/log/tedge/agent/*.log
}
stop_services() {
if command_exists systemctl; then
sudo systemctl stop tedge-agent >/dev/null 2>&1 || true
sudo systemctl stop tedge-mapper-c8y >/dev/null 2>&1 || true
fi
}
purge_tedge() {
echo "Purging tedge"
# try stopping agent (as downgrading can have problems)
stop_services
# Remove existing config files as it can cause issues
sudo apt-get purge -y "tedge*" "c8y*"
# Refresh path, to ensure old binaries are still not being detected
hash -r
}
remove_tedge() {
echo "Removing tedge"
# try stopping agent (as downgrading can have problems)
stop_services
# Remove packages but keep configuration files
sudo apt-get remove -y "tedge*" "c8y*"
# Refresh path, to ensure old binaries are still not being detected
hash -r
}
install_tedge() {
configure_repos
# Check if any packages are incompatible, if so remove the previous version first
# Use new and old packages names, and check each of them one by one
packages="tedge tedge-mapper tedge-agent c8y-log-plugin c8y-configuration-plugin c8y-remote-access-plugin"
packages="$packages tedge tedge_mapper tedge_agent c8y_log_plugin c8y_configuration_plugin"
REMOVE_BEFORE_INSTALL=0
for package in $packages; do
if command_exists "$package"; then
EXISTING_VERSION=$("$package" --version | tail -1 | cut -d' ' -f2 || true)
if [ -n "$EXISTING_VERSION" ]; then
if uses_old_package_name "$VERSION" && uses_new_package_name "$EXISTING_VERSION"; then
REMOVE_BEFORE_INSTALL=1
break
fi
fi
fi
done
if [ "$REMOVE_BEFORE_INSTALL" = 1 ]; then
echo "Uninstalling tedge before downgrading because the package names changed"
# TODO: This does not work as the script requires bash and not sh
curl -sSL https://raw.githubusercontent.com/thin-edge/thin-edge.io/main/uninstall-thin-edge_io.sh | sudo bash -s remove
# Preserve c8y settings
if [ -n "$C8Y_BASEURL" ]; then
c8y_url=$(parse_domain "$C8Y_BASEURL")
sudo sh -c "
echo '[c8y]' > /etc/tedge/tedge.toml;
echo 'url = \"${c8y_url}\"' >> /etc/tedge/tedge.toml
"
else
sudo rm -f /etc/tedge/tedge.toml
fi
sudo rm -f /etc/tedge/system.toml
# Refresh path, to ensure old binaries are still not being detected
hash -r
fi
if [ "$INSTALL_METHOD" = "apt" ] && uses_old_package_name "$VERSION"; then
echo "Installing versions older than 0.9.0 is not supported via apt. Using the 'script' install method"
INSTALL_METHOD="script"
fi
case "$INSTALL_METHOD" in
apt)
echo "Installing thin-edge.io using apt"
if ! install_via_apt; then
echo "Installing via apt failed, installing via script"
install_via_script
fi
;;
local)
echo "Installing thin-edge.io using local files (from path=$INSTALL_SOURCEDIR)"
install_via_local_files
;;
*)
echo "Installing thin-edge.io using the 'get-thin-edge_io.sh' script"
# Remove system.toml as the latest official release does not support custom reboot command
rm -f /etc/tedge/system.toml
install_via_script
;;
esac
# Enable all services by default
if command -v systemctl >/dev/null 2>&1; then
systemctl enable mosquitto ||:
if [ "$TEDGE_MAPPER" = "c8y" ]; then
systemctl enable tedge-mapper-c8y ||:
fi
systemctl enable tedge-agent ||:
systemctl enable c8y-log-plugin ||:
systemctl enable c8y-configuration-plugin ||:
systemctl enable ssh ||:
fi
if command_exists apt; then
echo "Installing community plugins"
sudo apt-get install -y c8y-command-plugin
fi
}
prompt_value() {
user_text="$1"
value="$2"
SHOULD_PROMPT=1
CAN_PROMPT=1
if [ "$SHOULD_PROMPT" = 1 ] && [ "$CAN_PROMPT" = 1 ]; then
printf "\n%s (%s): " "$user_text" "${value:-not set}" >&2
read -r user_input
if [ -n "$user_input" ]; then
value="$user_input"
fi
fi
echo "$value"
}
bootstrap_c8y() {
# If bootstrapping is called, then it assumes the full bootstrapping
# needs to be done.
# Force disconnection of mapper before setting url
sudo tedge disconnect "$TEDGE_MAPPER" >/dev/null 2>&1 || true
DEVICE_ID=$(prompt_value "Enter the device.id" "$DEVICE_ID")
# Remove existing certificate if it does not match
if tedge cert show >/dev/null 2>&1; then
echo "Removing existing device certificate"
sudo tedge cert remove
fi
echo "Creating certificate: $DEVICE_ID"
sudo tedge cert create --device-id "$DEVICE_ID"
# Cumulocity URL
C8Y_BASEURL=$(prompt_value "Enter the Cumulocity IoT url" "$C8Y_BASEURL")
# Normalize url, by stripping url schema
if [ -n "$C8Y_BASEURL" ]; then
C8Y_BASEURL=$(parse_domain "$C8Y_BASEURL")
fi
echo "Setting c8y.url to $C8Y_BASEURL"
sudo tedge config set c8y.url "$C8Y_BASEURL"
C8Y_USER=$(prompt_value "Enter your Cumulocity user" "$C8Y_USER")
if [ -n "$C8Y_USER" ]; then
echo "Uploading certificate to Cumulocity using tedge"
if [ -n "$C8Y_PASSWORD" ]; then
C8YPASS="$C8Y_PASSWORD" tedge cert upload c8y --user "$C8Y_USER"
else
echo ""
tedge cert upload c8y --user "$C8Y_USER"
fi
else
fail "When manually bootstrapping you have to upload the certificate again as the device certificate is recreated"
fi
# Grace period for the server to process the certificate
# but it is not critical for the connection, as the connection
# supports automatic retries, but it can improve the first connection success rate
sleep "$UPLOAD_CERT_WAIT"
}
connect_mappers() {
# retry connection attempts
sudo tedge disconnect "$TEDGE_MAPPER" || true
CONNECT_ATTEMPT=0
while true; do
CONNECT_ATTEMPT=$((CONNECT_ATTEMPT + 1))
if sudo tedge connect "$TEDGE_MAPPER"; then
break
else
if [ "$CONNECT_ATTEMPT" -ge "$MAX_CONNECT_ATTEMPTS" ]; then
echo "Failed after $CONNECT_ATTEMPT connection attempts. Giving up"
exit 2
fi
fi
echo "WARNING: Connection attempt failed ($CONNECT_ATTEMPT of $MAX_CONNECT_ATTEMPTS)! Retrying to connect in 2s"
sleep 2
done
}
display_banner_c8y() {
echo
echo "----------------------------------------------------------"
echo "Device information"
echo "----------------------------------------------------------"
echo ""
echo "tedge.version: $(tedge --version 2>/dev/null | tail -1 | cut -d' ' -f2)"
echo "device.id: ${DEVICE_ID}"
DEVICE_SEARCH=$(echo "$DEVICE_ID" | sed 's/-/*/g')
echo "Cumulocity IoT: https://${C8Y_BASEURL}/apps/devicemanagement/index.html#/assetsearch?filter=*${DEVICE_SEARCH}*"
echo ""
echo "----------------------------------------------------------"
}
configure_test_user() {
if [ -n "$TEST_USER" ]; then
if ! id -u "$TEST_USER" >/dev/null 2>&1; then
TEST_USER_SHELL="/bin/sh"
if command_exists bash; then
TEST_USER_SHELL="$(which bash)"
fi
sudo useradd -ms "${TEST_USER_SHELL}" "${TEST_USER}" && echo "${TEST_USER}:${TEST_USER}" | sudo chpasswd && sudo adduser "${TEST_USER}" sudo
fi
# TODO: Should the test user be restricted to specific commands?
# sudo sh -c "echo 'tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init, /sbin/shutdown, /bin/kill, /bin/systemctl status, /bin/systemctl restart' > /etc/sudoers.d/tedge"
mkdir -p /etc/ssh/authorized-keys/
if [ ! -f "/etc/ssh/authorized-keys/$TEST_USER" ]; then
echo "Creating empty authorized-keys file: /etc/ssh/authorized-keys/$TEST_USER"
touch "/etc/ssh/authorized-keys/$TEST_USER"
fi
fi
}
post_configure() {
echo "Setting sudoers.d config"
sudo sh -c "echo '%sudo ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/all"
sudo sh -c "echo 'tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init, /sbin/shutdown, /bin/kill, /bin/systemctl status, /bin/systemctl status *, /bin/systemctl restart *' > /etc/sudoers.d/tedge"
# optionally create a test user to show-off c8y-remote-access-plugin
# no user is created if the test user name is not defined
configure_test_user
}
main() {
# ---------------------------------------
# Preparation (clean and disconnect)
# ---------------------------------------
# Cleanup device as sometimes the existing state can affect tests
if [ "$CLEAN" = 1 ]; then
banner "Preparing device"
purge_tedge
clean_files
fi
# ---------------------------------------
# Install
# ---------------------------------------
if [ "$INSTALL" = 1 ]; then
banner "Installing thin-edge.io"
install_tedge
fi
# ---------------------------------------
# Bootstrap
# ---------------------------------------
if [ "$BOOTSTRAP" = 1 ]; then
banner "Bootstraping device"
# Check if tedge is installed before trying to bootstrap
if ! command_exists tedge; then
fail "Can not bootstrap as tedge is not installed"
fi
bootstrap_c8y
fi
# ---------------------------------------
# Connect
# ---------------------------------------
if [ "$CONNECT" = 1 ]; then
banner "Connecting mapper"
connect_mappers
fi
# ---------------------------------------
# Post setup
# ---------------------------------------
if [ "$BOOTSTRAP" = 1 ] || [ "$CONNECT" = 1 ]; then
display_banner_c8y
fi
post_configure
}
main
@reubenmiller
Copy link
Author

reubenmiller commented Mar 2, 2023

Instructions

  1. Download the script

    wget https://gist.githubusercontent.com/reubenmiller/d933886b2e85c55c10236cba15cce8a6/raw/d7060950c1b4601200c1a7452f646504a0778ae3/bootstrap.sh
  2. Make the script executable

    chmod +x bootstrap.sh
  3. Execute it

    sudo -E ./bootstrap.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment