Vấn đề thực tế: Nhập password/token mãi không chán à?
Sau khi GitHub bỏ xác thực bằng password từ tháng 8/2021, mình phải chuyển sang dùng Personal Access Token (PAT). Và cái cảm giác phải paste token 40 ký tự mỗi lần git push thật sự rất phiền. Đã thế, token lại expire sau 30–90 ngày, phải generate cái mới rồi cập nhật lại.
Mình đã thử qua 4 cách khác nhau trong 6 tháng deploy thực tế, từ đơn giản nhất đến cách mà mình đang dùng hiện tại. Bài này tổng hợp lại những gì mình học được.
So sánh 4 cách lưu Git Credentials trên Linux
Cách 1: git-credential-store (lưu plaintext vào file)
Git hỗ trợ sẵn, không cần cài thêm gì. Một lệnh là xong:
git config --global credential.helper store
Credentials sẽ được lưu vào ~/.git-credentials ở dạng plaintext:
https://username:[email protected]
Ưu điểm: Zero setup, hoạt động ngay, không phụ thuộc thêm package nào.
Nhược điểm: Token lưu plaintext — bất kỳ process nào chạy với quyền user đều đọc được. Máy bị compromise là token bị lộ hoàn toàn. Không phù hợp với máy shared hoặc production server.
Cách 2: git-credential-cache (lưu tạm trong RAM)
# Lưu credentials trong RAM, timeout sau 1 giờ (3600 giây)
git config --global credential.helper 'cache --timeout=3600'
Ưu điểm: Credentials không ghi ra disk, an toàn hơn store.
Nhược điểm: Reboot là mất, phải nhập lại. Không hoạt động trên hệ thống thiếu Unix socket (một số distro minimal setup). Với server chạy 24/7, cứ mỗi giờ lại phải nhập lại — không thực tế.
Cách 3: libsecret (tích hợp với GNOME Keyring / KWallet)
Trên Ubuntu hay Fedora có GNOME, đây là lựa chọn ngon mà nhiều người hay bỏ qua. libsecret giao tiếp trực tiếp với Secret Service API — credentials được mã hóa bởi OS, không phải bởi app, lưu trong keyring của hệ thống.
# Cài libsecret
sudo apt install libsecret-1-0 libsecret-1-dev git
# Build git-credential-libsecret
cd /usr/share/doc/git/contrib/credential/libsecret
sudo make
# Cấu hình
git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
Ưu điểm: Credentials được mã hóa bởi OS, tích hợp sẵn với GNOME/KDE, không cần daemon riêng.
Nhược điểm: Chỉ chạy được khi có desktop environment (GNOME, KDE). Trên headless server, GNOME Keyring không khởi động được — nó cần D-Bus session và GUI environment để hoạt động.
Cách 4: Git Credential Manager (GCM) — Cross-platform
Microsoft build cái này và open source nó. GCM xử lý OAuth2 hoàn chỉnh — không cần tự tạo PAT thủ công, chỉ cần login một lần qua browser là xong. Hỗ trợ GitHub, GitLab, Bitbucket, Azure DevOps đều đủ. Trên Linux, GCM linh hoạt với nhiều backend lưu trữ khác nhau.
Ưu điểm: OAuth2 tự động (không cần PAT thủ công), hoạt động cả desktop lẫn headless server, nhiều backend storage, cross-platform.
Nhược điểm: Cần cài thêm .NET runtime, binary khá nặng (~100MB). Nếu chỉ dùng một service thì hơi overkill.
Phân tích: Nên chọn cách nào?
| Tiêu chí | store | cache | libsecret | GCM |
|---|---|---|---|---|
| Bảo mật | ❌ Plaintext | ✅ RAM only | ✅ Encrypted | ✅ Encrypted |
| Persistent | ✅ | ❌ | ✅ | ✅ |
| Headless server | ✅ | ✅ | ❌ | ✅ (với secret-service hoặc plaintext) |
| Desktop Linux | ✅ | ✅ | ✅ | ✅ |
| OAuth2 tự động | ❌ | ❌ | ❌ | ✅ |
| Setup phức tạp | Rất dễ | Rất dễ | Trung bình | Trung bình |
Kết luận thực tế của mình:
- Desktop Linux (Ubuntu, Fedora, Mint): Dùng libsecret — native, nhẹ, an toàn, tích hợp luôn với keyring có sẵn.
- Headless server / VPS: Dùng GCM với GPG-encrypted plaintext store hoặc đơn giản hơn là SSH key (không cần credential helper gì cả).
- Team nhiều service (GitHub + GitLab + Bitbucket): Dùng GCM cho OAuth2 tự động.
Triển khai: libsecret trên Ubuntu/Debian Desktop
Bước 1: Cài đặt
sudo apt update
sudo apt install libsecret-1-0 libsecret-1-dev git make gcc
Bước 2: Build git-credential-libsecret
# Tìm đường dẫn source (tùy version git)
ls /usr/share/doc/git/contrib/credential/libsecret/
# Build
cd /usr/share/doc/git/contrib/credential/libsecret/
sudo make
# Verify
ls -la git-credential-libsecret
Bước 3: Cấu hình global
git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
# Verify cấu hình
cat ~/.gitconfig | grep credential
Lần đầu git push, bạn sẽ được hỏi token. Nhập xong, libsecret lưu vào GNOME Keyring. Từ lần sau trở đi, tự động lấy ra không cần nhập lại.
Triển khai: Git Credential Manager trên Headless Server
Bước 1: Tải và cài GCM
# Kiểm tra release mới nhất tại: https://github.com/git-ecosystem/git-credential-manager/releases
GCM_VERSION="2.5.1"
wget https://github.com/git-ecosystem/git-credential-manager/releases/download/v${GCM_VERSION}/gcm-linux_amd64.${GCM_VERSION}.deb
sudo dpkg -i gcm-linux_amd64.${GCM_VERSION}.deb
Bước 2: Cấu hình backend lưu trữ
Trên headless server, GCM không thể dùng GNOME Keyring. Có 2 lựa chọn:
# Option A: Dùng GPG-encrypted file (khuyến nghị)
git-credential-manager configure
git config --global credential.credentialStore gpg
# Tạo GPG key nếu chưa có
gpg --gen-key
# Option B: Plaintext (tương đương git-credential-store nhưng qua GCM)
git config --global credential.credentialStore plaintext
Bước 3: Test với GitHub
# Clone repo private để test
git clone https://github.com/your-org/private-repo.git
# GCM sẽ mở browser (nếu có) hoặc hiện URL để authenticate
# Sau khi authenticate lần đầu, mọi git operation sau đều tự động
Một tình huống thực tế mình đã gặp
Mình từng mất code quan trọng vì force push nhầm branch — từ đó luôn cẩn thận với git push --force. Nhưng cũng từ incident đó, mình nhận ra mình đang paste token vào terminal một cách thoải mái, không để ý rằng lịch sử terminal có thể lưu lại token đó.
# ĐỪNG làm thế này — token lộ trong history!
git clone https://username:[email protected]/org/repo.git
# Kiểm tra bash history
history | grep ghp_
# → Đây là lý do cần credential helper thay vì inline token
Sau khi chuyển sang libsecret, token không còn xuất hiện trong command line hay history nữa. Git lấy token từ keyring internally — sạch hơn hẳn.
Bonus: Quản lý nhiều tài khoản GitHub cùng lúc
Có cả tài khoản cá nhân lẫn tài khoản công ty trên GitHub? GCM xử lý tốt hơn libsecret trong trường hợp này:
# Cấu hình per-repo (override global)
cd ~/work-project
git config credential.https://github.com.username work-username
# Hoặc dùng SSH với nhiều key (cách mình ưa hơn)
# Thêm vào ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
# Clone bằng alias
git clone git@github-personal:username/personal-repo.git
git clone git@github-work:org/work-repo.git
Dọn dẹp credentials cũ
Cần xóa credentials cũ hoặc reset để nhập lại từ đầu — đây là các lệnh tương ứng cho từng method:
# Xóa credentials đã lưu (libsecret)
git credential-libsecret erase
protocol=https
host=github.com
# Nhấn Ctrl+D
# Xóa toàn bộ cache (git-credential-cache)
git credential-cache exit
# Xóa file store thủ công
rm ~/.git-credentials
Tóm lại
Dùng Linux desktop thì cài libsecret trước — nhẹ, native, setup xong trong 10 phút. Quản lý server hoặc phải xử lý nhiều Git service cùng lúc thì GCM xứng đáng với thời gian setup ban đầu. Còn nếu server chỉ cần pull/push từ một repo duy nhất, deploy SSH key và quên credential helper đi cho khỏe — đó là cách mình đang dùng trên hầu hết VPS production.

