mirror of
https://github.com/Screenly/Anthias.git
synced 2025-12-23 22:38:05 -05:00
417 lines
12 KiB
Bash
Executable File
417 lines
12 KiB
Bash
Executable File
#!/bin/bash -e
|
|
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
# -*- sh-basic-offset: 4 -*-
|
|
|
|
set -euo pipefail
|
|
|
|
BRANCH="master"
|
|
ANSIBLE_PLAYBOOK_ARGS=()
|
|
REPOSITORY="https://github.com/Screenly/Anthias.git"
|
|
ANTHIAS_REPO_DIR="/home/${USER}/screenly"
|
|
GITHUB_API_REPO_URL="https://api.github.com/repos/Screenly/Anthias"
|
|
GITHUB_RELEASES_URL="https://github.com/Screenly/Anthias/releases"
|
|
GITHUB_RAW_URL="https://raw.githubusercontent.com/Screenly/Anthias"
|
|
DOCKER_TAG="latest"
|
|
UPGRADE_SCRIPT_PATH="${ANTHIAS_REPO_DIR}/bin/upgrade_containers.sh"
|
|
ARCHITECTURE=$(uname -m)
|
|
DISTRO_VERSION=$(lsb_release -rs)
|
|
|
|
INTRO_MESSAGE=(
|
|
"Anthias requires a dedicated Raspberry Pi and an SD card."
|
|
"You will not be able to use the regular desktop environment once installed."
|
|
""
|
|
"When prompted for the version, you can choose between the following:"
|
|
" - **latest:** Installs the latest version from the \`master\` branch."
|
|
" - **tag:** Installs a pinned version based on the tag name."
|
|
""
|
|
"Take note that \`latest\` is a rolling release."
|
|
)
|
|
MANAGE_NETWORK_PROMPT=(
|
|
"Would you like Anthias to manage the network for you?"
|
|
)
|
|
VERSION_PROMPT=(
|
|
"Which version of Anthias would you like to install?"
|
|
)
|
|
VERSION_PROMPT_CHOICES=(
|
|
"latest"
|
|
"tag"
|
|
)
|
|
SYSTEM_UPGRADE_PROMPT=(
|
|
"Would you like to perform a full system upgrade as well?"
|
|
)
|
|
SUDO_ARGS=()
|
|
|
|
TITLE_TEXT=$(cat <<EOF
|
|
@@@@@@@@@
|
|
@@@@@@@@@@@@ d8888 888 888 d8b
|
|
@@@@@@@ @@@ @@ d88888 888 888 Y8P
|
|
@@@@@@@@@@@@@ @@@ d88P888 888 888
|
|
@@@@@@@@@@ @@ @@@@ d88P 888 88888b. 888888 88888b. 888 8888b. .d8888b
|
|
@@@@@ @@@@@@@@ d88P 888 888 "88b 888 888 "88b 888 "88b 88K
|
|
@@@%: :@@@@@@@@ d88P 888 888 888 888 888 888 888 .d888888 "Y8888b.
|
|
@@-:::::::%@@@@@@@ d8888888888 888 888 Y88b. 888 888 888 888 888 X88
|
|
@=::::=%@@@@@@@@ d88P 888 888 888 "Y888 888 888 888 "Y888888 88888P'
|
|
@@@@@@@@@@
|
|
EOF
|
|
)
|
|
|
|
# Install gum from Charm.sh.
|
|
# Gum helps you write shell scripts more efficiently.
|
|
function install_prerequisites() {
|
|
if [ -f /usr/bin/gum ] && [ -f /usr/bin/jq ]; then
|
|
return
|
|
fi
|
|
|
|
sudo apt -y update && sudo apt -y install gnupg
|
|
|
|
sudo mkdir -p /etc/apt/keyrings
|
|
curl -fsSL https://repo.charm.sh/apt/gpg.key | \
|
|
sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg
|
|
echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" \
|
|
| sudo tee /etc/apt/sources.list.d/charm.list
|
|
|
|
sudo apt -y update && sudo apt -y install gum jq
|
|
}
|
|
|
|
function display_banner() {
|
|
local TITLE="${1:-Anthias Installer}"
|
|
local COLOR="212"
|
|
|
|
gum style \
|
|
--foreground "${COLOR}" \
|
|
--border-foreground "${COLOR}" \
|
|
--border "thick" \
|
|
--margin "1 1" \
|
|
--padding "2 6" \
|
|
"${TITLE}"
|
|
}
|
|
|
|
function display_section() {
|
|
local TITLE="${1:-Section}"
|
|
local COLOR="#00FFFF"
|
|
|
|
gum style \
|
|
--foreground "${COLOR}" \
|
|
--border-foreground "${COLOR}" \
|
|
--border "thick" \
|
|
--align center \
|
|
--width 95 \
|
|
--margin "1 1" \
|
|
--padding "1 4" \
|
|
"${TITLE}"
|
|
}
|
|
|
|
function initialize_ansible() {
|
|
sudo mkdir -p /etc/ansible
|
|
echo -e "[local]\nlocalhost ansible_connection=local" | \
|
|
sudo tee /etc/ansible/hosts > /dev/null
|
|
}
|
|
|
|
function initialize_locales() {
|
|
display_section "Initialize Locales"
|
|
|
|
if [ ! -f /etc/locale.gen ]; then
|
|
# No locales found. Creating locales with default UK/US setup.
|
|
echo -e "en_GB.UTF-8 UTF-8\nen_US.UTF-8 UTF-8" | \
|
|
sudo tee /etc/locale.gen > /dev/null
|
|
sudo locale-gen
|
|
fi
|
|
}
|
|
|
|
function install_packages() {
|
|
display_section "Install Packages via APT"
|
|
|
|
local APT_INSTALL_ARGS=(
|
|
"git"
|
|
"libffi-dev"
|
|
"libssl-dev"
|
|
"whois"
|
|
)
|
|
|
|
if [ "$DISTRO_VERSION" -ge 12 ]; then
|
|
APT_INSTALL_ARGS+=(
|
|
"python3-dev"
|
|
"python3-full"
|
|
)
|
|
else
|
|
APT_INSTALL_ARGS+=(
|
|
"python3"
|
|
"python3-dev"
|
|
"python3-pip"
|
|
"python3-venv"
|
|
)
|
|
fi
|
|
|
|
if [ "$MANAGE_NETWORK" = "Yes" ]; then
|
|
APT_INSTALL_ARGS+=("network-manager")
|
|
fi
|
|
|
|
if [ "$ARCHITECTURE" != "x86_64" ]; then
|
|
sudo sed -i 's/apt.screenlyapp.com/archive.raspbian.org/g' \
|
|
/etc/apt/sources.list
|
|
fi
|
|
|
|
sudo apt update -y
|
|
sudo apt-get install -y "${APT_INSTALL_ARGS[@]}"
|
|
}
|
|
|
|
function install_ansible() {
|
|
display_section "Install Ansible"
|
|
|
|
REQUIREMENTS_URL="$GITHUB_RAW_URL/$BRANCH/requirements/requirements.host.txt"
|
|
if [ "$DISTRO_VERSION" -le 11 ]; then
|
|
ANSIBLE_VERSION="ansible-core==2.15.9"
|
|
else
|
|
ANSIBLE_VERSION=$(curl -s $REQUIREMENTS_URL | grep ansible)
|
|
fi
|
|
|
|
SUDO_ARGS=()
|
|
|
|
if python3 -c "import venv" &> /dev/null; then
|
|
gum format 'Module `venv` is detected. Activating virtual environment...'
|
|
|
|
echo
|
|
|
|
python3 -m venv /home/${USER}/installer_venv
|
|
source /home/${USER}/installer_venv/bin/activate
|
|
|
|
SUDO_ARGS+=("--preserve-env" "env" "PATH=$PATH")
|
|
fi
|
|
|
|
# @TODO: Remove me later. Cryptography 38.0.3 won't build at the moment.
|
|
# See https://github.com/Screenly/Anthias/issues/1654 for details.
|
|
sudo ${SUDO_ARGS[@]} pip install cryptography==38.0.1
|
|
sudo ${SUDO_ARGS[@]} pip install "$ANSIBLE_VERSION"
|
|
}
|
|
|
|
function set_device_type() {
|
|
if [ ! -f /proc/device-tree/model ] && [ "$(uname -m)" = "x86_64" ]; then
|
|
export DEVICE_TYPE="x86"
|
|
elif grep -qF "Raspberry Pi 5" /proc/device-tree/model || grep -qF "Compute Module 5" /proc/device-tree/model; then
|
|
export DEVICE_TYPE="pi5"
|
|
elif grep -qF "Raspberry Pi 4" /proc/device-tree/model || grep -qF "Compute Module 4" /proc/device-tree/model; then
|
|
export DEVICE_TYPE="pi4"
|
|
elif grep -qF "Raspberry Pi 3" /proc/device-tree/model || grep -qF "Compute Module 3" /proc/device-tree/model; then
|
|
export DEVICE_TYPE="pi3"
|
|
elif grep -qF "Raspberry Pi 2" /proc/device-tree/model; then
|
|
export DEVICE_TYPE="pi2"
|
|
else
|
|
export DEVICE_TYPE="pi1"
|
|
fi
|
|
}
|
|
|
|
function run_ansible_playbook() {
|
|
display_section "Run the Anthias Ansible Playbook"
|
|
set_device_type
|
|
|
|
sudo -u ${USER} ${SUDO_ARGS[@]} ansible localhost \
|
|
-m git \
|
|
-a "repo=$REPOSITORY dest=${ANTHIAS_REPO_DIR} version=${BRANCH} force=yes"
|
|
cd ${ANTHIAS_REPO_DIR}/ansible
|
|
|
|
if [ "$ARCHITECTURE" == "x86_64" ]; then
|
|
if [ ! -f /etc/sudoers.d/010_${USER}-nopasswd ]; then
|
|
ANSIBLE_PLAYBOOK_ARGS+=("--ask-become-pass")
|
|
fi
|
|
|
|
ANSIBLE_PLAYBOOK_ARGS+=(
|
|
"--skip-tags" "raspberry-pi"
|
|
)
|
|
fi
|
|
|
|
sudo -E -u ${USER} ${SUDO_ARGS[@]} \
|
|
ansible-playbook site.yml "${ANSIBLE_PLAYBOOK_ARGS[@]}"
|
|
}
|
|
|
|
function upgrade_docker_containers() {
|
|
display_section "Initialize/Upgrade Docker Containers"
|
|
|
|
wget -q \
|
|
"$GITHUB_RAW_URL/master/bin/upgrade_containers.sh" \
|
|
-O "$UPGRADE_SCRIPT_PATH"
|
|
|
|
sudo -u ${USER} \
|
|
DOCKER_TAG="${DOCKER_TAG}" \
|
|
GIT_BRANCH="${BRANCH}" \
|
|
"${UPGRADE_SCRIPT_PATH}"
|
|
}
|
|
|
|
function cleanup() {
|
|
display_section "Clean Up Unused Packages and Files"
|
|
|
|
sudo apt-get autoclean
|
|
sudo apt-get clean
|
|
sudo docker system prune -f
|
|
sudo apt autoremove -y
|
|
sudo apt-get install plymouth --reinstall -y
|
|
sudo find /usr/share/doc \
|
|
-depth \
|
|
-type f \
|
|
! -name copyright \
|
|
-delete
|
|
sudo find /usr/share/doc \
|
|
-empty \
|
|
-delete
|
|
sudo rm -rf \
|
|
/usr/share/man \
|
|
/usr/share/groff \
|
|
/usr/share/info/* \
|
|
/usr/share/lintian \
|
|
/usr/share/linda /var/cache/man
|
|
sudo find /usr/share/locale \
|
|
-type f \
|
|
! -name 'en' \
|
|
! -name 'de*' \
|
|
! -name 'es*' \
|
|
! -name 'ja*' \
|
|
! -name 'fr*' \
|
|
! -name 'zh*' \
|
|
-delete
|
|
sudo find /usr/share/locale \
|
|
-mindepth 1 \
|
|
-maxdepth 1 \
|
|
! -name 'en*' \
|
|
! -name 'de*' \
|
|
! -name 'es*' \
|
|
! -name 'ja*' \
|
|
! -name 'fr*' \
|
|
! -name 'zh*' \
|
|
! -name 'locale.alias' \
|
|
-exec rm -r {} \;
|
|
}
|
|
|
|
function modify_permissions() {
|
|
sudo chown -R ${USER}:${USER} /home/${USER}
|
|
|
|
# Run `sudo` without entering a password.
|
|
if [ ! -f /etc/sudoers.d/010_${USER}-nopasswd ]; then
|
|
echo "${USER} ALL=(ALL) NOPASSWD: ALL" | \
|
|
sudo tee /etc/sudoers.d/010_${USER}-nopasswd > /dev/null
|
|
sudo chmod 0440 /etc/sudoers.d/010_${USER}-nopasswd
|
|
fi
|
|
}
|
|
|
|
function write_anthias_version() {
|
|
local GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
local GIT_SHORT_HASH=$(git rev-parse --short HEAD)
|
|
local ANTHIAS_VERSION="Anthias Version: ${GIT_BRANCH}@${GIT_SHORT_HASH}"
|
|
|
|
echo "${ANTHIAS_VERSION}" > ~/version.md
|
|
echo "$(lsb_release -a 2> /dev/null)" >> ~/version.md
|
|
}
|
|
|
|
function post_installation() {
|
|
local POST_INSTALL_MESSAGE=()
|
|
|
|
display_section "Installation Complete"
|
|
|
|
if [ -f /var/run/reboot-required ]; then
|
|
POST_INSTALL_MESSAGE+=(
|
|
"Please reboot and run \`${UPGRADE_SCRIPT_PATH}\` "
|
|
"to complete the installation."
|
|
)
|
|
else
|
|
POST_INSTALL_MESSAGE+=(
|
|
"You need to reboot the system for the installation to complete."
|
|
)
|
|
fi
|
|
|
|
echo
|
|
|
|
gum style --foreground "#00FFFF" "${POST_INSTALL_MESSAGE[@]}" | gum format
|
|
|
|
echo
|
|
|
|
gum confirm "Do you want to reboot now?" && \
|
|
gum style --foreground "#FF00FF" "Rebooting..." | gum format && \
|
|
sudo reboot
|
|
}
|
|
|
|
function set_custom_version() {
|
|
BRANCH=$(
|
|
gum input \
|
|
--header "Enter the tag name you want to install" \
|
|
)
|
|
|
|
local STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
"${GITHUB_API_REPO_URL}/git/refs/tags/$BRANCH")
|
|
|
|
if [ "$STATUS_CODE" -ne 200 ]; then
|
|
gum style "Invalid tag name." \
|
|
| gum format
|
|
echo
|
|
exit 1
|
|
fi
|
|
|
|
local DOCKER_TAG_FILE_URL="${GITHUB_RELEASES_URL}/download/${BRANCH}/docker-tag"
|
|
STATUS_CODE=$(curl -sL -o /dev/null -w "%{http_code}" \
|
|
"$DOCKER_TAG_FILE_URL")
|
|
|
|
if [ "$STATUS_CODE" -ne 200 ]; then
|
|
gum style "This version doesn't have a \`docker-tag\` file." \
|
|
| gum format
|
|
echo
|
|
exit 1
|
|
fi
|
|
|
|
DOCKER_TAG=$(curl -sL "$DOCKER_TAG_FILE_URL")
|
|
}
|
|
|
|
function main() {
|
|
install_prerequisites && clear
|
|
|
|
display_banner "${TITLE_TEXT}"
|
|
|
|
gum format "${INTRO_MESSAGE[@]}"
|
|
echo
|
|
gum confirm "Do you still want to continue?" || exit 0
|
|
gum confirm "${MANAGE_NETWORK_PROMPT[@]}" && \
|
|
export MANAGE_NETWORK="Yes" || \
|
|
export MANAGE_NETWORK="No"
|
|
|
|
VERSION=$(
|
|
gum choose \
|
|
--header "${VERSION_PROMPT}" \
|
|
-- "${VERSION_PROMPT_CHOICES[@]}"
|
|
)
|
|
|
|
if [ "$VERSION" == "latest" ]; then
|
|
BRANCH="master"
|
|
else
|
|
set_custom_version
|
|
fi
|
|
|
|
gum confirm "${SYSTEM_UPGRADE_PROMPT[@]}" && {
|
|
SYSTEM_UPGRADE="Yes"
|
|
} || {
|
|
SYSTEM_UPGRADE="No"
|
|
ANSIBLE_PLAYBOOK_ARGS+=("--skip-tags" "system-upgrade")
|
|
}
|
|
|
|
display_section "User Input Summary"
|
|
gum format "**Manage Network:** ${MANAGE_NETWORK}"
|
|
gum format "**Branch/Tag:** \`${BRANCH}\`"
|
|
gum format "**System Upgrade:** ${SYSTEM_UPGRADE}"
|
|
gum format "**Docker Tag Prefix:** \`${DOCKER_TAG}\`"
|
|
|
|
if [ ! -d "${ANTHIAS_REPO_DIR}" ]; then
|
|
mkdir "${ANTHIAS_REPO_DIR}"
|
|
fi
|
|
|
|
initialize_ansible
|
|
initialize_locales
|
|
install_packages
|
|
install_ansible
|
|
run_ansible_playbook
|
|
|
|
upgrade_docker_containers
|
|
cleanup
|
|
modify_permissions
|
|
|
|
write_anthias_version
|
|
post_installation
|
|
}
|
|
|
|
main
|