diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..4b376ce --- /dev/null +++ b/init.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Function to print messages +info() { + echo -e "${GREEN}[INFO] $1${NC}" +} + +error() { + echo -e "${RED}[ERROR] $1${NC}" >&2 + exit 1 +} + +# Detect OS +OS="" +if [ -f /etc/os-release ]; then + . /etc/os-release + case $ID in + ubuntu) + OS="ubuntu" + ;; + arch) + OS="arch" + ;; + *) + error "Unsupported OS: $ID" + ;; + esac +else + error "Cannot detect OS. /etc/os-release not found." +fi + +info "Detected OS: $OS" + +# Ensure we're in the dotfiles directory +if [ ! -f "$(pwd)/.gitmodules" ]; then + error "This script must be run from the dotfiles repository directory" +fi + +# Install prerequisites +info "Installing prerequisites..." + +if [ "$OS" = "ubuntu" ]; then + # Update package lists + sudo apt update && sudo apt upgrade -y + + # Install required packages + sudo apt install -y git tmux stow fzf gcc + + # Install optional packages (bat, fd-find, zoxide) + sudo apt install -y bat fd-find + curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash + + # Install eza (community-maintained ls alternative) + sudo mkdir -p /etc/apt/keyrings + wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg + echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list + sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list + sudo apt update + sudo apt install -y eza + + # Install Neovim from GitHub releases (latest stable) + info "Installing Neovim from GitHub releases..." + NVIM_VERSION=$(curl -s https://api.github.com/repos/neovim/neovim/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + wget -O /tmp/nvim-linux64.tar.gz "https://github.com/neovim/neovim/releases/download/${NVIM_VERSION}/nvim-linux64.tar.gz" + sudo tar -C /usr/local -xzf /tmp/nvim-linux64.tar.gz + sudo ln -sf /usr/local/nvim-linux64/bin/nvim /usr/local/bin/nvim + rm /tmp/nvim-linux64.tar.gz + + # Install thefuck + sudo apt install -y python3-pip + pip3 install thefuck --user + +elif [ "$OS" = "arch" ]; then + # Ensure yay is installed for AUR packages + if ! command -v yay &> /dev/null; then + info "Installing yay..." + sudo pacman -S --needed git base-devel + git clone https://aur.archlinux.org/yay.git /tmp/yay + cd /tmp/yay + makepkg -si --noconfirm + cd - && rm -rf /tmp/yay + fi + + # Install all packages + yay -S --noconfirm git tmux neovim zoxide stow fzf bat eza fd gcc thefuck +fi + +# Initialize and update submodules +info "Initializing git submodules..." +git submodule update --init --recursive + +# Backup existing config files +info "Backing up existing configuration files..." +BACKUP_DIR="$HOME/.dotfiles_backup_$(date +%F_%H-%M-%S)" +mkdir -p "$BACKUP_DIR" + +for file in .gitconfig .zshrc .tmux.conf .bashrc; do + [ -f "$HOME/$file" ] && mv "$HOME/$file" "$BACKUP_DIR/$file" && info "Backed up ~/$file to $BACKUP_DIR/$file" +done + +for dir in .config/nvim .config/mc kam .oh-my-zsh .tmux; do + [ -d "$HOME/$dir" ] && mv "$HOME/$dir" "$BACKUP_DIR/$(basename $dir)" && info "Backed up ~/$dir to $BACKUP_DIR/$(basename $dir)" +done + +# Create symlinks with stow +info "Creating symlinks with stow..." +stow . + +# Change shell to zsh +if [ "$(basename "$SHELL")" != "zsh" ]; then + info "Changing shell to zsh..." + ZSH_PATH=$(which zsh) + if [ -z "$ZSH_PATH" ]; then + error "zsh not found. Please install zsh and run 'chsh -s $(which zsh)' manually." + fi + chsh -s "$ZSH_PATH" + info "Shell changed to zsh. Please log out and log back in for the change to take effect." +fi + +# Final instructions +info "Dotfiles setup complete!" +echo "To source tmux configuration:" +echo "1. Start tmux with 'tmux'" +echo "2. Press : (default is Ctrl+b)" +echo "3. Type 'source ~/.tmux.conf' and press Enter" +echo +echo "Backup of previous configs is stored in: $BACKUP_DIR" +echo "You may need to log out and log back in for zsh to take effect." diff --git a/local_seed.sh b/local_seed.sh new file mode 100755 index 0000000..596fd63 --- /dev/null +++ b/local_seed.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Default values +ANONYMOUS=false +USERNAME="goodhumored" + +# Function to print messages +info() { + echo -e "${GREEN}[INFO] $1${NC}" +} + +error() { + echo -e "${RED}[ERROR] $1${NC}" >&2 + exit 1 +} + +# Function to generate random username for anonymous mode +generate_random_username() { + echo "user$(head /dev/urandom | tr -dc a-z0-9 | head -c 8)" +} + +# Function to display usage +usage() { + echo "Usage: $0 [options]" + echo "Options:" + echo " -u, --username Username to create (default: goodhumored)" + echo " -a, --anonymous Run in anonymous mode (random username, no dotfiles)" + exit 1 +} + +# Parse command line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + -u|--username) USERNAME="$2"; shift ;; + -a|--anonymous) ANONYMOUS=true ;; + *) echo "Unknown parameter: $1"; usage ;; + esac + shift +done + +# Set username for anonymous mode +if [ "$ANONYMOUS" = true ]; then + USERNAME=$(generate_random_username) +fi + +# Check if running as root +if [ "$(id -u)" -ne 0 ]; then + error "This script must be run with sudo privileges" +fi + +# Create user and setup home directory +info "Creating user $USERNAME..." +useradd -m -s /bin/bash -G sudo "$USERNAME" +chmod 700 "/home/$USERNAME" + +# Setup SSH directory and authorized_keys +info "Setting up SSH directory..." +mkdir -p "/home/$USERNAME/.ssh" +chmod 700 "/home/$USERNAME/.ssh" +touch "/home/$USERNAME/.ssh/authorized_keys" +chmod 600 "/home/$USERNAME/.ssh/authorized_keys" +chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh" + +# Install dependencies +info "Installing dependencies..." +apt-get update +apt-get install -y git stow + +# Clone and setup dotfiles (non-anonymous mode only) +if [ "$ANONYMOUS" = false ]; then + info "Cloning dotfiles repository..." + su - "$USERNAME" -c "git clone https://github.com/goodhumored/dotfiles /home/$USERNAME/dotfiles" + info "Running init.sh..." + su - "$USERNAME" -c "cd /home/$USERNAME/dotfiles && ./init.sh" +fi + +info "Local server setup complete!" +echo "Username: $USERNAME" +if [ "$ANONYMOUS" = false ]; then + echo "Dotfiles have been cloned and initialized." +else + echo "Anonymous mode: No dotfiles cloned." +fi +echo "You can now add an SSH public key to /home/$USERNAME/.ssh/authorized_keys" diff --git a/seed.sh b/seed.sh new file mode 100755 index 0000000..ec554e0 --- /dev/null +++ b/seed.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +set -e + +# Defaults +ANONYMOUS=false +PORT=22 +NEW_USER="goodhumored" +PASS_DIR="$HOME/.password-store" + +# Random username for anonymous mode +generate_random_username() { + echo "user$(head /dev/urandom | tr -dc a-z0-9 | head -c 8)" +} + +# Usage +usage() { + echo "Usage: $0 [options]" + echo " -h, --host Server IP" + echo " -p, --port SSH port (default: 22)" + echo " -r, --root_user Sudo user for SSH" + echo " -s, --server_name Server name for SSH config" + echo " -u, --username User to create (default: goodhumored)" + echo " -n, --pass_name Password store name" + echo " -a, --anonymous Anonymous mode" + exit 1 +} + +# Check sshpass +if ! command -v sshpass &> /dev/null; then + echo "Ошибка: нужен sshpass." + echo "Установи: sudo apt-get install sshpass (Ubuntu) или sudo pacman -S sshpass (Arch)" + exit 1 +fi + +# Parse args +while [[ "$#" -gt 0 ]]; do + case $1 in + -h|--host) HOST="$2"; shift ;; + -p|--port) PORT="$2"; shift ;; + -r|--root_user) ROOT_USER="$2"; shift ;; + -s|--server_name) SERVER_NAME="$2"; shift ;; + -u|--username) NEW_USER="$2"; shift ;; + -n|--pass_name) PASS_NAME="$2"; shift ;; + -a|--anonymous) ANONYMOUS=true ;; + *) echo "Неизвестный параметр: $1"; usage ;; + esac + shift +done + +# Validate args +if [ -z "$HOST" ] || [ -z "$ROOT_USER" ] || [ -z "$SERVER_NAME" ]; then + echo "Ошибка: нужны host, root_user и server_name" + usage +fi + +# Prompt for password +if [ "$ANONYMOUS" = false ]; then + if [ -z "$PASS_NAME" ]; then + read -p "Имя для хранения пароля: " PASS_NAME + fi + read -s -p "Пароль для SSH и sudo: " ROOT_PASS + echo +fi + +# Set username for anonymous +if [ "$ANONYMOUS" = true ]; then + NEW_USER=$(generate_random_username) +fi + +# Generate SSH key +KEY_PATH="$HOME/.ssh/keys/$SERVER_NAME" +mkdir -p "$HOME/.ssh/keys" +ssh-keygen -t ed25519 -f "$KEY_PATH" -N "" -C "$SERVER_NAME" + +# Read public key +PUBLIC_KEY=$(cat "$KEY_PATH.pub") + +# Generate and store password +NEW_PASS="" +if [ "$ANONYMOUS" = false ]; then + mkdir -p "$PASS_DIR" + NEW_PASS="$(pass generate "$PASS_NAME" 16 | tail -n1)" + echo "DEBUG: Generated password: '$NEW_PASS'" +fi + +# Update SSH config +CONFIG_FILE="$HOME/.ssh/config" +touch "$CONFIG_FILE" +chmod 600 "$CONFIG_FILE" + +# Remove old entry +sed -i "/Host $SERVER_NAME/,/^\s*$/d" "$CONFIG_FILE" + +# Add new entry +cat << EOF >> "$CONFIG_FILE" + +Host $SERVER_NAME + HostName $HOST + Port $PORT + User $NEW_USER + IdentityFile $KEY_PATH +EOF + +# SSH commands +SSH_COMMANDS=$(cat << ENDSSH +set -e +echo '\$PUBLIC_KEY' + +# Create user +echo "\$SUDO_PASS" | sudo -S useradd -m -s /bin/bash -G sudo "\$NEW_USER" +echo "\$SUDO_PASS" | sudo -S chmod 700 "/home/\$NEW_USER" + +# Set password +if [ -n "\$NEW_PASS" ]; then + echo "DEBUG: Setting password for \$NEW_USER: \$NEW_PASS" + echo "\$SUDO_PASS" | sudo -S bash -c "echo \"\$NEW_USER:\$NEW_PASS\" | chpasswd" +fi + +# Setup SSH dir +echo "\$SUDO_PASS" | sudo -S mkdir -p "/home/\$NEW_USER/.ssh" +echo "\$SUDO_PASS" | sudo -S chmod 700 "/home/\$NEW_USER/.ssh" +echo "\$SUDO_PASS" | sudo -S touch "/home/\$NEW_USER/.ssh/authorized_keys" +echo "\$SUDO_PASS" | sudo -S chmod 600 "/home/\$NEW_USER/.ssh/authorized_keys" +echo "\$SUDO_PASS" | sudo -S chown -R "\$NEW_USER:\$NEW_USER" "/home/\$NEW_USER/.ssh" +echo "\$SUDO_PASS" | sudo -S bash -c "echo \"\$PUBLIC_KEY\" >> /home/\$NEW_USER/.ssh/authorized_keys" + +# Install deps +echo "\$SUDO_PASS" | sudo -S apt-get update +echo "\$SUDO_PASS" | sudo -S apt-get install -y git stow +ENDSSH +) + +# Run SSH commands +SSHPASS="$ROOT_PASS" sshpass -e ssh -p "$PORT" "$ROOT_USER@$HOST" "SUDO_PASS='$ROOT_PASS' ANONYMOUS=$ANONYMOUS NEW_USER='$NEW_USER' PUBLIC_KEY='$PUBLIC_KEY' NEW_PASS='$NEW_PASS' bash -c '$SSH_COMMANDS'" + +ssh "$SERVER_NAME" bash -c "$(cat << ENDSSH +set -e +git clone https://github.com/goodhumored/dotfiles +cd dotfiles +./init.sh +ENDSSH +)" + +echo "Настройка завершена!" +echo "Пользователь: $NEW_USER" +echo "SSH команда: ssh $SERVER_NAME" +if [ "$ANONYMOUS" = false ]; then + echo "Пароль сохранен в: $PASS_NAME" +fi diff --git a/seed_v2.sh b/seed_v2.sh new file mode 100644 index 0000000..b116b94 --- /dev/null +++ b/seed_v2.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +set -euo pipefail + +# --- Константы --- +DEFAULT_PORT=22 +DEFAULT_USER="goodhumored" +PASS_DIR="$HOME/.password-store" +KEYS_DIR="$HOME/.ssh/keys" + +# --- Утилиты --- +require() { + if ! command -v "$1" &> /dev/null; then + echo "Ошибка: нужна утилита '$1'" + exit 1 + fi +} +require sshpass +require ssh-keygen +require pass + +# --- Параметры --- +ANONYMOUS=false +PORT="$DEFAULT_PORT" +NEW_USER="$DEFAULT_USER" + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--host) HOST="$2"; shift ;; + -p|--port) PORT="$2"; shift ;; + -r|--root_user) ROOT_USER="$2"; shift ;; + -s|--server_name) SERVER_NAME="$2"; shift ;; + -u|--username) NEW_USER="$2"; shift ;; + -n|--pass_name) PASS_NAME="$2"; shift ;; + -a|--anonymous) ANONYMOUS=true ;; + *) echo "Неизвестный параметр: $1"; exit 1 ;; + esac + shift +done + +[[ -z "${HOST:-}" || -z "${ROOT_USER:-}" || -z "${SERVER_NAME:-}" ]] && { + echo "Ошибка: нужны --host, --root_user и --server_name" + exit 1 +} + +# --- Логика --- +if $ANONYMOUS; then + NEW_USER="user$(tr -dc a-z0-9 > "$CONFIG_FILE" + +Host $SERVER_NAME + HostName $HOST + Port $PORT + User $NEW_USER + IdentityFile $KEY_PATH +EOF + +# --- SSH Настройка сервера --- +SSH_COMMANDS=$(cat <<'EOS' +set -euo pipefail + +sudo useradd -m -s /bin/bash -G sudo "$NEW_USER" +echo "$NEW_USER:$NEW_PASS" | sudo chpasswd + +sudo mkdir -p "/home/$NEW_USER/.ssh" +sudo chmod 700 "/home/$NEW_USER/.ssh" +echo "$PUBLIC_KEY" | sudo tee "/home/$NEW_USER/.ssh/authorized_keys" > /dev/null +sudo chmod 600 "/home/$NEW_USER/.ssh/authorized_keys" +sudo chown -R "$NEW_USER:$NEW_USER" "/home/$NEW_USER/.ssh" + +sudo apt-get update +sudo apt-get install -y git stow + +if [ "$ANONYMOUS" = "false" ]; then + sudo -u "$NEW_USER" git clone https://github.com/goodhumored/dotfiles /home/"$NEW_USER"/dotfiles + sudo -u "$NEW_USER" bash -c "cd /home/$NEW_USER/dotfiles && ./init.sh" +fi +EOS +) + +SSHPASS="$ROOT_PASS" sshpass -e ssh -p "$PORT" "$ROOT_USER@$HOST" \ + env NEW_USER="$NEW_USER" NEW_PASS="$NEW_PASS" PUBLIC_KEY="$(cat "$KEY_PATH.pub")" ANONYMOUS="$ANONYMOUS" bash -c "$SSH_COMMANDS" + +echo "Готово! Новый пользователь: $NEW_USER (SSH: ssh $SERVER_NAME)"