Last active 22 hours ago

Revision f6c6c05827e11c0bd096e7004614ad378b5cc90c

install.sh Raw
1#!/bin/bash
2
3set -e
4
5# Цвета для вывода
6ANSI_RED=$(tput -Txterm setaf 1)
7ANSI_GREEN=$(tput -Txterm setaf 2)
8ANSI_YELLOW=$(tput -Txterm setaf 3)
9ANSI_RESET=$(tput -Txterm sgr0)
10
11# ==================== ФУНКЦИИ ====================
12
13# Проверка прав root
14check_root() {
15 if [ "$EUID" -ne 0 ]; then
16 echo -e "${ANSI_RED}Ошибка: скрипт должен запускаться от root${ANSI_RESET}"
17 exit 1
18 fi
19}
20
21# Запрос имени хоста
22ask_hostname() {
23 local current_hostname=$(hostname)
24 read -e -p "${ANSI_YELLOW}Введите имя хоста: (текущее: $current_hostname) ${ANSI_RESET}" -i "${current_hostname}" NEW_HOSTNAME
25 echo "$NEW_HOSTNAME"
26}
27
28# Запрос - создавать ли пользователя
29ask_create_user() {
30 local choice
31 echo -e "${ANSI_YELLOW}Создать нового пользователя? (y/n):${ANSI_RESET}"
32 read -p "Create user [Y/N]? " choice
33 if [[ "$choice" =~ ^[Yy]$ ]]; then
34 CREATE_USER="yes"
35 else
36 CREATE_USER="no"
37 fi
38}
39
40# Запрос имени пользователя
41ask_username() {
42 local username
43 echo -e "${ANSI_YELLOW}Введите имя нового пользователя:${ANSI_RESET}" >&2
44 read -p "Username: " username
45 if [ -z "$username" ]; then
46 echo -e "${ANSI_RED}Имя пользователя не может быть пустым.${ANSI_RESET}" >&2
47 exit 1
48 fi
49 echo "$username"
50}
51
52# Запрос пароля
53ask_password() {
54 local username=$1
55 local user_pass
56 echo -e "${ANSI_YELLOW}Введите пароль для пользователя $username:${ANSI_RESET}" >&2
57 read -s -p "Password: " user_pass
58 echo >&2
59 if [ -z "$user_pass" ]; then
60 echo -e "${ANSI_RED}Пароль не может быть пустым.${ANSI_RESET}" >&2
61 exit 1
62 fi
63 echo "$user_pass"
64}
65
66# Запрос настройки прокси
67ask_proxy() {
68 echo -e "\n${ANSI_YELLOW}Использовать прокси-сервер apt-cacher-ng? (y/n):${ANSI_RESET}"
69 read -p -e "Use proxy? " -i "N" USE_PROXY
70 if [[ "$USE_PROXY" =~ ^[Yy]$ ]]; then
71 echo -e "${ANSI_YELLOW}Введите URL прокси-сервера (например: http://192.168.111.87:3142):${ANSI_RESET}"
72 read -e -p "Proxy URL: " -i "http://192.168.111.87:3142" PROXY_URL
73 if [ -n "$PROXY_URL" ]; then
74 configure_proxy "$PROXY_URL"
75 fix_debian_keys
76 fi
77 fi
78}
79
80# Настройка прокси для apt
81configure_proxy() {
82 local proxy_url=$1
83 echo -e "${ANSI_GREEN}Настройка прокси для apt...${ANSI_RESET}"
84 cat > /etc/apt/apt.conf.d/02aptproxy << EOF
85Acquire::http::proxy "$proxy_url";
86Acquire::ftp::proxy "$proxy_url";
87EOF
88 echo -e "${ANSI_GREEN}Прокси настроен в /etc/apt/apt.conf.d/02aptproxy${ANSI_RESET}"
89}
90
91# Установка имени хоста
92set_hostname() {
93 local hostname=$1
94 echo -e "\n${ANSI_GREEN}=== Установка имени хоста: $hostname ===${ANSI_RESET}"
95 hostnamectl set-hostname "$hostname"
96 if grep -q "^127.0.1.1" /etc/hosts; then
97 sed -i "s/^127.0.1.1.*/127.0.1.1\t$hostname/" /etc/hosts
98 else
99 echo "127.0.1.1\t$hostname" >> /etc/hosts
100 fi
101 echo -e "${ANSI_GREEN}Имя хоста установлено.${ANSI_RESET}"
102}
103
104# Добавление репозитория MEPHI
105add_mephi_repository() {
106 . /etc/os-release 2>/dev/null || { echo "Failed to determine release"; exit 1; }
107 [ -z "$VERSION_CODENAME" ] && echo "VERSION_CODENAME not found" && exit 1
108
109 local conf_file="/etc/apt/sources.list.d/debian_mephi.list"
110
111 if grep -qs "mirror.mephi.ru.*$VERSION_CODENAME" "$conf_file" 2>/dev/null; then
112 echo -e "Repository for $VERSION_CODENAME already exists in $conf_file"
113 else
114 echo -e "Adding repository for Debian $VERSION_CODENAME"
115 cat >> "$conf_file" << EOF
116
117# Added $(date '+%Y-%m-%d')
118deb http://mirror.mephi.ru/debian/ $VERSION_CODENAME main non-free-firmware
119deb-src http://mirror.mephi.ru/debian/ $VERSION_CODENAME main non-free-firmware
120EOF
121 echo "Repository added, updating package list..."
122 apt update
123 fi
124}
125
126# Обновление системы
127update_system() {
128 echo -e "${ANSI_GREEN}=== Обновление системы ===${ANSI_RESET}"
129 apt update
130 apt -y upgrade
131}
132
133# Установка пакетов
134install_packages() {
135 local packages=(
136 pv nano curl wget sudo lsb-release iptables
137 unzip pigz zstd
138 ncdu gdu
139 screen tmux lynx
140 htop btop iftop mtr ioping
141 git jq yq pwgen
142 bind9-dnsutils net-tools ssh-audit
143 cloud-guest-utils qemu-guest-agent
144 console-setup
145 )
146
147 echo -e "${ANSI_GREEN}Installing packages...${ANSI_RESET}"
148 apt-get update
149 apt-get install -y "${packages[@]}"
150}
151
152# Настройка SSH
153configure_ssh() {
154 echo -e "${ANSI_GREEN}Allowing SSH root login${ANSI_RESET}"
155 sed -i 's/^.*PermitRootLogin.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
156 systemctl restart sshd
157 echo -e "${ANSI_GREEN}Ok.${ANSI_RESET}"
158}
159
160# Настройка таймзоны и локали
161configure_locale() {
162 echo "tzdata tzdata/Areas select Europe" | debconf-set-selections
163 echo "tzdata tzdata/Zones/Europe select Moscow" | debconf-set-selections
164 DEBIAN_FRONTEND=noninteractive dpkg-reconfigure tzdata
165
166 cat > /etc/locale.gen << EOF
167ru_RU.UTF-8 UTF-8
168en_US.UTF-8 UTF-8
169EOF
170
171 locale-gen
172 update-locale LANG=en_US.UTF-8
173 locale -a | grep -E "en_US|ru_RU"
174 source /etc/default/locale
175
176 dpkg-reconfigure console-setup
177 dpkg-reconfigure keyboard-configuration
178}
179
180# Настройка journald
181configure_journald() {
182 mkdir -p /etc/systemd/journald.conf.d
183 cat > /etc/systemd/journald.conf.d/size.conf << EOF
184[Journal]
185SystemMaxUse=1G
186SystemMaxFileSize=50M
187MaxLevelStore=warning
188EOF
189
190 systemctl restart systemd-journald
191}
192
193# Создание пользователя
194create_user() {
195 local username=$1
196 local password=$2
197
198 useradd -m "$username" && echo "$username:$password" | chpasswd && passwd -e "$username"
199 usermod -aG sudo "$username"
200
201 touch "/home/$username/.Xauthority"
202 chown "$username:$username" "/home/$username/.Xauthority"
203
204 echo -e "${ANSI_GREEN}Пользователь $username с паролем '${ANSI_YELLOW}$password${ANSI_GREEN}' создан${ANSI_RESET}"
205}
206
207# Настройка истории для пользователя
208configure_user_history() {
209 local username=$1
210 cat >> "/home/$username/.bashrc" << 'EOF'
211export HISTSIZE=10000
212export HISTFILESIZE=50000
213export HISTTIMEFORMAT="%F %T "
214export HISTCONTROL=ignoredups:ignorespace
215shopt -s histappend
216export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
217export TERM=xterm-256color
218EOF
219 chown "$username:$username" "/home/$username/.bashrc"
220}
221
222# Настройка истории для root
223configure_root_history() {
224 cat >> /root/.bashrc << 'EOF'
225export HISTSIZE=10000
226export HISTFILESIZE=50000
227export HISTTIMEFORMAT="%F %T "
228export HISTCONTROL=ignoredups:ignorespace
229shopt -s histappend
230export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
231export TERM=xterm-256color
232EOF
233 source /root/.bashrc
234}
235
236# Очистка документации git
237clean_git_docs() {
238 rm -rf /usr/share/doc/git/RelNotes
239}
240
241# Финальное сообщение
242finish_setup() {
243 echo -e "${ANSI_GREEN}=== Настройка завершена ===${ANSI_RESET}"
244}
245
246# Запись конфигурационного файла
247write_config_file() {
248 local file_path=$1
249 local create_backup=${2:-true} # создать резервную копию? (по умолчанию true)
250
251 echo -e "${ANSI_GREEN}=== Запись конфигурации в $file_path ===${ANSI_RESET}"
252
253 # Создание резервной копии
254 if [ "$create_backup" = true ] && [ -f "$file_path" ]; then
255 local backup_path="${file_path}.backup.$(date +%Y%m%d_%H%M%S)"
256 cp "$file_path" "$backup_path"
257 echo -e "${ANSI_YELLOW}Создана резервная копия: $backup_path${ANSI_RESET}"
258 fi
259
260 # Создание директории, если её нет
261 local dir_path=$(dirname "$file_path")
262 if [ ! -d "$dir_path" ]; then
263 mkdir -p "$dir_path"
264 echo -e "${ANSI_YELLOW}Создана директория: $dir_path${ANSI_RESET}"
265 fi
266
267 # Чтение содержимого из heredoc
268 cat > "$file_path"
269
270 # Установка правильных прав (опционально)
271 chmod 644 "$file_path"
272
273 echo -e "${ANSI_GREEN}Файл успешно записан: $file_path${ANSI_RESET}"
274}
275
276make_motd_generator() {
277 write_config_file "/etc/update-motd.d/99-mymotd-generator" false << 'EOF'
278 #!/bin/bash
279
280 # Text Color Variables http://misc.flogisoft.com/bash/tip_colors_and_formatting
281 tcLtG="\033[00;37m" # LIGHT GRAY
282 tcDkG="\033[01;30m" # DARK GRAY
283 tcLtR="\033[01;31m" # LIGHT RED
284 tcLtGRN="\033[01;32m" # LIGHT GREEN
285 tcLtBL="\033[01;34m" # LIGHT BLUE
286 tcLtP="\033[01;35m" # LIGHT PURPLE
287 tcLtC="\033[01;36m" # LIGHT CYAN
288 tcW="\033[01;37m" # WHITE
289 tcRESET="\033[0m"
290 tcORANGE="\033[38;5;209m"
291
292 # Time of day
293 HOUR=$(date +"%H")
294 if [ $HOUR -lt 12 -a $HOUR -ge 0 ]; then TIME="morning"
295 elif [ $HOUR -lt 17 -a $HOUR -ge 12 ]; then TIME="afternoon"
296 else TIME="evening"
297 fi
298
299 # System uptime
300 uptime=`cat /proc/uptime | cut -f1 -d.`
301 upDays=$((uptime/60/60/24))
302 upHours=$((uptime/60/60%24))
303 upMins=$((uptime/60%60))
304
305 # System + Memory
306 MEMORY_USED=`free -b | grep Mem | awk '{print $3/$2 * 100.0}'`
307 SWAP_USED=`free -b | grep Swap | awk '{print $3/$2 * 100.0}'`
308 NUM_PROCS=`ps aux | wc -l`
309
310 # IP первого сетевого интерфейса
311 LOCAL_IP=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+' | grep -v '^127\.' | head -n 1)
312
313 # Имя сервера
314 HOSTNAME=$(hostname)
315
316 # ОS
317 OS=$(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"')
318
319 # Пользователь
320 USER_NAME=$(whoami)
321 [ "$USER_NAME" = "root" ] && USER_NAME="${tcLtR}${USER_NAME}${tcRESET}"
322
323 # Load average
324 LOADAVG=$(awk '{print $1" "$2" "$3}' /proc/loadavg)
325 SYS_LOADS=`cat /proc/loadavg | awk '{print $1}'`
326
327 # RAM: всего и свободно (в мегабайтах)
328 RAM_TOTAL=$(free -m | awk '/Mem:/ {print $2}')
329 RAM_FREE=$(free -m | awk '/Mem:/ {print $7}')
330 RAM_FREE_PCT=$(( RAM_FREE * 100 / RAM_TOTAL ))
331
332 # Количество CPU
333 CPU_COUNT=$(nproc)
334
335 # Uptime
336 UPTIME=$(uptime -p)
337
338 # HDD: для корневого раздела /
339 DISK_TOTAL_HUMAN=$(df -h / | awk 'NR==2 {print $2}')
340 DISK_FREE_HUMAN=$(df -h / | awk 'NR==2 {print $4}')
341
342 # Используем df без форматирования для процентов
343 DISK_TOTAL=$(df -k / | awk 'NR==2 {print $2}')
344 DISK_FREE=$(df -k / | awk 'NR==2 {print $4}')
345 DISK_FREE_PCT=$(( DISK_FREE * 100 / DISK_TOTAL ))
346
347 echo -e "$tcDkG ==============================================================="
348 echo -e $tcLtG " Good $TIME! $tcORANGE $LOCAL_IP"
349 echo -e $tcDkG "==============================================================="
350 echo -e $tcLtG " - Hostname :$tcW ${HOSTNAME}"
351 echo -e $tcLtG " - IP Address :$tcW ${LOCAL_IP:-N/A}"
352 echo -e $tcLtG " - User :$tcW ${USER_NAME}"
353 echo -e $tcLtG "==============================================================="
354 echo -e $tcLtG " - OS Release :$tcW ${OS}"
355 echo -e $tcLtG " - Kernel : `uname -a | awk '{print $1" "$3" "$12}'`"
356 echo -e $tcLtG " - Users : Currently `users | wc -w` user(s) logged on"
357 echo -e $tcLtG "==============================================================="
358 echo -e $tcLtG " - Server Time : `date`"
359 echo -e $tcLtG " - System load : ${SYS_LOADS} / ${NUM_PROCS} processes running"
360 echo -e $tcLtG " - Load average : ${LOADAVG}"
361 echo -e $tcLtG " - System uptime : ${upDays} days ${upHours} hours ${upMins} minutes"
362 echo -e $tcLtG "==============================================================="
363 echo -e $tcLtG " - CPU : ${CPU_COUNT} CPU"
364 echo -e $tcLtG " - RAM : ${RAM_TOTAL} MB, ${RAM_FREE} MB (${RAM_FREE_PCT}%) free"
365 echo -e $tcLtG " - HDD : ${DISK_TOTAL_HUMAN}, ${DISK_FREE_HUMAN} (${DISK_FREE_PCT}%) free"
366 echo -e $tcLtG " - Swap used % : ${SWAP_USED}"
367 echo -e $tcDkG "==============================================================="
368 echo -e $tcRESET ""
369EOF
370
371 write_config_file "/etc/issue" false << 'EOF'
372 Debian GNU/Linux 12 \n \l
373
374 Local IP: не доступен
375EOF
376}
377
378install_midnight_commanger() {
379 apt-get -y install mc
380
381 write_config_file "/root/.config/mc/ini" false << 'EOF'
382[Midnight-Commander]
383verbose=true
384shell_patterns=true
385auto_save_setup=true
386preallocate_space=false
387auto_menu=false
388use_internal_view=true
389use_internal_edit=false
390clear_before_exec=true
391confirm_delete=true
392confirm_overwrite=true
393confirm_execute=false
394confirm_history_cleanup=true
395confirm_exit=false
396confirm_directory_hotlist_delete=false
397confirm_view_dir=false
398safe_delete=false
399safe_overwrite=false
400use_8th_bit_as_meta=false
401mouse_move_pages_viewer=true
402mouse_close_dialog=false
403fast_refresh=false
404drop_menus=false
405wrap_mode=true
406old_esc_mode=true
407cd_symlinks=true
408show_all_if_ambiguous=false
409use_file_to_guess_type=true
410alternate_plus_minus=false
411only_leading_plus_minus=true
412show_output_starts_shell=false
413xtree_mode=false
414file_op_compute_totals=true
415classic_progressbar=true
416use_netrc=true
417ftpfs_always_use_proxy=false
418ftpfs_use_passive_connections=true
419ftpfs_use_passive_connections_over_proxy=false
420ftpfs_use_unix_list_options=true
421ftpfs_first_cd_then_ls=true
422ignore_ftp_chattr_errors=true
423editor_fill_tabs_with_spaces=false
424editor_return_does_auto_indent=false
425editor_backspace_through_tabs=false
426editor_fake_half_tabs=true
427editor_option_save_position=true
428editor_option_auto_para_formatting=false
429editor_option_typewriter_wrap=false
430editor_edit_confirm_save=true
431editor_syntax_highlighting=true
432editor_persistent_selections=true
433editor_drop_selection_on_copy=true
434editor_cursor_beyond_eol=false
435editor_cursor_after_inserted_block=false
436editor_visible_tabs=true
437editor_visible_spaces=true
438editor_line_state=false
439editor_simple_statusbar=false
440editor_check_new_line=false
441editor_show_right_margin=false
442editor_group_undo=true
443editor_state_full_filename=true
444editor_ask_filename_before_edit=false
445nice_rotating_dash=true
446shadows=true
447mcview_remember_file_position=false
448auto_fill_mkdir_name=true
449copymove_persistent_attr=true
450pause_after_run=1
451mouse_repeat_rate=100
452double_click_speed=250
453old_esc_mode_timeout=1000000
454max_dirt_limit=10
455num_history_items_recorded=60
456vfs_timeout=60
457ftpfs_directory_timeout=900
458ftpfs_retry_seconds=30
459fish_directory_timeout=900
460editor_tab_spacing=8
461editor_word_wrap_line_length=72
462editor_option_save_mode=0
463editor_backup_extension=~
464editor_filesize_threshold=64M
465editor_stop_format_chars=-+*\\,.;:&>
466mcview_eof=
467skin=modarcon16
468
469filepos_max_saved_entries=1024
470
471[Layout]
472output_lines=0
473left_panel_size=86
474top_panel_size=0
475message_visible=false
476keybar_visible=true
477xterm_title=true
478command_prompt=true
479menubar_visible=true
480free_space=true
481horizontal_split=false
482vertical_equal=true
483horizontal_equal=true
484
485[Misc]
486timeformat_recent=%b %e %H:%M
487timeformat_old=%b %e %Y
488ftp_proxy_host=gate
489ftpfs_password=anonymous@
490display_codepage=UTF-8
491source_codepage=Other_8_bit
492autodetect_codeset=
493spell_language=en
494clipboard_store=
495clipboard_paste=
496
497[Colors]
498base_color=
499linux=
500color_terminals=
501
502xterm-256color=
503
504[Panels]
505show_mini_info=true
506kilobyte_si=false
507mix_all_files=false
508show_backups=true
509show_dot_files=true
510fast_reload=false
511fast_reload_msg_shown=false
512mark_moves_down=true
513reverse_files_only=true
514auto_save_setup_panels=false
515navigate_with_arrows=false
516panel_scroll_pages=true
517panel_scroll_center=false
518mouse_move_pages=true
519filetype_mode=true
520permission_mode=false
521torben_fj_mode=false
522quick_search_mode=2
523select_flags=6
524
525[Panelize]
526Find *.orig after patching=find . -name \\*.orig -print
527Find SUID and SGID programs=find . \\( \\( -perm -04000 -a -perm /011 \\) -o \\( -perm -02000 -a -perm /01 \\) \\) -print
528Find rejects after patching=find . -name \\*.rej -print
529Modified git files=git ls-files --modified
530
531EOF
532
533 write_config_file "/root/.config/mc/panels.ini" false << 'EOF'
534[New Left Panel]
535display=listing
536reverse=false
537case_sensitive=true
538exec_first=false
539sort_order=name
540list_mode=full
541brief_cols=2
542user_format=half type name | size | owner
543user_status0=half type name | size | perm
544user_status1=half type name | size | perm
545user_status2=half type name | size | perm
546user_status3=half type name | size | perm
547user_mini_status=false
548filter_flags=7
549list_format=user
550
551[New Right Panel]
552display=listing
553reverse=false
554case_sensitive=true
555exec_first=false
556sort_order=name
557list_mode=full
558brief_cols=2
559user_format=half type name | size | owner
560user_status0=half type name | size | perm
561user_status1=half type name | size | perm
562user_status2=half type name | size | perm
563user_status3=half type name | size | perm
564user_mini_status=false
565filter_flags=7
566list_format=user
567
568[Dirs]
569current_is_left=false
570other_dir=/root
571EOF
572}
573
574# Обновление GPG ключей Debian
575fix_debian_keys() {
576 echo -e "${ANSI_GREEN}=== Исправление GPG-ключей Debian ===${ANSI_RESET}"
577
578 # 1. Полностью удаляем кэш списков пакетов
579 rm -rf /var/lib/apt/lists/*
580
581 # 2. Удаляем старые проблемные ключи из trusted.gpg.d и связки apt-key
582 rm -f /etc/apt/trusted.gpg.d/*54404762BBB6E853* \
583 /etc/apt/trusted.gpg.d/*6ED0E7B82643E131* 2>/dev/null || true
584 apt-key del 54404762BBB6E853 2>/dev/null || true
585 apt-key del 6ED0E7B82643E131 2>/dev/null || true
586
587 # 3. Очищаем кэш apt
588 apt-get clean
589
590 # 4. Принудительно переустанавливаем пакет с ключами (без проверки подписи)
591 apt-get install --reinstall -y --allow-unauthenticated debian-archive-keyring
592
593 # 5. Если прокси-сервер используется, настраиваем переменные окружения для gpg
594 if [ -n "$PROXY_URL" ]; then
595 export http_proxy="$PROXY_URL"
596 export https_proxy="$PROXY_URL"
597 fi
598
599 # 6. Пытаемся получить ключи напрямую с keyserver (альтернативный источник)
600 echo "Получение свежих ключей с keyserver..."
601 gpg --keyserver keyserver.ubuntu.com --recv-keys 54404762BBB6E853 6ED0E7B82643E131 2>/dev/null || \
602 gpg --keyserver pgp.mit.edu --recv-keys 54404762BBB6E853 6ED0E7B82643E131 2>/dev/null || \
603 gpg --keyserver keys.openpgp.org --recv-keys 54404762BBB6E853 6ED0E7B82643E131 2>/dev/null || true
604
605 # 7. Экспортируем ключи в директорию apt (если были получены)
606 gpg --export 54404762BBB6E853 > /etc/apt/trusted.gpg.d/debian-security-automatic.gpg 2>/dev/null || true
607 gpg --export 6ED0E7B82643E131 > /etc/apt/trusted.gpg.d/debian-archive-automatic.gpg 2>/dev/null || true
608
609 # 8. Снова очищаем списки и обновляем
610 rm -rf /var/lib/apt/lists/*
611 apt-get update --allow-insecure-repositories || true
612
613 echo -e "${ANSI_GREEN}Ключи обновлены.${ANSI_RESET}"
614}
615
616# ==================== ОСНОВНАЯ ЛОГИКА ====================
617
618main() {
619 # check_root
620
621 echo -e "${ANSI_GREEN}=== Настройка системы ===${ANSI_RESET}"
622
623 NEW_HOSTNAME=$(ask_hostname)
624
625 ask_create_user
626
627 echo $CREATE_USER
628
629 if [ "$CREATE_USER" = "yes" ]; then
630 NEW_USER=$(ask_username)
631 USER_PASS=$(ask_password "$NEW_USER")
632 create_user "$NEW_USER" "$USER_PASS"
633 configure_user_history "$NEW_USER"
634 fi
635
636 ask_proxy
637
638 # Выполнение настроек
639 configure_root_history
640
641 set_hostname "$NEW_HOSTNAME"
642 add_mephi_repository
643 update_system
644 install_packages
645 configure_ssh
646 configure_locale
647 configure_journald
648 clean_git_docs
649
650 make_motd_generator
651
652 install_midnight_commanger
653
654 finish_setup
655}
656
657# Запуск главной функции
658main "$@"