Auf dieser Seite
Die Website, die du gerade liest, läuft nicht auf AWS, nicht auf Vercel und nicht auf einem Raspberry Pi. Sie läuft auf einem Samsung Galaxy S20+ mit kaputtem Display, das bei mir zu Hause in Wien in einer Schublade liegt. In diesem Beitrag zeige ich dir genau, wie ich ein altes Android-Handy zum Heimserver gemacht habe: ohne Root, ohne offene Ports am Router, mit einer echten Domain samt HTTPS, einer Next.js-Seite, einer PostgreSQL-Datenbank und ein paar selbst gehosteten Tools obendrauf. Ich erzähle dir auch, was nicht funktioniert hat, denn genau das hat mich mehr Abende gekostet als alles andere zusammen.

Warum ein altes Handy und kein Raspberry Pi?
Ehrlich gesagt fing es mit der Frage „Geht das überhaupt?“ an. Das Display meines S20+ war gesprungen, und die Reparatur hätte mehr gekostet, als das Handy noch wert ist. Alles andere war aber in Ordnung, und als ich mir die technischen Daten angesehen habe, kam ich mir etwas albern vor, es in der Schublade liegen zu lassen:
| Galaxy S20+ (SM-G985F) | Typisches Raspberry-Pi-4-Setup | |
|---|---|---|
| CPU | 8 Kerne, Exynos 990, 64-Bit-ARM | 4 Kerne, Cortex-A72, 64-Bit-ARM |
| RAM | 8 GB | 1–8 GB |
| Speicher | 128 GB interner Flash | microSD oder USB-SSD (extra) |
| Notstrom | Eingebauter Akku, funktioniert als USV | Braucht ein separates USV-HAT |
| Netzwerk | Wi-Fi 6 | Gigabit-Ethernet, Wi-Fi 5 |
| Kosten für mich | 0 €, hatte ich schon | Board, Gehäuse, Netzteil, Speicher |
Ein Handy bringt außerdem seine eigene unterbrechungsfreie Stromversorgung mit. Fällt der Strom mal für eine Minute aus, merkt der Server das nicht einmal. Und im Leerlauf braucht es sehr wenig Strom, denn genau darauf, Akku zu sparen, sind Handys ausgelegt.

Die Nachteile sind aber auch real, und ich komme noch darauf zurück: Android ist nicht Linux im Sinne einer Server-Distribution, es gibt kein Docker, und das System will alles, was zu lange im Hintergrund läuft, unbedingt beenden.
Die Architektur auf einen Blick
Visitor ── HTTPS ──► Cloudflare edge (TLS, WAF, rate limiting)
│
│ outbound-only tunnel, no open ports at home
▼
┌─────────────── Samsung Galaxy S20+ · Android 13 · Termux, no root ───────────────┐
│ cloudflared ──► Next.js blog :3000 (udocker, node:22) │
│ ──► solar dashboard :3001 (udocker, node:22) │
│ ──► Umami analytics :3002 (udocker) │
│ PostgreSQL 18 on 127.0.0.1 · cron backups at 03:00 · sshd :8022 (LAN, key only) │
│ Termux:Boot starts everything after a reboot │
└────────────────────────────────────────────────────────────────────────────────────┘Die Grundidee: Das Handy baut eine Verbindung nach außen zu Cloudflare auf, und Besucher kommen über genau diese Verbindung herein. Mein Router hat überhaupt keine Portweiterleitung, meine Heim-IP wird nie öffentlich, und ich brauche weder eine statische IP noch DynDNS.
Schritt 1: das Display-Problem loswerden

Mit kaputtem Touchscreen kannst du am Gerät selbst nicht viel machen, also ist das erste Ziel, es vom Computer aus zu steuern. Wenn der Touch noch teilweise funktioniert, aktiviere die Developer options („Entwickleroptionen“, dafür siebenmal auf „Build number“ bzw. „Buildnummer“ tippen) und USB debugging („USB-Debugging“). Danach spiegelt scrcpy den Bildschirm auf deinen Laptop, und du kannst Maus und Tastatur verwenden:
brew install scrcpy
brew install --cask android-platform-tools
adb devices # accept the prompt on the phone once
scrcpy # the phone's screen in a window on your computerMit Wireless debugging („Wireless-Debugging“) brauchst du danach auch kein Kabel mehr. Ab hier habe ich das Handy nie wieder angefasst; alles lief über adb und später über SSH.
Schritt 2: Termux installieren (über F-Droid, nicht Google Play)
Termux gibt dir eine echte Linux-Umgebung auf Android: eine Shell, einen Paketmanager und tausende Pakete, die für ARM kompiliert sind. Installiere es über F-Droid oder GitHub, denn die Version im Google Play Store ist veraltet und bekommt keine Paket-Updates. Installiere Termux:Boot aus derselben Quelle; das brauchst du, um nach einem Neustart alles wieder hochzufahren.

