1.5 KiB
Backend contract
The admin UI is a single backend/admin.html file. It sends the configured admin
Bearer token in memory/session storage and calls only /admin/api/* endpoints.
Device flow
- Operator creates a user and device in the page.
- Backend returns a one-time
enrollment_urland a stablesubscription_url. - The app makes the first request with
X-Device-Token: <random token>andUser-Agent: vpnapp/vMAJOR.MINOR/DEVICE_UUID. - Backend checks URL UUID, credential, and User-Agent UUID atomically, records the User-Agent, and returns the user's decrypted-for-transport config payload.
- Polling every few hours uses the same device token and bound User-Agent. A different installation cannot reuse the same device binding unless the token is copied; UUID and User-Agent alone never authenticate.
The device endpoint must be deployed behind TLS. The admin token is not accepted on
/d/{device_id}. Server configs and user secrets are Fernet-encrypted at rest with
VPNAPP_SECRET_KEY; only sanitized fields are shown in the admin list.
The reusable client-side request code is in app/services/subscription.py. It accepts
an injected secret store, emits the required User-Agent, performs one-time enrollment,
refreshes the device subscription asynchronously, and maps the response into the
separate VLESS/Amnezia/FreeTurn profile models. Android should connect its injected
store to Keystore-backed native storage before shipping credentials.