M5Cardputer-SSHClient
Pocket SSH client on the M5Cardputer: ESP32-S3, physical keyboard, C++
git clone https://github.com/fernandofatech/tool-m5cardputer-sshclient.gitListen to guide
generated on playGenerated only on first play
Powered by Amazon Polly + OmniVoice
A C++ experiment that turns the M5Cardputer — an ESP32-S3 with a 56-key QWERTY keyboard and a 1.14-inch screen — into a pocket SSH client for operating a host without opening the laptop.
What it is and why it exists
This repository is an experiment, not a product. The question it answers is not "can SSH run on a microcontroller?" — it's "how much of a usable terminal fits in 8 MB of flash, 240×135 pixels, and a keyboard the size of a credit card?".
The M5Cardputer is an M5Stack device built around the StampS3 module: an ESP32-S3 with 2.4 GHz Wi-Fi, a physical keyboard, a colour IPS screen, a microSD slot and a small battery. It's the only off-the-shelf hardware in that price range that combines real text input with a radio and a display in a body that fits in a pocket. That makes it the natural candidate for a tool I always missed in the homelab: something I grab from a drawer, join to the network, and use to run a systemctl restart or watch a journalctl -f without pulling out a laptop.
What the project delivers: C++ firmware for the Arduino/ESP32 ecosystem that joins the Cardputer to Wi-Fi, opens an SSH session to a host, and bridges the physical keyboard to the remote terminal, rendering output on the screen. What it does not deliver: full terminal emulation, multi-session management, or any security guarantee beyond what the SSH library provides. It's embedded/IoT portfolio material, published to show the decisions — and the limits — of bringing a cryptographic protocol to an MCU.
At a glance
platform: <type>/<scope> branches, Conventional Commits, version derived from commits.How the pieces connect
From keypress to byte on screen: the firmware bridges the Cardputer hardware and the remote host.
- Keyboard driver · mapa de teclas → bytes
- SSH client · sessão + canal interativo
- Terminal renderer · 240×135, buffer de linhas
- Wi-Fi 2.4 GHz · ESP32-S3
- Host remoto · sshd na porta 22
How it works under the hood
The firmware has four responsibilities, and each one has a cost that shows up in the hardware.
Networking: the ESP32-S3 brings up Wi-Fi via Espressif's Arduino core and opens a TCP socket to the host. Nothing new here — the heavy lifting is done by the lwIP stack shipped with the SDK.
Protocol: SSH is the expensive part. Key exchange, symmetric cipher and MAC run in software, and that's what decides whether the session opens in seconds or in tens of seconds. An SSH client in the ESP32 ecosystem relies on an Arduino port of an SSH library; that library's binary size and RAM footprint are the project's main constraint, and that's why the target board matters: the StampS3 has PSRAM, and without it the session simply doesn't fit.
Input: the Cardputer keyboard is not USB HID — it's a matrix read by M5Stack's library. The firmware has to translate a physical key into a terminal byte, including modifier combinations the keyboard lacks a dedicated key for. The mapping is the most hand-crafted part of the code.
Output: the screen is 240×135 pixels. With a legible font that yields somewhere between 40 and 50 columns by 10 to 15 rows — less than a vt100 at 80×24. The renderer keeps a line buffer and redraws what changed; it does not interpret full escape sequences, so full-screen programs like htop or vim degrade. One-line commands and streaming logs work well.
The practical lesson behind this: the bottleneck of an embedded SSH client isn't the network or the crypto — it's the screen.
Install and use
- 1
Prepare the toolchain
Install PlatformIO (via VS Code or
pip install platformio) or Arduino IDE 2.x with Espressif's ESP32 core. Add M5Stack board support and the Cardputer libraries through the library manager. - 2
Clone the repository
git clone https://github.com/fernandofatech/tool-m5cardputer-sshclientand open the folder in your editor. Check the board configuration before building — the target ism5stack-stamps3, not the generic ESP32. - 3
Configure network and host
Fill in the Wi-Fi SSID and password plus the SSH host, port and user where the source expects them (configuration constants or a secrets file kept out of version control). Never commit credentials — that's what
.gitignoreis for. - 4
Build and flash
Connect the Cardputer over USB-C and flash. With PlatformIO,
pio run -t upload; in the Arduino IDE, pick the serial port and click Upload. The first build takes a few minutes because of the SSH library. - 5
Connect and operate
On boot the device joins Wi-Fi and opens the session. Type commands on the physical keyboard; output shows on screen. Follow the serial log with
pio device monitorto diagnose handshake or authentication failures.
# clone
git clone https://github.com/fernandofatech/tool-m5cardputer-sshclient
cd tool-m5cardputer-sshclient
# preencha Wi-Fi e host SSH onde o fonte indicar (fora do git)
# ...
# compile, grave e acompanhe o serial
pio run -t upload
pio device monitor -b 115200Credentials in flash
Wi-Fi and SSH passwords baked into the firmware sit in plain text in the ESP32 flash and can be read by anyone holding the device. For a bench experiment that's acceptable; for any host that matters, use a dedicated user with minimal permissions, a key instead of a password where the library supports it, and treat the Cardputer as a device that can be lost.
Limits you will hit
Anyone arriving with laptop ssh expectations will be frustrated at three points, and it's better to know beforehand.
Memory: the SSH key exchange allocates tens of KB of heap. On the ESP32-S3 with PSRAM that fits; on variants without PSRAM, or with Bluetooth running at the same time, the connection fails with an allocation error rather than a clear message. If the session drops during the handshake, look at free heap before looking at the network.
Screen: 240×135 pixels. Long output scrolls fast and there is no scrollback. What works is short commands and streaming logs — tail -f, journalctl -f, docker ps. Programs that redraw the whole screen have nowhere to fit.
Keyboard: the keys are small and Ctrl/Alt combinations depend on the map implemented in the firmware. Ctrl+C to interrupt a process is the minimum test worth doing right after flashing.
Battery: with Wi-Fi active and the screen on, runtime is minutes to a few hours, not a day. It's a quick-intervention tool, not a long-session one.
None of these limits is a defect of the project — they are properties of the hardware that the experiment makes visible. The value lies precisely in measuring where the line falls.
FAQ
Does it work on other M5Stack devices or a generic ESP32?
Not without work. The keyboard map and display driver are Cardputer-specific. An ESP32-S3 with PSRAM and a different keyboard means rewriting the input and output layer — the networking and SSH part is reusable.
Can I use it in production?
No. It's a portfolio experiment. If you need an emergency console for a server, a serial cable or an IP KVM costs less in maintenance than hardening this firmware.
How do I contribute?
Follow the fernandofatech/platform conventions: a feat/, fix/, chore/ or docs/ branch with a scope, Conventional Commits in the PR title. The version is derived from commits; don't write a version number by hand. The lint, CI, security and release pipeline comes from platform's reusable workflows.
References
Who it's for
Use this repository when: you own an M5Cardputer, want to understand what it costs to bring SSH to an ESP32-S3, and need a pocket console for short commands in the homelab. Don't use it when: the host truly matters, you expect vim or htop on the screen, or you need something that survives a lost device. The merit here is the measured experiment — and what it teaches about the line between networking, crypto and 240 pixels of width.
Architecture, AWS, AI and market deep dives — straight to your inbox. Free.
No spam · unsubscribe anytime