diff --git a/Makefile b/Makefile index 85d2996..a33a5e6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Makefile for dotfiles_server # Quick shortcuts for all installation commands -.PHONY: help setup ssh-port ssh-timeout php php-ext lazydocker \ +.PHONY: help setup ssh-port ssh-timeout hostname php php-ext lazydocker \ global-dev add-user zabbix-server zabbix-client update-zabbix-ip \ fix-mysql clean @@ -14,9 +14,10 @@ help: @echo "Usage: make " @echo "" @echo "System Setup:" - @echo " make setup - Setup the server" - @echo " make ssh-port PORT=XXXX - Change SSH port (default: 22)" - @echo " make ssh-timeout - Configure SSH timeout (5min auto-disconnect)" + @echo " make setup - Setup the server" + @echo " make ssh-port PORT=XXXX - Change SSH port (default: 22)" + @echo " make ssh-timeout - Configure SSH timeout (5min auto-disconnect)" + @echo " make hostname NAME=server - Change system hostname" @echo "" @echo "PHP & Development:" @echo " make php - Install PHP" @@ -40,6 +41,7 @@ help: @echo "Examples:" @echo " make setup" @echo " make ssh-port PORT=19742" + @echo " make hostname NAME=myserver" @echo " make php-ext VER=8.4" @echo " make global-dev-force" @echo " make add-user USER=john" @@ -62,6 +64,13 @@ ssh-port: ssh-timeout: @bash install.sh ssh_timeout +hostname: + @if [ -z "$(NAME)" ]; then \ + sudo bash install.sh hostname; \ + else \ + sudo bash install.sh hostname $(NAME); \ + fi + # PHP & Development php: @bash install.sh php @@ -128,6 +137,7 @@ clean: s: setup sp: ssh-port st: ssh-timeout +hn: hostname p: php pe: php-ext ld: lazydocker @@ -146,6 +156,7 @@ shortcuts: @echo " s = setup" @echo " sp = ssh-port" @echo " st = ssh-timeout" + @echo " hn = hostname" @echo " p = php" @echo " pe = php-ext" @echo " ld = lazydocker" @@ -161,6 +172,7 @@ shortcuts: @echo "Examples:" @echo " make s" @echo " make sp PORT=19742" + @echo " make hn NAME=myserver" @echo " make pe VER=8.4" @echo " make gdf" @echo " make au USER=john" diff --git a/docs/SSH-TIMEOUT-DEBUG.md b/docs/SSH-TIMEOUT-DEBUG.md index c169230..65ca001 100644 --- a/docs/SSH-TIMEOUT-DEBUG.md +++ b/docs/SSH-TIMEOUT-DEBUG.md @@ -1,24 +1,24 @@ -# Hướng dẫn Debug SSH Auto-Logout +# SSH Auto-Logout Debug Guide -## Vấn đề: SSH không tự động logout sau 5 phút +## Problem: SSH does not auto logout after 5 minutes -### Bước 1: Kiểm tra cấu hình hiện tại +### Step 1: Check current configuration -Chạy script verify: +Run the verify script: ```bash bash /path/to/setup/system/verify-ssh-timeout.sh ``` -Hoặc kiểm tra thủ công: +Or check manually: ```bash grep -E "^ClientAlive" /etc/ssh/sshd_config ``` -### Bước 2: Các nguyên nhân thường gặp +### Step 2: Common causes -#### ✅ Nguyên nhân 1: ssh.socket đang override cấu hình -**Triệu chứng:** Port trong sshd_config không có hiệu lực -**Giải pháp:** +#### ✅ Cause 1: ssh.socket is overriding configuration +**Symptom:** Port in sshd_config has no effect +**Solution:** ```bash sudo systemctl stop ssh.socket sudo systemctl disable ssh.socket @@ -26,13 +26,13 @@ sudo systemctl daemon-reload sudo systemctl restart ssh ``` -#### ✅ Nguyên nhân 2: Cấu hình bị duplicate hoặc comment -**Kiểm tra:** +#### ✅ Cause 2: Duplicate or commented configuration +**Check:** ```bash grep -n "ClientAlive" /etc/ssh/sshd_config ``` -**Giải pháp:** Xóa tất cả dòng cũ và thêm lại: +**Solution:** Remove all old lines and add again: ```bash sudo sed -i '/^ClientAliveInterval/d' /etc/ssh/sshd_config sudo sed -i '/^ClientAliveCountMax/d' /etc/ssh/sshd_config @@ -41,76 +41,76 @@ echo 'ClientAliveCountMax 5' | sudo tee -a /etc/ssh/sshd_config sudo systemctl restart ssh ``` -#### ✅ Nguyên nhân 3: Client SSH có keepalive riêng -**Triệu chứng:** Mac/Windows Terminal tự động gửi keepalive -**Kiểm tra client:** +#### ✅ Cause 3: SSH client has its own keepalive +**Symptom:** Mac/Windows Terminal automatically sends keepalive +**Check client:** - Mac/Linux: `cat ~/.ssh/config | grep ServerAlive` -- Windows: Kiểm tra PuTTY/Terminal settings +- Windows: Check PuTTY/Terminal settings -**Giải pháp:** Tắt keepalive ở client hoặc giảm thời gian timeout xuống: +**Solution:** Disable keepalive on client or reduce server timeout: ```bash -# Server side - giảm xuống 3 phút để test +# Server side - reduce to 3 minutes for testing ClientAliveInterval 30 ClientAliveCountMax 6 -# = 30s × 6 = 180s (3 phút) +# = 30s × 6 = 180s (3 minutes) ``` -#### ✅ Nguyên nhân 4: Service chưa restart đúng cách -**Giải pháp:** +#### ✅ Cause 4: Service not restarted properly +**Solution:** ```bash -# Kiểm tra service name +# Check service name systemctl list-units | grep ssh -# Restart đúng service -sudo systemctl restart sshd # hoặc +# Restart the correct service +sudo systemctl restart sshd # or sudo systemctl restart ssh # Verify sudo systemctl status sshd --no-pager ``` -### Bước 3: Test timeout +### Step 3: Test timeout -**Test 1: Kiểm tra config có load không** +**Test 1: Check if config is loaded** ```bash sudo sshd -T | grep clientalive ``` -Kết quả mong đợi: +Expected result: ``` clientaliveinterval 60 clientalivecountmax 5 ``` -**Test 2: Mở session mới và chờ** -1. Giữ session hiện tại -2. Mở terminal mới: `ssh user@server` -3. Không làm gì trong 5 phút -4. Session mới phải tự động ngắt +**Test 2: Open a new session and wait** +1. Keep the current session open +2. Open a new terminal: `ssh user@server` +3. Do nothing for 5 minutes +4. The new session should auto disconnect -**Test 3: Kiểm tra log** +**Test 3: Check logs** ```bash -# Xem SSH log realtime +# View SSH log in realtime sudo tail -f /var/log/auth.log | grep sshd -# Hoặc +# Or sudo journalctl -u ssh -f ``` -### Bước 4: Troubleshooting nâng cao +### Step 4: Advanced troubleshooting -#### Kiểm tra tất cả process liên quan: +#### Check all related processes: ```bash ps aux | grep sshd sudo ss -tlnp | grep ssh ``` -#### Kiểm tra Drop-in configs: +#### Check Drop-in configs: ```bash ls -la /etc/ssh/sshd_config.d/ cat /etc/ssh/sshd_config.d/*.conf 2>/dev/null ``` -#### Reset hoàn toàn: +#### Full reset: ```bash # Backup sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup @@ -133,40 +133,39 @@ sudo systemctl daemon-reload sudo systemctl restart ssh ``` -### Bước 5: Nếu vẫn không work +### Step 5: If still not working -Thử với TCPKeepAlive (khác với ClientAlive): +Try with TCPKeepAlive (different from ClientAlive): ```bash echo 'TCPKeepAlive yes' | sudo tee -a /etc/ssh/sshd_config sudo systemctl restart ssh ``` -Hoặc sử dụng cấu hình aggressive hơn: +Or use a more aggressive configuration: ```bash ClientAliveInterval 30 ClientAliveCountMax 3 -# = 30s × 3 = 90s (1.5 phút timeout) +# = 30s × 3 = 90s (1.5 minutes timeout) ``` -### ⚠️ LƯU Ý QUAN TRỌNG +### ⚠️ IMPORTANT NOTES -1. **Luôn giữ session hiện tại mở** khi test để tránh bị lock khỏi server -2. **Test với session mới** trước khi đóng session cũ -3. **Firewall** có thể giữ connection alive, kiểm tra: +1. **Always keep the current session open** when testing to avoid locking yourself out +2. **Test with a new session** before closing the old one +3. **Firewall** may keep the connection alive, check with: ```bash sudo iptables -L -n -v | grep ESTABLISHED ``` -4. **Client-side keepalive** có thể override server config +4. **Client-side keepalive** may override server config -### Script tự động fix tất cả +### Auto-fix script -Chạy lại script setup với force: +Rerun the setup script with force: ```bash sudo bash /path/to/setup/system/ssh_timeout.sh ``` -Sau đó verify: +Then verify: ```bash bash /path/to/setup/system/verify-ssh-timeout.sh ``` - diff --git a/install.sh b/install.sh index 5b8ef23..954f487 100755 --- a/install.sh +++ b/install.sh @@ -96,6 +96,11 @@ fix_mysql_frozen() { sudo bash fix-mysql-frozen.sh } +hostname_setup() { + cd "$CURRENT_DIR/setup/system" || exit + sudo bash hostname-setup.sh "$@" +} + usage() { echo "Usage: bash $0 [command] [args]" echo '' @@ -111,6 +116,7 @@ usage() { echo ' zabbix_server Install Zabbix Server (auto-detect Nginx/Apache)' echo ' zabbix_client Install Zabbix Agent (client) [server_ip]' echo ' update_zabbix_ip Update Zabbix Server IP for installed agent [new_ip]' + echo ' hostname Change system hostname [new_hostname]' echo ' fix_mysql Fix MySQL frozen issue after MariaDB to MySQL migration' echo '' echo 'Args for global_dev:' @@ -132,6 +138,9 @@ usage() { echo 'Args for update_zabbix_ip:' echo ' [new_ip] New Zabbix Server IP (optional, will prompt if not provided)' echo '' + echo 'Args for hostname:' + echo ' [new_hostname] New hostname (optional, will prompt if not provided)' + echo '' echo 'Example:' echo " bash $0 setup" echo " bash $0 ssh_port 12345" @@ -149,6 +158,8 @@ usage() { echo " bash $0 zabbix_client 192.168.1.100" echo " bash $0 update_zabbix_ip" echo " bash $0 update_zabbix_ip 192.168.1.200" + echo " bash $0 hostname" + echo " bash $0 hostname myserver" echo " bash $0 fix_mysql" echo '' } @@ -202,6 +213,11 @@ case "${1:-}" in fix_mysql_frozen ;; + hostname | hn) + shift # Remove command name + hostname_setup "$@" + ;; + *) usage exit 1 diff --git a/setup/packages/list.sh b/setup/packages/list.sh index dce8c16..52a8e32 100644 --- a/setup/packages/list.sh +++ b/setup/packages/list.sh @@ -9,10 +9,25 @@ if [ "" = "$PKG_OK" ]; then fi echo "=========================== zsh ===========================" -bash zsh.sh +while true; do + if [[ $ACCEPT_INSTALL =~ ^[Yy]$ ]]; then + yn="y" + else + read -r -p "Do you want to install zsh and oh-my-zsh? (Y/N) " yn + fi + case $yn in + [Yy]*) + bash zsh.sh + break + ;; + [Nn]*) break ;; + *) echo "Please answer yes or no." ;; + esac +done + installPackages() { - PACKAGE_LIST=("curl" "wget" "vim" "tmux" "nano" "npm" "certbot" "python3-certbot-nginx" "fail2ban" "htop" "btop") + PACKAGE_LIST=("curl" "wget" "make" "vim" "tmux" "nano" "npm" "certbot" "python3-certbot-nginx" "fail2ban" "htop" "btop") for packageName in "${PACKAGE_LIST[@]}"; do echo "=========================== $packageName ===========================" @@ -21,7 +36,7 @@ installPackages() { echo "Checking for $packageName: $PKG_OK" if [ "" = "$PKG_OK" ]; then echo "No $packageName. Setting up $packageName." - sudo apt-get install -y "$packageName" + sudo apt install -y "$packageName" fi echo "" done diff --git a/setup/packages/nvm-global.sh b/setup/packages/nvm-global.sh index c46b627..2f0e537 100755 --- a/setup/packages/nvm-global.sh +++ b/setup/packages/nvm-global.sh @@ -81,10 +81,16 @@ export NVM_DIR="/usr/local/nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Install latest LTS Node.js version -echo "" -echo "Installing latest LTS Node.js version..." if command -v nvm &>/dev/null; then - nvm install --lts + echo "Installing latest LTS Node.js version..." + if ! nvm install --lts --reinstall-packages-from=current; then + echo "Cleaning up existing Node.js installation directories..." + NODE_VERSION=$(nvm version-remote --lts) + if [ -d "$NVM_DIR/versions/node/$NODE_VERSION" ]; then + sudo rm -rf "$NVM_DIR/versions/node/$NODE_VERSION" + fi + nvm install --lts + fi nvm use --lts nvm alias default 'lts/*' @@ -200,4 +206,3 @@ echo " nvm --version" echo " node --version" echo " npm --version" echo "" - diff --git a/setup/system/hostname-setup.sh b/setup/system/hostname-setup.sh new file mode 100755 index 0000000..0483691 --- /dev/null +++ b/setup/system/hostname-setup.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +# ======================== Change System Hostname ======================== +# This script changes the system hostname and updates all necessary files +# including /etc/hostname, /etc/hosts, and cloud-init metadata + +echo '==========================================' +echo '🔧 Setting up system hostname' +echo '==========================================' +echo '' + +# Get current hostname +CURRENT_HOSTNAME=$(hostname) +echo "📌 Current hostname: $CURRENT_HOSTNAME" +echo '' + +# Get new hostname from argument or prompt +NEW_HOSTNAME=$1 + +while true; do + if [[ $ACCEPT_INSTALL =~ ^[Yy]$ ]] && [[ -n $NEW_HOSTNAME ]]; then + yn="y" + else + if [[ -z $NEW_HOSTNAME ]]; then + read -r -p "Enter new hostname: " NEW_HOSTNAME + fi + echo "" + read -r -p "Change hostname to '$NEW_HOSTNAME'? (Y/N) " yn + fi + + case $yn in + [Yy]*) + # Validate hostname + # RFC 1123: hostname can contain letters, digits, hyphens, max 63 chars + if [[ ! $NEW_HOSTNAME =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then + echo "❌ Invalid hostname format!" + echo " Hostname must:" + echo " - Start and end with alphanumeric character" + echo " - Contain only letters, digits, and hyphens" + echo " - Be 1-63 characters long" + echo "" + NEW_HOSTNAME="" + if [[ $ACCEPT_INSTALL =~ ^[Yy]$ ]]; then + break + fi + continue + fi + + echo "" + echo "=========================== Hostname Change ===========================" + echo "Old hostname: $CURRENT_HOSTNAME" + echo "New hostname: $NEW_HOSTNAME" + echo "" + echo "Processing..." + + # ============ 1. Change hostname using hostnamectl ============ + echo "1️⃣ Updating system hostname with hostnamectl..." + if command -v hostnamectl >/dev/null 2>&1; then + sudo hostnamectl set-hostname "$NEW_HOSTNAME" + echo "✓ hostnamectl updated" + else + # Fallback for systems without hostnamectl + echo "$NEW_HOSTNAME" | sudo tee /etc/hostname >/dev/null + sudo hostname "$NEW_HOSTNAME" + echo "✓ /etc/hostname updated" + fi + + # ============ 2. Update /etc/hosts ============ + echo "" + echo "2️⃣ Updating /etc/hosts..." + + # Backup /etc/hosts + sudo cp /etc/hosts /etc/hosts.backup.$(date +%Y%m%d%H%M%S) + + # Replace old hostname with new hostname in /etc/hosts + # Handle both 127.0.1.1 format and other variations + sudo sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts 2>/dev/null || true + sudo sed -i "s/$CURRENT_HOSTNAME/$NEW_HOSTNAME/g" /etc/hosts 2>/dev/null || true + + # Ensure there's an entry for the new hostname + if ! grep -q "$NEW_HOSTNAME" /etc/hosts; then + # Add entry if not exists + if grep -q "127.0.1.1" /etc/hosts; then + sudo sed -i "s/127.0.1.1.*/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts + else + echo "127.0.1.1 $NEW_HOSTNAME" | sudo tee -a /etc/hosts >/dev/null + fi + fi + echo "✓ /etc/hosts updated" + echo " Backup created: /etc/hosts.backup.$(date +%Y%m%d%H%M%S)" + + # ============ 3. Update cloud-init metadata (if exists) ============ + echo "" + echo "3️⃣ Checking cloud-init metadata..." + if [ -f /etc/cloud/cloud.cfg ]; then + CLOUD_HOSTNAME=$(sudo grep "preserve_hostname:" /etc/cloud/cloud.cfg | grep -v "#" || echo "") + if [[ -z $CLOUD_HOSTNAME ]] || [[ $CLOUD_HOSTNAME == *"false"* ]]; then + # Set preserve_hostname: true to prevent cloud-init from overwriting + sudo sed -i 's/preserve_hostname:.*/preserve_hostname: true/' /etc/cloud/cloud.cfg 2>/dev/null || true + if ! grep -q "^preserve_hostname:" /etc/cloud/cloud.cfg; then + echo "preserve_hostname: true" | sudo tee -a /etc/cloud/cloud.cfg >/dev/null + fi + echo "✓ cloud-init configured to preserve hostname" + else + echo "✓ cloud-init already configured to preserve hostname" + fi + else + echo " (cloud-init not found, skipping)" + fi + + # ============ 4. Update Postfix mail server (if exists) ============ + echo "" + echo "4️⃣ Checking Postfix configuration..." + if command -v postconf >/dev/null 2>&1; then + sudo postconf -e "myhostname=$NEW_HOSTNAME" + echo "✓ Postfix myhostname updated to $NEW_HOSTNAME" + else + echo " (Postfix not found, skipping)" + fi + + # ============ 5. Summary ============ + echo "" + echo "==========================================" + echo "✨ Hostname changed successfully!" + echo "==========================================" + echo "" + echo "New hostname: $NEW_HOSTNAME" + echo "" + echo "⚠️ NOTE:" + echo " - Changes take effect immediately" + echo " - You may need to reconnect SSH for prompt to update" + echo " - Some services may need restart" + echo "" + echo "🔍 Verify:" + echo " hostname # Should show $NEW_HOSTNAME" + echo " hostname -f # Should show FQDN" + echo " cat /etc/hostname # Should show $NEW_HOSTNAME" + echo "" + + break + ;; + [Nn]*) break ;; + *) + echo "Please answer yes or no." + NEW_HOSTNAME="" + ;; + esac +done diff --git a/setup/system/ssh_timeout.sh b/setup/system/ssh_timeout.sh index aca4ba7..24edcb2 100644 --- a/setup/system/ssh_timeout.sh +++ b/setup/system/ssh_timeout.sh @@ -51,10 +51,17 @@ sudo sed -i '/Auto logout after/d' /etc/zsh/zshenv 2>/dev/null sudo sed -i '/Auto logout after/d' /etc/zsh/zshrc 2>/dev/null # Add to /etc/zsh/zshenv ONLY (loaded first for all zsh sessions) -sudo tee -a /etc/zsh/zshenv > /dev/null < /dev/null <<'EOF' # Auto logout after 5 minutes of inactivity -TMOUT=$TIMEOUT_SECONDS +TMOUT=300 + +# Custom message before logout for ZSH +TRAPALRM() { + print '\n👋 Hi, timed out waiting for input, bye!' + kill -HUP $$ +} + readonly TMOUT export TMOUT EOF