diff --git a/.github/scripts/build-docs.py b/.github/scripts/build-docs.py index e2b1ec5..34ae247 100644 --- a/.github/scripts/build-docs.py +++ b/.github/scripts/build-docs.py @@ -138,72 +138,98 @@ def md_to_html(md): html.append(convert_table(rows)) continue - # Ordered lists - olm = re.match(r'^\s*\d+\.\s+(.+)$', line) - if olm: - items = [] - while i < len(lines) and re.match(r'^\s*\d+\.\s+', lines[i]): - item_text = re.sub(r'^\s*\d+\.\s+', '', lines[i]) - item_html = inline_format(item_text) - i += 1 - extra = [] - while i < len(lines): - s = lines[i].lstrip() - indent = len(lines[i]) - len(s) - if indent >= 3 and s.startswith('```'): - ch, i = consume_code(lines, i) - extra.append(ch) - elif indent >= 3 and s.startswith('> '): - extra.append(f'
{inline_format(s[2:])}') - i += 1 - elif lines[i].strip() == '': - i += 1 - continue - elif indent >= 3 and s.strip(): - extra.append(inline_format(s)) - i += 1 - else: - break - items.append(f'
{inline_format(s[2:])}') + parts.append(ch) + elif cind > base_indent and s.startswith('> '): + parts.append(f'
{inline_format(s[2:])}') i += 1 - elif lines[i].strip() == '': - i += 1 - continue - elif indent >= 3 and s.strip(): - extra.append(inline_format(s)) + elif cind > base_indent and s.strip(): + parts.append(f'
{inline_format(s)}
') i += 1 else: break - items.append(f'No changelog available.
' + + older_rows = [] + for r in releases[1:]: + tag = r.get('tag_name', '') + rd = r.get('published_at', '')[:10] + rn = r.get('name', tag) + older_rows.append( + f'| Version | Date |
|---|
No changelog available.
' - older_rows = [] - for r in releases[1:]: - tag = r['tag_name'] - rd = r.get('published_at', '')[:10] - rn = r['name'] - older_rows.append(f'| Version | Date |
|---|
To keep this list useful and reliable, please follow these rules when adding or updating entries:
zip, tar, img) or a downloadable kernel package; inexperienced users should not need to compile the kernel themselves.Baseband / Build string (Mandatory for Non-GKI devices only).Root Method used, such as Magisk, KernelSU, APatch or none.(Compile only the kernel without adding any implementation methods; you need to patch init_boot yourself to achieve root.)Status to one of: Working, Partial, or Unusable.zip, tar, img) or a downloadable kernel package; inexperienced users should not need to compile the kernel themselves.
+Baseband / Build string (Mandatory for Non-GKI devices only).
+Root Method used, such as Magisk, KernelSU, APatch or none.(Compile only the kernel without adding any implementation methods; you need to patch init_boot yourself to achieve root.)
+Status to one of: Working, Partial, or Unusable.
+© 2026 Droidspaces · GPLv3 · by ravindu644 and contributors
You can turn your Android device into a secure, accessible-from-anywhere Linux server by combining Droidspaces with Tailscale and standard Linux security tools.
apt, which is only available in Debian and Ubuntu-based distributions.--net=nat). Using host networking while running a firewall like UFW can interfere with the Android host's connectivity, or it won't even work.apt, which is only available in Debian and Ubuntu-based distributions.
+--net=nat). Using host networking while running a firewall like UFW can interfere with the Android host's connectivity, or it won't even work.
+To handle firewall rules and network debugging, you first need to install the essential networking tools and ensure compatibility with the Android kernel.
apt update && apt install -y net-tools iptables
-nftables backend by default, which often fails in Droidspaces containers on Android kernels. You must switch to the legacy iptables backend to ensure your firewall works:update-alternatives --set iptables /usr/sbin/iptables-legacy
+- Install tools:
+
apt update && apt install -y net-tools iptables
+
+
+- Switch to Legacy iptables:
+
Modern Ubuntu/Debian versions use the nftables backend by default, which often fails in Droidspaces containers on Android kernels. You must switch to the legacy iptables backend to ensure your firewall works:
+update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
-
+To maintain a secure server, creating a dedicated user with sudo privileges and disabling direct root access over SSH is best practice.
1000 to the first non-root user (like ubuntu). To use this ID for your personal user, you should first detect and completely remove any existing UID 1000:# Identify and delete the default user associated with UID 1000
+- Reclaim UID 1000: Linux distributions usually assign UID
1000 to the first non-root user (like ubuntu). To use this ID for your personal user, you should first detect and completely remove any existing UID 1000:
+# Identify and delete the default user associated with UID 1000
DEFAULT_USER=$(getent passwd 1000 | cut -d: -f 1)
userdel -r "$DEFAULT_USER"
groupdel "$DEFAULT_USER" 2>/dev/null
-
-- Create your personal user as UID 1000 (Replace
YOUR_USER with your desired username):useradd -m -u 1000 -s /bin/bash YOUR_USER
+
+
+- Create your personal user as UID 1000 (Replace
YOUR_USER with your desired username):
+useradd -m -u 1000 -s /bin/bash YOUR_USER
usermod -aG sudo YOUR_USER
passwd YOUR_USER
-
-- Install OpenSSH Server:
apt install -y openssh-server
-
-- Disable Root Login:Edit
/etc/ssh/sshd_config to prevent direct root access:sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
+
+
+- Install OpenSSH Server:
+
apt install -y openssh-server
+
+
+- Disable Root Login:
+
Edit /etc/ssh/sshd_config to prevent direct root access:
+sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart ssh
-
+Tailscale provides a secure P2P tunnel to your container, allowing you to access it from any device in your Tailnet without opening ports on your public router.
curl -fsSL https://tailscale.com/install.sh | sh
-tailscale up
-curl -fsSL https://tailscale.com/install.sh | sh
+tailscale up
+Since Droidspaces NAT mode currently only supports IPv4, we should disable IPv6 in UFW to avoid initialization errors.
sed -i 's/IPV6=yes/IPV6=no/' /etc/default/ufw
-ufw default deny incoming
+- Disable IPv6 in UFW:
+
sed -i 's/IPV6=yes/IPV6=no/' /etc/default/ufw
+
+
+- Set Default Policies:
+
ufw default deny incoming
ufw default allow outgoing
-
-- Whitelist the Tailscale Interface:Instead of whitelisting specific IP addresses, tell UFW to trust anything coming through your private Tailscale tunnel:
ufw allow in on tailscale0
-
-- Enable the Firewall:
ufw --force enable
-
+Instead of whitelisting specific IP addresses, tell UFW to trust anything coming through your private Tailscale tunnel:
+ufw allow in on tailscale0
+ufw --force enable
+Fail2Ban monitors your system logs and automatically blocks IP addresses that show malicious behavior.
apt install -y fail2ban
-/etc/fail2ban/jail.local to protect SSH and integrate it with UFW:[DEFAULT]
+- Install Fail2Ban:
+
apt install -y fail2ban
+
+
+- Create a Local Configuration:
+
Create a persistent configuration file at /etc/fail2ban/jail.local to protect SSH and integrate it with UFW:
+[DEFAULT]
# Ban for 1 hour after 5 failed attempts within 10 minutes
bantime = 1h
findtime = 10m
@@ -485,10 +558,13 @@ Step 5: Add Brute-Force
enabled = true
port = ssh
backend = systemd
-
-- Start and Verify:
systemctl restart fail2ban
+
+
+- Start and Verify:
+
systemctl restart fail2ban
fail2ban-client status sshd
-
+Your "Mobile Server" is now officially a hardened fortress! Anyone attempting to access it from the open internet will be blocked, while you maintain full access through your private Tailscale network.
Droidspaces supports running Docker natively inside your containers on all supported kernel versions. This allows you to run nested containerized services (like Portainer, Home Assistant, etc.) directly on your Android device.
f2fs filesystem does not support the overlay features required by Docker's overlay2 storage driver. Using a rootfs.img ensures you are running on a native ext4 filesystem.docker0 bridge and provide internet access to nested containers.f2fs filesystem does not support the overlay features required by Docker's overlay2 storage driver. Using a rootfs.img ensures you are running on a native ext4 filesystem.
+docker0 bridge and provide internet access to nested containers.
+daemon.json configuration disables Docker's internal bridge (docker0) and all automatic port forwarding. You will only be able to run docker containers with internet with the --network host flag.
eg: docker run -it --network host ubuntu© 2026 Droidspaces · GPLv3 · by ravindu644 and contributors
diff --git a/docs/features.html b/docs/features.html index 341e06f..47b36c4 100644 --- a/docs/features.html +++ b/docs/features.html @@ -4,15 +4,15 @@ - ---net)Droidspaces supports three networking modes that determine whether a network namespace (CLONE_NEWNET) is used:
--net=host) - Default: Droidspaces deliberately does not unshare the network namespace. The container shares the host's network stack. This greatly simplifies setup: containers get internet access immediately without virtual bridges, NAT, or firewall rules. On Android, where networking is already complex (cellular, Wi-Fi, VPN), this avoids a whole category of connectivity issues.--net=nat): The container is placed in a private network namespace. It is connected to the host via a virtual bridge or veth pair, providing Pure Network Isolation while maintaining internet access through the host's upstream interfaces. Compatible with the vast majority of Android devices.--net=none): The container is placed in a private, air-gapped network namespace with only the loopback interface enabled for maximum security.--net=host) - Default: Droidspaces deliberately does not unshare the network namespace. The container shares the host's network stack. This greatly simplifies setup: containers get internet access immediately without virtual bridges, NAT, or firewall rules. On Android, where networking is already complex (cellular, Wi-Fi, VPN), this avoids a whole category of connectivity issues.
+--net=nat): The container is placed in a private network namespace. It is connected to the host via a virtual bridge or veth pair, providing Pure Network Isolation while maintaining internet access through the host's upstream interfaces. Compatible with the vast majority of Android devices.
+--net=none): The container is placed in a private, air-gapped network namespace with only the loopback interface enabled for maximum security.
+A chroot only changes the apparent root directory for a process. It provides no process isolation, no mount isolation, no hostname isolation, and no IPC isolation. Any process inside a chroot shares the host's PID space, can see and signal other processes, and cannot run an init system like systemd.
Without an init system, you're running individual processes in a chroot. You can't manage services, you can't use systemctl, you don't have journald for logging, and you don't have proper session management. It's a glorified shell.
Droidspaces boots a real init system. When systemd starts as PID 1 inside the container:
systemctl start/stop/enablejournalctllogin, su, and sudosystemctl start/stop/enable
+journalctl
+login, su, and sudo
+Three things are required for systemd to function inside a container:
CLONE_NEWPID) followed by a fork, making the container's init the first process in its namespace.droidspaces to /run/systemd/container and sets the container=droidspaces environment variable.CLONE_NEWPID) followed by a fork, making the container's init the first process in its namespace.
+droidspaces to /run/systemd/container and sets the container=droidspaces environment variable.
+Droidspaces is theoretically compatible with any init system that can run as PID 1, including:
The init binary is strictly expected at /sbin/init. If this binary is missing or not executable, Droidspaces will fail to boot the container to ensure that services and session management function as expected.
Droidspaces uses OverlayFS, a union filesystem built into the Linux kernel:
When the container stops, the upper layer (in RAM) is discarded. The original rootfs remains untouched.
# Volatile container from a directory
@@ -490,10 +518,14 @@ The systemd 258+ Fix
NOTE This information is based on current developer understanding of systemd's behavior in Droidspaces and may require further verification.
Droidspaces handles this with a "dynamic hole-punching" technique:
-- Pinning Subsystems: All
/sys subdirectories are self-bind-mounted to preserve read-write access to individual hardware subsystems.
-- Read-Only Remount: The top-level
/sys is remounted read-only.
-- Container Identification: systemd detects the read-only
/sys, correctly identifies the container environment, and falls back to container-native console management.
-- Hardware Access: Individual hardware subsystems remain fully accessible via the pinned sub-mounts created in step 1.
+- Pinning Subsystems: All
/sys subdirectories are self-bind-mounted to preserve read-write access to individual hardware subsystems.
+
+- Read-Only Remount: The top-level
/sys is remounted read-only.
+
+- Container Identification: systemd detects the read-only
/sys, correctly identifies the container environment, and falls back to container-native console management.
+
+- Hardware Access: Individual hardware subsystems remain fully accessible via the pinned sub-mounts created in step 1.
+
Usage
droidspaces --name=gpu-test --rootfs=/path/to/rootfs --hw-access start
@@ -501,16 +533,21 @@ Usage
Automatic GPU Group Setup
When --hw-access is enabled, Droidspaces automatically:
-- Scans host GPU devices - Before
pivot_root, it probes ~40 known GPU device paths (/dev/dri/*, /dev/mali*, /dev/kgsl-3d0, /dev/nvidia*, etc.) and collects their group IDs via stat(). Dangerous nodes like /dev/dri/card* are explicitly skipped to prevent host kernel panics, as these nodes are restricted to the host's display manager.
-- Creates matching groups - After
pivot_root, it appends entries like gpu_:x::root to the container's /etc/group. The container's root user is automatically added to each group.
-- Idempotent restarts - On container restart, existing groups are detected and skipped (no duplicate entries).
+- Scans host GPU devices - Before
pivot_root, it probes ~40 known GPU device paths (/dev/dri/*, /dev/mali*, /dev/kgsl-3d0, /dev/nvidia*, etc.) and collects their group IDs via stat(). Dangerous nodes like /dev/dri/card* are explicitly skipped to prevent host kernel panics, as these nodes are restricted to the host's display manager.
+
+- Creates matching groups - After
pivot_root, it appends entries like gpu_:x::root to the container's /etc/group. The container's root user is automatically added to each group.
+
+- Idempotent restarts - On container restart, existing groups are detected and skipped (no duplicate entries).
+
This eliminates the need for manual groupadd/usermod commands inside the container, while ensuring the host's kernel stability by avoiding restricted hardware paths.
X11 Socket Mounting
For GUI application support, Droidspaces automatically bind-mounts the X11 socket directory:
-- Android (Termux X11): Detects and mounts
/data/data/com.termux/files/usr/tmp/.X11-unix
-- Desktop Linux: Mounts
/tmp/.X11-unix via /proc/1/root/tmp/.X11-unix
+- Android (Termux X11): Detects and mounts
/data/data/com.termux/files/usr/tmp/.X11-unix
+
+- Desktop Linux: Mounts
/tmp/.X11-unix via /proc/1/root/tmp/.X11-unix
+
TIP X11 support can be enabled independently using the --termux-x11 (-X) flag. This is the recommended way to use GUI applications on Android if you do not need full GPU/hardware access, as it preserves a higher level of isolation.
After starting the container, set DISPLAY=:0 inside the container to use the X11 display.
@@ -551,8 +588,10 @@ Syntax
Limits
-- Destination must be an absolute path
-- Path traversal (
..) in destinations is rejected for security
+- Destination must be an absolute path
+
+- Path traversal (
..) in destinations is rejected for security
+
Automatic Directory Creation
If the destination directory doesn't exist inside the rootfs, Droidspaces creates it automatically using mkdir -p.
@@ -594,10 +633,14 @@ Why Use Images?
How It Works
When you use --rootfs-img:
-- Filesystem check: Droidspaces runs
e2fsck -f -y on the image to ensure integrity
-- SELinux context: On Android, applies the
vold_data_file SELinux context to prevent silent I/O denials
-- Loop mount: The image is mounted at
/mnt/Droidspaces/
-- Retry logic: On kernel 4.14, mounts may fail due to stale loop device state. Droidspaces retries up to 3 times with
sync() and settle delays.
+- Filesystem check: Droidspaces runs
e2fsck -f -y on the image to ensure integrity
+
+- SELinux context: On Android, applies the
vold_data_file SELinux context to prevent silent I/O denials
+
+- Loop mount: The image is mounted at
/mnt/Droidspaces/
+
+- Retry logic: On kernel 4.14, mounts may fail due to stale loop device state. Droidspaces retries up to 3 times with
sync() and settle delays.
+
Usage
# Image-based container (--name is mandatory)
@@ -619,8 +662,10 @@ The "Jail" Trick
Cgroup v1 and v2 Support
Droidspaces supports both cgroup versions:
-- Cgroup v2 (unified): Used by modern distributions. Mounted as a single hierarchy.
-- Cgroup v1 (legacy): Used by older distributions. Droidspaces handles comounted controllers (e.g.,
cpu,cpuacct) and creates symlinks for secondary names in older kernels or --force-cgroupv1 mode.
+- Cgroup v2 (unified): Used by modern distributions. Mounted as a single hierarchy.
+
+- Cgroup v1 (legacy): Used by older distributions. Droidspaces handles comounted controllers (e.g.,
cpu,cpuacct) and creates symlinks for secondary names in older kernels or --force-cgroupv1 mode.
+
Forcing Legacy Cgroup V1 (--force-cgroupv1)
On legacy Android kernels (3.18, 4.4, or 4.9), the host system may either lack Cgroup v2 support entirely or provide a partial implementation without the essential controllers (CPU, memory, etc.) required by modern systemd. This inconsistency often causes systemd to misidentify the environment, leading to critical boot failures.
@@ -642,10 +687,73 @@ Nested Containers (Docker, Podman,
TIP Legacy Kernel Networking: When running Docker/Podman inside Droidspaces on legacy kernels, modern nftables may fail to route traffic. We recommend using Droidspaces' NAT mode and switching your container's networking stack to iptables-legacy and ip6tables-legacy.
Android-Specific Tuning
-
Droidspaces includes several sophisticated subsystems designed specifically to handle the "opinionated" nature of the Android Linux kernel.
-Safe Udev Trigger
-Standard Linux distributions use udevadm trigger to "coldplug" hardware devices during boot. On many Android devices, triggering all devices simultaneously causes the kernel to deadlock or panic because Android's own hardware drivers (which are already running) do not expect another manager to re-trigger them.
-The Solution: Droidspaces masks the standard udev trigger services and installs a Safe Udev Trigger. This service only triggers a strictly defined subset of subsystems (usb, block, input, tty) that are safe to re-scan. This enables the container to see new USB drives or keyboards without risking a system crash.
+To handle the "opinionated" nature of the Android Linux kernel and ensure container stability, network connectivity, and hardware access, several adjustments must be applied to the container's rootfs.
+NOTE The Droidspaces backend itself does not alter the rootfs. These changes are applied automatically when the user installs a new rootfs tarball using the Android App's built-in installer, or are pre-baked when using our official rootfs tarball from the Droidspaces rootfs-builder.
+1. Android Network & Hardware Groups
+Older Android kernels restrict network socket creation and direct hardware access to specific, hardcoded Group IDs (GIDs). Droidspaces maps and configures these groups inside the container's rootfs:
+
+- GID Mapping: Appends Android-specific groups to
/etc/group:
+
+aid_inet (3003): Allows internet access.
+
+aid_net_raw (3004): Allows raw socket creation (e.g., for ping).
+
+aid_net_admin (3005): Allows network administration.
+
+
+
+- Permissions Assignment: Adds the container's
root user to the aid_inet, aid_net_raw, input, video, and tty groups.
+
+- Package Manager Fix: Configures the Debian/Ubuntu
_apt user to use aid_inet as its primary group, allowing packages to be installed and updated without permission errors.
+
+- User Automation: Modifies
/etc/adduser.conf so any newly created user automatically inherits these groups.
+
+
+2. Udev Trigger & Service Overrides
+Standard Linux distributions run udevadm trigger to coldplug hardware devices during boot. Triggering all subsystems simultaneously on an Android device can cause the kernel to panic.
+
+- Hardware Access Guards: Since udev services are only useful when hardware access is explicitly enabled, Droidspaces injects a drop-in
ExecCondition override that prevents systemd-udevd.service, systemd-udev-trigger.service, and systemd-udev-settle.service from starting unless the container is configured with hardware access (enable_hw_access=1):
+[Service]
+ExecCondition=
+ExecCondition=/bin/sh -c "grep -q 'enable_hw_access=1' /run/droidspaces/container.config"
+
+
+- Safe Udev Trigger: Instead of scanning everything, Droidspaces overrides the default
systemd-udev-trigger.service using a drop-in configuration. If hardware access is enabled, this limits the trigger to a strictly defined, safe subset of subsystems:
+[Service]
+ExecStart=
+ExecStart=-/usr/bin/udevadm trigger --subsystem-match=usb --subsystem-match=block --subsystem-match=input --subsystem-match=tty --subsystem-match=net
+
+This allows the container to dynamically detect new USB drives, keyboards, and network interfaces without risking a host crash.
+
+- Read-Only Path Fix: Overrides
ConditionPathIsReadWrite for all udev units to prevent failures in environments where key system directories are mounted read-only.
+
+
+3. Optimizing systemd & Logging
+The Android kernel is notoriously verbose. Without tuning, standard journald setups would read host kernel messages and generate gigabytes of logs, quickly filling up the device's internal storage:
+
+- Journald Adjustments: Disables reading kernel messages and system auditing (
ReadKMsg=no, Audit=no) in journald.conf to prevent the container from hoarding system-wide kernel logs.
+
+- Volatile Storage: Configures systemd journal logs to store in-memory only (
Storage=volatile) and enforces strict maximum size constraints (200MB) to prevent constant writes from wearing out and filling the device's physical internal flash storage.
+
+- Service Masking: Masks
systemd-networkd-wait-online.service to prevent boot delays, and systemd-journald-audit.socket to prevent systemd deadlocks in old kernels like 4.9.
+
+- Power Key Handling: Instructs
systemd-logind to ignore host power and suspend key events so the container does not attempt to handle host power state transitions.
+
+
+4. NAT Mode Network Guards
+Under Host networking mode, running network managers like NetworkManager or systemd-networkd inside the container can conflict with the Android host's routing tables and break cellular/Wi-Fi connectivity.
+Droidspaces injects a drop-in ExecCondition override for standard network services (such as NetworkManager.service, systemd-networkd.service, dhcpcd.service, and systemd-resolved.service). This ensures these services only execute if the container is explicitly configured in NAT mode:
+[Service]
+ExecCondition=
+ExecCondition=/bin/sh -c "grep -q 'net_mode=nat' /run/droidspaces/container.config"
+
+5. Storage and DHCP Configuration
+
+- systemd-networkd Config: Automatically configures
10-eth-dhcp.network to enable DHCP and IPv6 route acceptance for any eth* interfaces.
+
+- Logrotate Limit: Enforces a
maxsize 50M limit in /etc/logrotate.conf to prevent logs from consuming excessive disk space over time.
+
+
© 2026 Droidspaces · GPLv3 · by ravindu644 and contributors
diff --git a/docs/getting-started.html b/docs/getting-started.html
deleted file mode 100644
index d24d637..0000000
--- a/docs/getting-started.html
+++ /dev/null
@@ -1,539 +0,0 @@
-
-
-
-
-
-
-
- Getting Started - Droidspaces Docs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/gpu-acceleration.html b/docs/gpu-acceleration.html
index cfb6c1a..1e3daeb 100644
--- a/docs/gpu-acceleration.html
+++ b/docs/gpu-acceleration.html
@@ -3,17 +3,17 @@
-
-
+
+
GPU Acceleration - Droidspaces Docs
-
+
-
+
@@ -64,7 +64,7 @@
.sidebar-content {
flex: 1; min-width: 0;
padding: 2rem 2rem 4rem;
- max-width: 960px;
+ max-width: none;
}
.sidebar-content h1 {
font-family: var(--mono); font-size: clamp(1.5rem, 2.5vw, 2rem);
@@ -95,12 +95,14 @@
.sidebar-content strong { color: var(--text); }
.sidebar-content a {
color: var(--accent2); text-decoration: none;
+ word-break: break-word; overflow-wrap: anywhere;
}
.sidebar-content a:hover { text-decoration: underline; }
.sidebar-content code {
font-family: var(--mono); font-size: 0.82rem;
background: var(--bg3); padding: 0.15rem 0.4rem;
border-radius: 4px; color: var(--accent2);
+ word-break: break-word; overflow-wrap: anywhere;
}
.sidebar-content pre {
background: var(--bg2); border: 1px solid var(--border);
@@ -150,13 +152,17 @@
}
.table-wrap {
overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
margin-bottom: 1.5rem;
}
.table-wrap table {
+ width: max-content;
+ min-width: 100%;
margin-bottom: 0;
}
.sidebar-content table {
- width: 100%; border-collapse: collapse; font-size: 0.85rem;
+ width: max-content; min-width: 100%;
+ border-collapse: collapse; font-size: 0.85rem;
margin-bottom: 1.5rem;
}
.sidebar-content th {
@@ -169,7 +175,8 @@
.sidebar-content td {
padding: 0.75rem 1rem; border-bottom: 1px solid var(--border);
color: var(--muted);
- word-break: break-word;
+ white-space: normal; word-break: normal;
+ overflow-wrap: break-word; max-width: 300px;
}
.sidebar-content img {
max-width: 100%; border-radius: 8px; border: 1px solid var(--border);
@@ -362,17 +369,16 @@
@@ -393,40 +398,64 @@ Droidspaces GPU Acceleration Guide
This guide provides step-by-step instructions for enabling GPU acceleration in your Droidspaces containers. Whether you are running on an Android device or a Linux desktop, Droidspaces offers multiple ways to leverage hardware acceleration for a smooth graphical experience.
Quick Navigation
-- Android Devices- 01. Termux-X11 + llvmpipe (Software Rendering)- 02. Termux-X11 + VirGL (Non-Qualcomm GPUs)- 03. Turnip (Native Qualcomm/Adreno)
-- Linux Desktop (AMD/Intel)
+- Android Devices
+
+
+- Linux Desktop (AMD/Intel)
+
Android
Hardware acceleration on Android is achieved by bridging the container's graphics stack with a host-side X server (Termux-X11). Droidspaces handles the complex mount management and security contexts required to make this seamless.
-TIP If you want to enjoy an out-of-the-box XFCE desktop environment experience, you can download our pre-configured XFCE tarballs from the official Droidspaces Rootfs Builder Releases.
+TIP If you want to enjoy an out-of-the-box XFCE desktop environment experience, you can download our pre-configured XFCE tarballs from the Rootfs repository or from the official Droidspaces Rootfs Builder Releases.
01. Termux-X11 + llvmpipe
This method uses software rendering via llvmpipe. While it doesn't provide full hardware acceleration, it is the most stable way to run GUI applications when a compatible GPU driver isn't available.
The "Unified Tmpfs Bridge"
When you enable the Termux X11 toggle in the Droidspaces app, the following sequence occurs:
-- Host-side Preparation: Droidspaces creates a
tmpfs mount on top of Termux's /data/data/com.termux/files/usr/tmp in the host's mount namespace.
-- Bypassing FBE Encryption: While a direct bind-mount of
/data/data/com.termux/files/usr/tmp to the container is possible, it frequently breaks applications like apt or any tool performing heavy I/O in /tmp. This happens because Termux's data directory is protected by Android's File-Based Encryption (FBE), leading to "Required key not available" (ENOKEY) errors. By bridging the path via tmpfs, X11 sockets and temporary files become fully readable and writable by the container.
-- Bind Mounting: This "Unified Tmpfs Bridge" is then bind-mounted to the container's
/tmp directory, enabling seamless communication between the container and the Termux-X11 app.
+- Host-side Preparation: Droidspaces creates a
tmpfs mount on top of Termux's /data/data/com.termux/files/usr/tmp in the host's mount namespace.
+
+- Bypassing FBE Encryption: While a direct bind-mount of
/data/data/com.termux/files/usr/tmp to the container is possible, it frequently breaks applications like apt or any tool performing heavy I/O in /tmp. This happens because Termux's data directory is protected by Android's File-Based Encryption (FBE), leading to "Required key not available" (ENOKEY) errors. By bridging the path via tmpfs, X11 sockets and temporary files become fully readable and writable by the container.
+
+- Bind Mounting: This "Unified Tmpfs Bridge" is then bind-mounted to the container's
/tmp directory, enabling seamless communication between the container and the Termux-X11 app.
+
Setup Requirements
-- Termux:
pkg install x11-repo && pkg install termux-x11
-- Container:
sudo apt install mesa-utils (for testing with glxgears)
+- Termux:
pkg install x11-repo && pkg install termux-x11
+
+- Container:
sudo apt install mesa-utils (for testing with glxgears)
+
Implementation Steps
-- Configure Container: In the Droidspaces app, navigate to your container's configuration.
-- Enable X11: Toggle Termux-X11 to
ON (Hardware Access is not required for software rendering).
-- Environment: Add
DISPLAY=:0 to the Environment Variables section and save.
-- Start Container: Launch your container.
-- Launch X Server: Open the Termux app and run:
termux-x11 :0
-
-- Verify: Run
glxgears inside the container terminal. The output will render in the Termux-X11 app.
-- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
dbus-launch --exit-with-session startxfce4
-
+- Configure Container: In the Droidspaces app, navigate to your container's configuration.
+
+- Enable X11: Toggle Termux-X11 to
ON (Hardware Access is not required for software rendering).
+
+- Environment: Add
DISPLAY=:0 to the Environment Variables section and save.
+
+- Start Container: Launch your container.
+
+- Launch X Server: Open the Termux app and run:
+
termux-x11 :0
+
+
+- Verify: Run
glxgears inside the container terminal. The output will render in the Termux-X11 app.
+
+- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
+
dbus-launch --exit-with-session startxfce4
+
+
@@ -434,22 +463,34 @@ 02. Termux-X11 + VirGL
This method provides GPU acceleration for non-Qualcomm devices (Mali/PowerVR) via a virglrenderer bridge. It translates OpenGL calls from the container into commands that the host Android OS can execute.
Setup Requirements
-- Termux:
pkg install x11-repo && pkg install termux-x11 virglrenderer-android
-- Container:
sudo apt install mesa-utils (for testing with glxgears)
+- Termux:
pkg install x11-repo && pkg install termux-x11 virglrenderer-android
+
+- Container:
sudo apt install mesa-utils (for testing with glxgears)
+
Implementation Steps
-- Container Configuration: Enable Termux-X11 in the Droidspaces container settings. Then, add the following to the Environment Variables section:
DISPLAY=:0
+- Container Configuration: Enable Termux-X11 in the Droidspaces container settings. Then, add the following to the Environment Variables section:
+
DISPLAY=:0
GALLIUM_DRIVER=virpipe
-
-- Start Container: Launch your container.
-- Start VirGL Server: Open Termux and run the server in the background:
virgl_test_server_android &
-
-- Start X Server: In Termux, run:
termux-x11 :0
-
-- Verify Acceleration: Run
glxinfo -B and look for "VirGL" in the renderer string.
-- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
dbus-launch --exit-with-session startxfce4
-
+
+
+- Start Container: Launch your container.
+
+- Start VirGL Server: Open Termux and run the server in the background:
+
virgl_test_server_android &
+
+
+- Start X Server: In Termux, run:
+
termux-x11 :0
+
+
+- Verify Acceleration: Run
glxinfo -B and look for "VirGL" in the renderer string.
+
+- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
+
dbus-launch --exit-with-session startxfce4
+
+
TIP If the renderer fails to initialize, try starting the VirGL server with the Vulkan backend:
virgl_test_server_android --angle-vulkan &
@@ -459,21 +500,38 @@ 03. Turnip (Native Qualcomm/Adreno)
For Qualcomm Adreno GPUs, Droidspaces supports native hardware acceleration using the Turnip driver. This bypasses the need for virgl and provides near-native performance.
Requirements
-- Custom Mesa driver: Installed following the instructions from the Mesa for Android Container repository.
-- Termux:
pkg install x11-repo && pkg install termux-x11
+- Custom Mesa driver: Installed following the instructions from the Mesa for Android Container repository.
+
+- Termux:
pkg install x11-repo && pkg install termux-x11
+
Implementation Steps
-- Install the custom Mesa driver from the Mesa for Android Container repository.
-- Enable GPU Access: In the container settings, enable GPU Access and Termux X11.
-- Set Display: Add
DISPLAY=:0 to your environment variables.
-- Launch Sequence:- Start the container via Droidspaces.- Open Termux and run
termux-x11 :0
-- Permission Management (Non-Root Users):If you are using a non-root user, you must grant them access to the GPU device nodes:
sudo usermod -aG droidspaces-gpu
-
-- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
dbus-launch --exit-with-session startxfce4
-
+- Install the custom Mesa driver from the Mesa for Android Container repository.
+
+- Enable GPU Access: In the container settings, enable GPU Access and Termux X11.
+
+- Set Display: Add
DISPLAY=:0 to your environment variables.
+
+- Launch Sequence:
+
+- Start the container via Droidspaces.
+
+- Open Termux and run
termux-x11 :0
+
+
+
+- Permission Management (Non-Root Users):
+
If you are using a non-root user, you must grant them access to the GPU device nodes:
+sudo usermod -aG droidspaces-gpu
+
+
+- Start Desktop Environment: To launch the full XFCE desktop (if installed), run:
+
dbus-launch --exit-with-session startxfce4
+
+
-TIP If you encounter any problems related to DRI3, try editing /data/adb/modules/droidspaces/etc/droidspaces.te and uncommenting the line:
+TIP If you encounter any problems related to DRI3, try editing /data/adb/modules/droidspaces/sepolicy.rule and uncommenting the line:
allow untrusted_app_27 droidspacesd fd use
@@ -481,19 +539,27 @@ Linux Desktop (AMD/Intel)
On Linux-based hosts, GPU acceleration works natively with zero additional configuration within Droidspaces.
Requirements
-- An active X11 or Wayland session on your host.
-- Functional GPU drivers (Mesa/Intel/AMD).
+- An active X11 or Wayland session on your host.
+
+- Functional GPU drivers (Mesa/Intel/AMD).
+
Implementation Steps
-- Enable Hardware Access: Ensure the Hardware Access toggle is enabled in your container configuration (or use the
--hw-access CLI flag).
-- Xhost Permission: On your host machine, allow the container to connect to your X server:
xhost +local:
-
-- Set Display Variable: Add the host's
DISPLAY number to the container's environment (usually :0):echo "DISPLAY=:0" >> /etc/environment
-
-- Run Applications: GUI applications launched from the container will render natively with full hardware acceleration.
+- Enable Hardware Access: Ensure the Hardware Access toggle is enabled in your container configuration (or use the
--hw-access CLI flag).
+
+- Xhost Permission: On your host machine, allow the container to connect to your X server:
+
xhost +local:
+
+
+- Set Display Variable: Add the host's
DISPLAY number to the container's environment (usually :0):
+echo "DISPLAY=:0" >> /etc/environment
+
+
+- Run Applications: GUI applications launched from the container will render natively with full hardware acceleration.
+
-
+
© 2026 Droidspaces · GPLv3 · by ravindu644 and contributors
diff --git a/docs/index.html b/docs/index.html
index ca610cc..89da0fc 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -4,11 +4,11 @@
Documentation - Droidspaces
-
-
-
+
+
+
- Redirecting to Getting Started...
+ Redirecting to Installation...