Skip to content

Keystores

Sia edited this page May 26, 2026 · 4 revisions

Android Keystore Management (v1.5.0+)

vibe-coder-server can generate and store Android signing keystores per package name. The UI lives under Settings → Keystores (/settings/keystores) and writes 4 files per package into the persistent volume ${VIBE_DATA_ROOT}/dev-tools/keystores/ (host) → /home/vibe/keystores/ (container).

File set per package

For an Android applicationId like com.siamakerlab.myapp, creation produces:

File Purpose
com.siamakerlab.myapp.keystore Release signing key (PKCS12, RSA 4096, validity 25 years by default)
com.siamakerlab.myapp-debug.keystore Debug signing key (same DN + password, separate file so debug-vs-release fingerprints differ)
com.siamakerlab.myapp-keystore.properties Gradle signing config: storeFile / storePassword / keyAlias / keyPassword
com.siamakerlab.myapp-admob.properties (Optional) AdMob app ID + ad-unit IDs — written only if at least one ID is provided in the form

Permissions are set to 600 (files) and 700 (directory) on creation.

Pre-fill defaults (server.yml)

Edit server.yml (or its env equivalent) once with the operator's standard distinguished-name fields:

keystore:
  defaults:
    name: "Jangwook Lee"           # CN
    organization: "Sia Makerlab"   # O
    unit: "Mobile"                 # OU
    country: "KR"                  # C (2 letters)
    state: "Chungbuk"              # ST
    city: "Jecheon"                # L
    defaultPassword: "********"    # plaintext — env override recommended
    validityYears: 25

Then every keystore form in the UI is pre-filled and only requires the package name (and optionally AdMob IDs).

The plaintext defaultPassword is convenient but exposes the key — for production-style deployments set the value via the env var VIBECODER_KEYSTORE_DEFAULT_PASSWORD (or compose secret file) and leave the YAML field blank.

Web flow

  1. Open /settings/keystores.
  2. Read the Existing keystores table to confirm what already exists.
  3. Use the Create keystore form:
    • Type the Android applicationId (must match ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$).
    • Password (pre-filled from defaults).
    • Optionally expand "AdMob IDs" if you want the -admob.properties file too.
    • Submit. The 4 files appear immediately.
  4. Back up ${VIBE_DATA_ROOT}/dev-tools/keystores/ to a separate disk or cloud storage. Losing the release .keystore makes Play Store updates to that applicationId permanently impossible.

Android build wiring

In app/build.gradle.kts:

import java.io.FileInputStream
import java.util.Properties

val keystorePropertiesFile = file("/home/vibe/keystores/com.siamakerlab.myapp-keystore.properties")
val keystoreProperties = Properties().apply {
    if (keystorePropertiesFile.exists()) {
        FileInputStream(keystorePropertiesFile).use { load(it) }
    }
}

android {
    signingConfigs {
        create("release") {
            if (keystorePropertiesFile.exists()) {
                storeFile = file(keystoreProperties["storeFile"]!!)
                storePassword = keystoreProperties["storePassword"] as String
                keyAlias = keystoreProperties["keyAlias"] as String
                keyPassword = keystoreProperties["keyPassword"] as String
            }
        }
    }
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

If your Gradle build runs outside the vibe-coder-server container, mount the keystores volume into the build container (or copy the relevant files to a path Gradle can read).

AdMob properties file

If the form's "AdMob IDs" block was filled, -admob.properties contains:

admobAppId=ca-app-pub-XXXX~YYYY
appOpenAdUnitId=ca-app-pub-XXXX/YYYY
bannerAdUnitId=ca-app-pub-XXXX/YYYY
nativeAdUnitId=ca-app-pub-XXXX/YYYY

Load it the same way as keystore.properties and apply via manifestPlaceholders["admobAppId"] + buildConfigField("String", "BANNER_AD_UNIT_ID", "\"${...}\"").

Delete

The table next to each keystore has a Delete button. It removes all four files atomically and asks for confirmation. There is no recovery — make sure the host backup is current before deleting anything signed by a release key in production.

REST API (planned — currently SSR only)

A future patch may expose GET /api/keystores + POST /api/keystores so the Android client can manage keystores from the phone. For now the admin UI is the only entry point.

Clone this wiki locally