A Release Checklist for Self-Hosted Android APKs
Putting an APK on a website and adding a download button looks like a complete release. The hard questions usually arrive with the next version. Can the new package update the installed app? Can a user detect a damaged download? Is the signing key still available? Is the package ready for Android’s developer verification rollout?
Self-hosting does not eliminate release engineering. It transfers responsibilities that an app store normally helps manage—signing identity, version ordering, artifact delivery, and installation trust—into your build and website workflows.
A debug APK is not a durable release artifact
An APK produced by assembleDebug is signed with a debug certificate created by the Android SDK and is configured for debugging. It is useful on development machines, emulators, and temporary test devices. It is not an appropriate identity for a public app that must receive reliable updates for years. The debug keystore is deliberately an insecure development credential, and app stores do not accept debug signing as a production identity.
A public build should use a release variant signed with a long-lived private key:
./gradlew clean assembleRelease
Do not treat “it installs” as proof that an APK is releasable. Successful installation only confirms that the current package is structurally acceptable. It says nothing about whether the next package can update it.
Three values define update identity
Whether a new APK can update an installed app depends on at least three properties:
- The
applicationIdmatches the installed app. - The signing certificate matches the existing release or follows a valid signing-key lineage.
- The new
versionCodeis higher than the installed version.
versionName is a user-visible string. versionCode is the positive integer Android uses to order releases and prevent downgrades. Record both, but never rely on a filename or versionName for the platform’s update decision:
android {
defaultConfig {
applicationId = "com.example.puzzle"
versionCode = 12
versionName = "1.3.0"
}
}
Replacing the signing certificate without a valid rotation plan normally prevents the new APK from updating the existing app. A user must uninstall the old version first, which may also delete local data. The signing-key recovery plan is therefore as important as source-code backup.
Keep signing secrets out of the repository
Never commit a release keystore, alias, or password to Git. A CI system can inject an encrypted secret into a temporary file and environment variables, then remove the material after the build. Keep at least one encrypted offline backup of the key and document the recovery procedure instead of depending on a single developer workstation.
If the same app is distributed through both Google Play and a website, decide how the signing identity will work across channels before configuring Play App Signing. Android’s documentation notes that developers who need the same signing key across stores should provide their own app signing key during setup instead of accepting a platform-generated key that cannot be exported.
Verify the APK rather than trusting its filename
The Android SDK Build Tools include apksigner, which can verify that the APK signature is expected to work across the supported Android versions and print the signing certificate:
apksigner verify \
--verbose \
--print-certs \
app-release.apk
CI should store the expected SHA-256 certificate fingerprint and compare it after every build. This catches a build machine using the wrong keystore. Modifying an APK after signing invalidates the signature; when zipalign is a separate step, alignment must happen before signing.
Inspect the artifact’s actual package name, versionCode, versionName, minimum SDK, and debuggable flag as well. Reading only the Gradle source is insufficient because build variants, flavors, or stale configuration can make the resulting APK differ from the intended release.
A SHA-256 digest identifies the file, not the developer
Publishing an APK’s SHA-256 digest is useful. A person or deployment check can detect a truncated download and confirm that the server contains the exact artifact approved for release:
shasum -a 256 app-release.apk
However, an attacker who can replace both the APK and the digest shown on the page can still make the comparison pass. The digest supports file-integrity checking, the APK signature carries update identity, and HTTPS protects transport. None replaces the other. A practical release record includes file size, APK SHA-256, signing-certificate SHA-256 fingerprint, version values, and release date.
Download URLs need stability and traceability
Overwriting app.apk is convenient but makes caches, rollback, and incident analysis harder. Preserve an immutable, versioned artifact instead:
/downloads/puzzle-1.3.0-12.apk
The page’s “latest version” button can point to the new file while older URLs remain available for a defined retention period. The server should return the correct content length and the APK media type, application/vnd.android.package-archive. An HTML error page must not masquerade as an APK with 200 OK.
After deployment, request the public URL and verify its status, size, and SHA-256. Checking that the file exists in a repository is not an end-to-end delivery test.
The download page is part of the product
A website visitor does not receive all the context an app store normally provides. Show the app name, platform requirements, version, release date, changelog, file size, and digest. Link to technical support and the privacy policy. Explain the system flow for installing from another source without encouraging users to disable device security protections.
Test both a clean installation and an update from the currently public release. The update test must use a real previous APK while retaining its data. That is how a release catches certificate changes, version mistakes, database migration failures, and backup restoration problems.
Developer verification belongs on the 2026 checklist
As of September 18, 2026, Android developer verification is available. The first enforcement phase starts September 30 on certified devices in Brazil, Indonesia, Singapore, and Thailand for participating app stores. Android currently plans to expand the protections globally across certified devices beginning in 2027.
The official FAQ says that direct website sideloading is not covered by the September 2026 initial phase, but it recommends preparing for verification before the global rollout. Developers distributing only outside Google Play use Android Developer Console. Developers that also use Play can manage relevant package names in Play Console. Proving ownership of an existing package may require the current private signing key, which is another reason the key must remain recoverable.
Turn release into a repeatable pipeline
A reliable self-hosted release can follow one fixed sequence:
- Increment and check
versionCodeandversionName. - Build the release APK from a clean commit.
- Sign with the protected long-lived key.
- Run
apksigner verify --print-certsand compare the certificate. - Inspect package ID, versions, SDK levels, permissions, and debuggable state.
- Run automated tests plus clean-install and upgrade tests on a real device.
- Generate the digest, file size, and release record.
- Upload an immutable versioned APK and update the download page.
- Download the public artifact and compare its digest again.
- Retain the last known-good artifact and a documented rollback path.
The freedom of self-hosting comes from controlling the entire delivery chain, not from omitting release steps. Once signing identity, monotonic versions, artifact integrity, and download-page metadata are automated checks, a website download becomes a sustainable and auditable release channel instead of a one-time file share.