#!/bin/bash #################################################################### #### Code-Server Update Script #### #### #### #### Updates code-server to the latest version. Can be run #### #### manually or via cron for automatic updates. #### #### #### #### Supported: RHEL/Rocky/Alma 8+, Oracle Linux 8+, #### #### Debian 11+, Ubuntu 20.04+ #### #### #### #### Author: Phil Connor #### #### Contact: contact@mylinux.work #### #### Website: https://mylinux.work #### #### License: MIT #### #### Version: 2.0 #### #### #### #### Usage: #### #### sudo ./update-code-server.sh #### #### sudo ./update-code-server.sh --check #### #### sudo ./update-code-server.sh --force #### #### sudo ./update-code-server.sh --install-cron #### #### sudo ./update-code-server.sh --help #### #################################################################### set -euo pipefail # ============================================================================ # USER CONFIGURATION -- edit these or override with command-line options # ============================================================================ SERVDIR="/usr/local/code-server" # code-server install directory # ============================================================================ # INTERNAL VARIABLES # ============================================================================ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' VERSION="2.0" ARCH="" CHECK_ONLY=0 FORCE=0 INSTALL_CRON=0 CRON_DAYS=25 # ============================================================================ # HELPER FUNCTIONS # ============================================================================ log() { echo -e "${GREEN}[+]${NC} $1"; } log_warn() { echo -e "${YELLOW}[!]${NC} $1"; } log_err() { echo -e "${RED}[x]${NC} $1" >&2; } log_info() { echo -e "${CYAN}[>]${NC} $1"; } show_help() { cat </dev/null 2>&1; then log_err "Required command not found: $cmd" exit 1 fi done # code-server must be installed (unless just installing cron) if [[ $INSTALL_CRON -eq 0 ]] && ! command -v code-server >/dev/null 2>&1; then log_err "code-server is not installed or not in PATH" exit 1 fi } # ============================================================================ # GET VERSIONS # ============================================================================ get_current_version() { code-server --version 2>/dev/null | head -1 | awk '{print $1}' } get_latest_version() { local version version=$(curl -fsSL "https://api.github.com/repos/coder/code-server/releases/latest" | \ grep '"tag_name"' | head -1 | grep -oP 'v\K[0-9]+\.[0-9]+\.[0-9]+') if [[ -z "$version" ]]; then log_err "Failed to determine latest code-server version" exit 1 fi echo "$version" } # ============================================================================ # UPDATE CODE-SERVER # ============================================================================ update_codeserver() { local current_version latest_version current_version=$(get_current_version) latest_version=$(get_latest_version) log_info "Installed version: $current_version" log_info "Latest version: $latest_version" # Check mode -- just report and exit if [[ $CHECK_ONLY -eq 1 ]]; then if [[ "$current_version" == "$latest_version" ]]; then log "code-server is up to date" else log_warn "Update available: $current_version -> $latest_version" fi return fi # Decide whether to update if [[ $FORCE -eq 0 ]]; then if [[ "$current_version" == "$latest_version" ]]; then log "code-server is already up to date ($current_version)" return fi # Verify the latest version is actually newer (not a downgrade) if [[ "$(printf '%s\n' "$current_version" "$latest_version" | sort -V | tail -1)" != "$latest_version" ]]; then log "Installed version ($current_version) is newer than latest release ($latest_version)" return fi fi log "Updating code-server: $current_version -> $latest_version" # Stop service systemctl stop code-server # Download local tarball="code-server-${latest_version}-linux-${ARCH}.tar.gz" local url="https://github.com/coder/code-server/releases/download/v${latest_version}/${tarball}" cd /tmp log_info "Downloading $tarball" curl -fsSL -o "$tarball" "$url" tar xzf "$tarball" # Install cp -r "code-server-${latest_version}-linux-${ARCH}"/* "$SERVDIR"/ # Cleanup rm -rf "/tmp/$tarball" "/tmp/code-server-${latest_version}-linux-${ARCH}" # Start service systemctl start code-server log "code-server updated to $latest_version" } # ============================================================================ # INSTALL CRON # ============================================================================ install_cron() { local script_dest="/usr/local/bin/update-code-server.sh" local script_src # Copy this script to /usr/local/bin script_src=$(readlink -f "$0") if [[ "$script_src" != "$script_dest" ]]; then cp "$script_src" "$script_dest" log "Copied update script to $script_dest" fi chmod 700 "$script_dest" # Build cron entry -- run every N days at 3:00 AM local cron_line="0 3 */${CRON_DAYS} * * ${script_dest} 2>&1 | logger -t update-code-server" local cron_marker="# code-server auto-update" # Remove existing code-server cron entries local existing_cron existing_cron=$(crontab -l 2>/dev/null || true) local new_cron new_cron=$(echo "$existing_cron" | grep -v "$cron_marker" | grep -v "update-code-server" || true) # Add new entry echo "${new_cron} ${cron_line} ${cron_marker}" | crontab - log "Cron job installed -- updates every $CRON_DAYS days at 3:00 AM" log_info "View with: crontab -l" } # ============================================================================ # MAIN # ============================================================================ main() { parse_args "$@" echo "" echo "==============================================" echo " Code-Server Update Script v${VERSION}" echo "==============================================" echo "" detect_arch preflight_checks if [[ $INSTALL_CRON -eq 1 ]]; then install_cron fi # Run update unless we are only installing cron if [[ $INSTALL_CRON -eq 0 ]] || command -v code-server >/dev/null 2>&1; then update_codeserver fi echo "" } main "$@"