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.
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
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
DEFAULT_USER=$(getent passwd 1000 | cut -d: -f 1)
userdel -r "$DEFAULT_USER"
groupdel "$DEFAULT_USER" 2>/dev/null
YOUR_USER with your desired username):
useradd -m -u 1000 -s /bin/bash YOUR_USER
usermod -aG sudo YOUR_USER
passwd YOUR_USER
apt install -y openssh-server
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
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
ufw default allow outgoing
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
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
maxretry = 5
# Use UFW as the banning action
banaction = ufw
# Whitelist to prevent accidental lockouts:
# 1. YOUR_TAILSCALE_IP: Your private tunnel address (e.g. 100.74.132.81)
# 2. 172.28.0.0/16: The internal Droidspaces NAT bridge (covers all containers)
# 3. YOUR_LAN_SUBNET: Your local Wi-Fi range if using port forwarding (e.g. if your LAN IP is 192.168.1.15, use 192.168.1.0/24)
ignoreip = YOUR_TAILSCALE_IP 172.28.0.0/16 YOUR_LAN_SUBNET
[sshd]
enabled = true
port = ssh
backend = systemd
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.
Running Droidspaces in host networking mode will cause Docker to fail when attempting to create the docker0 interface. Always choose NAT mode for your container.
You can easily change to the NAT mode by editing the container configuration using the Android app.
Docker relies heavily on iptables for its networking stack. Modern distributions often default to the nftables backend, which can cause "chain not found" errors in containers. Switch to the legacy backend before installing Docker:
update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
Use the official Docker installation script or the distribution's package manager:
# Using the official convenience script
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
To run Docker commands without prefixing them with sudo, add your user to the docker group:
# Replace YOUR_USER with your username
usermod -aG docker YOUR_USER
# Apply the group change without logging out
newgrp docker
Test that Docker can pull and run a nested container:
docker run --rm hello-world
If you see the "Hello from Docker!" message, you are successfully running nested containers on Android! 🐳
docker run command fails, run sudo dockerd manually in your terminal. This will output real-time logs and help you identify if there are any missing kernel modules, filesystem conflicts, or network bridge issues.If you absolutely must run Docker in host networking mode, or if your kernel is too old to support iptables-legacy and NAT networking, you can disable Docker's internal networking management as a last resort.
Run these commands to configure the daemon:
mkdir -p /etc/docker
cat < /etc/docker/daemon.json
{
"iptables": false,
"ip6tables": false,
"bridge": "none"
}
EOF
systemctl restart docker
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