Nên dùng WSL hay VPS để phát triển?
WSL phù hợp code local, còn VPS giữ service chạy khi bạn đóng laptop. So sánh uptime, IP public, systemd, tốc độ file, backup và cầu nối SSH.
Nên dùng WSL hay VPS để phát triển?
WSL và VPS khác nhau ở một điểm chính: khả năng luôn sẵn sàng. WSL (Windows Subsystem for Linux) chạy Ubuntu trong một virtual machine tồn tại và dừng cùng phiên Windows của bạn. VPS (virtual private server) chạy Ubuntu tương tự trên một địa chỉ IP public vẫn hoạt động khi laptop của bạn đã đóng. Hầu hết developer cuối cùng đều dùng cả hai, trong đó server là máy luôn có thể truy cập.
Hệ điều hành không phải điểm khác biệt đáng chú ý vì cả hai đều chạy Ubuntu. Điểm khác nằm ở uptime, khả năng truy cập từ Internet, những gì systemd có thể đảm bảo, tốc độ thao tác với file, cách network hoạt động và bên nào quản lý bản sao lưu. Mỗi phần bên dưới đều mô tả một khác biệt mà bạn có thể quan sát trực tiếp trên máy của mình.
WSL dừng khi bạn đóng laptop vì sao?
WSL 2 chạy một Linux kernel thật trong một máy ảo nhẹ do Windows khởi động theo yêu cầu. Máy ảo này chỉ tồn tại khi có một distribution đang chạy, và distribution chỉ chạy khi có tiến trình đang sử dụng nó. Kiểm tra trạng thái từ PowerShell:
wsl --version
wsl --list --runningĐóng mọi terminal WSL, chờ một phút, rồi chạy lại wsl --list --running. Khi lệnh báo không có distribution nào đang chạy, shell bạn đã khởi động cũng biến mất, cùng với mọi thứ đang chạy trong đó. wsl --shutdown thực hiện việc tương tự ngay lập tức. Đây là cách hữu ích để kiểm tra hệ thống của bạn sẽ hoạt động thế nào sau khi restart.
Sleep và hibernate cũng dừng máy ảo. Timer đặt để dump database lúc 03:00 sẽ không chạy khi laptop đóng nắp, vì kernel cần thực thi timer đó không hoạt động. Không có thành phần nào ghi log lỗi, nên trông như job chưa từng được schedule. Chính hành vi này khiến nhiều người dùng thêm một máy thứ hai: build queue, chat bot, nightly backup hoặc webhook receiver đều cần một máy tính luôn bật.
systemd có hoạt động trong WSL không?
Có. Hỗ trợ được thêm vào WSL 0.67.6 và bị tắt mặc định trên các bản cài đặt cũ hơn. Nếu chưa bật, systemctl status ssh sẽ in:
System has not been booted with systemd as init system (PID 1). Can't operate.Trước tiên hãy đọc file cấu hình vì có thể file này đã tồn tại. Nếu file không có section [boot], hãy thêm một section; nếu đã có, hãy thêm dòng duy nhất đó vào section hiện có.
cat /etc/wsl.conf
sudo tee -a /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOFChạy wsl --shutdown trong PowerShell, mở một shell Ubuntu mới, rồi kiểm tra bằng systemctl list-units --type=service --state=running. Nếu thấy danh sách unit, systemd đang là PID 1 và journalctl -b sẽ hoạt động từ thời điểm đó.
Điểm cần lưu ý là ý nghĩa của điều enable hứa hẹn trên từng máy. Trên VPS, sudo systemctl enable --now caddy nghĩa là service khởi động khi boot, nên service sẽ chạy lại sau khi reboot hoặc nâng cấp kernel mà không cần có người đăng nhập. Trong WSL, điều đó nghĩa là service khởi động khi distribution khởi động, còn distribution chỉ khởi động khi bạn mở terminal. Vì vậy, service chỉ chạy trong lúc bạn đang làm việc, trái với lý do service tồn tại. Container cũng có cùng hạn chế, nên để service Docker Compose khởi động khi boot phụ thuộc vào một lần boot mà WSL chỉ thực hiện khi bạn yêu cầu.
Webhook có thể truy cập server đang chạy trong WSL không?
Không nếu không có cấu hình bổ sung, vì nguyên nhân nằm ở cách bố trí mạng. Ở chế độ mặc định, WSL 2 đặt máy ảo phía sau NAT (network address translation) trên một virtual adapter riêng. Hãy xem địa chỉ này:
ip -4 addr show eth0
ip route show defaultĐịa chỉ đó là địa chỉ private và được cấp lại mỗi lần máy ảo khởi động, nên sẽ thay đổi. Bản thân Windows vẫn có thể truy cập localhost:3000 vì WSL chuyển tiếp các kết nối localhost vào distribution. Một máy khác trong mạng của bạn thì không thể, trừ khi bạn thêm proxy rule từ Administrator PowerShell:
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.24.108.3Rule đó chỉ định một địa chỉ, nên sẽ hỏng vào lần tiếp theo địa chỉ thay đổi. Mirrored networking là lựa chọn tốt hơn: distribution nhận cùng các interface và địa chỉ với Windows. Tính đến tháng 8 năm 2026, tính năng này cần Windows 11 22H2 hoặc mới hơn. Đặt nội dung sau vào %UserProfile%\.wslconfig rồi chạy wsl --shutdown:
[wsl2]
networkingMode=mirroredMirrored mode giải quyết vấn đề mạng nội bộ. Nó không cấp cho bạn một địa chỉ public. Router của bạn lại chạy NAT, hầu hết các kết nối gia đình không có inbound port mà bạn kiểm soát được, và nhiều ISP còn thêm một lớp NAT khác bên trên. Vì vậy GitHub không thể POST event đến laptop của bạn, đồng nghiệp cũng không thể mở demo link của bạn. Tunnel service có thể xử lý vấn đề này, nhưng tunnel client chạy trên laptop, nghĩa là laptop vẫn phải là máy được duy trì hoạt động.
VPS giải quyết vấn đề này từ phía ngược lại. VPS có địa chỉ IPv4 public và thường có cả địa chỉ IPv6 public, chỉ mở những port bạn cho phép. Trỏ một A record đến đó, cho phép port 80 và 443, rồi server sẽ phản hồi từ mọi nơi. Đây cũng là điều kiện để cấp public certificate, vì HTTP-01 challenge yêu cầu Let's Encrypt tải một file qua port 80 trên public name. Cấp chứng chỉ Let's Encrypt bằng Certbot và nginx chỉ mất 5 phút trên server nhưng không thể thực hiện trong WSL. Để làm việc local, bạn vẫn có thể dùng HTTPS được browser tin cậy trong WSL bằng cách thêm CA của riêng bạn vào trust store của Ubuntu.
Vì sao git chạy chậm trên /mnt/c?
Vì các file không nằm trên filesystem Linux. WSL cung cấp 2 vùng lưu trữ có chi phí truy cập rất khác nhau. Thư mục home nằm trên filesystem ext4 bên trong một virtual disk và hoạt động như một disk Linux thông thường. /mnt/c là drive Windows, được một component ở phía Windows cung cấp qua giao thức 9P (Plan 9 filesystem protocol), nên mỗi thao tác open và mỗi lần stat đều phải đi qua ranh giới đó.
Một file thì không vấn đề gì. git status trên một repository lớn thực hiện hàng nghìn lần gọi stat, và mỗi lần gọi đều phải trả chi phí vượt qua ranh giới. Hãy tự đo thay vì tin vào một con số của bất kỳ ai, kể cả số liệu trên trang này:
cd /mnt/c/Users/you/code/myrepo && time git status
cp -r /mnt/c/Users/you/code/myrepo ~/myrepo
cd ~/myrepo && time git statusChạy mỗi lệnh 2 lần và so sánh lần chạy thứ 2 để cả 2 lần đều dùng dữ liệu đã nằm trong cache. Windows real-time antivirus scanning làm tăng thêm chi phí ở phía /mnt/c. Vì vậy, cùng một repository có thể chạy chậm hơn trên laptop của công ty so với laptop cá nhân.
Cách khắc phục trong WSL là giữ working copy bên dưới ~ và mở nó bằng WSL remote mode của editor. Chế độ này chạy editor server bên trong distribution thay vì truy cập xuyên qua ranh giới. Explorer vẫn có thể duyệt các file đó tại \\wsl.localhost\Ubuntu\home\you. VPS không gặp vấn đề này vì chỉ có một filesystem và đó là Linux. Chi phí bạn phải trả ở đó là network latency khi chỉnh sửa, nên nhiều người làm việc trong terminal multiplexer hoặc remote editor session. Điểm cần lưu ý trên server nhỏ là CPU dùng chung. steal time từ một máy hàng xóm gây nhiễu xuất hiện trong top dưới dạng cột st.
WSL vượt trội ở những điểm này
- Miễn phí và đã có sẵn trên máy. Bạn chỉ cần bật tính năng này, cài Ubuntu là có thể làm việc trong một phút, không phải trả phí và không có bề mặt public cần bảo vệ.
- Có thể xóa và tạo lại dễ dàng hơn server.
wsl --export Ubuntu D:\wsl-backups\ubuntu.targhi toàn bộ distribution vào một file, cònwsl --importkhôi phục hoặc clone distribution đó với tên khác. Thử một bản Ubuntu mới trên WSL chỉ là việc clone và rollback, trong khi nâng cấp VPS từ 24.04 lên 26.04 là thay đổi một chiều mà bạn phải lên lịch dựa trên các service đang chạy trên đó. - Làm việc với GPU trực tiếp. Với Windows GPU driver hiện tại, card có thể được sử dụng bên trong distribution, nên workload CUDA và ROCm chạy trên phần cứng bạn đã sở hữu. Thuê GPU cùng phân khúc theo giờ sẽ tốn chi phí thực tế.
- Vòng lặp chỉnh sửa ngắn hơn. File và browser đều ở local, nên dev server trên
localhost:5173mở ngay trong browser mà bạn đã đăng nhập.
Đó là những lợi thế thực tế. Vì vậy, câu trả lời thông thường là dùng cả hai máy thay vì chỉ dùng một máy.
Ai sở hữu các bản backup?
Bạn chịu trách nhiệm trên cả hai máy, và WSL là nơi nhiều người thường bất ngờ. Bản distribution là một file đĩa ảo (ext4.vhdx) nằm trong profile người dùng Windows của bạn. Không có provider nào tự snapshot file này cho bạn. wsl --unregister Ubuntu sẽ xóa file mà không có cách hoàn tác, còn việc cài lại Windows sẽ xóa nó cùng mọi dữ liệu khác. Hãy export theo lịch mà bạn thực sự có thể duy trì:
wsl --export Ubuntu D:\wsl-backups\ubuntu-2026-08-18.tarTrên VPS, snapshot của provider bảo vệ bạn khi host bị hỏng. Nó không bảo vệ bạn nếu rm -rf nằm trong sai thư mục, và một snapshot được lưu trong cùng account với server có thể biến mất cùng server chỉ vì một lần đăng nhập bị đánh cắp. Hãy đẩy các bản backup ở cấp file ra khỏi máy và thử restore một bản trước khi thực sự cần đến. Trong cả hai trường hợp, bạn là người chịu trách nhiệm. Điểm khác biệt thực tế là server có thể tự đẩy bản backup vào lúc 03:00 mà không cần ai để laptop mở.
Cầu nối: SSH từ WSL đến VPS
Một máy thứ hai chỉ trở thành việc phiền phức nếu kết nối chưa được thiết lập đúng cách. Bạn chỉ cần làm việc này một lần trong WSL.
Tạo key trong distribution thay vì ở phía Windows, để private key nằm trên filesystem ext4 với quyền Unix mà ssh chấp nhận:
ssh-keygen -t ed25519 -C "dev@laptop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.10Key Ed25519 ngắn và nhanh. ssh-copy-id thêm public key vào ~/.ssh/authorized_keys trên server với mode phù hợp. Kiến thức cơ bản về quản lý SSH key trình bày cách xoay vòng và thu hồi chúng sau này.
Đặt tên cho server trong ~/.ssh/config:
Host dev
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ForwardAgent yes
ServerAliveInterval 30Bây giờ ssh dev sẽ kết nối. IdentitiesOnly yes ngăn client đưa ra mọi key mà nó đang giữ. Đây là nguyên nhân tạo ra Too many authentication failures khi agent đã nạp nhiều key. ServerAliveInterval 30 giữ cho session trên kết nối gia đình không bị ngắt mà không có thông báo.
ForwardAgent yes là dòng lệnh giúp quy trình này dễ sử dụng. Khi key đã được nạp vào agent trên laptop, git clone git@github.com:you/app.git có thể hoạt động trên server mà private key không bao giờ phải được đưa lên đó. Kiểm tra bằng ssh -T git@github.com từ VPS. Lệnh này phải trả về Hi you! You've successfully authenticated. Chỉ forward agent đến những server bạn tin cậy, vì root trên máy đó có thể sử dụng agent socket của bạn trong khi bạn đang kết nối. Trên server dùng chung với người khác, deploy key riêng cho từng repository là lựa chọn an toàn hơn.
WSL không giữ agent chạy giữa các shell, vì vậy mỗi terminal mới lại yêu cầu key. keychain giải quyết vấn đề này:
sudo apt update && sudo apt install -y keychain
echo 'eval "$(keychain --eval --quiet id_ed25519)"' >> ~/.bashrcMở shell mới và chạy ssh-add -l. Lệnh này phải in fingerprint của key. Error connecting to agent có nghĩa là dòng lệnh chưa được đọc, vì vậy hãy kiểm tra shell của bạn có thực sự source ~/.bashrc hay không.
Chạy công việc trên server bên trong một terminal multiplexer, để kết nối bị ngắt không làm công việc dừng lại:
tmux new -s dev
# Ctrl-b then d to detach
tmux attach -t devBuild vẫn tiếp tục khi bạn đóng laptop. Đây là toàn bộ lý do cần máy thứ hai. Cách làm tương tự được dùng để chạy Claude Code trên VPS trong tmux và tiếp tục session từ một thiết bị khác.
Hãy harden máy trước khi đưa bất kỳ thứ gì lên đó. 10 phút đầu tiên trên một VPS mới hướng dẫn tạo user không phải root, SSH chỉ dùng key, cấu hình firewall và bật automatic security updates theo thứ tự để không tự khóa quyền truy cập.
Dùng máy nào cho công việc nào?
Dùng WSL khi công việc diễn ra trên màn hình của bạn. Chỉnh sửa code, chạy test suite, chạy dev server trên localhost, notebook, thử nghiệm GPU và mọi thứ bạn khởi động rồi trực tiếp theo dõi.
Dùng VPS khi công việc cần có thể truy cập được hoặc phải tiếp tục chạy sau khi bạn kết thúc session. Ví dụ: staging URL để client mở, webhook endpoint, cron job dùng clock thực, bot, database nhỏ để service khác kết nối đến, hoặc một tác vụ import bạn khởi động vào chiều thứ Sáu.
Nếu bạn vẫn chưa quyết định máy thứ hai dùng để làm gì, những thứ mọi người thực sự chạy trên VPS là danh sách hữu ích hơn so với bảng so sánh specification, còn VPS là gì giải thích phần virtualisation bên dưới. Nếu tooling của bạn chỉ chạy trên Windows, đó là một quyết định riêng; Linux so với Windows Server là trang dành cho trường hợp này.
Một thói quen giúp hai máy không trở thành hai máy được cấu hình dở dang: code nằm trong git, và cả hai máy đều là client của repository. Không có dữ liệu quan trọng nào chỉ tồn tại trên một máy.
FAQ
Tôi có thể host website với domain thực từ WSL không?
Không đáng tin cậy. WSL 2 nằm sau NAT trên máy của bạn, router lại thực hiện NAT một lần nữa, và hầu hết kết nối Internet gia đình không cung cấp cổng inbound để forward. Dịch vụ tunnel có thể expose một cổng local, nhưng tunnel client chạy trên laptop, nên website sẽ ngừng hoạt động bất cứ khi nào laptop chuyển sang chế độ sleep. Certificate còn làm việc này khó hơn, vì challenge HTTP-01 yêu cầu Let's Encrypt tải một file qua cổng 80 trên public name. VPS có public IP address và A record đáp ứng cả hai điều kiện mà không cần workaround.
systemctl enable có hoạt động trong WSL không?
Có, sau khi bật systemd. Việc này nghĩa là systemd=true trong [boot] tại /etc/wsl.conf, sau đó chạy wsl --shutdown. Nếu chưa bật, systemctl trả về System has not been booted with systemd as init system (PID 1). Can't operate. Ngay cả khi systemd đang chạy, enable chỉ khởi động service khi distribution khởi động, mà distribution lại khởi động khi bạn mở shell. Trên server, cùng lệnh đó có nghĩa là service sẽ chạy lại sau reboot mà không cần người dùng đăng nhập.
Tại sao địa chỉ IP WSL của tôi liên tục thay đổi?
Trong chế độ NAT mặc định, virtual machine nhận một private address mới từ WSL virtual adapter mỗi lần khởi động. Mọi rule netsh interface portproxy hoặc địa chỉ hard-code đều ngừng hoạt động sau wsl --shutdown. Kiểm tra địa chỉ hiện tại bằng ip -4 addr show eth0. Mirrored networking mode trên Windows 11 loại bỏ địa chỉ riêng bằng cách cung cấp cho distribution cùng các interface với Windows: đặt networkingMode=mirrored trong [wsl2] tại %UserProfile%\.wslconfig.
/mnt/c có thực sự chậm hơn không, hay chỉ là một hiểu lầm?
Nó chậm hơn, và một phút test sẽ chứng minh điều đó trên chính máy của bạn. Các file trong ~ nằm trên virtual disk ext4. Các file trong /mnt/c được một component phía Windows cung cấp qua giao thức 9P, nên mỗi lần gọi stat đều phải đi qua boundary, còn git status trên một tree lớn sẽ tạo ra hàng nghìn lần gọi như vậy. Copy repository vào ~, chạy time git status hai lần tại mỗi vị trí, rồi so sánh các lần chạy warm. Giữ các bản working copy trong ~ và dùng WSL remote mode của editor.
Tôi còn cần WSL sau khi có VPS không?
Hầu hết mọi người dùng cả hai. WSL miễn phí và khởi động ngay, nên đây vẫn là nơi bạn edit và test; các tác vụ GPU cũng nên chạy ở đó. Server là máy luôn hoạt động: nó giữ public name và chạy các job phải tiếp tục sau khi laptop đóng. Lưu code trong git và coi cả hai máy là client của repository; việc chuyển công việc giữa chúng sẽ không tốn thêm gì.