Trả lời nhanh: Build Android không cần máy có màn hình và không cần Android Studio. Trên một VPS Linux, bạn chỉ cần JDK, bộ Android SDK command line tools và Gradle là chạy được lệnh dựng ra file APK hoặc AAB. Đây là điểm khác biệt lớn so với iOS, vốn bắt buộc máy macOS. Phần tốn thời gian nhất là Gradle, và đó cũng là chỗ ổ đĩa nhanh giúp nhiều nhất.
Nhiều đội làm app Android vẫn build trên máy cá nhân của một bạn trong nhóm, và mọi thứ chỉ ổn cho tới khi bạn đó nghỉ phép hoặc máy hỏng. Chuyển việc build lên một máy chủ riêng giải quyết cả hai chuyện: ai cũng lấy được bản mới nhất, và máy cá nhân không còn phải è cổ mỗi lần đóng gói. Bài này đi trọn quy trình dựng máy build Android trên VPS Linux, từ lệnh cài đầu tiên tới lúc có file APK ký sẵn để đưa lên cửa hàng.
Chuẩn bị máy: ba thứ cần cài và một thứ dễ quên
Bắt đầu với một VPS Ubuntu sạch, tối thiểu 4GB RAM (8GB thì dễ thở, vì Gradle mặc định xin khá nhiều bộ nhớ). Cài JDK trước:
sudo apt update && sudo apt install -y openjdk-17-jdk unzip wgetjava -version # xác nhận đã có JDK 17Tiếp theo là Android SDK. Đừng tải Android Studio, chỉ cần bộ công cụ dòng lệnh:
mkdir -p ~/android/cmdline-tools && cd ~/android/cmdline-toolswget https://dl.google.com/android/repository/commandlinetools-linux-latest.zip -O tools.zipunzip tools.zip && mv cmdline-tools latestexport ANDROID_HOME=$HOME/androidexport PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-toolsĐường dẫn tệp tải về thay đổi theo thời gian, nên lấy liên kết mới nhất từ trang tải chính thức của Android thay vì chép cứng. Sau đó cài đúng các gói dự án cần và nhận giấy phép, đây chính là thứ dễ quên khiến lệnh build dừng giữa chừng với thông báo chưa chấp nhận điều khoản:
sdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0"yes | sdkmanager --licensesCuối cùng thêm hai dòng export ở trên vào ~/.bashrc để lần đăng nhập sau không phải gõ lại.
Chạy lệnh build và hiểu mình đang tạo ra file gì
Vào thư mục dự án và dùng Gradle wrapper có sẵn trong repo, không cài Gradle riêng:
./gradlew assembleRelease # tạo file APK bản release./gradlew bundleRelease # tạo file AAB để nộp lên Google PlayPhân biệt cho đúng: APK là file cài trực tiếp lên máy, dùng để gửi cho khách thử hoặc phát hành ngoài cửa hàng. AAB là định dạng Google Play yêu cầu khi nộp bản mới, cửa hàng tự cắt ra APK phù hợp cho từng dòng máy. Nếu bạn định lên Play thì bản chính thức phải là AAB.
Lần build đầu luôn lâu vì Gradle tải toàn bộ phụ thuộc, thường vài phút tới hơn chục phút tùy dự án và đường truyền. Các lần sau nhanh hơn nhiều nhờ cache. Với dự án Flutter hay React Native, lệnh gọi khác một chút nhưng bên dưới vẫn là Gradle chạy đúng những bước này, nên phần chuẩn bị máy ở trên dùng chung được.
Ký file: phần quan trọng nhất và cũng dễ sai nhất
Google Play chỉ nhận bản đã ký bằng khóa của bạn. Tạo keystore một lần và giữ cẩn thận, vì mất keystore đồng nghĩa không cập nhật được ứng dụng đang có trên cửa hàng:
keytool -genkey -v -keystore shop.jks -keyalg RSA -keysize 2048 -validity 10000 -alias shopBa quy tắc bắt buộc. Một, không commit keystore vào Git, kể cả repo riêng tư. Hai, không viết mật khẩu vào file cấu hình trong repo, hãy đọc từ biến môi trường:
// trong build.gradle, đọc mật khẩu từ biến môi trườngsigningConfigs { release { storeFile file(System.getenv("KEYSTORE_PATH")) storePassword System.getenv("KEYSTORE_PASS") keyAlias System.getenv("KEY_ALIAS") keyPassword System.getenv("KEY_PASS") }}Ba, sao lưu keystore ra ít nhất hai nơi ngoài máy chủ build, ví dụ trong trình quản lý mật khẩu tự host theo bài Vaultwarden. Đây là loại mất mát không có cách cứu.
Tự động hóa: mỗi lần đẩy code là có bản mới
Khi máy build đã chạy tay được, bước tiếp theo là để nó tự chạy. Hai đường phổ biến. Đường một, cài self hosted runner của GitHub Actions ngay trên VPS này, mỗi lần có commit vào nhánh phát hành thì runner tự build và cất file ra một thư mục hoặc đẩy lên nơi lưu trữ. Cách làm nằm ở bài runner tự host, và lý do tiết kiệm nằm ở bài CI/CD tự host.
Đường hai, viết một script build rồi gọi bằng cron hoặc gọi tay qua SSH, đủ dùng cho đội hai ba người. Dù chọn đường nào, hãy để agent AI viết giúp phần script và file cấu hình CI, vì đó là loại việc lặp khuôn mà nó làm nhanh và ít sai. Trước khi giao, đặt sẵn ràng buộc cho agent theo bài viết file luật CLAUDE.md, nhất là điều cấm đụng vào keystore. Nhớ ghi rõ trong yêu cầu là không được đưa mật khẩu keystore vào file cấu hình.
Một mẹo tiết kiệm thời gian đáng kể: bật cache Gradle dùng chung giữa các lần chạy thay vì để mỗi lần tải lại từ đầu. Chỉ riêng việc này thường cắt hơn một nửa thời gian build ở các lần sau.
Cấu hình máy nên chọn và giới hạn phải biết
Cấu hình: 4 vCPU và 8GB RAM là điểm dễ chịu cho dự án vừa. Gradle chạy song song nhiều tác vụ nên CPU nhiều nhân giúp thấy rõ, còn RAM dưới 4GB thì hay gặp lỗi hết bộ nhớ khi biên dịch. Về ổ đĩa, build Android là kiểu tải đọc ghi hàng vạn file nhỏ, giống hệt hiện tượng phân tích trong bài npm install chậm, nên ổ NVMe rút ngắn thời gian rõ rệt so với ổ thường. Dung lượng nên từ 60GB trở lên vì SDK, cache Gradle và các bản dựng tích lũy rất nhanh. Chính máy này cũng dùng được làm máy dev từ xa, khỏi phải nuôi hai máy riêng.
Giới hạn phải biết: máy Linux này không build được ứng dụng iOS. Ký và đóng gói file IPA bắt buộc chạy trên macOS, đó là ràng buộc của Apple chứ không phải chuyện cấu hình. Nếu dự án của bạn làm cả hai nền tảng, mô hình thực tế là dùng VPS Linux cho Android, cho backend và cho phần tự động hóa, còn phần iOS thì cần một máy Mac hoặc dịch vụ máy Mac đám mây. Nói rõ ranh giới này ngay từ đầu giúp bạn khỏi mua nhầm hạ tầng.
Cài JDK và công cụ dòng lệnh
sudo apt updatesudo apt install -y openjdk-17-jdk unzip wget git # Bo cong cu dong lenh cua Android SDKsudo mkdir -p /opt/android-sdk/cmdline-toolscd /tmpwget https://dl.google.com/android/repository/commandlinetools-linux-latest.zipunzip commandlinetools-linux-latest.zipsudo mv cmdline-tools /opt/android-sdk/cmdline-tools/latestPhiên bản JDK phải khớp với yêu cầu của dự án. Dự án dùng plugin Android Gradle đời mới thường cần JDK 17, dự án cũ hơn có khi vẫn ở JDK 11. Cài sai bản là nguyên nhân của những thông báo lỗi rất khó hiểu, nên hãy mở file cấu hình Gradle của dự án ra xem trước.
Sau đó khai báo biến môi trường cho mọi phiên đăng nhập:
# /etc/profile.d/android.shexport JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64export ANDROID_HOME=/opt/android-sdkexport PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-toolsCài đúng thành phần và chấp nhận giấy phép
# Xem du an yeu cau phien ban nao roi cai dung phien ban dosdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0" # Buoc bat buoc, thieu la build dung giua chungyes | sdkmanager --licensesBước chấp nhận giấy phép là chỗ vấp kinh điển. Trên máy cá nhân, Android Studio hỏi và bạn bấm đồng ý nên không để ý. Trên máy chủ không có ai bấm, nên nếu quên thì bản dựng chạy được một lúc rồi dừng với thông báo về giấy phép chưa được chấp nhận, thường vào đúng lúc bạn đang vội.
Về số phiên bản: đừng cài bừa bản mới nhất. Mở file build.gradle của dự án, xem compileSdk và buildToolsVersion rồi cài đúng những bản đó. Cài dư chỉ tốn đĩa, cài thiếu thì Gradle tự tải và làm bản dựng đầu tiên lâu bất thường.
Chạy thử và tinh chỉnh Gradle
git clone <repo> && cd <repo>chmod +x gradlew./gradlew assembleDebugLần đầu sẽ lâu vì Gradle tải toàn bộ thư viện phụ thuộc. Những lần sau nhanh hơn nhiều nhờ bộ nhớ đệm, miễn là bạn giữ nguyên thư mục ~/.gradle.
Hai tinh chỉnh đáng làm trong file gradle.properties:
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1gorg.gradle.parallel=trueorg.gradle.caching=trueCon số bộ nhớ phải nhỏ hơn RAM thật của máy, chừa lại phần cho hệ điều hành. Đặt -Xmx bằng đúng dung lượng RAM là công thức chắc chắn dẫn tới tiến trình bị giết. Trên máy 8GB, mức 4g là an toàn.
Nếu máy hay chạm trần bộ nhớ vào lúc cao điểm, thêm vài GB swap. Swap chậm hơn RAM nhiều nhưng đóng vai trò lưới an toàn, giúp bản dựng chậm lại thay vì chết hẳn.
Chuẩn bị cho CI và nhiều người dùng chung
Vài việc biến máy này thành hạ tầng dùng được lâu dài:
- Tạo người dùng riêng cho CI, không dùng tài khoản quản trị. Cấp cho nó quyền đọc SDK và quyền ghi trong thư mục làm việc, thế là đủ.
- Dọn rác định kỳ. Thư mục
buildcủa các dự án và bộ nhớ đệm Gradle phình rất nhanh. Một tác vụ định kỳ hằng tuần xóa bản dựng cũ giúp bạn khỏi cảnh đầy ổ vào ngày phát hành. - Giữ keystore ở nơi an toàn, đừng để trong repo. Đây là chìa khóa ký ứng dụng, mất là mất luôn khả năng cập nhật app trên cửa hàng.
- Cắm vào CI theo cách trong bài runner tự host, để mỗi lần đẩy code là có bản dựng mới.
Toàn bộ quy trình từ mã nguồn tới file APK cài được nằm ở bài build APK trên VPS Linux, đọc tiếp bài đó sau khi máy đã dựng xong.
Ký tệp: phần quan trọng nhất và dễ sai nhất
| Việc | Vì sao quan trọng | Hậu quả nếu sai |
|---|---|---|
| Giữ tệp khóa ký ở nơi an toàn | Mất là không cập nhật được ứng dụng đã phát hành | Phải phát hành lại dưới tên gói khác, mất toàn bộ người dùng cũ |
| Không đưa tệp khóa vào kho mã nguồn | Ai có khóa là ký được ứng dụng giả danh bạn | Rủi ro rất cao |
| Sao lưu tệp khóa ở ít nhất hai nơi | Đây là tài sản không thay thế được | Mất là không có cách khôi phục |
| Dùng khóa riêng cho bản thử và bản phát hành | Tránh nhầm lẫn khi phát hành | Ký nhầm khóa là bản cập nhật bị từ chối |
Nói thẳng: mất tệp khóa ký là sự cố không sửa được. Người dùng đã cài ứng dụng của bạn sẽ không nhận được bản cập nhật nào nữa, và bạn phải phát hành lại như một ứng dụng hoàn toàn mới. Sao lưu nó như sao lưu giấy tờ nhà.
Cấu hình máy và giới hạn cần biết
# Bo nho la thu cham tran truoc, khong phai so nhan# Toi thieu 4 GB, nen co 8 GB cho du an that # Kiem trong luc buildwatch -n2 'free -h'dmesg | tail -20 | grep -i "out of memory\|killed process" # Neu bi dung tien trinh: dat vung nho tamfallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfileecho '/swapfile none swap sw 0 0' >> /etc/fstab # Gioi han bo nho cho tien trinh buildexport GRADLE_OPTS="-Xmx3g" # Don bo nho dem dinh ky, no phinh rat nhanhdu -sh ~/.gradle ~/.android 2>/dev/nullrm -rf ~/.gradle/caches/build-cache-*| Quy mô dự án | Bộ nhớ | Ổ đĩa |
|---|---|---|
| Dự án nhỏ, ít thư viện | 4 GB | 40 GB |
| Dự án thật, nhiều thư viện | 8 GB | 80 GB |
| Dự án lớn, nhiều biến thể bản dựng | 16 GB | 160 GB |
Ba việc giảm thời gian dựng
- Giữ bộ nhớ đệm giữa các lần dựng. Đây là thay đổi cho hiệu quả lớn nhất, nhất là khi dựng trong container.
- Ổ NVMe tạo khác biệt rõ, vì dựng là thao tác đọc ghi hàng chục nghìn tệp nhỏ.
- Chỉ dựng biến thể cần thiết, đừng dựng tất cả biến thể mỗi lần.
Về máy chủ: xem VPS NVMe. Về quy trình dựng tự động, xem bài về triển khai tự động.
Câu hỏi thường gặp
VPS Linux có build được app iOS không?
Không. Việc biên dịch, ký và đóng gói IPA phụ thuộc công cụ chỉ chạy trên macOS. VPS Linux vẫn hữu ích cho phần backend, API, kho lưu bản dựng và tự động hóa những bước không cần Mac, nhưng bước tạo file cài đặt iOS thì bắt buộc có máy Mac.
Build Flutter hoặc React Native có khác gì không?
Phần chuẩn bị máy giống hệt vì bên dưới vẫn là Gradle, chỉ khác lệnh gọi và cần cài thêm bộ công cụ tương ứng của Flutter hoặc Node. Thời gian build thường lâu hơn dự án Android thuần vì có thêm bước biên dịch của framework.
Lỗi hết bộ nhớ khi chạy Gradle thì xử lý thế nào?
Tăng RAM cho máy là cách chắc nhất, hoặc giới hạn bộ nhớ cho Gradle và daemon Kotlin trong file gradle.properties. Nếu máy chỉ có 4GB, hãy giảm số tác vụ chạy song song. Trên máy nhiều dự án, tắt daemon sau mỗi lần build để giải phóng bộ nhớ.
Có cần emulator trên máy build không?
Không cần nếu bạn chỉ đóng gói. Emulator chỉ cần khi muốn chạy kiểm thử giao diện tự động, và nó nặng hơn nhiều, đòi hỗ trợ ảo hóa lồng nhau nên phải kiểm tra trước với nhà cung cấp. Phần lớn đội nhỏ chỉ build trên máy chủ rồi cài thử trên máy thật.
Có cần cài Android Studio trên máy chủ không?
Không, và không nên. Bản có giao diện chiếm hàng chục GB cùng nhiều thành phần vô dụng trên máy không màn hình. Bộ công cụ dòng lệnh làm đúng phần việc build với dung lượng nhỏ hơn nhiều lần.
Máy build Android cấu hình bao nhiêu là đủ?
4 vCPU và 8GB RAM là mức khởi đầu tốt cho dự án vừa. Dự án lớn hoặc build nhiều nhánh song song nên lên 8 vCPU và 16GB. Dung lượng đĩa nên từ 60GB vì SDK và bản dựng trung gian chiếm nhanh.
Vì sao build chạy được một lúc rồi dừng?
Hai nguyên nhân phổ biến. Một là chưa chấp nhận giấy phép SDK, chạy lệnh sdkmanager với tham số licenses là xong. Hai là hết bộ nhớ nên tiến trình bị hệ điều hành giết, khi đó hãy giảm mức Xmx của Gradle hoặc nâng RAM.
Máy này build được app Flutter và React Native không?
Được, vì cả hai đều dùng chuỗi công cụ Android bên dưới cho nhánh Android. Bạn chỉ cần cài thêm bộ công cụ của nền tảng tương ứng. Riêng nhánh iOS thì vẫn phải qua máy Mac, không có đường vòng.
