Skip to content

Instantly share code, notes, and snippets.

@vck
Created February 5, 2026 04:15
Show Gist options
  • Select an option

  • Save vck/dfddce29b1d4d74aa83681ee1e9aa02c to your computer and use it in GitHub Desktop.

Select an option

Save vck/dfddce29b1d4d74aa83681ee1e9aa02c to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
echo "==========================================="
echo "EC2 Ubuntu Bootstrap Script (No Docker)"
echo "Optimized for 1GB RAM"
echo "==========================================="
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# Check if running as root
if [ "$EUID" -ne 0 ]; then
warn "Not running as root, using sudo where needed"
SUDO="sudo"
else
SUDO=""
fi
# ==================== SYSTEM INFO ====================
log "Checking system information..."
CPU_CORES=$(nproc --all)
TOTAL_RAM=$(free -m | awk '/^Mem:/{print $2}')
log "System: $(lsb_release -d | cut -f2)"
log "CPU Cores: $CPU_CORES"
log "Total RAM: ${TOTAL_RAM}MB"
if [ "$TOTAL_RAM" -lt 900 ]; then
warn "Low RAM detected (${TOTAL_RAM}MB)! Enabling aggressive optimizations."
AGGRESSIVE_OPTIMIZATION=true
fi
# ==================== PHASE 1: SYSTEM OPTIMIZATION ====================
log "Phase 1: System Optimization"
# Update system (minimal)
log "Updating package lists..."
$SUDO apt-get update -y
# Install ONLY essentials
log "Installing essential packages..."
$SUDO apt-get install -y \
curl \
wget \
git \
rsync \
htop \
nload \
ncdu \
fail2ban \
unattended-upgrades \
ufw \
cron \
software-properties-common \
build-essential \
libssl-dev \
ca-certificates
# Remove unnecessary packages
log "Removing unnecessary packages..."
$SUDO apt-get remove -y --purge \
snapd \
lxd \
lxcfs \
popularity-contest \
ubuntu-advantage-tools \
command-not-found \
mlocate
$SUDO apt-get autoremove -y
$SUDO apt-get clean
# ==================== PHASE 2: MEMORY OPTIMIZATION ====================
log "Phase 2: Memory Optimization"
# Create optimal swap file based on RAM
SWAP_SIZE="1G"
if [ "$AGGRESSIVE_OPTIMIZATION" = true ]; then
SWAP_SIZE="2G" # More swap for low RAM
fi
log "Setting up ${SWAP_SIZE} swap file..."
if swapon --show | grep -q "."; then
log "Swap already exists:"
swapon --show
info "Keeping existing swap"
else
# Create swap file
$SUDO fallocate -l $SWAP_SIZE /swapfile
$SUDO chmod 600 /swapfile
$SUDO mkswap /swapfile
$SUDO swapon /swapfile
# Make permanent
echo '/swapfile none swap sw 0 0' | $SUDO tee -a /etc/fstab
# Optimize swappiness (lower = less swap usage)
if [ "$AGGRESSIVE_OPTIMIZATION" = true ]; then
SWAPPINESS=5
else
SWAPPINESS=10
fi
echo "vm.swappiness=$SWAPPINESS" | $SUDO tee -a /etc/sysctl.conf
echo "vm.vfs_cache_pressure=50" | $SUDO tee -a /etc/sysctl.conf
$SUDO sysctl -p
fi
# Disable memory-hungry services
log "Disabling memory-intensive services..."
$SUDO systemctl disable --now \
apport \
whoopsie \
systemd-timesyncd \
ModemManager \
pppd-dns \
cups-browsed \
cups
# Disable automatic updates service (we'll use cron)
$SUDO systemctl disable --now apt-daily{,-upgrade}.{timer,service}
# ==================== PHASE 3: SECURITY ====================
log "Phase 3: Security Configuration"
# Setup UFW (Uncomplicated Firewall)
log "Configuring firewall..."
$SUDO ufw default deny incoming
$SUDO ufw default allow outgoing
$SUDO ufw allow ssh
$SUDO ufw allow 80/tcp # HTTP
$SUDO ufw allow 443/tcp # HTTPS
$SUDO ufw --force enable
# Configure fail2ban
log "Setting up fail2ban..."
$SUDO cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
$SUDO systemctl enable fail2ban
$SUDO systemctl start fail2ban
# SSH hardening
log "Hardening SSH configuration..."
SSHD_CONFIG="/etc/ssh/sshd_config"
$SUDO sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' $SSHD_CONFIG
$SUDO sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' $SSHD_CONFIG
$SUDO sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' $SSHD_CONFIG
$SUDO sed -i 's/#ClientAliveInterval 0/ClientAliveInterval 300/' $SSHD_CONFIG
$SUDO sed -i 's/#ClientAliveCountMax 3/ClientAliveCountMax 2/' $SSHD_CONFIG
echo "AllowUsers ubuntu" | $SUDO tee -a $SSHD_CONFIG
$SUDO systemctl restart sshd
# Automatic security updates (lightweight)
log "Configuring automatic security updates..."
cat << EOF | $SUDO tee /etc/apt/apt.conf.d/50unattended-upgrades > /dev/null
Unattended-Upgrade::Allowed-Origins {
"\${distro_id}:\${distro_codename}-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
EOF
# ==================== PHASE 4: APPLICATION ENVIRONMENT ====================
log "Phase 4: Setting up Application Environment"
# Create directory structure
log "Creating directory structure..."
$SUDO mkdir -p /var/www/app/{releases,shared}
$SUDO mkdir -p /var/log/app
$SUDO mkdir -p /opt/{scripts,backups,monitoring}
$SUDO mkdir -p /home/ubuntu/.ssh
# Set proper permissions
$SUDO chown -R ubuntu:ubuntu /var/www/app
$SUDO chown -R ubuntu:ubuntu /var/log/app
$SUDO chown -R ubuntu:ubuntu /opt/scripts
$SUDO chown -R ubuntu:ubuntu /opt/backups
$SUDO chown -R ubuntu:ubuntu /opt/monitoring
$SUDO chown -R ubuntu:ubuntu /home/ubuntu/.ssh
# ==================== PHASE 5: NODE.JS SETUP (Optional) ====================
if [ "$INSTALL_NODE" = "true" ]; then
log "Installing Node.js via NodeSource..."
# Use Node.js 18.x (LTS)
curl -fsSL https://deb.nodesource.com/setup_18.x | $SUDO -E bash -
$SUDO apt-get install -y nodejs
# Install PM2 for process management
log "Installing PM2 process manager..."
$SUDO npm install -g pm2
pm2 startup ubuntu --hp /home/ubuntu
$SUDO env PATH=$PATH:/usr/bin pm2 startup ubuntu -u ubuntu --hp /home/ubuntu
# Configure npm for low RAM
log "Configuring npm for low memory..."
npm config set maxsockets 1
npm config set fetch-retries 2
npm config set fetch-retry-mintimeout 20000
npm config set fetch-retry-maxtimeout 120000
npm config set cache-min 9999999
# Clean npm cache
npm cache clean --force
fi
# ==================== PHASE 6: DEPLOYMENT SCRIPTS ====================
log "Phase 6: Creating Deployment Scripts"
# Main lightweight deploy script
log "Creating deploy script..."
cat << 'EOF' | $SUDO tee /opt/scripts/deploy.sh > /dev/null
#!/bin/bash
set -e
# Configuration
APP_NAME="myapp"
APP_DIR="/var/www/app"
CURRENT_DIR="$APP_DIR/current"
RELEASES_DIR="$APP_DIR/releases"
SHARED_DIR="$APP_DIR/shared"
LOG_DIR="/var/log/app"
MAX_RAM_MB=800
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_DIR/deploy.log"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_DIR/deploy.log"
exit 1
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$LOG_DIR/deploy.log"
}
info() {
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_DIR/deploy.log"
}
# Check system resources
check_resources() {
log "Checking system resources..."
# Check memory
MEM_FREE=$(free -m | awk '/^Mem:/{print $4}')
SWAP_FREE=$(free -m | awk '/^Swap:/{print $4}')
info "Memory: ${MEM_FREE}MB free, Swap: ${SWAP_FREE}MB free"
if [ "$MEM_FREE" -lt 50 ] && [ "$SWAP_FREE" -lt 100 ]; then
warn "Low memory detected! Attempting cleanup..."
# Clear caches
sync
echo 1 | sudo tee /proc/sys/vm/drop_caches > /dev/null
sleep 2
MEM_FREE=$(free -m | awk '/^Mem:/{print $4}')
if [ "$MEM_FREE" -lt 30 ]; then
error "Insufficient memory to deploy (only ${MEM_FREE}MB free)"
fi
fi
# Check disk space
DISK_FREE=$(df -m / | awk 'NR==2 {print $4}')
if [ "$DISK_FREE" -lt 100 ]; then
warn "Low disk space: ${DISK_FREE}MB free"
/opt/scripts/cleanup.sh
fi
}
# Git operations with retry
git_clone_or_pull() {
local repo_url="$1"
local target_dir="$2"
if [ -d "$target_dir/.git" ]; then
log "Updating existing repository..."
cd "$target_dir"
git fetch --all --prune
git reset --hard origin/$BRANCH
git clean -fd
else
log "Cloning repository (shallow clone)..."
git clone --depth 1 --branch $BRANCH "$repo_url" "$target_dir"
fi
}
# Deploy application
deploy() {
check_resources
TIMESTAMP=$(date +%Y%m%d%H%M%S)
RELEASE_DIR="$RELEASES_DIR/$TIMESTAMP"
log "Starting deployment #$TIMESTAMP..."
# Create release directory
mkdir -p "$RELEASE_DIR"
# Clone/update code
git_clone_or_pull "$REPO_URL" "$RELEASE_DIR"
cd "$RELEASE_DIR"
# Install dependencies if package.json exists
if [ -f "package.json" ]; then
log "Installing dependencies with low-memory settings..."
# Set memory limit for npm
export NODE_OPTIONS="--max-old-space-size=256"
# Clean npm cache first
npm cache clean --force
# Install production dependencies only
npm ci --omit=dev --ignore-scripts --no-audit --no-fund
# Run build if build script exists
if [ -f "package.json" ] && grep -q '"build"' package.json; then
log "Building application..."
npm run build
fi
fi
# Link shared files
if [ -d "$SHARED_DIR" ]; then
log "Linking shared files..."
for item in $(ls -A "$SHARED_DIR/"); do
if [ -e "$RELEASE_DIR/$item" ]; then
rm -rf "$RELEASE_DIR/$item"
fi
ln -sf "$SHARED_DIR/$item" "$RELEASE_DIR/$item"
done
fi
# Stop application
log "Stopping application..."
sudo systemctl stop "$APP_NAME" 2>/dev/null || true
pm2 stop "$APP_NAME" 2>/dev/null || true
# Switch current release
log "Activating release..."
rm -f "$CURRENT_DIR"
ln -sf "$RELEASE_DIR" "$CURRENT_DIR"
# Start application
log "Starting application..."
# Try systemd first, then pm2, then direct
if [ -f "$CURRENT_DIR/$APP_NAME.service" ]; then
sudo cp "$CURRENT_DIR/$APP_NAME.service" /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable "$APP_NAME"
sudo systemctl start "$APP_NAME"
elif command -v pm2 &> /dev/null && [ -f "$CURRENT_DIR/ecosystem.config.js" ]; then
cd "$CURRENT_DIR"
pm2 start ecosystem.config.js
pm2 save
elif [ -f "$CURRENT_DIR/package.json" ]; then
cd "$CURRENT_DIR"
NODE_OPTIONS="--max-old-space-size=400" nohup npm start > "$LOG_DIR/app.log" 2>&1 &
fi
# Clean old releases (keep last 5)
log "Cleaning old releases..."
ls -dt "$RELEASES_DIR"/*/ | tail -n +6 | xargs rm -rf 2>/dev/null || true
log "Deployment completed successfully!"
# Show deployment info
info "Current release: $TIMESTAMP"
info "App directory: $CURRENT_DIR"
# Run health check
/opt/scripts/health-check.sh
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--repo)
REPO_URL="$2"
shift 2
;;
--branch)
BRANCH="$2"
shift 2
;;
--app-name)
APP_NAME="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
BRANCH=${BRANCH:-"main"}
APP_NAME=${APP_NAME:-"myapp"}
if [ -z "$REPO_URL" ]; then
echo "Usage: $0 --repo <git-repo-url> [--branch <branch>] [--app-name <name>]"
exit 1
fi
deploy
EOF
$SUDO chmod +x /opt/scripts/deploy.sh
# Health check script
log "Creating health check script..."
cat << 'EOF' | $SUDO tee /opt/scripts/health-check.sh > /dev/null
#!/bin/bash
# Configuration
APP_NAME="myapp"
LOG_FILE="/var/log/app/health.log"
ALERT_THRESHOLD=80
CRITICAL_THRESHOLD=90
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
# Check system health
check_system() {
echo "=== System Health Check $(date '+%Y-%m-%d %H:%M:%S') ==="
# Memory usage
MEM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
MEM_USED=$(free -m | awk '/^Mem:/{print $3}')
MEM_PERCENT=$((MEM_USED * 100 / MEM_TOTAL))
if [ "$MEM_PERCENT" -ge "$CRITICAL_THRESHOLD" ]; then
echo -e "${RED}✗ Memory: ${MEM_PERCENT}% (${MEM_USED}/${MEM_TOTAL}MB) - CRITICAL${NC}"
return 1
elif [ "$MEM_PERCENT" -ge "$ALERT_THRESHOLD" ]; then
echo -e "${YELLOW}⚠ Memory: ${MEM_PERCENT}% (${MEM_USED}/${MEM_TOTAL}MB) - WARNING${NC}"
return 2
else
echo -e "${GREEN}✓ Memory: ${MEM_PERCENT}% (${MEM_USED}/${MEM_TOTAL}MB)${NC}"
fi
# Swap usage
SWAP_TOTAL=$(free -m | awk '/^Swap:/{print $2}')
if [ "$SWAP_TOTAL" -gt 0 ]; then
SWAP_USED=$(free -m | awk '/^Swap:/{print $3}')
SWAP_PERCENT=$((SWAP_USED * 100 / SWAP_TOTAL))
if [ "$SWAP_PERCENT" -gt 50 ]; then
echo -e "${YELLOW}⚠ Swap: ${SWAP_PERCENT}% used${NC}"
fi
fi
# Disk usage
DISK_PERCENT=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$DISK_PERCENT" -ge "$CRITICAL_THRESHOLD" ]; then
echo -e "${RED}✗ Disk: ${DISK_PERCENT}% used - CRITICAL${NC}"
return 1
elif [ "$DISK_PERCENT" -ge "$ALERT_THRESHOLD" ]; then
echo -e "${YELLOW}⚠ Disk: ${DISK_PERCENT}% used - WARNING${NC}"
return 2
else
echo -e "${GREEN}✓ Disk: ${DISK_PERCENT}% used${NC}"
fi
# Load average
LOAD=$(uptime | awk -F'load average:' '{print $2}')
CPU_CORES=$(nproc)
LOAD1=$(echo $LOAD | cut -d, -f1 | tr -d ' ')
if (( $(echo "$LOAD1 > $CPU_CORES" | bc -l) )); then
echo -e "${YELLOW}⚠ Load: $LOAD (1 min)${NC}"
else
echo -e "${GREEN}✓ Load: $LOAD${NC}"
fi
return 0
}
# Check application
check_app() {
echo -e "\n=== Application Check ==="
# Check if app is running
if systemctl is-active --quiet "$APP_NAME"; then
echo -e "${GREEN}✓ Service: $APP_NAME is running${NC}"
# Check service status
SERVICE_STATUS=$(systemctl status "$APP_NAME" | grep "Active:" | cut -d':' -f2-)
echo " Status:$SERVICE_STATUS"
# Check recent logs for errors
ERROR_COUNT=$(sudo journalctl -u "$APP_NAME" --since "5 minutes ago" | grep -i "error\|fail\|exception" | wc -l)
if [ "$ERROR_COUNT" -gt 0 ]; then
echo -e "${YELLOW}⚠ Found $ERROR_COUNT errors in recent logs${NC}"
fi
elif command -v pm2 &> /dev/null && pm2 list | grep -q "$APP_NAME"; then
echo -e "${GREEN}✓ PM2: $APP_NAME is running${NC}"
pm2 info "$APP_NAME" | grep -E "status|uptime|memory"
else
echo -e "${RED}✗ Application $APP_NAME is not running${NC}"
return 1
fi
# Check if app responds (optional - customize port)
if command -v curl &> /dev/null; then
if curl -s -f http://localhost:3000/health > /dev/null 2>&1; then
echo -e "${GREEN}✓ Health endpoint: Responding${NC}"
elif curl -s -f http://localhost:3000 > /dev/null 2>&1; then
echo -e "${GREEN}✓ Application: Responding on port 3000${NC}"
fi
fi
return 0
}
# Main
main() {
EXIT_CODE=0
# Run checks
check_system || EXIT_CODE=1
check_app || EXIT_CODE=1
# Log to file
{
echo "=== Health Check $(date '+%Y-%m-%d %H:%M:%S') ==="
free -m
df -h /
systemctl status "$APP_NAME" --no-pager
} >> "$LOG_FILE"
echo -e "\n=== Summary ==="
if [ $EXIT_CODE -eq 0 ]; then
echo -e "${GREEN}✅ All systems operational${NC}"
else
echo -e "${RED}❌ Issues detected${NC}"
fi
# Keep log file manageable
tail -n 1000 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
exit $EXIT_CODE
}
main
EOF
$SUDO chmod +x /opt/scripts/health-check.sh
# Cleanup script
log "Creating cleanup script..."
cat << 'EOF' | $SUDO tee /opt/scripts/cleanup.sh > /dev/null
#!/bin/bash
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log "Starting system cleanup..."
# Clear package cache
sudo apt-get clean
sudo apt-get autoremove -y
# Clear temporary files (older than 1 day)
log "Cleaning temporary files..."
find /tmp -type f -atime +1 -delete 2>/dev/null || true
find /var/tmp -type f -atime +1 -delete 2>/dev/null || true
# Clear old logs (keep last 3 days)
log "Rotating logs..."
find /var/log -name "*.log" -type f -mtime +3 -delete 2>/dev/null || true
find /var/log -name "*.gz" -type f -delete 2>/dev/null || true
# Clear journal logs (keep last 1 day)
sudo journalctl --vacuum-time=1d 2>/dev/null || true
# Clear npm cache (if Node.js is installed)
if command -v npm &> /dev/null; then
log "Cleaning npm cache..."
npm cache clean --force 2>/dev/null || true
rm -rf ~/.npm/_logs/* 2>/dev/null || true
fi
# Clear old app releases (keep last 3)
if [ -d "/var/www/app/releases" ]; then
log "Cleaning old releases..."
ls -dt /var/www/app/releases/*/ 2>/dev/null | tail -n +4 | xargs rm -rf 2>/dev/null || true
fi
# Clear old backups (keep last 7 days)
if [ -d "/opt/backups" ]; then
log "Cleaning old backups..."
find /opt/backups -type f -mtime +7 -delete 2>/dev/null || true
fi
# Clear browser-like caches
log "Cleaning user caches..."
rm -rf ~/.cache/* 2>/dev/null || true
# Clear APT lists (keep current)
log "Cleaning APT lists..."
rm -rf /var/lib/apt/lists/* 2>/dev/null || true
sudo apt-get update
# Drop caches (careful with production!)
log "Optimizing memory..."
sync
echo 1 | sudo tee /proc/sys/vm/drop_caches > /dev/null 2>&1 || true
# Check disk usage
log "Disk usage after cleanup:"
df -h /
log "Cleanup completed!"
EOF
$SUDO chmod +x /opt/scripts/cleanup.sh
# ==================== PHASE 7: SYSTEMD SERVICE ====================
log "Phase 7: Creating Systemd Service"
cat << 'EOF' | $SUDO tee /etc/systemd/system/myapp.service > /dev/null
[Unit]
Description=My Application
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/var/www/app/current
# Memory limits - CRITICAL for 1GB RAM
MemoryMax=700M
MemorySwapMax=300M
LimitNOFILE=4096
LimitNPROC=50
# Environment
Environment="NODE_ENV=production"
Environment="PORT=3000"
Environment="NODE_OPTIONS=--max-old-space-size=400"
# Start command
ExecStart=/usr/bin/npm start
# Alternative if using direct Node:
# ExecStart=/usr/bin/node server.js
# Restart policy
Restart=always
RestartSec=10
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ReadWritePaths=/var/log/app /var/www/app/current
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
EOF
# ==================== PHASE 8: MONITORING & CRON ====================
log "Phase 8: Setting up Monitoring"
# Simple monitoring script
cat << 'EOF' | $SUDO tee /opt/monitoring/monitor.sh > /dev/null
#!/bin/bash
# Lightweight monitoring script
LOG_FILE="/var/log/app/monitor.log"
MAX_LOG_SIZE=10485760 # 10MB
# Rotate log if too large
if [ -f "$LOG_FILE" ] && [ $(stat -c%s "$LOG_FILE") -gt $MAX_LOG_SIZE ]; then
mv "$LOG_FILE" "${LOG_FILE}.old"
fi
{
echo "=== System Monitor $(date '+%Y-%m-%d %H:%M:%S') ==="
echo "Uptime: $(uptime -p)"
echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
# Memory
free -m | awk 'NR==2{printf "Memory: Used=%dMB (%.1f%%), Free=%dMB\n", $3, $3*100/$2, $4}'
# Disk
df -h / | awk 'NR==2{printf "Disk: Used=%s (%s), Free=%s\n", $3, $5, $4}'
# Top 5 processes by memory
echo -e "\nTop 5 processes by memory:"
ps aux --sort=-%mem | head -6
# Service status
echo -e "\nService status:"
systemctl is-active myapp && echo "myapp: ACTIVE" || echo "myapp: INACTIVE"
echo "====================================="
} >> "$LOG_FILE"
EOF
$SUDO chmod +x /opt/monitoring/monitor.sh
# Setup cron jobs
log "Setting up cron jobs..."
# Create crontab for ubuntu user
CRON_FILE="/home/ubuntu/crontab"
cat << 'EOF' > "$CRON_FILE"
# Run health check every 5 minutes
*/5 * * * * /opt/scripts/health-check.sh >/dev/null 2>&1
# Run cleanup daily at 3 AM
0 3 * * * /opt/scripts/cleanup.sh >/dev/null 2>&1
# Run monitoring every hour
0 * * * * /opt/monitoring/monitor.sh >/dev/null 2>&1
# Update package lists weekly
0 2 * * 1 apt-get update >/dev/null 2>&1
# Security updates daily at 4 AM
0 4 * * * unattended-upgrade -v >/dev/null 2>&1
# Log rotation
0 0 * * * logrotate /etc/logrotate.d/myapp >/dev/null 2>&1
EOF
# Install crontab
crontab "$CRON_FILE"
rm "$CRON_FILE"
# Log rotation config
cat << 'EOF' | $SUDO tee /etc/logrotate.d/myapp > /dev/null
/var/log/app/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0640 ubuntu ubuntu
sharedscripts
postrotate
systemctl kill -s USR1 myapp.service 2>/dev/null || true
endscript
}
EOF
# ==================== PHASE 9: KERNEL OPTIMIZATIONS ====================
log "Phase 9: Kernel Optimizations"
cat << 'EOF' | $SUDO tee -a /etc/sysctl.conf > /dev/null
# Memory optimizations
vm.overcommit_memory = 1
vm.overcommit_ratio = 50
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
vm.vfs_cache_pressure = 50
vm.swappiness = 10
# Network optimizations for fewer connections
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 2048
net.core.netdev_max_backlog = 1000
# TCP optimizations
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 30
# Security
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
EOF
$SUDO sysctl -p
# ==================== PHASE 10: FINAL SETUP ====================
log "Phase 10: Final Configuration"
# Create README
cat << 'EOF' | tee /home/ubuntu/README.md > /dev/null
# EC2 Instance - Lightweight Setup (No Docker)
## Quick Start Guide
### Application Structure:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment