606 lines
15 KiB
Bash
606 lines
15 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Standalone Ubuntu deployment bootstrap
|
|
# Download this single file to the server, make it executable, then run it.
|
|
# Configuration
|
|
# -----------------------------------------------------------------------------
|
|
|
|
if [[ -t 1 ]]; then
|
|
COLOR_INFO='\033[1;34m'
|
|
COLOR_WARN='\033[1;33m'
|
|
COLOR_ERROR='\033[1;31m'
|
|
COLOR_RESET='\033[0m'
|
|
else
|
|
COLOR_INFO=''
|
|
COLOR_WARN=''
|
|
COLOR_ERROR=''
|
|
COLOR_RESET=''
|
|
fi
|
|
|
|
BASE_PACKAGES=(
|
|
apt-transport-https
|
|
build-essential
|
|
ca-certificates
|
|
curl
|
|
git
|
|
gnupg
|
|
jq
|
|
lsb-release
|
|
software-properties-common
|
|
unzip
|
|
wget
|
|
zip
|
|
)
|
|
|
|
INSTALL_DOCKER=false
|
|
INSTALL_NODE=false
|
|
INSTALL_AWS=false
|
|
INSTALL_AZURE=false
|
|
INSTALL_ANSIBLE=true
|
|
INSTALL_INFISICAL=true
|
|
INSTALL_PYTHON=false
|
|
INSTALL_PHP=false
|
|
INSTALL_COMPOSER=false
|
|
INSTALL_JAVA=false
|
|
INSTALL_MAVEN=false
|
|
INSTALL_GO=false
|
|
INSTALL_COREPACK=false
|
|
INSTALL_NGINX=false
|
|
INSTALL_UFW=false
|
|
INSTALL_FAIL2BAN=false
|
|
INSTALL_CERTBOT=false
|
|
INSTALL_PM2=false
|
|
DEPLOY_NODE=false
|
|
DEPLOY_PYTHON=false
|
|
DEPLOY_DOCKER=false
|
|
DEPLOY_LARAVEL=false
|
|
DEPLOY_SPRINGBOOT=false
|
|
DEPLOY_NEXT=false
|
|
DEPLOY_NUXT=false
|
|
DEPLOY_GO_FIBER=false
|
|
UPDATE_ONLY=false
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Logging and helpers
|
|
# -----------------------------------------------------------------------------
|
|
|
|
log() {
|
|
printf '%b[INFO]%b %s\n' "${COLOR_INFO}" "${COLOR_RESET}" "$1"
|
|
}
|
|
|
|
warn() {
|
|
printf '%b[WARN]%b %s\n' "${COLOR_WARN}" "${COLOR_RESET}" "$1"
|
|
}
|
|
|
|
die() {
|
|
printf '%b[ERROR]%b %s\n' "${COLOR_ERROR}" "${COLOR_RESET}" "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
install_apt_packages() {
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y "$@"
|
|
}
|
|
|
|
enable_service() {
|
|
systemctl enable --now "$1"
|
|
}
|
|
|
|
run_when_enabled() {
|
|
local enabled="$1"
|
|
local handler="$2"
|
|
|
|
if [[ "${enabled}" == true ]]; then
|
|
"${handler}"
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./setup_ubuntu_tools.sh [options]
|
|
|
|
This is a standalone bootstrap script.
|
|
You only need this single file on the Ubuntu server.
|
|
|
|
Default behavior:
|
|
- Update apt cache
|
|
- Upgrade installed packages
|
|
- Install common base tools for Ubuntu servers
|
|
- Install Ansible and Infisical CLI
|
|
|
|
Options:
|
|
--deploy-laravel Install a ready-to-deploy Laravel server stack
|
|
--deploy-springboot Install a ready-to-deploy Spring Boot server stack
|
|
--deploy-next Install a ready-to-deploy Next.js server stack
|
|
--deploy-nuxt Install a ready-to-deploy Nuxt server stack
|
|
--deploy-go-fiber Install a ready-to-deploy Go Fiber server stack
|
|
--deploy-node Install a ready-to-deploy Node.js server stack
|
|
--deploy-python Install a ready-to-deploy Python server stack
|
|
--deploy-docker Install a ready-to-deploy Docker server stack
|
|
--docker Install Docker Engine and Docker Compose plugin
|
|
--node Install Node.js LTS
|
|
--aws Install AWS CLI v2
|
|
--azure Install Azure CLI
|
|
--no-ansible Skip default Ansible installation
|
|
--no-infisical Skip default Infisical CLI installation
|
|
--python Install Python 3, venv and pip
|
|
--php Install PHP runtime for Laravel-style apps
|
|
--composer Install Composer
|
|
--java Install OpenJDK 21
|
|
--maven Install Maven
|
|
--go Install Go toolchain from Ubuntu repo
|
|
--corepack Enable pnpm and yarn via Corepack
|
|
--nginx Install and enable Nginx
|
|
--ufw Install and configure UFW for SSH, HTTP, HTTPS
|
|
--fail2ban Install and enable Fail2ban
|
|
--certbot Install Certbot for Let's Encrypt
|
|
--pm2 Install PM2 globally with npm
|
|
--update-only Only run apt update and upgrade
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
wget https://your-server/setup_ubuntu_tools.sh
|
|
chmod +x setup_ubuntu_tools.sh
|
|
sudo ./setup_ubuntu_tools.sh --deploy-laravel
|
|
./setup_ubuntu_tools.sh --deploy-laravel
|
|
./setup_ubuntu_tools.sh --deploy-springboot
|
|
./setup_ubuntu_tools.sh --deploy-next
|
|
./setup_ubuntu_tools.sh --deploy-go-fiber
|
|
./setup_ubuntu_tools.sh --deploy-node
|
|
./setup_ubuntu_tools.sh --deploy-python
|
|
./setup_ubuntu_tools.sh --deploy-docker
|
|
./setup_ubuntu_tools.sh --docker --node --python --nginx
|
|
sudo ./setup_ubuntu_tools.sh --docker --aws --azure
|
|
EOF
|
|
}
|
|
|
|
require_root() {
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
die "Please run this script with sudo or as root."
|
|
fi
|
|
}
|
|
|
|
require_ubuntu() {
|
|
if [[ ! -r /etc/os-release ]]; then
|
|
die "Cannot detect operating system."
|
|
fi
|
|
|
|
. /etc/os-release
|
|
|
|
if [[ "${ID:-}" != "ubuntu" ]]; then
|
|
die "This script currently supports Ubuntu only."
|
|
fi
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Installers
|
|
# -----------------------------------------------------------------------------
|
|
|
|
system_update() {
|
|
log "Updating apt package index"
|
|
apt-get update -y
|
|
|
|
log "Upgrading installed packages"
|
|
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
|
|
}
|
|
|
|
install_base_tooling() {
|
|
log "Installing base packages"
|
|
install_apt_packages "${BASE_PACKAGES[@]}"
|
|
}
|
|
|
|
install_runtime_python() {
|
|
log "Installing Python tools"
|
|
install_apt_packages python3 python3-pip python3-venv
|
|
}
|
|
|
|
install_runtime_php() {
|
|
log "Installing PHP runtime and common Laravel extensions"
|
|
install_apt_packages \
|
|
php-cli \
|
|
php-common \
|
|
php-curl \
|
|
php-fpm \
|
|
php-mbstring \
|
|
php-mysql \
|
|
php-xml \
|
|
php-zip \
|
|
php-bcmath \
|
|
php-intl
|
|
}
|
|
|
|
install_runtime_composer() {
|
|
log "Installing Composer"
|
|
install_apt_packages composer
|
|
}
|
|
|
|
install_runtime_java() {
|
|
log "Installing OpenJDK 21"
|
|
install_apt_packages openjdk-21-jdk
|
|
}
|
|
|
|
install_runtime_maven() {
|
|
log "Installing Maven"
|
|
install_apt_packages maven
|
|
}
|
|
|
|
install_runtime_go() {
|
|
log "Installing Go toolchain"
|
|
install_apt_packages golang-go
|
|
}
|
|
|
|
install_service_nginx() {
|
|
log "Installing Nginx"
|
|
install_apt_packages nginx
|
|
enable_service nginx
|
|
}
|
|
|
|
install_service_ufw() {
|
|
log "Installing and configuring UFW"
|
|
install_apt_packages ufw
|
|
ufw allow OpenSSH
|
|
ufw allow 'Nginx Full'
|
|
ufw --force enable
|
|
}
|
|
|
|
install_service_fail2ban() {
|
|
log "Installing Fail2ban"
|
|
install_apt_packages fail2ban
|
|
enable_service fail2ban
|
|
}
|
|
|
|
install_service_certbot() {
|
|
log "Installing Certbot"
|
|
install_apt_packages certbot python3-certbot-nginx
|
|
}
|
|
|
|
install_runtime_node() {
|
|
log "Installing Node.js LTS"
|
|
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
|
|
install_apt_packages nodejs
|
|
}
|
|
|
|
install_runtime_corepack() {
|
|
if ! command -v corepack >/dev/null 2>&1; then
|
|
die "Corepack requires Node.js. Re-run with --node, --deploy-next, or --deploy-nuxt."
|
|
fi
|
|
|
|
log "Enabling corepack and preparing pnpm/yarn"
|
|
corepack enable
|
|
corepack prepare pnpm@latest --activate
|
|
corepack prepare yarn@stable --activate
|
|
}
|
|
|
|
install_runtime_pm2() {
|
|
if ! command -v npm >/dev/null 2>&1; then
|
|
die "PM2 requires Node.js. Re-run with --node or --deploy-node."
|
|
fi
|
|
|
|
log "Installing PM2"
|
|
npm install -g pm2
|
|
}
|
|
|
|
install_cli_aws() {
|
|
local tmp_dir
|
|
tmp_dir="$(mktemp -d)"
|
|
|
|
log "Installing AWS CLI v2"
|
|
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "${tmp_dir}/awscliv2.zip"
|
|
unzip -q "${tmp_dir}/awscliv2.zip" -d "${tmp_dir}"
|
|
"${tmp_dir}/aws/install" --update
|
|
rm -rf "${tmp_dir}"
|
|
}
|
|
|
|
install_cli_azure() {
|
|
log "Installing Azure CLI"
|
|
curl -fsSL https://aka.ms/InstallAzureCLIDeb | bash
|
|
}
|
|
|
|
install_cli_ansible() {
|
|
log "Installing Ansible"
|
|
install_apt_packages ansible
|
|
}
|
|
|
|
install_cli_infisical() {
|
|
log "Installing Infisical CLI"
|
|
curl -fsSL https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh | bash
|
|
apt-get update -y
|
|
install_apt_packages infisical
|
|
}
|
|
|
|
install_runtime_docker() {
|
|
log "Setting up Docker repository"
|
|
install -m 0755 -d /etc/apt/keyrings
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
|
chmod a+r /etc/apt/keyrings/docker.asc
|
|
|
|
. /etc/os-release
|
|
echo \
|
|
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${VERSION_CODENAME} stable" \
|
|
> /etc/apt/sources.list.d/docker.list
|
|
|
|
apt-get update -y
|
|
|
|
log "Installing Docker Engine"
|
|
install_apt_packages \
|
|
docker-ce \
|
|
docker-ce-cli \
|
|
containerd.io \
|
|
docker-buildx-plugin \
|
|
docker-compose-plugin
|
|
|
|
if [[ -n "${SUDO_USER:-}" ]]; then
|
|
usermod -aG docker "${SUDO_USER}" || warn "Could not add ${SUDO_USER} to docker group"
|
|
warn "Log out and back in to use Docker without sudo."
|
|
fi
|
|
}
|
|
|
|
prepare_deploy_directories() {
|
|
log "Creating common deployment directories"
|
|
install -d -m 0755 /var/www/apps
|
|
install -d -m 0755 /var/log/apps
|
|
}
|
|
|
|
enable_common_web_profile() {
|
|
INSTALL_NGINX=true
|
|
INSTALL_UFW=true
|
|
INSTALL_FAIL2BAN=true
|
|
INSTALL_CERTBOT=true
|
|
}
|
|
|
|
enable_profile_laravel() {
|
|
INSTALL_PHP=true
|
|
INSTALL_COMPOSER=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_springboot() {
|
|
INSTALL_JAVA=true
|
|
INSTALL_MAVEN=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_next() {
|
|
INSTALL_NODE=true
|
|
INSTALL_COREPACK=true
|
|
INSTALL_PM2=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_nuxt() {
|
|
enable_profile_next
|
|
}
|
|
|
|
enable_profile_go_fiber() {
|
|
INSTALL_GO=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_node() {
|
|
INSTALL_NODE=true
|
|
INSTALL_PM2=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_python() {
|
|
INSTALL_PYTHON=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
enable_profile_docker() {
|
|
INSTALL_DOCKER=true
|
|
enable_common_web_profile
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Profiles
|
|
# -----------------------------------------------------------------------------
|
|
|
|
apply_deploy_profiles() {
|
|
if [[ "${DEPLOY_NODE}" == true ]]; then
|
|
enable_profile_node
|
|
fi
|
|
|
|
if [[ "${DEPLOY_PYTHON}" == true ]]; then
|
|
enable_profile_python
|
|
fi
|
|
|
|
if [[ "${DEPLOY_DOCKER}" == true ]]; then
|
|
enable_profile_docker
|
|
fi
|
|
|
|
if [[ "${DEPLOY_LARAVEL}" == true ]]; then
|
|
enable_profile_laravel
|
|
fi
|
|
|
|
if [[ "${DEPLOY_SPRINGBOOT}" == true ]]; then
|
|
enable_profile_springboot
|
|
fi
|
|
|
|
if [[ "${DEPLOY_NEXT}" == true ]]; then
|
|
enable_profile_next
|
|
fi
|
|
|
|
if [[ "${DEPLOY_NUXT}" == true ]]; then
|
|
enable_profile_nuxt
|
|
fi
|
|
|
|
if [[ "${DEPLOY_GO_FIBER}" == true ]]; then
|
|
enable_profile_go_fiber
|
|
fi
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Output
|
|
# -----------------------------------------------------------------------------
|
|
|
|
show_versions() {
|
|
log "Installed versions"
|
|
command -v git >/dev/null 2>&1 && git --version || true
|
|
command -v curl >/dev/null 2>&1 && curl --version | head -n 1 || true
|
|
command -v jq >/dev/null 2>&1 && jq --version || true
|
|
command -v python3 >/dev/null 2>&1 && python3 --version || true
|
|
command -v php >/dev/null 2>&1 && php --version | head -n 1 || true
|
|
command -v composer >/dev/null 2>&1 && composer --version || true
|
|
command -v java >/dev/null 2>&1 && java --version | head -n 1 || true
|
|
command -v mvn >/dev/null 2>&1 && mvn --version | head -n 1 || true
|
|
command -v go >/dev/null 2>&1 && go version || true
|
|
command -v node >/dev/null 2>&1 && node --version || true
|
|
command -v npm >/dev/null 2>&1 && npm --version || true
|
|
command -v pnpm >/dev/null 2>&1 && pnpm --version || true
|
|
command -v yarn >/dev/null 2>&1 && yarn --version || true
|
|
command -v pm2 >/dev/null 2>&1 && pm2 --version || true
|
|
command -v ansible >/dev/null 2>&1 && ansible --version | head -n 1 || true
|
|
command -v infisical >/dev/null 2>&1 && infisical --version || true
|
|
command -v aws >/dev/null 2>&1 && aws --version || true
|
|
command -v az >/dev/null 2>&1 && az version | jq -r '.["azure-cli"]' || true
|
|
command -v docker >/dev/null 2>&1 && docker --version || true
|
|
command -v nginx >/dev/null 2>&1 && nginx -v 2>&1 || true
|
|
command -v certbot >/dev/null 2>&1 && certbot --version || true
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# CLI
|
|
# -----------------------------------------------------------------------------
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--deploy-laravel)
|
|
DEPLOY_LARAVEL=true
|
|
;;
|
|
--deploy-springboot)
|
|
DEPLOY_SPRINGBOOT=true
|
|
;;
|
|
--deploy-next)
|
|
DEPLOY_NEXT=true
|
|
;;
|
|
--deploy-nuxt)
|
|
DEPLOY_NUXT=true
|
|
;;
|
|
--deploy-go-fiber)
|
|
DEPLOY_GO_FIBER=true
|
|
;;
|
|
--deploy-node)
|
|
DEPLOY_NODE=true
|
|
;;
|
|
--deploy-python)
|
|
DEPLOY_PYTHON=true
|
|
;;
|
|
--deploy-docker)
|
|
DEPLOY_DOCKER=true
|
|
;;
|
|
--docker)
|
|
INSTALL_DOCKER=true
|
|
;;
|
|
--node)
|
|
INSTALL_NODE=true
|
|
;;
|
|
--aws)
|
|
INSTALL_AWS=true
|
|
;;
|
|
--azure)
|
|
INSTALL_AZURE=true
|
|
;;
|
|
--no-ansible)
|
|
INSTALL_ANSIBLE=false
|
|
;;
|
|
--no-infisical)
|
|
INSTALL_INFISICAL=false
|
|
;;
|
|
--python)
|
|
INSTALL_PYTHON=true
|
|
;;
|
|
--php)
|
|
INSTALL_PHP=true
|
|
;;
|
|
--composer)
|
|
INSTALL_COMPOSER=true
|
|
;;
|
|
--java)
|
|
INSTALL_JAVA=true
|
|
;;
|
|
--maven)
|
|
INSTALL_MAVEN=true
|
|
;;
|
|
--go)
|
|
INSTALL_GO=true
|
|
;;
|
|
--corepack)
|
|
INSTALL_COREPACK=true
|
|
;;
|
|
--nginx)
|
|
INSTALL_NGINX=true
|
|
;;
|
|
--ufw)
|
|
INSTALL_UFW=true
|
|
;;
|
|
--fail2ban)
|
|
INSTALL_FAIL2BAN=true
|
|
;;
|
|
--certbot)
|
|
INSTALL_CERTBOT=true
|
|
;;
|
|
--pm2)
|
|
INSTALL_PM2=true
|
|
;;
|
|
--update-only)
|
|
UPDATE_ONLY=true
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
die "Unknown option: $1"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Main flow
|
|
# -----------------------------------------------------------------------------
|
|
|
|
main() {
|
|
parse_args "$@"
|
|
require_root
|
|
require_ubuntu
|
|
apply_deploy_profiles
|
|
system_update
|
|
|
|
if [[ "${UPDATE_ONLY}" == true ]]; then
|
|
log "Update-only mode complete"
|
|
exit 0
|
|
fi
|
|
|
|
install_base_tooling
|
|
prepare_deploy_directories
|
|
|
|
run_when_enabled "${INSTALL_PYTHON}" install_runtime_python
|
|
run_when_enabled "${INSTALL_PHP}" install_runtime_php
|
|
run_when_enabled "${INSTALL_COMPOSER}" install_runtime_composer
|
|
run_when_enabled "${INSTALL_JAVA}" install_runtime_java
|
|
run_when_enabled "${INSTALL_MAVEN}" install_runtime_maven
|
|
run_when_enabled "${INSTALL_GO}" install_runtime_go
|
|
run_when_enabled "${INSTALL_NODE}" install_runtime_node
|
|
run_when_enabled "${INSTALL_COREPACK}" install_runtime_corepack
|
|
run_when_enabled "${INSTALL_PM2}" install_runtime_pm2
|
|
run_when_enabled "${INSTALL_ANSIBLE}" install_cli_ansible
|
|
run_when_enabled "${INSTALL_INFISICAL}" install_cli_infisical
|
|
run_when_enabled "${INSTALL_AWS}" install_cli_aws
|
|
run_when_enabled "${INSTALL_AZURE}" install_cli_azure
|
|
run_when_enabled "${INSTALL_DOCKER}" install_runtime_docker
|
|
run_when_enabled "${INSTALL_NGINX}" install_service_nginx
|
|
run_when_enabled "${INSTALL_UFW}" install_service_ufw
|
|
run_when_enabled "${INSTALL_FAIL2BAN}" install_service_fail2ban
|
|
run_when_enabled "${INSTALL_CERTBOT}" install_service_certbot
|
|
|
|
show_versions
|
|
log "Bootstrap complete"
|
|
}
|
|
|
|
main "$@" |