# redroid 13 Control Kit
This folder contains the local control entrypoint for the remote redroid 13 environment.
The goal is to keep one script and one workflow that can:
- build the image on the server
- launch one or many redroid instances
- bootstrap Magisk and Google framework settings
- check whether a running instance is actually usable
- expose a web UI for Docker management
## Architecture
The repository is split into two layers:
```mermaid
flowchart LR
A["Local workstation
Windows / Git Bash"] --> B["redroid13.sh
Paramiko over SSH"]
B --> C["Remote host
/home/eric/redroid-android13"]
C --> D["Docker / Podman"]
D --> E["redroid container"]
E --> F["Android 13 system image"]
F --> G["Google framework"]
F --> H["Magisk / root"]
B --> I["Portainer web panel"]
```
### Local side
`redroid13.sh` is the only file you usually run from this folder. It:
- asks for the SSH password once
- connects to the server with `paramiko`
- executes build, launch, bootstrap, and health-check commands remotely
- resolves the best image for the server architecture
### Remote side
The server repo, `/home/eric/redroid-android13`, contains the actual Android build and bootstrap code:
- `redroid.py` builds the image layers
- `run_redroid.py` launches the container
- `bootstrap_redroid.py` applies the post-boot hardening
- `stuff/magisk.py` packages Magisk
- `stuff/mindthegapps.py` packages Google apps/framework
## Compatibility Model
The script is designed to work with both x86_64 and arm64 hosts.
### Image selection
The script resolves the image automatically unless you override it.
- x86_64 host: `redroid/redroid:13.0.0_mindthegapps_houdini_magisk`
- arm64 host: `redroid/redroid:13.0.0_mindthegapps_magisk`
You can still override the image explicitly with `REDROID_IMAGE`.
If your arm64 build uses a different tag, set `REDROID_IMAGE_ARM64` to match it.
### Runtime bridge
`run_redroid.py` already resolves bridge mode from the image tag when `--bridge auto` is used.
- `houdini` images use native bridge translation for x86 apps on x86 hosts
- arm64 images can stay on the default bridge path
### Root handling
`bootstrap_redroid.py` now probes root using both of the common Magisk styles:
- `su root id`
- `su 0 id`
That avoids the old `su -mm -c` mismatch and keeps Magisk-compatible bootstrapping stable across the current image variants.
## What The Script Does
The shell entrypoint supports:
- building the Android 13 image
- starting one instance
- starting multiple instances
- bootstrapping a single container
- bootstrapping all running redroid containers
- listing containers
- checking a running instance
- starting Portainer
- showing runtime info
It also resolves:
- the server architecture
- the appropriate image tag
- the right ADB / Magisk bootstrap path
## Prerequisites
Local machine:
- Bash
- Python 3
- `paramiko` installed for Python 3
Remote server:
- Docker or Podman
- access to `/home/eric/redroid-android13`
- working ADB server
- a redroid-compatible Linux host
## Quick Start
Run the script from this folder:
```bash
./redroid13.sh
```
The menu is interactive and covers the common workflow:
1. build the image
2. start one instance
3. start a batch of instances
4. bootstrap an instance
5. list containers
6. check a running instance
7. start Portainer
8. stop an instance
9. bootstrap all redroid containers
10. show runtime info
11. exit
## Non-Interactive Usage
The same script also supports command-style usage:
```bash
./redroid13.sh build
./redroid13.sh start
./redroid13.sh batch
./redroid13.sh bootstrap redroid13-1
./redroid13.sh bootstrap-all
./redroid13.sh list
./redroid13.sh redroid-list
./redroid13.sh check
./redroid13.sh portainer
./redroid13.sh info
./redroid13.sh stop redroid13-1
```
## Recommended Defaults
These defaults are tuned for a stable Android 13 desktop-style setup:
- `REDROID_GPU_MODE=guest`
- `REDROID_ADB_INSECURE=1`
- `REDROID_DEVICE_PROFILE=pixel-7-pro`
- `REDROID_ROOT_TIMEOUT=60`
- `REDROID_BOOT_TIMEOUT=120`
- `REDROID_WAIT_TCP=120`
That combination prioritizes boot reliability over host-GPU speed.
## Environment Variables
You can override the behavior without editing the script.
| Variable | Purpose | Default |
| --- | --- | --- |
| `REDROID_SSH_HOST` | Remote server address | `192.168.2.179` |
| `REDROID_SSH_USER` | SSH user | `eric` |
| `REDROID_REMOTE_REPO` | Remote repo path | `/home/eric/redroid-android13` |
| `REDROID_IMAGE` | Force a specific image | auto-select by architecture |
| `REDROID_IMAGE_X86` | x86_64 image | `redroid/redroid:13.0.0_mindthegapps_houdini_magisk` |
| `REDROID_IMAGE_ARM64` | arm64 image | `redroid/redroid:13.0.0_mindthegapps_magisk` |
| `REDROID_ARCH_PROFILE` | `auto`, `x86_64`, or `arm64` | `auto` |
| `REDROID_DEVICE_PROFILE` | Device fingerprint preset | `pixel-7-pro` |
| `REDROID_GPU_MODE` | `guest`, `host`, or `auto` | `guest` |
| `REDROID_ADB_INSECURE` | Inject insecure adb boot props | `1` |
| `REDROID_BOOT_TIMEOUT` | Seconds to wait for Android boot | `120` |
| `REDROID_ROOT_TIMEOUT` | Seconds to wait for Magisk root | `60` |
| `REDROID_WAIT_TCP` | Seconds to wait for ADB TCP | `120` |
| `REDROID_DEFAULT_PORT` | First ADB port | `5570` |
| `REDROID_PORT_STEP` | Port step in batch mode | `1` |
| `REDROID_INSTANCE_PREFIX` | Instance name prefix | `redroid13` |
| `REDROID_DEFAULT_COUNT` | Batch size prompt default | `3` |
| `REDROID_PORTAINER_PORT` | Portainer port | `9000` |
| `REDROID_DATA_PREFIX` | Host data directory prefix | `/home/eric/data-redroid13` |
## Multi-Instance Layout
The script uses one host data directory per instance:
```text
/home/eric/data-redroid13-redroid13-1
/home/eric/data-redroid13-redroid13-2
/home/eric/data-redroid13-redroid13-3
```
Ports are assigned sequentially:
- `5570`
- `5571`
- `5572`
This keeps each container isolated and makes it easy to reboot or replace a single instance.
## Bootstrap Flow
The bootstrap phase does the important post-boot cleanup:
- waits for Android boot completion
- waits for Magisk root when root-only actions are required
- sets provisioning flags
- disables setup wizard if the package exists
- sets mock location for shell
- applies the selected device profile through `resetprop`
- applies proxy settings
- installs the optional extreme script when requested
That bootstrap logic is the part that keeps Google Play and Magisk behavior stable after first boot.
## Portainer
The script can start Portainer on the remote host.
Once it is running:
- open `http://:9000`
- use it to inspect containers, logs, volumes, and restart policies
## Troubleshooting
### ADB connects but shell fails
Check whether the instance actually reached a usable boot state:
```bash
./redroid13.sh check
```
If `sys.boot_completed` is not `1`, the container may still be booting or the guest may have stalled.
### Magisk root is unavailable
The bootstrap logic now retries root with the currently supported `su` syntax.
If you still do not see root:
- check the container logs on the remote host
- verify the image tag you selected
- make sure the container was started from the current repository revision
### Google Play login looks broken
That usually means one of these is still wrong:
- device fingerprint
- setup wizard state
- provisioning state
- Google Play Services package state
Use `./redroid13.sh check` to inspect all of those in one shot.
### Host GPU causes boot issues
If a container never becomes reachable over ADB, switch back to guest GPU mode:
```bash
REDROID_GPU_MODE=guest ./redroid13.sh start
```
Host GPU is faster when it works, but guest GPU is the safe default for headless servers.
## Notes
- This folder is a control layer, not the Android build itself.
- The actual server-side fixes live in the remote repository at `/home/eric/redroid-android13`.
- The goal is stability first: Magisk root, Google framework, and repeatable multi-instance startup.