Настройка підписи Android-додатків (Keystore, Signing Config)
Втрата keystore-файлу—необоротна. Якщо приватний ключ втрачений, оновлення існуючого додатку в Google Play неможливо. Потрібно публікувати новий додаток з новим package name, втрачаючи всі відзиви, історію загрузок та позиції. Це не перебільшення—саме так закінчуються історії з keystore «який лежав тільки на ноутбуку розробника».
Створення та зберігання keystore
Генерація через keytool:
keytool -genkeypair -v \
-keystore release.keystore \
-alias myapp \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storetype JKS
-validity 10000—приблизно 27 років. Google рекомендує мінімум 25 років для додатків в Play Store. Більш короткий період—та Google Play в майбутньому відкаже приймати оновлення.
Keystore не можна зберігати в git-репозиторії. Ніколи. Навіть у приватному. Правила зберігання: зашифрований бекап у хмарному сховищі (мінімум двох), фізична копія поза офісом, паролі—окремо від файлу.
Конфігурація Signing Config у Gradle
Прямий вказ шляху та паролів у build.gradle—антипаттерн:
// ТАК НЕ РОБИТИ—паролі в репозиторії
signingConfigs {
release {
storeFile file("../keys/release.keystore")
storePassword "mysecretpassword" // потрапить в git
keyAlias "myapp"
keyPassword "mysecretpassword"
}
}
Правильний підхід—через змінні оточення або local.properties:
// build.gradle (app)
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('keystore.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias'] ?: System.getenv('KEY_ALIAS')
keyPassword keystoreProperties['keyPassword'] ?: System.getenv('KEY_PASSWORD')
storeFile keystoreProperties['storeFile'] ?
file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword'] ?: System.getenv('STORE_PASSWORD')
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
keystore.properties—в .gitignore. На CI передаємо змінні оточення прямо.
Kotlin DSL варіант
// build.gradle.kts
val keystoreProperties = Properties()
val keystoreFile = rootProject.file("keystore.properties")
if (keystoreFile.exists()) {
keystoreProperties.load(keystoreFile.inputStream())
}
android {
signingConfigs {
create("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
?: System.getenv("KEY_ALIAS")
keyPassword = keystoreProperties.getProperty("keyPassword")
?: System.getenv("KEY_PASSWORD")
storeFile = keystoreProperties.getProperty("storeFile")?.let { file(it) }
storePassword = keystoreProperties.getProperty("storePassword")
?: System.getenv("STORE_PASSWORD")
}
}
}
Play App Signing
Google пропонує Play App Signing—ваш upload key підписує APK/AAB при загрузці, Google перепаковує з окремим app signing key. Це страховка: якщо upload key втрачений, Google може його ротувати. При цьому fingerprint сертифіката для SHA-256 (потрібен для Firebase, OAuth, deeplinks) беруться з app signing key, не з upload key—путають регулярно.
Включити Play App Signing: Play Console → Release → Setup → App signing. Після включення не можна відключити.
# Перевірити fingerprint поточного keystore
keytool -list -v -keystore release.keystore -alias myapp
# В Play Console: Setup → App signing → App signing key certificate—порівняти SHA-256
CI/CD інтеграція
На GitHub Actions:
- name: Sign APK
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > release.keystore
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=$(pwd)/release.keystore \
-Pandroid.injected.signing.store.password=$STORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
-Pandroid.injected.signing.key.password=$KEY_PASSWORD
Keystore кодуємо в base64 (base64 release.keystore) та зберігаємо в секретах репозиторія. На агенті декодуємо в файл, використовуємо, видаляємо.
Робочий процес
Генерація production keystore з коректним сроком дії, безпечне зберігання.
Настройка Signing Config у Gradle через змінні оточення, без паролів в коді.
Опціонально: підключення Play App Signing, отримання нового fingerprint для Firebase/OAuth.
Конфігурація CI/CD pipeline з секретами, тестова сборка release APK/AAB.
Часова шкала
Настройка Signing Config та CI/CD для одного флейвора—2–4 години. При кількох flavor-конфігураціях та інтеграції з Play App Signing—1 день.







