{"id":914,"date":"2026-08-29T06:04:29","date_gmt":"2026-08-29T06:04:29","guid":{"rendered":"https:\/\/thethriftydev.com\/blog\/?p=914"},"modified":"2026-08-29T07:02:56","modified_gmt":"2026-08-29T07:02:56","slug":"hermes-ai-gateway-android-phone","status":"publish","type":"post","link":"https:\/\/thethriftydev.com\/blog\/hermes-ai-gateway-android-phone\/","title":{"rendered":"Run a Hermes AI Gateway on an $80 Android Phone (Termux)"},"content":{"rendered":"<h2>Why would you run an AI agent on a phone instead of a VPS?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-why.jpg\" alt=\"Split diagram: agent layer (outbound work) runs on the phone, public ingress stays on the VPS\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Split diagram: agent layer (outbound work) runs on the phone, public ingress stays on the VPS.<\/figcaption><\/figure>\n<p>An $80 used phone, zero dollars a month, and one afternoon of reps. That is the whole bill for a 24\/7 self-hosted AI agent that remembers you, runs scheduled jobs, browses, writes code, and answers you on Telegram. No rented compute for the brain of the operation. The VPS I still keep around has been demoted to what it is actually good at: public ingress for websites.<\/p>\n<p>Here is the thing about the agent layer specifically: it does not need inbound ports, a static IP, or a datacenter. A personal AI gateway is an <em>outbound<\/em> workload. It polls Telegram, calls model APIs, runs your crons. All dial-out. A phone behind carrier-grade NAT does dial-out just fine. What a phone has that a $6 VPS does not: a built-in battery (your UPS is free), 3 watts of power draw, and physical possession. Your agent&#8217;s memory, keys, and soul live in a drawer you own, not on someone else&#8217;s metal.<\/p>\n<p>Not a flex, just real reps: everything below is the exact playbook from building this yesterday on a Moto G 2025. Same commands, same errors, same fixes.<\/p>\n<h2>What do you need to pull this off?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-parts.jpg\" alt=\"Bill of materials for the $80 phone AI gateway build\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Bill of materials for the $80 phone AI gateway build.<\/figcaption><\/figure>\n<ul>\n<li><strong>A spare Android phone.<\/strong> I used a <a href=\"https:\/\/www.motorola.com\/us\/smartphones-moto-g-5g\/p\" rel=\"nofollow noopener\" target=\"_blank\">Moto G 2025<\/a>, $80 used, Android 16, 4 GB of RAM. Ignore the box if it says 8 GB. That is &#8220;RAM Boost,&#8221; which is swap, and <code>\/proc\/meminfo<\/code> will tell you the truth: 3.56 GB usable. It is enough, but you will learn to respect it.<\/li>\n<li><strong>Termux<\/strong> (F-Droid build), plus <a href=\"https:\/\/wiki.termux.com\/wiki\/Termux:Boot\" rel=\"nofollow noopener\" target=\"_blank\">Termux:Boot<\/a>.<\/li>\n<li><strong>Hermes Agent<\/strong>, the <a href=\"https:\/\/github.com\/NousResearch\/hermes-agent\" rel=\"nofollow noopener\" target=\"_blank\">open-source agent harness from Nous Research<\/a>. Free, MIT-ish, runs a gateway that connects to Telegram and ~20 other platforms (<a href=\"https:\/\/hermes-agent.nousresearch.com\/docs\" rel=\"nofollow noopener\" target=\"_blank\">docs<\/a>).<\/li>\n<li><strong>A model API key.<\/strong> Your agent is only as sovereign as its brain; pick your provider accordingly.<\/li>\n<li>Optional but transformative: <strong><a href=\"https:\/\/github.com\/RikkaApps\/Shizuku\" rel=\"nofollow noopener\" target=\"_blank\">Shizuku<\/a><\/strong>, for shell-level control without root.<\/li>\n<\/ul>\n<h2>How do you install Hermes Agent on Termux?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-install.jpg\" alt=\"Install timeline with both setup traps flagged\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Install timeline with both setup traps flagged.<\/figcaption><\/figure>\n<p>The official installer works on Termux, with two traps that cost me an hour so they will not cost you one.<\/p>\n<p><strong>Trap one: Python.<\/strong> Termux&#8217;s default python is 3.14 now, and Hermes wants <code>&gt;=3.11,&lt;3.14<\/code>. The venv builds fine and then pip rejects the package. The fix is the versioned interpreter, which the tur repo carries:<\/p>\n<pre><code>pkg install python3.13\ncd ~\/.hermes\/hermes-agent\nrm -rf venv &amp;&amp; python3.13 -m venv venv<\/code><\/pre>\n<p><strong>Trap two: native wheels.<\/strong> PyPI has no aarch64-Android wheels for the Rust-heavy deps, so pip compiles <code>cryptography<\/code>, <code>pydantic-core<\/code>, and friends from source. That means you need the toolchain first, and about 30 patient minutes:<\/p>\n<pre><code>pkg install clang rust make pkg-config libffi openssl\n.\/venv\/bin\/pip install -e '.[termux-all]' -c constraints-termux.txt<\/code><\/pre>\n<p><code>psutil<\/code> refuses to build on Android at all (upstream issue <a href=\"https:\/\/github.com\/giampaolo\/psutil\/issues\/2762\" rel=\"nofollow noopener\" target=\"_blank\">psutil#2762<\/a>), but the Hermes installer ships a shim that patches it: <code>scripts\/install_psutil_android.py<\/code>. Run that against your venv before the big install if the installer did not already.<\/p>\n<p>Then the profile. If you are migrating from another machine, <code>hermes profile export<\/code> on the old box, <code>hermes profile import<\/code> on the phone, and carry the three files the exporter deliberately skips: <code>.env<\/code>, <code>auth.json<\/code>, and <code>state.db<\/code>. That is your agent&#8217;s memory, credentials, and session history. Start the gateway:<\/p>\n<pre><code>hermes --profile migrated gateway run<\/code><\/pre>\n<p>At this point the agent answers Telegram. On a phone. You could stop here and have a toy. The rest of this post is what makes it an appliance.<\/p>\n<h2>How do you keep Android from killing it?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-hardening.jpg\" alt=\"Four hardening layers that keep the gateway alive\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Four hardening layers that keep the gateway alive.<\/figcaption><\/figure>\n<p>Android treats your agent like a misbehaving flashlight app. Out of the box, it will silently suspend the whole thing the moment the screen turns off. The symptom: the agent goes dark in your pocket, then dumps replies to everything at once when you wake the phone. Four fixes, in the order they bit me:<\/p>\n<p><strong>1. The supervisor loop.<\/strong> A watchdog that restarts the gateway if it dies, gated on a flag file so you can stop it cleanly:<\/p>\n<pre><code>while [ -f \"$HOME\/.agent-autorun\" ]; do\n  if ! pgrep -f \"gateway run\" &gt;\/dev\/null; then\n    \"$PREFIX\/bin\/hermes\" --profile migrated gateway run &gt;&gt; \"$LOG\" 2&gt;&amp;1\n  fi\n  sleep 15\ndone<\/code><\/pre>\n<p><strong>2. Start at boot.<\/strong> Termux:Boot runs anything in <code>~\/.termux\/boot\/<\/code> after a reboot. Mine acquires the <a href=\"https:\/\/wiki.termux.com\/wiki\/Termux-wake-lock\" rel=\"nofollow noopener\" target=\"_blank\">wake lock<\/a> and launches the supervisor:<\/p>\n<pre><code>sleep 20\ntermux-wake-lock\nnohup \"$HOME\/.agent-watchdog.sh\" &amp;<\/code><\/pre>\n<p><strong>3. The battery screen you actually have to tap.<\/strong> Settings \u2192 Apps \u2192 Termux \u2192 Battery \u2192 Unrestricted. There is no command for the full effect; do it once and move on. Also: never swipe Termux out of recents. That kills its foreground service, which is the thing standing between your agent and Android&#8217;s cached-app freezer.<\/p>\n<p><strong>4. The deep knobs.<\/strong> These need shell powers, which the next section covers: disable the phantom process killer (Android&#8217;s hidden reaper of forked processes), never let Wi-Fi sleep, exempt Termux from Doze, and pin its standby bucket to active:<\/p>\n<pre><code>settings put global settings_enable_monitor_phantom_procs false\nsettings put global wifi_sleep_policy 2\ndumpsys deviceidle whitelist +com.termux\ncmd appops set com.termux RUN_IN_BACKGROUND allow\nam set-standby-bucket com.termux active<\/code><\/pre>\n<p>Proof the stack works: after applying these, the phone answered a Telegram message with <code>mWakefulness=Dozing<\/code>. Screen off, in a pocket, agent fully operational. That line was the whole point of the exercise.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/05\/thethriftydev-profile-logo-150x150.png\" alt=\"Real Termux session on the phone: supervisor, Hermes gateway and proxy watchdog processes, rish shell showing uid 2000\" loading=\"lazy\"\/ width=\"150\" height=\"150\"><figcaption>Live on the phone: gateway supervised, watchdogged, shell powers via rish. Screen off, still answering.<\/figcaption><\/figure>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/termux-gateway-live.jpg\" alt=\"Real Termux session on the phone: supervisor, Hermes gateway and proxy watchdog processes, rish shell showing uid 2000\" loading=\"lazy\"\/ width=\"1500\" height=\"860\"><figcaption>Live on the phone: gateway supervised, watchdogged, shell powers via rish. Screen off, still answering.<\/figcaption><\/figure>\n<h2>How do you get shell powers without root?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-shell.jpg\" alt=\"Privilege ladder to shell uid 2000 without root\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Privilege ladder to shell uid 2000 without root.<\/figcaption><\/figure>\n<p><a href=\"https:\/\/developer.android.com\/tools\/adb#wireless\" rel=\"nofollow noopener\" target=\"_blank\">Wireless ADB<\/a>. Enable it in Developer options, pair once (<code>adb pair IP:port<\/code> with the six-digit code), and <code>adb shell id<\/code> reports <code>uid=2000(shell)<\/code>. The shell user is not root, and the distinction matters: it can manage packages, grant permissions, change settings, read logs, and inject input, but SELinux still cages it and <code>\/system<\/code> stays read-only. For running a server, it covers about 95% of what you want. The remaining 5% is stuff this box does not need to do.<\/p>\n<p>Two honest gotchas. First, wireless debugging is tied to the Wi-Fi session: hotspot hiccups and reboots can kill it, and the port rotates when it comes back. Second, adb-over-network is a terrible thing to depend on for automation you cannot babysit.<\/p>\n<p>The permanent answer is <strong>Shizuku<\/strong>. Install it (official GitHub APK), start it once over adb, and its server runs with shell privileges locally. Then <strong>rish<\/strong>, the Shizuku shell bridge, gives Termux shell powers through a local binder with no network involved at all:<\/p>\n<pre><code>rish -c 'id'\n# uid=2000(shell) ... context=u:r:shell:s0<\/code><\/pre>\n<p>After that, wireless debugging can die whenever it wants. Wi-Fi drops, hotspot bounces, none of it touches your access. Shizuku does die on reboot, so after a power cycle you start it once more over adb (or one tap in its app), and everything is immune again until next reboot.<\/p>\n<h2>What does this actually let you do?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-capable.jpg\" alt=\"Capability checklist of the drawer server\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Capability checklist of the drawer server.<\/figcaption><\/figure>\n<ul>\n<li><strong>A 24\/7 agent that remembers.<\/strong> Persistent memory and skills across sessions, scheduled cron jobs, a personal operator that knows your infrastructure because it lives inside it.<\/li>\n<li><strong>Telegram as the front-end.<\/strong> Message it from anywhere. It answers from the drawer.<\/li>\n<li><strong>Real tools.<\/strong> Terminal, headless Chromium (yes, on the phone; it swaps a little), file access, SSH into the rest of your stack.<\/li>\n<li><strong>The VPS goes on a diet.<\/strong> Public websites, dashboards, and anything needing real ingress stay hosted. The expensive part, the always-on compute with your credentials in it, comes home.<\/li>\n<li><strong>Your stack, physically.<\/strong> If a provider changes its terms tomorrow, the agent does not care. It is already here.<\/li>\n<\/ul>\n<h2>What is the catch?<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-catch.jpg\" alt=\"Honest ledger of limits\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Honest ledger of limits.<\/figcaption><\/figure>\n<p>Honest ledger, because anti-hype is the register here. Four gigs of RAM is a real ceiling: fine for an agent, tight for headless browsing, and big compiles will push swap. It is not a public server: no inbound ports through carrier NAT, so websites stay on the VPS. Termux is still an app, which is why the entire hardening section above exists. And you will want the phone plugged in permanently; hotspot plus gateway plus the odd Rust compile is not a battery lifestyle.<\/p>\n<p>None of those are dealbreakers. They are the price list, and the price is one evening and eighty dollars.<\/p>\n<h2>Frequently Asked Questions<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-faq.jpg\" alt=\"Quick answers about the phone gateway\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Quick answers about the phone gateway.<\/figcaption><\/figure>\n<h3>Can a phone really replace a VPS?<\/h3>\n<p>For the agent layer, yes. A personal AI gateway is an outbound workload: it polls Telegram and calls APIs, so it needs no inbound ports or static IP. For public-facing sites (blogs, apps, dashboards), no: those keep their real server, which can shrink to a cheap ingress box.<\/p>\n<h3>Do you need root to run Hermes on Android?<\/h3>\n<p>No. Termux runs the gateway fine as a normal app, and wireless ADB plus Shizuku provides shell-level control (uid 2000) for device management without touching <code>\/system<\/code> or tripping Play Integrity. SELinux stays enforcing the whole time.<\/p>\n<h3>What happens when the phone reboots?<\/h3>\n<p>Termux:Boot fires a script that takes the wake lock and starts the gateway supervisor, so the agent comes back on its own. Shizuku does not survive reboot, so shell-level powers need one adb command (or one tap) after each power cycle.<\/p>\n<h3>How much data and power does it use?<\/h3>\n<p>Power: about 3 watts, and the battery doubles as a free UPS. Data: light. The gateway long-polls Telegram and calls model APIs on demand; a few hundred megabytes a month unless you make it compile things.<\/p>\n<h3>Why not just use a hosted AI assistant app?<\/h3>\n<p>Because then your memory, credentials, and tools live on someone else&#8217;s computer under someone else&#8217;s terms. Rented tools are the default; they are not the only option. This one is yours, end to end.<\/p>\n<h2>Your move<\/h2>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thethriftydev.com\/blog\/wp-content\/uploads\/2026\/08\/sec-cta.jpg\" alt=\"Three steps to your own phone gateway\" loading=\"lazy\"\/ width=\"1600\" height=\"900\"><figcaption>Three steps to your own phone gateway.<\/figcaption><\/figure>\n<p>The playbook is above, every command tested on real hardware this week. Spare phone in a drawer, Termux from F-Droid, one afternoon. The first time your phone answers you with the screen off, you will get it.<\/p>\n<p>Grateful for good tools and the people who build them. Own the stack, own the life.<\/p>\n<p><script type=\"application\/ld+json\">\n{\n \"@context\": \"https:\/\/schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Can a phone really replace a VPS?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"For the agent layer, yes. A personal AI gateway is an outbound workload: it polls Telegram and calls APIs, so it needs no inbound ports or static IP. For public-facing sites, no: those keep a real server, which can shrink to a cheap ingress box.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Do you need root to run Hermes on Android?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"No. Termux runs the gateway as a normal app, and wireless ADB plus Shizuku provides shell-level control (uid 2000) without touching \/system or tripping Play Integrity. SELinux stays enforcing.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"What happens when the phone reboots?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"Termux:Boot fires a script that takes the wake lock and starts the gateway supervisor, so the agent returns on its own. Shizuku needs one adb command or one tap after each power cycle.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"How much data and power does it use?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"About 3 watts of power, and the battery doubles as a free UPS. Data use is light: a Telegram long-poll plus model API calls on demand, a few hundred megabytes a month unless it compiles software.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Why not just use a hosted AI assistant app?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"Hosted apps keep your memory, credentials, and tools on someone else's computer under someone else's terms. Running your own gateway keeps the entire stack under your physical control.\"\n   }\n  }\n ]\n}\n<\/script><\/p>\n<p>Views: 1<\/p>","protected":false},"excerpt":{"rendered":"<p>Why would you run an AI agent on a phone instead of a VPS? Split diagram: agent layer (outbound work) runs on the phone, public ingress stays on the VPS. An $80 used phone, zero dollars a month, and one afternoon of reps. That is the whole bill for a 24\/7 self-hosted AI agent that&hellip; <a class=\"more-link\" href=\"https:\/\/thethriftydev.com\/blog\/hermes-ai-gateway-android-phone\/\">Continue reading <span class=\"screen-reader-text\">Run a Hermes AI Gateway on an $80 Android Phone (Termux)<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":908,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,93,63],"tags":[119,121,120],"class_list":["post-914","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-sovereign-builder","category-tutorials","tag-hermes-agent","tag-self-hosted","tag-termux","entry"],"_links":{"self":[{"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/posts\/914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/comments?post=914"}],"version-history":[{"count":4,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/posts\/914\/revisions"}],"predecessor-version":[{"id":928,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/posts\/914\/revisions\/928"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/media\/908"}],"wp:attachment":[{"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/media?parent=914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/categories?post=914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thethriftydev.com\/blog\/wp-json\/wp\/v2\/tags?post=914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}