
Direnv là gì? Quản lý biến môi trường theo project tự động

Direnv là công cụ dòng lệnh cho phép nạp và gỡ bỏ biến môi trường tự động khi bạn di chuyển giữa các thư mục project. Thay vì cấu hình chung trong .bashrc hay .zshrc, Direnv đọc file .envrc riêng ở mỗi thư mục, kích hoạt biến môi trường chỉ khi cần thiết.
Tại sao cần Direnv?
Trong phát triển phần mềm hiện đại, mỗi project thường yêu cầu:
- Phiên bản ngôn ngữ khác nhau (Python 3.11 vs 3.12, Node 18 vs 20)
- API keys, database URLs, secret keys riêng biệt
- PATH tùy chỉnh trỏ tới binary local (ví dụ
./node_modules/.bin) - Feature flags, debug modes chỉ bật trong dev
Cách truyền thống ghi hết vào ~/.bashrc gây ô nhiễm namespace, xung đột phiên bản, và rò rỉ secret giữa project. Direnv giải quyết bằng cách cô lập môi trường theo thư mục.
Cách hoạt động
Direnv hook vào shell (bash, zsh, fish, elvish). Khi bạn cd vào thư mục có file .envrc:
- Direnv kiểm tra hash của
.envrc(bảo mật: từ chối load nếu file thay đổi mà chưadirenv allow) - Tạo subshell, export các biến trong
.envrc - Khi
cdra khỏi thư mục, tự độngunsettất cả biến đã load
Cài đặt
# macOS
brew install direnv
# Linux (Debian/Ubuntu)
sudo apt install direnv
# Arch
sudo pacman -S direnv
# Nix
nix-env -iA nixpkgs.direnv
Sau đó thêm hook vào shell config:
# bash - thêm vào ~/.bashrc
eval "$(direnv hook bash)"
# zsh - thêm vào ~/.zshrc
eval "$(direnv hook zsh)"
# fish - thêm vào ~/.config/fish/config.fish
direnv hook fish | source
Khởi động lại shell hoặc chạy source ~/.bashrc.
Tạo file .envrc
Trong thư mục project, tạo file .envrc:
# Ví dụ project Python
export PYTHONPATH="$(pwd)/src:$PYTHONPATH"
export DJANGO_SETTINGS_MODULE="myproject.settings.dev"
export DATABASE_URL="postgresql://user:pass@localhost:5432/myproject_dev"
export REDIS_URL="redis://localhost:6379/0"
export DEBUG=1
# Nạp .env file nếu có (khuyến nghị dùng direnv stdlib)
dotenv_if_exists .env
Chạy direnv allow để cho phép load. Lần sau cd vào sẽ tự động nạp.
Tích hợp với công cụ quản lý phiên bản
Direnv có stdlib hỗ trợ use_nix, use_python, use_node, use_ruby, use_go, use_rust… tự động cài và kích hoạt phiên bản đúng:
# .envrc cho project Python
use python 3.11
layout python3
dotenv_if_exists .env
Khi cd vào, Direnv sẽ:
- Kiểm tra Python 3.11 có sẵn không (tải nếu dùng
direnv-venvhoặcasdf/pyenv) - Tạo virtualenv
.direnv/python-3.11 - Activate virtualenv, set
VIRTUAL_ENV, updatePATH

Bảo mật: direnv allow/deny
Mỗi lần .envrc thay đổi, Direnv chặn load và yêu cầu xác nhận:
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
Điều này ngăn chặn supply chain attack khi kẻ xấu chèn mã độc vào .envrc trong repo chia sẻ. Luôn cat .envrc trước khi direnv allow.
So sánh với các giải pháp khác
| Công cụ | Cơ chế | Ưu điểm | Nhược điểm |
|---|---|---|---|
| Direnv | Hook shell, per-directory .envrc | Tự động, bảo mật, stdlib phong phú | Cần cài binary, hook shell |
| autoenv | Hook shell, .env file | Đơn giản | Không có allow/deny, ít feature hơn |
| dotenv (Python/Node) | Load thủ công trong code | Không phụ thuộc shell | Phải gọi code, không tự động khi cd |
| Shell rc files | Export thủ công | Không cài thêm | Ô nhiễm global, dễ xung đột |
Mẹo nâng cao
Chia sẻ .envrc mẫu trong team
Commit .envrc.example vào repo, teammate copy thành .envrc và điền secret cá nhân. Thêm .envrc vào .gitignore.
Kết hợp với 1Password CLI
# .envrc
export AWS_ACCESS_KEY_ID="$(op read op://Private/AWS/access_key_id)"
export AWS_SECRET_ACCESS_KEY="$(op read op://Private/AWS/secret_access_key)"
Secret không bao giờ chạm disk, chỉ tồn tại trong memory shell session.
Watch file thay đổi tự động reload
# .envrc
watch_file .env
dotenv
Khi .env thay đổi, Direnv tự động reload mà không cần direnv reload thủ công.

Kết luận
Direnv là công cụ nhỏ gọn nhưng thay đổi to lớn cách quản lý môi trường phát triển. Nó đưa configuration xuống cấp độ project, tự động hóa activate/deactivate, và có cơ chế bảo mật allow/deny thiết yếu cho teamwork. Nếu bạn làm việc đa project, nhiều ngôn ngữ, nhiều secret — Direnv nên có trong toolkit hàng ngày.
Nguồn tham khảo: direnv.net, GitHub direnv