Das sind die Pakete, auf denen mein Server heute läuft:
pkg update && pkg upgrade
pkg install openssh rsync cronie termux-services postgresql cloudflared udockerSchritt 3: per SSH verbinden und nie wieder die Handytastatur benutzen
Der SSH-Server von Termux lauscht auf Port 8022, und dein Benutzername ist der Android-App-User (etwa
u0_a123, prüfen kannst du ihn mit whoami). Ich habe meinen Public Key rüberkopiert und den Passwort-Login abgeschaltet:
# on the phone
sshd
# on the Mac
ssh-copy-id -p 8022 [email protected]
ssh -p 8022 [email protected]Danach setzt du PasswordAuthentication no in $PREFIX/etc/ssh/sshd_config. SSH bleibt nur im Heimnetz erreichbar;
es ist kein Teil des Tunnels.
Schritt 4: Android daran hindern, deinen Server zu beenden
Das war die erste große Überraschung. Eine Zeit lang lief alles problemlos, dann war die Website einfach weg. Kein Fehler, keine Logzeile. Android 12 und neuer haben einen Phantom Process Killer, der Kindprozesse von Apps beendet, wenn es „zu viele“ davon gibt, und ein Webserver mit Supervisor, Tunnel und Datenbank ist genau das.
Drei Einstellungen haben das Problem für mich gelöst:
# from the computer, with adb connected (Android 12L/13)
adb shell "settings put global settings_enable_monitor_phantom_procs false"# in Termux: keep the CPU awake while Termux runs
termux-wake-lockUnd in den Android-Einstellungen: Stell Termux auf Battery → Unrestricted („Akku → Nicht eingeschränkt“), damit es nicht in den Ruhezustand geschickt wird. Ab Android 14 gibt es in den Entwickleroptionen einen Schalter namens „Disable child process restrictions“, der dasselbe macht wie der adb-Befehl.
Akku-Tipp: Ein Handy, das rund um die Uhr am Ladegerät hängt, tut dem Akku nicht gut. Schalte bei Samsung Protect battery („Akku schützen“) ein, dann hört es bei 85 % auf zu laden. Falls sich der Akku jemals aufbläht, nimm das Handy außer Betrieb.
Schritt 5: Node.js und Next.js mit udocker betreiben
Auf einem Handy ohne Root gibt es kein echtes Docker, weil Docker Kernel-Features braucht, die Android Apps nicht zur
Verfügung stellt. udocker ist der Trick: Es lädt normale Docker-Images und
führt sie mit proot aus, komplett im User Space. Meine Seite läuft also im offiziellen node:22-Image, demselben, das
ich auch überall sonst verwenden würde:
udocker pull node:22-bookworm-slim
udocker create --name=nextjs node:22-bookworm-slim
udocker run -v ~/sites/main:/app -w /app nextjs \
/bin/sh -c "PORT=3000 HOSTNAME=127.0.0.1 node server.js"Gebaut wird nicht auf dem Handy. Die Next.js-Seite nutzt output: "standalone", und ein kleines deploy.sh auf meinem
Mac baut sie mit Podman in einem linux/arm64-Container (dieselbe CPU-Architektur wie das Handy), überträgt das
Ergebnis per rsync über SSH und startet sie neu. Ein komplettes Deployment dauert ungefähr so lange wie ein Kaffee.
podman run --rm --platform linux/arm64 -v "$PWD:/src:ro" -v "$PWD/.out:/out" node:22-bookworm-slim \
sh -c "cp -r /src /build && cd /build && npm ci && npm run build && cp -r .next/standalone/. /out/"
rsync -az --delete -e "ssh -p 8022" .out/ [email protected]:sites/main/Auf dem Handy überwacht ein winziges Shell-Skript jede Seite: Es startet den Prozess, schreibt seine PID und startet ihn fünf Sekunden nach dem Beenden neu. Nichts Besonderes, aber es hat bisher gereicht.
Stolperfallen mit udocker
- Android erlaubt keine Hardlinks im App-Speicher. Images, die welche verwenden (zum Beispiel alles, was mit pnpm
installiert wurde), scheitern auf seltsame Weise. Solche Images mache ich auf meinem Mac flach, exportiere sie als
einzelnes Tarball und nutze
udocker import. - udocker überspringt jeden Pfad, der
dev/enthält, wenn es ein Layer entpackt, weil das wie ein Geräteordner aussieht. Dadurch war Umami kaputt, bis ich die betroffenennode_modules/.../dev-Ordner von Hand hineinkopiert habe. - Nicht alles funktioniert unter proot. Ich wollte OpenObserve für Logs und Traces nutzen, und es blieb beim Start einfach hängen. Stattdessen bin ich auf ein natives Jaeger-Binary umgestiegen, das problemlos läuft.
Schritt 6: PostgreSQL auf Android
Das ist der einfache Teil. PostgreSQL 18 ist ein ganz normales Termux-Paket und läuft nativ, ohne Container:
initdb $PREFIX/var/lib/postgresql
pg_ctl -D $PREFIX/var/lib/postgresql -l ~/postgres.log start
createdb mainEs lauscht nur auf 127.0.0.1. Ein Cronjob führt jede Nacht um 03:00 pg_dumpall aus und hebt Backups 14 Tage lang
auf, und jedes Deployment von meinem Mac erstellt zuerst ein frisches Backup und kopiert es vom Handy herunter. Ein
Server, der dir auf den Boden fallen kann, braucht Backups, die nicht auf ihm selbst liegen.
Schritt 7: eine echte Domain mit HTTPS, ohne Ports zu öffnen
Cloudflare Tunnel ist das, was das
Ganze für mich sicher genug macht. cloudflared läuft auf dem Handy und hält eine ausgehende Verbindung zu Cloudflare.
Besucher sprechen mit Cloudflares Edge (mit dessen TLS-Zertifikat, WAF und Rate Limiting), und Cloudflare leitet die
Anfrage durch den Tunnel an localhost auf dem Handy weiter.
cloudflared tunnel login
cloudflared tunnel create phone
cloudflared tunnel route dns phone radionbalan.comDie Konfiguration ordnet Hostnamen lokalen Ports zu. Meine wird von einem Skript aus einem Ordner pro Seite erzeugt, eine neue Subdomain hinzuzufügen ist also eine Datei und ein Befehl:
tunnel: <tunnel-id>
credentials-file: /data/data/com.termux/files/home/.cloudflared/<tunnel-id>.json
ingress:
- hostname: radionbalan.com
service: http://localhost:3000
- hostname: solar.radionbalan.com
service: http://localhost:3001
- service: http_status:404Die letzte Regel ist wichtig: Jeder Hostname, den du nicht aufgelistet hast, bekommt ein 404, statt versehentlich irgendwo zu landen.
Schritt 8: Neustarts überstehen mit Termux:Boot
Handys starten für Updates neu, und manchmal auch ohne Grund. Termux:Boot führt jedes Skript in ~/.termux/boot/ aus,
sobald Android hochgefahren ist. Meins ist kurz:
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
pg_ctl -D "$PREFIX/var/lib/postgresql" -l "$HOME/sites/postgres.log" start
crond
$HOME/bin/site start-all
sleep 20
$HOME/bin/tunnelÖffne die Termux:Boot-App nach der Installation einmal, sonst lässt Android sie nie laufen.
Was heute auf dem Handy läuft
| Dienst | Was es ist | Wie es läuft |
|---|---|---|
| radionbalan.com | Dieser Blog, Next.js 16 | udocker, node:22 |
| solar.radionbalan.com | Privates Dashboard für meinen Solar-Wechselrichter und meine Wärmepumpe, liest den Wechselrichter alle 10 s per Modbus TCP aus | udocker, node:22 |
| stats.radionbalan.com | Umami, Analytics ohne Cookies | udocker, flaches Image |
| Jaeger | OpenTelemetry-Traces, nur lokal | natives Binary |
| PostgreSQL 18 | Daten für Solar und Umami | natives Termux-Paket |
| Statusseite | Kleine Python-Seite mit Sicherheitschecks und Backups, nur lokal | natives Python |
Das Solar-Dashboard ist mein Lieblingsteil. Das Handy hängt im selben WLAN wie mein Huawei-Wechselrichter, liest die Erzeugungsdaten also direkt im Haus aus, speichert sie in PostgreSQL und zeigt sie auf einer Seite an, die ich von überall öffnen kann. Wenn dich das interessiert: Ich habe darüber geschrieben, wie ich mit überschüssigem Solarstrom und einem ESP32 heize.
Sicherheit: was ich gemacht habe und warum
Eine öffentliche Website aus dem eigenen Wohnzimmer zu betreiben klingt beängstigend, deshalb hier die Checkliste, auf die ich mich festgelegt habe:
- Keine offenen Ports am Router. Der gesamte Traffic kommt durch den Cloudflare-Tunnel.
- Unbekannte Hostnamen liefern ein 404 in der Tunnel-Konfiguration.
- Jeder Dienst lauscht auf 127.0.0.1, nie auf dem WLAN-Interface, mit Ausnahme von SSH.
- SSH funktioniert nur mit Schlüssel und ist nur im Heimnetz erreichbar.
- Admin-Tools ohne Login (Jaeger, die Statusseite) sind überhaupt nicht im Tunnel. Ich erreiche sie über eine
SSH-Portweiterleitung wie
ssh -p 8022 -N -L 16686:127.0.0.1:16686 [email protected]. - Secrets liegen in
.env-Dateien auf dem Handy und nie in Git. - Backups verlassen das Gerät bei jedem Deployment.
Ist das schnell genug?
Für eine private Website: ja, locker. Die Seiten sind statisch oder fast statisch, Cloudflare cacht die Assets, und das Handy liefert hauptsächlich HTML aus. Die schwerere Arbeit (der Build) passiert auf meinem Mac. Was man merkt, ist der Overhead von udocker, weil proot Systemaufrufe abfängt; CPU-lastige Arbeit in einem Container ist langsamer als nativ. Für einen Blog, ein kleines Dashboard und Analytics bei meinem Traffic hat das Handy reichlich Luft.
Einschränkungen, ganz ehrlich
- Es ist ein einzelnes Gerät. Wenn das Handy stirbt, ist die Seite offline, bis ich sie auf einem anderen wiederhergestellt habe. Deshalb sind die Backups und das Deploy-Skript wichtiger als jedes Tuning.
- Kein echtes Docker oder Docker Compose. udocker deckt viel ab, aber manche Images brauchen Nacharbeit und manche laufen gar nicht.
- Android-Updates können die Regeln ändern. Jede neue Version verschärft die Hintergrund-Limits ein Stück weiter.
- Die Upload-Geschwindigkeit deines Heim-Internets ist dein Bandbreiten-Limit. Für Text und ein paar Bilder reicht das, für Video nicht.
- Fernwartung braucht zusätzliche Arbeit. Im Moment deploye ich von zu Hause aus; SSH durch den Tunnel steht als Nächstes auf meiner Liste.
FAQ
Kann man ein altes Android-Handy ohne Root als Server nutzen?
Ja. Alles in diesem Beitrag läuft ohne Root: Termux für die Linux-Umgebung, udocker für Container, native Pakete für PostgreSQL und cloudflared. Mit Root wären manche Dinge einfacher, nötig ist es aber nicht.
Kann ich Docker auf Android betreiben?
Den echten Docker-Daemon auf einem normalen Handy ohne Root nicht, weil er Kernel-Features braucht, die Apps nicht nutzen dürfen. udocker führt stattdessen die meisten Docker-Images im User Space aus, mit einigen Einschränkungen (keine Hardlinks, langsamere Systemaufrufe).
Wie mache ich meinen Handy-Server aus dem Internet erreichbar?
Nutze einen Tunnel, zum Beispiel Cloudflare Tunnel. Das Handy verbindet sich nach außen, du brauchst also keine Portweiterleitung, keine statische IP und kein DynDNS, und deine Heim-IP-Adresse bleibt privat.
Schadet der Serverbetrieb dem Akku des Handys?
Wenn ein Akku ständig am Ladegerät hängt, altert er schneller. Begrenze die Ladung auf 85 % (bei Samsung heißt das Protect battery bzw. „Akku schützen“), lagere das Handy an einem kühlen Ort und prüfe es ab und zu auf Aufblähungen.
Was kann ich auf einem alten Handy hosten?
Eine statische oder Next.js-Website, eine kleine API, eine Datenbank, Analytics wie Umami, Smart-Home-Dashboards, einen Git-Mirror oder einen Dateisynchronisations-Dienst. Alles Leichtgewichtige, das keine speziellen Kernel-Features braucht.
Fazit
Ein altes Android-Handy zum Heimserver umzubauen, hat mich zwei Abende für die Grundlagen gekostet und ein paar weitere für die lästigen Details: Phantom Process Killer, die Eigenheiten von udocker und sicherzustellen, dass nach einem Neustart alles wieder hochkommt. Dafür habe ich einen leisen, stromsparenden Server mit eingebauter USV bekommen, der mich nichts gekostet hat, eine echte Domain über HTTPS ausliefert und mein Heimnetz nicht offenlegt. Wenn du ein Handy mit kaputtem Display in der Schublade hast, gib ihm ein zweites Leben. Im schlimmsten Fall lernst du viel über Linux, Android und Netzwerke. Im besten Fall liest du gerade seine Ausgabe.
