Історія команд у терміналі Linux зручна, але й небезпечна: паролі, токени, адреси серверів — усе це може залишитися в plain text. У цій статті я, Kernelka, покажу, як налаштувати автоочистку та шифрування історії в Bash і Zsh при виході із сесії. Буде безпечно, акуратно й зручно 🔒
Чому варто чистити й шифрувати історію
Навіть якщо ви досвідчено користуєтеся терміналом Linux, випадкове введення секретів безпосередньо в команді — типова помилка. Автоматичне прибирання історії (і/або її шифрування) захищає від:
- витоку токенів та паролів у
~/.bash_historyабо~/.zsh_history; - доступу до ваших команд іншими користувачами системи;
- індексації історії резервними копіями чи збирачами логів.
Нижче — покроково: базова гігієна, шифрування GPG, варіанти без історії та автоматизація задач через cron та systemd timers.
Налаштування Bash: автоочистка й шифрування при виході
Крок 1. Створіть GPG-ключ (один раз)
gpg --full-generate-key
# Подивитися ідентифікатор (email/KEYID)
gpg --list-keys
Запам'ятайте email або KEYID — далі він знадобиться як отримувач для шифрування.
Крок 2. Додайте налаштування до ~/.bashrc
Цей фрагмент зберігає історію в RAM під час сесії та шифрує її при виході у файл із міткою часу. Так ми уникаємо колізій між кількома вікнами термінала.
# ----- Kernelka: безпечна історія для Bash -----
# Редагуйте на свій e-mail або KEYID з gpg --list-keys
export KH_GPG_RECIPIENT="your-email@example.com"
# Гігієна історії
export HISTSIZE=5000
export HISTFILESIZE=5000
export HISTCONTROL=ignoredups:erasedups:ignorespace
shopt -s histappend
# Зберігати історію в RAM (tmpfs) для поточної сесії
_kh_dir="${XDG_RUNTIME_DIR:-/dev/shm}/khist-bash"
mkdir -p "$_kh_dir"
export HISTFILE="$_kh_dir/history-$$.bash"
# Писати команду негайно після виконання
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
# Шифрувати історію при виході із сесії
_kh_encrypt_history_bash() {
history -a # дочитати останні команди в файл
if [[ -s "$HISTFILE" ]]; then
local ts
ts=$(date +%F_%H%M%S)
local tgt="$HOME/.bash_history-${ts}-$$.gpg"
gpg --yes --encrypt -r "$KH_GPG_RECIPIENT" -o "$tgt" "$HISTFILE" && \
shred -u -z "$HISTFILE"
fi
}
trap _kh_encrypt_history_bash EXIT
# ----- /Kernelka -----
Тепер під час кожного виходу з вікна Bash ви отримаєте зашифрований файл у домашній теці, а тимчасовий plaintext у RAM буде надійно стерто.
Налаштування Zsh: автоочистка й шифрування при виході
Крок 1. Увімкніть гігієну історії
# Додайте в ~/.zshrc
setopt APPEND_HISTORY INC_APPEND_HISTORY SHARE_HISTORY \
HIST_IGNORE_SPACE HIST_REDUCE_BLANKS
HISTSIZE=5000
SAVEHIST=5000
Крок 2. Зберігайте історію в RAM і шифруйте при виході
# ----- Kernelka: безпечна історія для Zsh -----
export KH_GPG_RECIPIENT="your-email@example.com"
_kh_dir="${XDG_RUNTIME_DIR:-/dev/shm}/khist-zsh"
mkdir -p "$_kh_dir"
export HISTFILE="$_kh_dir/history-$$.zsh"
# Записувати команди одразу
precmd() { fc -W } # зберегти історію перед промптом
# Шифрувати при виході
_kh_encrypt_history_zsh() {
fc -W # ще раз переконатися, що останнє записано
if [[ -s "$HISTFILE" ]]; then
local ts
ts=$(date +%F_%H%M%S)
local tgt="$HOME/.zsh_history-${ts}-$$.gpg"
gpg --yes --encrypt -r "$KH_GPG_RECIPIENT" -o "$tgt" "$HISTFILE" && \
shred -u -z "$HISTFILE"
fi
}
TRAPEXIT() { _kh_encrypt_history_zsh }
# ----- /Kernelka -----
Результат — plaintext-історія живе лише в пам'яті під час сесії, а на диску залишається лише зашифрована копія.
Альтернативні способи
1) Повне вимкнення історії
# Bash
export HISTFILE=/dev/null
export HISTSIZE=0
export HISTFILESIZE=0
# Zsh
unsetopt HIST_SAVE_NO_DUPS
HISTSIZE=0; SAVEHIST=0; export HISTFILE=/dev/null
Різко, але безсумнівно безпечно.
2) Класична автоочистка через файли logout
# ~/.bash_logout
history -c; history -w # записати порожню історію
shred -u -z ~/.bash_history 2>/dev/null || true
# ~/.zlogout
: >| ~/.zsh_history
shred -u -z ~/.zsh_history 2>/dev/null || true
Майте на увазі: ~/.bash_logout виконується лише для login-shell. У звичайних емуляторах термінала краще використовувати варіант із trap у ~/.bashrc/~/.zshrc.
3) Ротація та прибирання зашифрованих файлів (systemd user)
Це вже приємні трюки Linux і легка автоматизація задач: почистимо зашифровані архіви старше 30 днів.
# ~/.config/systemd/user/khist-prune.service
[Unit]
Description=Prune old encrypted shell histories
[Service]
Type=oneshot
ExecStart=/usr/bin/find %h -maxdepth 1 \( -name ".bash_history-*.gpg" -o -name ".zsh_history-*.gpg" \) -mtime +30 -delete
# ~/.config/systemd/user/khist-prune.timer
[Unit]
Description=Run history prune daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=default.target
# Активувати
systemctl --user daemon-reload
systemctl --user enable --now khist-prune.timer
За бажанням замініть на cron, але systemd timers на десктопах працюють стабільніше.
GUI-спосіб: створення GPG-ключа через Seahorse
- Встановіть «Passwords and Keys» (Seahorse), якщо його немає.
- Відкрийте програму → PGP Keys → плюсик → «PGP Key…» → заповніть ім'я та email.
- Створіть ключ і додайте цей email/KEYID у змінну
KH_GPG_RECIPIENTу ваших bash скрипти для~/.bashrc/~/.zshrc.
На KDE можете використати KGpg — кроки схожі ✨
FAQ
Чому моя історія не очищається після закриття вкладки термінала?
Ймовірно, у вас не виконується ~/.bash_logout, бо це не login-shell. Використовуйте варіант із trap EXIT у ~/.bashrc або zsh-функцію TRAPEXIT у ~/.zshrc.
Як виключити секрети з історії, але зберігати решту?
У Bash встановіть HISTCONTROL=ignorespace та вводьте чутливі команди зі стартовим пробілом — такі рядки не потраплять в історію. У Zsh працює setopt HIST_IGNORE_SPACE.
Що робити з кількома одночасними вікнами?
У наведених прикладах історія зберігається в RAM із прив'язкою до PID ($$) — кожне вікно має окремий файл, який шифрується при виході. Це уникає конфліктів запису.
GPG просить пароль під час виходу. Це нормально?
Так. Налаштуйте gpg-agent для кешування пароля або використовуйте розумну тривалість кешу. Не створюйте ключ без пароля — це знижує безпеку.
Як подивитися зашифровану історію?
gpg -d ~/.bash_history-2024-10-01_190200-12345.gpg | less
# або для Zsh
gpg -d ~/.zsh_history-*.gpg | less
Чи підходить це для Fish?
Ідея та інструменти ті самі (RAM + GPG + видалення при виході), але файли/хуки інші. У цій статті зосередженося на Bash і Zsh.
Порада від Kernelka
Тримайте історію корисною, але безпечною: встановіть ліміти HISTSIZE і SAVEHIST, вмикайте ignorespace, а для чутливих сценаріїв використовуйте змінні середовища (наприклад, TOKEN) замість прямого введення секретів. Так ваші трюки Linux залишаться зручними, а ризики — мінімальними 🙂
Підсумок
- Використайте RAM для тимчасової історії (
/dev/shmабо$XDG_RUNTIME_DIR). - Шифруйте історію GPG при виході з сесії й стирайте plaintext через
shred. - Налаштуйте гігієну історії:
HISTCONTROL/setopt, ліміти розміру, пробіл для чутливих команд. - Додайте прибирання архівів через systemd timers для охайності.
- За потреби — повністю вимкніть історію.