🇷🇺 Русский · 🇬🇧 English
Каждый раз, когда поднимаешь новый VPS, повторяется одно и то же: поставить нормальный ls, накатить Docker, разобраться со свопом на маленьком сервере, включить SSH только по ключу и не забыть про UFW. Чтобы не повторять регулярно одно и то же — написал скрипт с меню на 14 пунктов, который делает это всё сам, спрашивая только там, где решение реально важно принять тебе, а не ему.
Работает на Ubuntu и Debian, умеет русский и английский интерфейс, а кроме меню имеет неинтерактивный режим для cloud-init и Ansible, сухой прогон, аудит сервера и снимки конфигов перед изменением.
Ubuntu 24.04/26.04 или Debian 12/13, root-доступ, исходящий интернет.
На чужой системе скрипт не станет ничего делать: он проверяет дистрибутив на старте и честно отказывается, а не падает где-то посередине.
- Быстрый старт
- Что делает каждый пункт
- Аудит сервера
- Неинтерактивный режим
- Снимки конфигов и откат
- Язык интерфейса
- Кастомизация
- FAQ
- Contributing
- Лицензия
curl -fsSL https://raw.githubusercontent.com/SkyDeaD/UbuntuServer-Fast-Configuration/main/install.sh | sudo bash && source ~/.bashrcСтавится как команда usfc и сразу открывает меню — без ожидания: apt update больше не гоняется на старте, он подтягивается лениво и только перед реальной установкой. Функция usfc() (не alias) добавляется в .bashrc сама при первом запуске — дальше просто usfc, sudo руками писать не нужно, а когда меню закрывается, она сама подтягивает .bashrc в твою же сессию, так что новые алиасы/промпт видны сразу, без ручного source или переподключения (подробнее — в FAQ).
В меню — номер пункта (5, можно несколько сразу: 1 3 5 или 1,3,5), раздел целиком (C/B/S/P), всё сразу (A), можно сочетать (B,S). На пачку из нескольких пунктов все вопросы задаются заранее, одним блоком с пояснениями — что такое zram, нужен ли автозапуск nginx и Docker, нужен ли Cloudflare-плагин с токеном. Дальше пункты идут без остановок, а в конце показывается сводка: что встало, что упало, что пропущено. I (или ?, а также R) — справка и откат по пунктам: что делает каждый, какой у него сейчас статус, как выключить и как удалить совсем. H — справка по алиасам, U — снести сам usfc.
Пункты, помеченные в таблице значком ⇄, выключаются повторным выбором: скрипт видит, что настройка применена, и предлагает обратное действие. Остальные откатываются вручную — команды лежат на экране I у каждого пункта.
Многие хостеры отдают VPS, где есть только root. Скрипт это замечает и первым делом предлагает завести обычного пользователя с sudo (по умолчанию — да):
[!] Скрипт запущен от имени root.
[i] РЕКОМЕНДУЮ создать обычного пользователя с sudo: работать из-под root
небезопасно, SSH hardening без отдельного пользователя не работает вообще,
а алиасы/fastfetch/tmux сейчас лягут в /root и пропадут после перелогина.
Создать пользователя сейчас? [Y/n]:
Он спросит имя и пароль (скрытым вводом, с повтором), добавит в группу sudo и предложит скопировать ключи из /root/.ssh/authorized_keys — без этого новый пользователь просто не сможет зайти, если ты ходишь на сервер по ключу. Пароль короче 8 символов не принимается: сервер смотрит в интернет, и перебор по нему идёт круглосуточно. Пустой пароль допустим — тогда вход только по ключу.
Дальше скрипт переключается на нового пользователя прямо в работающей сессии, так что алиасы, fastfetch и tmux лягут уже ему, а не в /root. При выходе он напомнит перезайти под ним.
Если отказаться — ничего не сломается: пункт 1 «Пользователь + sudo» доступен в меню в любой момент. Как и SSH hardening с UFW, при выборе A («поставить всё») он пропускается: пароль и имя молча задефолтить нельзя.
usfc --help # справка
usfc --version # версия
usfc --no-update # не проверять обновления самого usfc
usfc --verbose # сырой вывод команд вместо спиннера
usfc --lang en # английский интерфейс на этот запуск
usfc --audit # проверить состояние сервера, ничего не меняя
usfc --list # профили и id пунктов
usfc --apply web # применить набор пунктов без меню
usfc --dry-run # показать, что было бы сделано
usfc --backups # снимки конфигов
usfc --restore # вернуть конфиги из снимкаПеременная USFC_APT_LOCK_TIMEOUT (по умолчанию 300 с) задаёт, сколько ждать освобождения блокировки dpkg. Ждать приходится потому, что на только что загруженном сервере apt-daily.timer запускает unattended-upgrades, и тот держит /var/lib/dpkg/lock-frontend минутами — без ожидания любая установка падала бы мгновенно с E: Could not get lock.
Полный лог всех выполненных команд всегда пишется в /var/log/usfc.log — даже когда на экране только спиннер.
Цвет отключается переменной NO_COLOR (значение неважно, важно наличие), а также сам собой при TERM=dumb и когда вывод идёт не в терминал — например usfc > log.txt.
Не доверяешь curl | sudo bash и хочешь применить то же самое руками, пункт за пунктом? — держи ручную инструкцию.
Что менялось от версии к версии — в CHANGELOG.md.
База, сервисы, защита — по порядку
Пользователь + sudo — создаёт обычного пользователя с sudo, копирует ему SSH-ключи из /root и переключает на него всю дальнейшую настройку. Нужен, когда сервер выдали с одним лишь root. Подробности — выше.
Базовые пакеты — micro, curl, wget, git, nano, unzip, htop, jq, rsync и ещё несколько вещей, которые обычно ставишь в первую же минуту на любом сервере. После установки выводится список: что приехало сейчас, что уже стояло, и коротко — зачем каждый пакет нужен — в том числе software-properties-common, без которого не заработает add-apt-repository, нужный дальше для PPA fastfetch. certbot отсюда переехал в свой пункт (см. ниже).
CLI-утилиты + starship — современные замены классических утилит (eza вместо ls с иконками, bat/batcat вместо cat с подсветкой, fd/fdfind вместо find, ripgrep, zoxide — «умный» cd, ncdu для разбора места на диске) и starship-промпт — всё вместе, потому что это один и тот же слой "как выглядит и ощущается терминал". Алиасы в .bashrc (ls/ll/la/lt/cat/catp/scat/fd) и eval-строки для zoxide/starship пишутся сразу тем же пунктом, а не отдельным шагом позже.
fastfetch — показывает информацию о сервере (ОС, ядро, память, диск, IP) при каждом заходе по SSH. Версия не ниже 2.64.0 (более старые не умеют выравнивание в format-строках, которое использует прилагаемый config.jsonc). Конфиг и автозапуск пишутся в .bashrc сразу тем же пунктом.
tmux — мультиплексор терминала: держит сессию живой при обрыве связи (просто переподключаешься по SSH — и всё, что запускал, на месте, включая несколько окон/панелей). Ставится с минимальным конфигом (мышь, история на 10000 строк).
Docker + Compose — CE + Compose plugin из официального репозитория Docker (не пакет docker.io из репов Ubuntu — он старый).
nginx-full — веб-сервер/реверс-прокси.
Про автозапуск nginx и Docker. Оба пакета по умолчанию поднимают сервис сами, из postinst. Скрипт спрашивает об этом до установки, и по умолчанию отвечает нет — сервер не всегда нужно поднимать прямо сейчас. Чтобы «не запускать» означало именно это, а не «поднять и тут же погасить» (nginx успел бы занять
:80), установка оборачивается вpolicy-rc.d. Выключенный сервис меню считает законченным состоянием, а не недоделкой, и повторно не пристаёт.Передумать можно в любой момент. На установленной системе оба пункта работают выключателями: показывают текущее состояние и предлагают обратное — остановить работающий сервис или поднять остановленный вместе с автозапуском. У Docker при этом снимаются оба юнита,
docker.serviceиdocker.socket: без второго демон возвращается сам при первом же обращении к сокету, и «автозапуск выключен» оказывается неправдой.
Certbot + плагины — сам certbot плюс, по выбору, плагин nginx (HTTP-01, обычные сертификаты) и плагин dns-cloudflare (DNS-01, без которого не выпустить wildcard). Для Cloudflare тут же предлагается создать /root/.secrets/certbot/cloudflare.ini с API-токеном (скрытый ввод, права 600, нужны права токена Zone:DNS:Edit). Откажешься — пункт так и будет светиться в меню как ! токен CF не задан, потому что без файла плагин нерабочий.
Про WARNING от python-cloudflare 2.20. Плагин объявляет
Depends: python3-cloudflare (<< 3.0), а в архиве Ubuntu 26.04 лежит ровно одна подходящая версия —2.20.0, и Ubuntu баннер из неё не вырезала. Проверено на живой системе: баннер срабатывает в конструкторе клиента, то есть при реальном выпуске сертификата, а не при установке —apt install,certbot --versionиcertbot pluginsмолчат. Отключить его нельзя:warn_warning_2_20()сам зовётwarnings.simplefilter('always', ...), перебивая иPYTHONWARNINGS, иpython3 -W ignore. На выпуск сертификатов он не влияет — версия закреплена зависимостью пакета, а не выехала сама изpip. Скрипт предупреждает о нём заранее, чтобы баннер не выглядел поломкой.
Отдельно предлагается положить в /etc/letsencrypt/ заготовки ssl-dhparams.pem и options-ssl-nginx.conf. Их создаёт только nginx-installer certbot'а, а при выпуске wildcard через certbot certonly они не появляются — и типовой конфиг nginx, который на них ссылается, роняет сервер при старте. Оба файла берутся из самого пакета certbot, ничего не генерируется и не качается.
Docker log rotation — ограничивает логи контейнеров (лимит 10 МБ на файл): без этого логи Docker по умолчанию ничем не ограничены и со временем могут забить всё место на диске.
fail2ban — банит IP после нескольких неудачных попыток входа по SSH (защита от перебора паролей). Настраивается на реальный SSH-порт сервера, не хардкожен 22.
unattended-upgrades — сам ставит security-обновления системы, без твоего участия.
ZRAM + swap + earlyoom — zram (сжатая память прямо в оперативке; сколько % RAM под неё отдать — теперь спрашивается при установке, по умолчанию 75%) плюс резервный swap-файл на диске с более низким приоритетом, чтобы использовался только если не хватило zram. Размер спрашивается, а по умолчанию считается как min(RAM, свободно/4), зажатое в 512–4096 МБ: своп здесь — резерв под zram, поэтому пляшет от объёма памяти, а деление на 4 не даёт ему съесть тесный диск. Если swap-файл уже есть, скрипт покажет его текущий размер рядом с рекомендуемым и предложит пересоздать — но только когда они расходятся больше чем на 10%, и только для файлов: размер разделов и LVM он не трогает. Плюс vm.swappiness=80/vm.vfs_cache_pressure=50 и опционально earlyoom — защита от полного зависания сервера при нехватке памяти.
SSH hardening — переводит вход только на ключ, выключает вход по паролю и вход под root. Самый рискованный пункт меню, поэтому единственный с самопроверкой перед применением: перед тем как выключить пароль, скрипт заводит одноразовый ключ и реально проверяет вход по нему — если проверка не прошла, автоматически откатывает конфиг и оставляет пароль включённым.
UFW — файрвол: закрывает все порты, кроме нужных (SSH-порт и то, что сервер уже реально слушает на момент включения).
Раздел «защита» идёт последним осознанно: UFW при включении сканирует реально слушающие порты, и если Docker/nginx уже подняты, фаервол сразу увидит их порты, а не только 22-й.
Скрипт умеет не только настраивать, но и отвечать на вопрос «что с сервером прямо сейчас». Клавиша D в меню или usfc --audit:
Сеть
! Порты наружу: 22
Файрвол выключен — доступны все. Пункт 14
Доступ
! Вход по паролю разрешён
Перебор по SSH идёт круглосуточно. Пункт 13
✓ Root-логин: prohibit-password
! fail2ban не работает
Пункт 10
Итог: в норме: 9 замечаний: 3 важных: 0
Проверяются место на диске и inode (кончаются раньше места и выглядят как «нет места» при свободных гигабайтах), память и подкачка, упавшие systemd-юниты, порты наружу против правил UFW, вход по паролю и root-логин, неустановленные security-обновления, необходимость перезагрузки, срок жизни сертификатов.
Аудит только читает. Это не обещание, а проверяемое свойство: в CI есть тест, который сверяет слепок /etc, dpkg, passwd/group и свопа до и после прогона.
Всё то же самое, но без меню — для cloud-init, Ansible и скриптов развёртывания:
usfc --apply web # готовый профиль
usfc --apply docker,nginx,ufw # свои пункты
usfc --apply all --dry-run # показать, что было бы сделано
usfc --config /etc/usfc.conf # ответы на вопросы из файла
usfc --list # какие есть профили и idПрофили: minimal, web, dockerhost, secure. Коды возврата пригодны для CI: 0 — применилось, 1 — часть пунктов упала, 2 — не разобрали, что применять.
Конфиг разбирается построчно, а не через source: --config из непроверенного места не должен уметь запускать команды.
ITEMS=web
NGINX_AUTOSTART=Y
DOCKER_AUTOSTART=N
ZRAM_PERCENT=75
SWAP_MB=2048SSH hardening в неинтерактивном режиме пропускается — с явным сообщением. Закрыть себе доступ к серверу по чужому конфигу не та цена, которую стоит платить за автоматизацию. Настраивается отдельно, из меню.
Повторный запуск — честный no-op. Уже применённые пункты пропускаются. Это не оптимизация, а вопрос смысла: в меню повторный выбор
⇄-пункта означает «переключить», и без этой проверки--applyиз cloud-init выключал бы то, что просили включить.
--dry-run показывает, что было бы сделано, и не меняет систему. Перехват стоит не в отдельных функциях, а на уровне самих команд: usermod, install, chmod, systemctl, swapon и прочие подменяются на время прогона, а записи в системные файлы идут через одну общую точку. Читающие вызовы (systemctl is-active, sed без -i) пропускаются наружу — без них прогон врал бы уже про текущее состояние.
Полнота проверяется не глазами, а тестом: слепок системы до и после --apply all --dry-run обязан совпасть.
Перед тем как переписать любой системный файл, скрипт кладёт его копию в /var/backups/usfc/<метка>:
usfc --backups # что есть
usfc --restore 20260810-1021-4242 # вернуть как былоСнимок делается автоматически и только для файлов, которые правит сам скрипт: sshd_config.d/10-hardening.conf, fstab, daemon.json, 20auto-upgrades, 99-zram.conf, zramswap, .bashrc и остальные. Перед восстановлением снимается ещё один снимок — откат отката тоже должен быть возможен.
При первом запуске скрипт спрашивает язык на двух сразу — на этом шаге ещё неизвестно, какой из них понятен:
Язык интерфейса / Interface language
1) Русский
2) English
Выбор / Choice [1]:
Выбор запоминается и переживает обновление. Сменить потом — клавиша L в меню. Флаг --lang en работает разово и ничего не сохраняет: одиночный запуск на другом языке не должен молча переучивать инструмент.
src/config.jsonc для fastfetch — редактируешь и коммитишь, src/setup.sh тянет его по сырой ссылке при каждом запуске.
Свой форк — переменная окружения USFC_REPO_RAW_BASE подменяет источник обновлений и модулей, править код для этого не нужно. Версия проверяется через отдельный файл src/VERSION.
С версии 4.0.0 это не один файл, а точка входа плюс модули:
src/setup.sh загрузчик: bootstrap, самолечение, подключение модулей
src/MODULES манифест — он же порядок загрузки и порядок пунктов меню
src/lib/*.sh ядро по слоям: лог, разметка, apt, обновление, аудит…
src/lib/items/*.sh по одному файлу на пункт меню
Добавить пункт — это один новый файл в src/lib/items/ и строка в MODULES. Пункт сам себя регистрирует, поэтому синхронизировать шесть параллельных массивов, как раньше, больше не нужно:
usfc_item docker сервисы "Docker + Compose" "Docker CE + Compose из официального репозитория" \
"Docker + Compose" "Docker CE + Compose from the official repository"
usfc_item_toggle docker
usfc_item_full docker "полное описание" "full description"
usfc_item_rollback docker "команды удаления" "removal commands"
status_docker() { ...; }
apply_docker() { ...; }
disable_docker() { ...; }Английский вариант необязателен: пока его нет, показывается русский.
Иконки/шрифты в терминале выглядят как квадратики или кракозябры
Это шрифт твоего локального терминала (клиента), не сервера — Nerd Font для иконок eza/starship/fastfetch ставится и настраивается в приложении, через которое ты подключаешься по SSH, скрипт на это никак повлиять не может.
Docker не ставится, ошибка про кодовое имя дистрибутива
Официальный репозиторий Docker иногда отстаёт от свежих релизов Ubuntu — скрипт сам это ловит и переключается на совместимый noble. На Debian такого переключения нет намеренно: noble там чужая ветка репозитория, собранная под другие версии библиотек, и пункт честно останавливается вместо того, чтобы поставить заведомо неподходящие пакеты.
Что не работает на Debian
Почти всё работает. Отличия ровно два, и оба проверены на живых образах:
- Debian 12 (bookworm) — в репозиториях нет
ezaиfastfetch.ezaпросто не попадает в набор CLI-утилит, а алиасыls/ll/la/ltне пишутся в.bashrc(иначе они сломали быls). Пункт fastfetch объясняет, что пакета нет, и предлагает.debс GitHub. - Debian 13 (trixie) — есть всё, кроме
software-properties-common, который нужен только для PPA, то есть только на Ubuntu.
Хочу пересмотреть SSH hardening или UFW без пересоздания сервера
usfc ещё раз — на уже настроенных пунктах меню покажет текущее состояние и спросит, менять ли.
Делался в первую очередь под свои сервера, так что часть решений — это то, что удобно мне. Баги и пожелания приветствуются — открывай issue.






