在 Linux 中免密碼使用 sudo

sudo apt update sudo systemctl restart nginx sudo reboot

在使用 Linux 時,你會頻繁地使用到 sudo 指令。然而,每次都輸入密碼實在是令人感到厭煩。

當這種厭煩感達到頂點時,你最終會決定動手設定,讓 sudo 無需輸入密碼。想必點進這篇文章的你,也一定有過與我相似的感受。

在這篇文章中,我將整理出如何免除 sudo 密碼輸入的方法。

Linux 的 Tux 和金鑰安全

sudo 設定檔在哪裡?又該如何修改?

sudo 的主要設定檔位於:

/etc/sudoers

sudo 設定的語法一旦出錯,將會非常麻煩。如果設定不當導致 sudo 無法使用,恢復過程會很惱人。因此,我們建議使用專用指令 visudo

sudo visudo

visudo 在儲存時會進行語法檢查,並即時提示錯誤。就連官方手冊也強調務必使用 visudo

但請不要直接修改 /etc/sudoers

當你輸入 sudo visudo 時,/etc/sudoers 檔案會立即開啟,你可以直接進行修改。

然而,直接開啟並修改 /etc/sudoers 檔案並不是一個好習慣。

我通常偏好不更動主要的設定檔,而是在 /etc/sudoers.d/ 這個目錄下建立新的設定檔。

這樣日後要查找自己修改了哪些地方,或是要還原設定都會更加方便。

sudo 的設計允許它包含 sudoers.d 目錄中檔案的額外設定。

實際上,在 /etc/sudoers 檔案的最後一行,你會看到 include /etc/sudoers.d/

sudo visudo -f /etc/sudoers.d/no-password-common-commands

你可以自由命名檔案,只要能讓你日後輕鬆辨識即可。

不過,建議不要取得太隨便,否則日後可能會為自己帶來困擾。

喔!順帶一提,包含 ~. 的檔案名稱會被 sudoer 忽略。這個資訊可以在目錄中的 README 檔案註解裡找到。

了解設定格式

sudoers 的設定大致遵循以下格式:

這語法實在是...很難記住。建議你把它寫下來,或者直接將這篇部落格文章加入書籤。

雖然不常用,但偶爾需要用到時,就是會想不起來。

使用者名稱 主機=(執行身分) 選項: 指令

舉例來說,如果使用者名稱是 potter,並且希望免密碼執行 apt update,你可以這樣寫:

potter ALL=(ALL) NOPASSWD: /usr/bin/apt

各部分的說明如下:

  • potter : 要套用設定的使用者名稱。
  • ALL : 表示在所有主機上套用。
  • (ALL) : 表示可以以哪種使用者權限執行。我偶爾也會看到有人寫 (root)。我個人偏好使用 ALL。
  • NOPASSWD: 表示不詢問密碼。
  • /usr/bin/apt : 允許執行的指令「絕對路徑」。

如果你不確定指令的路徑,可以使用 which 來查詢。

~$which apt
/usr/bin/apt

~$which apt-get
/usr/bin/apt-get

~$which reboot
/usr/sbin/reboot

~$which systemctl
/usr/bin/systemctl

開放 ALL 的誘惑

此時,一個強烈的誘惑會浮現:

potter ALL=(ALL) NOPASSWD: ALL

這樣做非常簡潔。所有 sudo 指令都能免密碼執行,非常方便,簡直是太方便了。

雖然這是個人選擇,但我認為最好還是克制一下。因為我光是想像一個錯誤輸入的指令,就能直接以 root 權限執行,就感到不寒而慄。

即使腳本出現異常,也沒有密碼輸入這個最後的防線。如果你只是暫時開啟終端機,而有人動了它,那一切就都完了。世界上奇怪的人實在太多了...

選擇權在你。

僅允許常用指令免密碼執行

我個人傾向於「只開放常用指令」的折衷方案。這種方式相當不錯。

舉例來說,假設你只想讓 aptapt-getrebootsystemctl 等指令免密碼執行。

首先,開啟設定檔:

sudo visudo -f /etc/sudoers.d/no-password-common-commands

然後,像下面這樣撰寫:

potter ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /usr/sbin/reboot, /usr/bin/systemctl

現在,使用者 potter 就可以免密碼執行以下指令了:

sudo apt update
sudo apt -y upgrade
sudo apt-get update
sudo reboot
sudo systemctl reload nginx

如果你覺得開放所有 systemctl 指令會造成負擔,也可以只允許特定的指令:

potter ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx

分行撰寫,提高可讀性

當指令過多時,一行會顯得雜亂。此時,你可以使用 \ 來分行。

儘管這是 Linux 使用者常見且習慣的分行方式,但奇怪的是,實際操作時卻不常使用 \。不過,使用了確實能提升可讀性。

potter ALL=(ALL) NOPASSWD: \
    /usr/bin/apt, \
    /usr/bin/apt-get, \
    /usr/sbin/reboot, \
    /usr/bin/systemctl

看起來既美觀又整潔。

套用至特定群組

這項設定也相當實用。在多人管理的伺服器中,以群組為基礎的權限管理會更加方便。

如果想套用至特定群組,可以使用 %群組名稱 的格式。

例如,如果是 admin 群組,則會像這樣:

%admin ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/apt, /usr/bin/apt-get

延長密碼輸入的有效時間

如果你對完全取消密碼輸入感到不安,還有另一種方法:調整密碼再次詢問的時間。

基本上,一旦輸入密碼,系統在 10 到 15 分鐘內不會再次詢問,這個時間是可以調整的。

這可以透過 timestamp_timeout 設定來實現。

舉例來說,這樣設定就能讓 sudo 在 60 分鐘內不再詢問密碼:

Defaults timestamp_timeout=60

單位是「分鐘」,但如果設定為「0」,那將會是個惡夢,因為每次都必須輸入密碼。

如果設定為「-1」,則一旦輸入 sudo 密碼,直到關閉終端機前都不會再詢問。這幾乎與 ALL 設定提供同樣強大的便利性,但使用時仍會有些許不安。

當然,免密碼執行與延長有效時間這兩種設定是可以並存的。

例如,你可以這樣混合使用:

Defaults timestamp_timeout=30

potter ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /usr/sbin/reboot

常用指令免密碼,其他 sudo 指令則在驗證一次後維持 30 分鐘有效。

我認為這在便利性與安全性之間,取得了相當不錯的平衡點。

減少麻煩固然是好事,但我不想以增加不安感為代價。

總結

取消 sudo 密碼輸入其實並不難。

雖然上面的說明比較長,但簡要概括如下:

  1. 使用 visudo/etc/sudoers.d/ 下建立一個獨立的設定檔。
sudo visudo -f /etc/sudoers.d/no-password-common-commands
  1. 添加 NOPASSWD 規則即可。
Defaults timestamp_timeout=30

potter ALL=(ALL) NOPASSWD: \
    /usr/bin/apt, \
    /usr/bin/apt-get, \
    /usr/sbin/reboot

至於要開放到什麼程度,則取決於個人判斷,但我希望你能記住這一點:

唯有手指的便捷與內心的平靜同時獲得滿足,才是真正的舒適。