Создайте ключ ed25519
Создайте ключ на своём компьютере, а не на сервере. Ключи ed25519 короткие, быстрые и поддерживаются любым современным OpenSSH. Защитите ключ парольной фразой — SSH-агент избавит вас от необходимости вводить её при каждом подключении.
ssh-keygen -t ed25519 -C "alice@laptop"
# приватный ключ: ~/.ssh/id_ed25519 публичный ключ: ~/.ssh/id_ed25519.pub
ssh-add ~/.ssh/id_ed25519 # необязательно: загрузить его в SSH-агент
Скопируйте публичный ключ в учётную запись, под которой вы входите. В Linux и macOS:
ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@203.0.113.10
В Windows нет ssh-copy-id. В PowerShell:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh alice@203.0.113.10 "umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys"
С вашего компьютера уходит только файл .pub. Если приватный ключ мог быть скомпрометирован, удалите соответствующую строку из ~/.ssh/authorized_keys на сервере и создайте новый ключ.
Сокращения в ~/.ssh/config
Запись host избавляет от лишнего набора текста и применяет одинаковые параметры к ssh, scp и rsync:
Host gpu1
HostName 203.0.113.10
User alice
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 4
Теперь достаточно команды ssh gpu1. Параметр ServerAliveInterval каждые 30 секунд отправляет keep-alive, чтобы простаивающие сессии не обрывались маршрутизаторами на пути. В Linux и macOS файл не должен быть доступен для записи другим пользователям (chmod 600 ~/.ssh/config); в Windows он находится в %USERPROFILE%\.ssh\config.
Отключите вход по паролю
Когда вход по ключу заработает для вашего пользователя, отключите вход по паролю и интерактивный ввод пароля с клавиатуры, а также запретите root входить по паролю. Ubuntu читает файлы конфигурации из каталога /etc/ssh/sshd_config.d/ раньше остальных настроек, и для большинства параметров действует первое найденное значение. Файл, имя которого начинается с 00-, читается первым и переопределяет более поздние — например, файл cloud-init, который включает пароли обратно.
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sudo sshd -t && sudo systemctl restart ssh
sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '
Перезапуск SSH-службы не закрывает открытые сессии. Из второго терминала проверьте, что пароль теперь отклоняется, а ваш ключ всё ещё работает:
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password alice@203.0.113.10 # должно завершиться ошибкой
ssh gpu1 # должно сработать
Когда ваш sudo-пользователь заработает, можно пойти ещё дальше и указать PermitRootLogin no.
Базовый файрвол на ufw
Запретите весь входящий трафик, кроме SSH, а затем открывайте остальные порты по одному, когда они понадобятся:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose
Разрешите SSH, прежде чем выполнять ufw enable. Без этого правила вы не сможете открыть новую сессию SSH после активации файрвола.
Для публичного HTTPS-эндпоинта, например, обратного прокси, откройте sudo ufw allow 80,443/tcp. Всё остальное держите закрытым и обращайтесь к нему через SSH-туннели (см. ниже). Учтите, что Docker публикует порты контейнеров через собственные правила файрвола, которые ufw не фильтрует: публикуйте их только на 127.0.0.1, как описано в разделе Контейнеры.
fail2ban для SSH
Когда пароли отключены, подбор пароля не может увенчаться успехом, но всё равно заполняет журналы. fail2ban блокирует адреса, с которых продолжаются неудачные попытки входа. Пакет Ubuntu включает свой jail для SSH из коробки; небольшой переопределяющий файл задаёт политику блокировок:
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
# никогда не блокируйте свой постоянный адрес:
# ignoreip = 127.0.0.1/8 ::1 198.51.100.7
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Чтобы снять блокировку: sudo fail2ban-client set sshd unbanip 198.51.100.7.
Держите длительные задачи запущенными в tmux
Задача, запущенная в обычной SSH-сессии, останавливается при разрыве соединения. Внутри tmux она продолжает работать, и вы можете снова подключиться к ней из любой новой сессии:
tmux new -s train # запустить именованную сессию
python train.py 2>&1 | tee train.log # запустить задачу и сохранить журнал в файл
# отключиться: нажмите Ctrl-b, затем d
tmux ls # показать список сессий
tmux attach -t train # снова подключиться позже
Прокрутка истории — Ctrl-b [ (затем клавиши со стрелками, q для выхода). Файл журнала позволяет следить за ходом выполнения без подключения к сессии: tail -f train.log.
Проброс портов для Jupyter и TensorBoard
Держите Jupyter-ноутбуки и дашборды привязанными к 127.0.0.1 на сервере и обращайтесь к ним через SSH. Ничего лишнего не открывается наружу в интернет.
# на сервере, внутри tmux
jupyter lab --no-browser --ip=127.0.0.1 --port=8888
tensorboard --logdir runs --host 127.0.0.1 --port 6006
# на вашем компьютере
ssh -N -L 8888:127.0.0.1:8888 -L 6006:127.0.0.1:6006 gpu1
Затем откройте в браузере http://localhost:8888 (с токеном, который вывел Jupyter) и http://localhost:6006. Чтобы порты пробрасывались при каждом подключении, добавьте LocalForward 8888 127.0.0.1:8888 в запись gpu1 в ~/.ssh/config.
Копирование данных с помощью rsync и scp
# отправка: конечный слэш копирует содержимое dataset/ в /data/dataset/
rsync -avhP ./dataset/ gpu1:/data/dataset/
# скачивание результатов
rsync -avhP gpu1:/data/checkpoints/ ./checkpoints/
# отдельные файлы
scp ./config.yaml gpu1:~/
scp gpu1:~/results.csv .
rsync пропускает файлы, которые уже идентичны, поэтому при повторном запуске отправляется только изменённое; -P сохраняет частично переданные файлы, что позволяет прерванной передаче продолжиться, и показывает прогресс. Добавляйте -z для сжимаемых данных, таких как текст или CSV, но не для изображений, видео или архивов. В Windows scp есть по умолчанию, а rsync доступен через WSL.
Про большие наборы данных и резервное копирование в объектное хранилище см. раздел Хранилище и данные.
Нужна помощь с этим руководством?
Расскажите нам о своём GPU, командах, которые вы выполнили, и результате, который получили, через форму обратной связи.
