Files
Scripts/setup.sh
2025-11-21 18:25:32 +00:00

1146 lines
32 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -e
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Функции для логирования
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
# Функция проверки выполнения команды
run_cmd() {
local cmd="$1"
local description="$2"
log_info "$description..."
if eval "$cmd"; then
log_success "$description завершено"
else
log_error "$description не удалось"
return 1
fi
}
# Функция для безопасного создания директории
safe_mkdir() {
local dir="$1"
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
log_success "Создана директория: $dir"
fi
}
# Функция для отложенного переключения на Zsh
switch_to_zsh() {
local zsh_path
zsh_path=$(command -v zsh)
if [[ -n "$zsh_path" && -x "$zsh_path" ]]; then
log_info "Переключаю оболочку на Zsh..."
if sudo chsh -s "$zsh_path" "$USER"; then
log_success "Оболочка изменена на Zsh"
else
log_warning "Не удалось изменить оболочку по умолчанию автоматически"
echo "Вы можете изменить оболочку вручную командой: chsh -s $(which zsh)"
fi
else
log_error "Zsh не найден или не исполняем"
return 1
fi
}
# Функция для установки Zsh и плагинов
install_zsh() {
# Установка Zsh
if ! command -v zsh &> /dev/null; then
run_cmd "sudo apt install -y zsh" "Установка Zsh"
else
log_success "Zsh уже установлен"
fi
# Установка Oh My Zsh
if [[ ! -d "${HOME}/.oh-my-zsh" ]]; then
log_info "Устанавливаю Oh My Zsh..."
if sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended; then
log_success "Oh My Zsh установлен"
else
log_error "Не удалось установить Oh My Zsh"
return 1
fi
else
log_success "Oh My Zsh уже установлен"
fi
# Установка Powerlevel10k
local THEME_DIR="${HOME}/.oh-my-zsh/custom/themes/powerlevel10k"
if [[ ! -d "${THEME_DIR}" ]]; then
run_cmd "git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \"${THEME_DIR}\"" "Установка темы Powerlevel10k"
else
log_success "Powerlevel10k уже установлена"
fi
# Установка плагинов
local ZSH_CUSTOM="${ZSH_CUSTOM:-${HOME}/.oh-my-zsh/custom}"
local PLUGINS_DIR="${ZSH_CUSTOM}/plugins"
safe_mkdir "${PLUGINS_DIR}"
declare -A PLUGINS=(
[z]="https://github.com/rupa/z.git"
[zsh-syntax-highlighting]="https://github.com/zsh-users/zsh-syntax-highlighting.git"
[zsh-autosuggestions]="https://github.com/zsh-users/zsh-autosuggestions.git"
[zsh-completions]="https://github.com/zsh-users/zsh-completions.git"
[zsh-history-substring-search]="https://github.com/zsh-users/zsh-history-substring-search.git"
[autoenv]="https://github.com/Tarrasch/zsh-autoenv.git"
[zsh-interactive-cd]="https://github.com/changyuheng/zsh-interactive-cd.git"
[fasd]="https://github.com/clvv/fasd.git"
)
for name in "${!PLUGINS[@]}"; do
local target="${PLUGINS_DIR}/${name}"
if [[ ! -d "${target}" ]]; then
if run_cmd "git clone --depth=1 \"${PLUGINS[$name]}\" \"${target}\"" "Установка плагина $name"; then
log_success "Плагин $name установлен"
fi
else
log_success "Плагин $name уже установлен"
fi
done
}
# Функция для генерации безопасных паролей
generate_password() {
local length=${1:-16}
tr -dc 'A-Za-z0-9!@%^&*()' < /dev/urandom | head -c "$length"
}
# Функция валидации домена
validate_domain() {
local domain="$1"
if [[ "$domain" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+$ ]]; then
return 0
else
return 1
fi
}
# Функция для получения домена
get_domain() {
read -p "Хотите указать домен для сайта? [y/N]: " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
while true; do
read -p "Введите ваш домен (например, example.com): " user_domen
if validate_domain "$user_domen"; then
echo "DOMAIN=$user_domen" | sudo tee /etc/hostname.env >/dev/null
sudo chmod 600 /etc/hostname.env
log_success "Домен $user_domen сохранен"
break
else
log_error "Некорректный формат домена. Попробуйте снова."
fi
done
else
log_info "Домен не указан"
echo "DOMAIN=" | sudo tee /etc/hostname.env >/dev/null
sudo chmod 600 /etc/hostname.env
fi
}
# === Начало скрипта ===
log_info "Начинаю настройку системы..."
# === Добавление SSH-ключей ===
log_info "Добавляю SSH-ключи..."
safe_mkdir "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
AUTH_KEYS_FILE="$HOME/.ssh/authorized_keys"
# Создаём файл с нужными правами
touch "$AUTH_KEYS_FILE"
chmod 600 "$AUTH_KEYS_FILE"
# Обязательный ключ, который должен быть добавлен всегда
REQUIRED_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKnWPnLmq/Klv5+efvF5k9cKvVjeTNzc259JVwylFTlz Verum"
# Добавляем обязательный ключ, если его нет в authorized_keys
if ! grep -qxF "$REQUIRED_KEY" "$AUTH_KEYS_FILE"; then
echo "$REQUIRED_KEY" >> "$AUTH_KEYS_FILE"
log_success "Добавлен обязательный ключ: $REQUIRED_KEY"
else
log_info "Обязательный ключ уже присутствует"
fi
# Добавляем ключи, если их ещё нет в файле
while true; do
read -p "Введите публичный SSH-ключ (или оставьте пустым, чтобы закончить): " ssh_key
# Если пустая строка — заканчиваем ввод
if [[ -z "$ssh_key" ]]; then
log_info "Ввод SSH-ключей завершён"
break
fi
# Проверяем, есть ли ключ уже в файле
if grep -qxF "$ssh_key" "$AUTH_KEYS_FILE"; then
log_info "Ключ уже присутствует: $ssh_key"
else
echo "$ssh_key" >> "$AUTH_KEYS_FILE"
log_success "Добавлен ключ: $ssh_key"
fi
done
log_success "SSH-ключи обработаны"
# === Создание директорий под Docker ===
log_info "Создаю Docker директории и конфиги..."
safe_mkdir "/opt/wordpress"
safe_mkdir "/opt/npm"
safe_mkdir "/opt/dockge"
safe_mkdir "/opt/uptime-kuma"
safe_mkdir "/opt/watchtower"
# === WordPress конфиг ===
cat <<EOF > /opt/wordpress/php.ini
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
max_input_time = 300
EOF
# Создание паролей для WordPress
cat <<EOF > /opt/wordpress/.env
# Database
DB_NAME=wordpressdbname
DB_USER=wordpressuser
DB_PASSWORD=$(generate_password 16)
# WordPress
WP_DEBUG=false
WP_DEBUG_LOG=false
WP_DOMAIN=
EOF
cat <<EOF > /opt/wordpress/docker-compose.yml
services:
wordpress:
container_name: wordpress
image: wordpress:6.5-php8.2-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: ${DB_NAME}
TZ: ${TZ}
WP_DOMAIN: ${WP_DOMAIN}
WORDPRESS_CONFIG_EXTRA: |
define('WP_DEBUG', ${WP_DEBUG});
define('WP_DEBUG_LOG', ${WP_DEBUG_LOG});
define('WP_HOME', 'https://${WP_DOMAIN}');
define('WP_SITEURL', 'https://${WP_DOMAIN}');
date_default_timezone_set('Asia/Krasnoyarsk');
volumes:
# Контент WordPress с хоста
- ./wp-content/uploads:/var/www/html/wp-content/uploads
- ./wp-content/plugins:/var/www/html/wp-content/plugins
- ./wp-content/themes:/var/www/html/wp-content/themes
- ./wp-content/mytheme:/var/www/html/wp-content/themes/mytheme
# Настройки PHP
- ./config/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./config/php.ini:/usr/local/etc/php/php.ini:ro
# Логи Apache
- ./logs/wordpress:/var/log/apache2
# Бэкапы и дополнительные данные
- ./backups:/backups
# Если wp-config.php существует как **файл**, можно раскомментировать строку ниже
# - ./config/wp-config.php:/var/www/html/wp-config.php:ro
#ports:
#- "8080:80"
networks:
- wordpress_net
- proxy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/wp-admin/install.php"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
db:
container_name: wordpress-db
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
TZ: ${TZ}
volumes:
- ./data/mysql:/var/lib/mysql
- ./config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
- ./logs/mysql:/var/log/mysql
- ./backups/db:/docker-entrypoint-initdb.d
command:
- --default-time-zone=+07:00
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
networks:
- wordpress_net
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost -u${DB_USER} -p${DB_PASSWORD} || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
#phpmyadmin:
#container_name: wordpress-phpmyadmin
#image: phpmyadmin:latest
#restart: unless-stopped
#depends_on:
#db:
#condition: service_healthy
#environment:
#PMA_HOST: db
#PMA_USER: ${DB_USER}
#PMA_PASSWORD: ${DB_PASSWORD}
#PMA_PORT: 3306
#TZ: ${TZ}
#networks:
#- wordpress_net
#- proxy
# Если нужно прямое подключение, можно открыть порт:
# ports:
# - "8080:80"
networks:
wordpress_net:
driver: bridge
proxy:
external: true
EOF
# Генерация паролей и .env
safe_mkdir "/opt/npm"
cat <<EOF > /opt/npm/.env
# =========================
# Database Configuration
# =========================
DB_ROOT_PASSWORD=$(generate_password 16)
DB_NAME=npm_db_1
DB_USER=db_admin_user_npm_db
DB_USER_PASSWORD=$(generate_password 16)
EOF
chmod 600 /opt/npm/.env
log_success "NPM .env файл сгенерирован"
# Генерация docker-compose.yml для NPM
cat <<EOF > /opt/npm/docker-compose.yml
services:
app:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8181:81"
env_file:
- .env
volumes:
- "./data:/data"
- "./letsencrypt:/etc/letsencrypt"
networks:
- "proxy"
- "npm_net"
extra_hosts:
- "host.docker.internal:host-gateway"
db:
image: jc21/mariadb-aria:latest
container_name: npm_db
restart: unless-stopped
env_file:
- .env
volumes:
- "./mysql:/var/lib/mysql"
networks:
- "npm_net"
networks:
npm_net:
internal: true
proxy:
external: true
EOF
# Сохраняем пароли в защищенный файл
cat <<EOF > /opt/npm/.env
# =========================
# Database Configuration
# =========================
DB_ROOT_PASSWORD=$(generate_password 16)
DB_NAME=npm_db_1
DB_USER=db_admin_user_npm_db
DB_USER_PASSWORD=$(generate_password 16)
EOF
chmod 600 /opt/npm/.env
# Создаем директорию кастомного конфига
safe_mkdir "/opt/npm/data/nginx/custom"
# Создание конфигурации Nginx
cat > /opt/npm/data/nginx/custom/server_proxy.conf <<'CONFIG'
# ================================================
# Глобальные редиректы для всех доменов NPM
# ================================================
# Перенаправление HTTP → HTTPS
if ($scheme = http) {
return 301 https://$host$request_uri;
}
# Перенаправление с www → non-www (кроме специальных случаев)
if ($host ~* ^www\.(?<domain>.+)$) {
# Исключение для доменов, где www должен вести на другое место
# Если нужно исключить определенные домены, добавьте их здесь
# if ($domain = "special-domain.com") { break; }
return 301 https://$domain$request_uri;
}
CONFIG
# Создание скрипта www.sh
cat > /opt/npm/www.sh <<'SCRIPT'
#!/bin/bash
# Скрипт для применения конфигурации Nginx и перезагрузки сервиса
mkdir -p /opt/npm/data/nginx/custom
cat > /opt/npm/data/nginx/custom/server_proxy.conf <<'CONFIG'
# ================================================
# Глобальные редиректы для всех доменов NPM
# ================================================
# Перенаправление HTTP → HTTPS
if ($scheme = http) {
return 301 https://$host$request_uri;
}
# Перенаправление с www → non-www (кроме специальных случаев)
if ($host ~* ^www\.(?<domain>.+)$) {
# Исключение для доменов, где www должен вести на другое место
# Если нужно исключить определенные домены, добавьте их здесь
# if ($domain = "special-domain.com") { break; }
return 301 https://$domain$request_uri;
}
CONFIG
SCRIPT
# Делаем скрипт исполняемым
chmod +x /opt/npm/www.sh
# === Dockge конфиг ===
cat <<EOF > /opt/dockge/docker-compose.yml
services:
dockge:
image: louislam/dockge:1
container_name: dockge
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
#- DOCKGE_ENABLE_CONSOLE=true
#ports:
#- "5001:5001"
networks:
- proxy
networks:
proxy:
external: true
EOF
# === Uptime Kuma конфиг ===
cat <<EOF > /opt/uptime-kuma/docker-compose.yml
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
restart: unless-stopped
volumes:
- ./data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
#ports:
#- "3001:3001"
networks:
- uptime-net
- proxy
networks:
uptime-net:
driver: bridge
proxy:
external: true
EOF
# === Watchtower конфиг ===
cat <<EOF > /opt/watchtower/docker-compose.yml
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 3600 --cleanup
EOF
# Оповещение о успешном создании базовых контейнеров
log_success "Docker конфиги созданы"
# === Обновление системы и установка пакетов ===
run_cmd "sudo apt update && sudo apt upgrade -y" "Обновление системы"
run_cmd "sudo apt install -y \
mc \
gcc \
btop \
hollywood \
curl \
htop \
git \
ufw \
ndisc6 \
fail2ban \
python3-pip \
micro \
ca-certificates \
gnupg \
lsb-release \
software-properties-common \
apt-transport-https \
net-tools \
certbot \
neofetch \
fzf \
iputils-ping \
dnsutils \
curl \
zsh" "Установка системных пакетов"
# === Настройка Midnight Commander ===
log_info "Настройка Midnight Commander..."
MC_DIR="$HOME/.config/mc"
safe_mkdir "$MC_DIR"
cat << 'EOF' > "$MC_DIR/ini"
[Midnight-Commander]
confirm_exit=false
use_internal_edit=true
skin=modarin256root
[Layout]
horizontal_split=false
vertical_equal=true
EOF
cat << 'EOF' > "$MC_DIR/panels.ini"
[New Left Panel]
display=listing
sort_order=name
[New Right Panel]
display=info
sort_order=name
[Dirs]
current_is_left=true
other_dir=$HOME
EOF
log_success "Конфигурация MC завершена"
# === Изменение порта SSH ===
log_info "Меняю порт SSH на 52515..."
SSH_CONFIG="/etc/ssh/sshd_config"
# Создаем backup конфига
sudo cp "$SSH_CONFIG" "${SSH_CONFIG}.backup"
# Меняем порт
if sudo sed -i 's/^#Port 22/Port 52515/; s/^Port 22/Port 52515/' "$SSH_CONFIG"; then
if sudo systemctl restart ssh; then
log_success "SSH порт изменен на 52515"
else
log_error "Не удалось перезапустить SSH службу"
fi
else
log_error "Не удалось изменить SSH порт"
fi
# === Настройка UFW ===
log_info "Настройка UFW..."
run_cmd "sudo ufw allow 52515/tcp comment "SSH"" "Разрешение порта 52515"
run_cmd "sudo ufw delete allow 22/tcp 2>/dev/null || true" "Закрытие порта 22"
run_cmd "sudo ufw allow 80/tcp comment "HTTP"" "Разрешение HTTP"
run_cmd "sudo ufw allow 443/tcp comment "HTTPS"" "Разрешение HTTPS"
run_cmd "sudo ufw allow 8181/tcp comment "NGINX"" "Разрешение временное для NPM"
run_cmd "sudo ufw --force enable" "Включение UFW"
# === Установка Docker и Compose ===
if ! command -v docker >/dev/null 2>&1; then
log_info "Установка Docker..."
run_cmd "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg" "Добавление Docker GPG ключа"
run_cmd "echo \"deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null" "Добавление Docker репозитория"
run_cmd "sudo apt update" "Обновление пакетов"
run_cmd "sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin" "Установка Docker"
else
log_success "Docker уже установлен"
fi
# === Добавляем пользователя в группу docker ===
if ! groups "$USER" | grep -q '\bdocker\b'; then
run_cmd "sudo usermod -aG docker \"$USER\"" "Добавление пользователя в группу docker"
else
log_success "Пользователь уже в группе docker"
fi
run_cmd "sudo systemctl enable docker" "Включение автозапуска Docker"
run_cmd "sudo systemctl start docker" "Запуск Docker службы"
# === Создание Docker сети ===
log_info "Создание Docker сети proxy..."
if ! docker network inspect proxy >/dev/null 2>&1; then
if docker network create --driver bridge proxy; then
log_success "Docker сеть proxy создана"
else
log_error "Не удалось создать Docker сеть proxy"
fi
else
log_success "Docker сеть proxy уже существует"
fi
# === Улучшение nano ===
log_info "Настройка nano..."
HOME_DIR="$HOME"
if [[ -f "$HOME_DIR/.nanorc" ]]; then
mv "$HOME_DIR/.nanorc" "$HOME_DIR/.nanorc.bak"
log_info "Создан backup .nanorc"
fi
cat > "$HOME_DIR/.nanorc" <<'EOF'
set linenumbers
set softwrap
set tabsize 4
set tabstospaces
set autoindent
set smarthome
set indicator
set positionlog
#set mouse
set fill 80
EOF
safe_mkdir "$HOME_DIR/.nano"
if [[ ! -d "$HOME_DIR/.nano/syntax" ]]; then
if git clone https://github.com/scopatz/nanorc.git "$HOME_DIR/.nano/syntax" 2>/dev/null; then
log_success "Синтаксис для nano установлен"
else
log_warning "Не удалось установить синтаксис для nano"
fi
fi
# === Установка Zsh и плагинов ===
install_zsh
# === Получение домена ===
get_domain
# === Генерация .zshrc ===
log_info "Генерация .zshrc..."
cat << 'EOF' > ~/.zshrc
# Enable Powerlevel10k instant prompt
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="powerlevel10k/powerlevel10k"
plugins=(
git
z
zsh-syntax-highlighting
zsh-autosuggestions
zsh-completions
zsh-history-substring-search
autoenv
alias-finder
extract
zsh-interactive-cd
fasd
colored-man-pages
copypath
tmux
)
source $ZSH/oh-my-zsh.sh
# User configuration
export ipv4=$(curl -4 -s ifconfig.me 2>/dev/null || echo "unknown")
export ipv6=$(curl -6 -s ifconfig.me 2>/dev/null || echo "unknown")
export domen="$(cat /etc/hostname.domain 2>/dev/null || echo 'your-domain.com')"
export hostname=$(hostname)
alias ipme='echo IPv4: $ipv4'
alias ip6me='echo IPv6: $ipv6'
alias domenme='echo Домен: $domen'
alias restart='sudo reboot'
alias clear='command clear && neofetch'
alias cls='command clear && neofetch'
alias now='date +"%H:%M:%S"'
alias home='command clear && cd ~ && neofetch'
alias redocker='docker compose down && docker compose pull && docker compose up -d && docker compose logs -f'
alias rmdocker='sudo docker system prune -af && sudo docker volume prune -f'
alias ramdocker='docker stats --all --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}"'
home
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
. "/root/.acme.sh/acme.sh.env"
EOF
log_success ".zshrc сгенерирован"
# === Настройка Neofetch ===
log_info "Настройка Neofetch..."
NEOFETCH_CONFIG_DIR="$HOME/.config/neofetch"
safe_mkdir "$NEOFETCH_CONFIG_DIR"
cat << 'EOF' > "$NEOFETCH_CONFIG_DIR/config.conf"
print_info() {
info "${cl2} ╭─" distro
info "${cl2} ├─" kernel
info "${cl2} ├─" users
info "${cl2} ├─󰏗" packages
info "${cl2} ╰─" shell
echo
info "${cl6} ╭─" de
info "${cl6} ╭─" term
info "${cl6} ├─" public_ipv4_host
info "${cl6} ├─" public_ipv6_host
info "${cl6} ╰─🖧" public_domen
info "${cl6} ├─" term_font
info "${cl6} ├─󰂫" theme
info "${cl6} ├─󰂫" icons
info "${cl6} ╰─" font
echo
info "${cl4} ╭─" model
info "${cl4} ├─󰍛" cpu
info "${cl4} ├─󰍹" gpu
info "${cl4} ├─" resolution
info "${cl4} ├─" memory
info "${cl4} ├─ ${cl0}" disk
info "${cl4} ├─󰁹 ${cl0} " battery
info "${cl4} ╰─󰄉" uptime
prin " "
prin " \n \n \n \n \n \n ${cl3}\n \n ${cl5}\n \n ${cl2}\n \n ${cl6}\n \n ${cl4}\n \n ${cl1}\n \n ${cl7}\n \n ${cl0}\n "
}
##--------- Title
title_fqdn="on"
##--------- Kernel
kernel_shorthand="on"
##--------- Distro
distro_shorthand="off"
os_arch="on"
##--------- Uptime
uptime_shorthand="on"
##--------- Memory
memory_percent="on"
memory_unit="Gib"
##--------- Packages
package_managers="on"
##--------- Shell
shell_path="off"
shell_version="on"
##--------- CPU
speed_type="scaling_max_freq"
speed_shorthand="on"
cpu_brand="on"
cpu_speed="on"
cpu_cores="logical"
cpu_temp="on"
##--------- GPU
gpu_brand="on"
gpu_type="all"
##--------- Resolution
refresh_rate="on"
##--------- Gtk Theme / Icons / Font
gtk_shorthand="off"
gtk2="off"
gtk3="off"
##--------- IP Address
public_ipv4_host="$ipv4"
public_ipv6_host="$ipv6"
public_domen="$domen"
public_ip_timeout=2
##--------- Desktop Environment
de_version="on"
##--------- Disk
disk_show=('/')
disk_subtitle="mount"
disk_percent="on"
##--------- Song
music_player="auto"
song_format="%artist% - %album% - %title%"
song_shorthand="off"
mpc_args=()
##--------- Text Colors
colors=(distro)
##--------- Text Options
bold="on"
underline_enabled="on"
underline_char="󰍴"
separator=" "
##--------- Color Blocks
block_range=(1 8)
magenta="\033[1;35m"
green="\033[1;32m"
white="\033[1;37m"
blue="\033[1;34m"
red="\033[1;31m"
black="\033[1;40;30m"
yellow="\033[1;33m"
cyan="\033[1;36m"
reset="\033[0m"
bgyellow="\033[1;43;33m"
bgwhite="\033[1;47;37m"
cl0="${reset}"
cl1="${magenta}"
cl2="${green}"
cl3="${white}"
cl4="${blue}"
cl5="${red}"
cl6="${yellow}"
cl7="${cyan}"
cl8="${black}"
cl9="${bgyellow}"
cl10="${bgwhite}"
color_blocks="on"
block_width=4
block_height=1
col_offset="auto"
##--------- Progress Bars
bar_char_elapsed="-"
bar_char_total="="
bar_border="on"
bar_length=15
bar_color_elapsed="distro"
bar_color_total="distro"
cpu_display="on"
memory_display="on"
battery_display="on"
disk_display="on"
##--------- Backend Settings
image_backend="ascii"
image_source="auto"
##--------- Ascii Options
ascii_distro="auto"
ascii_colors=(distro)
ascii_bold="on"
##--------- Image Options
image_loop="off"
thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch"
crop_mode="normal"
crop_offset="center"
image_size="auto"
gap=2
yoffset=0
xoffset=0
background_color=
##--------- Misc Options
stdout="off"
EOF
log_success "Конфигурация Neofetch установлена"
# === Настройка fail2ban ===
# Путь к файлу конфигурации
JAIL_FILE="/etc/fail2ban/jail.local"
# Создаём резервную копию, если файл уже существует
if [[ -f "$JAIL_FILE" ]]; then
cp "$JAIL_FILE" "${JAIL_FILE}.bak_$(date +%Y%m%d_%H%M%S)"
fi
# Перезаписываем файл
cat > "$JAIL_FILE" << 'EOF'
[sshd]
enabled = true
port = 52515
filter = sshd
logpath = /var/log/auth.log
maxretry = 7
bantime = 1d
EOF
sudo systemctl restart fail2ban
sudo systemctl enable --now fail2ban
# === Финал ===
echo
log_success "🎉 Установка завершена!"
echo
log_info "📝 Важная информация:"
echo " - Пароли для NPM сохранены в: /opt/npm/.env"
echo " - SSH порт изменен на: 52515"
echo " - Docker установлен и настроен"
echo " - Zsh и плагины установлены"
echo
log_warning "⚠️ После перезагрузки оболочка Zsh будет установлена по умолчанию"
echo " и SSH будет доступен на порту 52515"
echo
log_info "🐳 Docker сети и сервисы готовы к использованию"
# === Переключение на Zsh ===
log_info "Переключаю оболочку пользователя на Zsh..."
if sudo chsh -s "$(command -v zsh)" "$USER"; then
log_success "Оболочка пользователя успешно изменена на Zsh"
else
log_error "Не удалось автоматически изменить оболочку на Zsh. Попробуйте вручную: chsh -s $(which zsh)"
fi
# === Проверка SSH ===
log_info "Проверяю, слушает ли SSH порт 52515..."
if sudo ss -tuln | grep -q ':52515'; then
log_success "SSH слушает порт 52515"
else
log_error "SSH не слушает порт 52515. Проверяю службу..."
sudo systemctl restart ssh || log_error "Не удалось перезапустить SSH"
fi
# === Проверка подключения по новому порту ===
log_info "Проверяю доступность SSH на порту 52515 локально..."
if nc -zv 127.0.0.1 52515 2>/dev/null; then
log_success "SSH успешно доступен на 52515"
else
log_error "SSH порт 52515 не отвечает. Проверьте ufw и конфиг /etc/ssh/sshd_config"
fi
# === Отключение и улучшение отправки к серверу ===
log_info "Переподключение файрвола..."
cp /etc/ufw/before.rules /etc/ufw/before.rules.bak_$(date +%F_%H-%M-%S) && cat > /etc/ufw/before.rules << 'EOF'
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines
# allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT
# quickly process packets for which we already have a connection
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP
# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-forward -p icmp --icmp-type echo-request -j DROP
# allow dhcp client to work
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT
#
# ufw-not-local
#
-A ufw-before-input -j ufw-not-local
# if LOCAL, RETURN
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
# if MULTICAST, RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
# if BROADCAST, RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
# all other non-local packets are dropped
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
# allow MULTICAST mDNS for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT
# allow MULTICAST UPnP for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
EOF
# === Перезагрузка системы ===
log_warning "Система будет перезагружена через 10 секунд для применения изменений..."
for i in {10..1}; do
echo -ne "${YELLOW}⏳ Перезагрузка через ${i} секунд...${NC}\r"
sleep 1
done
echo
log_info "Перезагружаю систему..."
sudo reboot