
Min ssh serial bridge
hnz1102/ssh-serial-bridge
Firmware for the ESP32-S3 that bridges an SSH connection (over Wi-Fi) to UART and USB CDC serial ports. Written in Rust (esp-idf-hal / esp-idf-svc) with a C component (wolfSSH) for the SSH server.

Firmware for the ESP32-S3 that bridges an SSH connection (over Wi-Fi) to UART and USB CDC serial ports. Written in Rust (esp-idf-hal / esp-idf-svc) with a C component (wolfSSH) for the SSH server.
Ssh bridge for raspberrypi is an open-source printed circuit board by hnz1102, from the hnz1102/ssh-serial-bridge repository on GitHub. It is a 2-layer board of 93 × 50 mm with 37 parts on 59 nets, routed with 307 tracks and 107 vias.
It is built around the ESP32-S3-WROOM-1-N16R8, AZ1117CH-3.3TRG1-50 and TLP3555A(F, with the USB4105-GF-A, CUHS20F60,H3F and MH2029-601Y among its other parts. Its parts include 15 resistors, 6 connectors, 4 capacitors, 4 ICs and 3 diodes. It belongs with the interfaces and adapters and radio and wireless boards and the ESP32 boards of this library.
SSH Serial Bridge
Firmware for the ESP32-S3 that bridges an SSH connection (over Wi-Fi) to UART and USB CDC serial ports. Written in Rust (esp-idf-hal / esp-idf-svc) with a C component (wolfSSH) for the SSH server.
| Feature | Description |
|---|---|
| SSH server | Port 22, username/password authentication via wolfSSH, multiple concurrent sessions (including shared sessions on the same serial port) |
| Serial ports | COM1 / COM2 (UART) and USB CDC (USB Host) — up to 4 ports (usb0–usb3) |
| Web UI | Browser-based configuration, terminal, and GPIO control |
| WebSocket terminal | Built-in xterm.js; access serial data from the browser at /terminal |
| WPS support | Wi-Fi Protected Setup (PBC mode) — configure Wi-Fi via button or Web UI |
| GPIO / PWM | Digital output (ON/OFF) on GPIO 4–9, 12 ; PWM output on GPIO 10–11 |
| SPI display | Optional ST7789V (320×240) display showing incoming serial data |
| UDP Syslog | RFC 5424 remote logging over UDP |
| NTP | Time synchronisation on boot; up to 4 servers configurable via Web UI |
| NVS settings | Persistent configuration stored in NVS; editable via Web UI at runtime |
SSH client ──[TCP:22]──► ssh_bridge.c (wolfSSH)
│
per-session ring buffers (PSRAM)
│
Rust usb_host.rs ◄─────────────┘
├── COM1 (UART1)
├── COM2 (UART2)
└── USB CDC (USB Host: PL2303 / FTDI / etc.)
Browser ──[HTTP/WS]──► httpserver.rs
├── /terminal (xterm.js + WebSocket /ws/serial)
├── / (configuration page)
└── /gpio (GPIO/PWM control page)ssh-serial-bridge/
├── src/
│ ├── main.rs # Entry point, peripheral initialisation
│ ├── usb_host.rs # USB Host (PL2303 etc.) + UART + SSH bridge control
│ ├── httpserver.rs # HTTP/WebSocket server, NVS config management
│ ├── wifi.rs # Wi-Fi STA connection (DHCP / static IP)
│ ├── syslogger.rs # UDP Syslog logger (RFC 5424)
│ ├── serial_display.rs # ST7789V SPI display rendering
│ ├── gpio_ctrl.rs # Shared GPIO / PWM state
│ ├── btn_ctrl.rs # GPIO0 button (short press: page cycle; long press: factory reset)
│ └── boot_log.rs # NVS boot counter and rolling reset-reason log (last 10 entries)
├── components/
│ ├── ssh_bridge/ # SSH server C component (wolfSSH wrapper)
│ ├── wolfssh/ # wolfSSH (github.com/wolfSSL/wolfssh, commit 157cb01f)
│ └── wolfssl/ # wolfSSL/wolfCrypt (github.com/wolfSSL/wolfssl, commit b7e7e755)
├── static/ # Embedded static files (xterm.js / css / fit addon)
├── cfg.toml # Build-time default configuration (gitignored — contains credentials)
├── cfg.toml.<board> # Board-specific templates (e.g. ssh-bridge-board / xiao-esp32s3)
├── sdkconfig.defaults # ESP-IDF build settings
├── partitions.csv # Flash partition table
├── build-flash-images.sh # Build merged flash + app-only OTA images per board
├── setup_components.sh # Initial setup script for components/
└── setup_env.sh # One-shot environment setup (Rust, espup, udev)| Port | Signal | Default GPIO | XIAO-ESP32S3 |
|---|---|---|---|
| COM1 | TX | 17 | 43 |
| COM1 | RX | 18 | 44 |
| COM2 | TX | 19 (41) | — |
| COM2 | RX | 20 (42) | — |
| GPIO | Function |
|---|---|
| 4–9, 12 | Digital output ON/OFF |
| 10–11 | PWM output (LEDC, 1 kHz, 14-bit) |
| Signal | GPIO |
|---|---|
| SCLK | 48 |
| MOSI | 45 |
| CS | 40 |
| DC | 39 |
| RST | 38 |
| GPIO | Function |
|---|---|
| 0 (BOOT) | Short press (<3 s): Cycle display page / Medium press (3–10 s): Toggle DC OUT (GPIO12) / Long press (≥10 s): NVS factory reset |
| Factory Reset Display Indicators: |
Before building, choose a board config and copy it to cfg.toml.
ssh-bridge-board: Board with a 2.0-inch TFT display for serial data outputmini-ssh-bridge-board: Small-display board using SSD1306xiao-esp32s3: XIAO ESP32S3 board# 2.0-inch TFT display board
cp cfg.toml.ssh-bridge-board cfg.toml
# SSD1306 mini display board
cp cfg.toml.mini-ssh-bridge-board cfg.toml
# XIAO ESP32S3 board
cp cfg.toml.xiao-esp32s3 cfg.tomlAfter copying, edit cfg.toml for your environment (Wi-Fi credentials, IP, etc.) if needed.
[ssh-serial-bridge]
wifi_ssid = "your-ssid"
wifi_psk = "your-password"
ip_mode = "dhcp" # "dhcp" or "static"
ip_address = "192.168.2.200"
subnet_mask = "255.255.255.0"
gateway = "192.168.2.1"
dns = "1.1.1.1"
syslog_server = "192.168.2.140:514"
syslog_enable = "false"
syslog_host_name = "esp32s3"
syslog_app_name = "ssh-bridge"
ssh_user = "admin"
ssh_password = "sshpass"
com1_tx_pin = "17" # XIAO-ESP32S3: 43
com1_rx_pin = "18" # XIAO-ESP32S3: 44
com1_baud = "115200"
com2_tx_pin = "41"
com2_rx_pin = "42"
com2_baud = "115200"
Values in cfg.toml are compiled into the firmware as defaults.
After boot they can be overridden via the Web UI or direct NVS writes; NVS values take priority.
WPS (Wi-Fi Protected Setup) allows you to connect to a Wi-Fi network without manually entering the SSID and password. This device supports WPS Push Button Configuration (PBC) mode.
If you don't have Wi-Fi credentials yet or want to reconfigure via WPS without Web UI access:
Edit cfg.toml before building (or rebuild the firmware):
wifi_ssid = "" # Set to empty string
wps_enable = "true" # Enable WPS mode on bootFlash the firmware to the device
On boot, the device will automatically enter WPS mode and wait for you to press the WPS button on your Wi-Fi router (timeout: 2 minutes)
Upon successful WPS connection, the credentials are saved to NVS and the device reboots
Alternative: Trigger WPS via Factory Reset
If the device is already running with Wi-Fi configured but you want to switch to WPS:
cfg.toml to set wps_enable = "true" and wifi_ssid = ""cfg.toml defaults, and reboot into WPS modeNote: Web UI is not accessible until Wi-Fi is connected, so this method is essential for initial setup or when you lose Wi-Fi access.
http://<device_ip>/When WPS is active:
If WPS fails or times out, the device will revert to the previously configured Wi-Fi credentials (from cfg.toml or NVS).
cfg.toml or the Web UI if WPS is not available on your routerRun setup_env.sh once on a fresh Ubuntu / Debian machine (or WSL2) before
building. The script performs all steps below automatically.
bash setup_env.shAfter the script finishes, open a new terminal (or reload your shell config) so the environment variables take effect:
source "$HOME/.cargo/env"
source ~/export-esp.sh| Step | Action |
|---|---|
| 1 | Install system packages via apt |
| 2 | Install Rust toolchain via rustup (skipped if already present) |
| 3 | Install ldproxy, espup, cargo-espflash via Cargo |
| 4 | Install & update the ESP32-S3 Xtensa toolchain via espup |
| 5 | Source ~/export-esp.sh (generated by espup) |
| 6 | Add udev rule for ESP32 USB device (303a:1001) and reload rules |
If you prefer to run the steps manually, expand each step below.
# 1. System packages
sudo apt update && sudo apt -y install \
git python3 python3-pip gcc build-essential curl \
pkg-config libudev-dev libtinfo5 clang libclang-dev \
llvm-dev udev libssl-dev python3.10-venv
# 2. Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Select option 1 (default install), then:
source "$HOME/.cargo/env"
# 3. Cargo tools
cargo install ldproxy
cargo install espup
cargo install cargo-espflash
# 4. ESP32-S3 toolchain
espup install
espup update
# 5. Activate ESP environment (add to ~/.bashrc / ~/.zshrc for persistence)
. ~/export-esp.sh
# 6. udev rulesesp channel (selected automatically via rust-toolchain.toml)Run once after cloning, or after a clean wipe of components/:
cd esp32-s3/ssh-serial-bridge
bash setup_components.shThis clones wolfssh and wolfssl at the verified commits and places the
ESP-IDF-specific CMakeLists.txt and include/user_settings.h on top.
cargo build --releaseespflash flash --release --monitorTo create a single binary file that includes all partitions (bootloader, partition table, data partitions, and the currently built app image) for distribution or web-based flashing:
cargo espflash save-image --release --merge --chip esp32s3 complete_flash.binThis creates a complete 8 MB flash image starting from offset 0x0.
The helper script builds all board configs and produces both image types:
flash_images/flash_<board>.bin (merged full-flash image, write at 0x0)flash_images/app_<board>.bin (app-only image for ssh ... update OTA)bash build-flash-images.shImportant: When flashing this image, always write it to offset 0x0, not 0x9000. Writing to 0x9000 will result in a boot failure with "invalid header: 0xffffffff" error.
# Using esptool.py
esptool.py --chip esp32s3 --port /dev/ttyUSB0 write_flash 0x0 complete_flash.bin
# Using espflash
espflash write-bin 0x0 complete_flash.binYou can also flash the binary via a web browser using the ESP Web Flasher:
complete_flash.bin0x0 (very important!)This method is ideal for:
| Partition | Offset | Size |
|---|---|---|
| nvs | 0x9000 | 24 KB |
| otadata | 0xF000 | 8 KB |
| phy_init | 0x11000 | 4 KB |
| ota_0 (app) | 0x20000 | 4032 KB |
| ota_1 (app) | 0x410000 | 4032 KB |
Flash: 8 MB, DIO mode, 40 MHz.
| URL | Method | Description |
|---|---|---|
/login | GET / POST | Login |
/logout | GET | Logout |
/ | GET | Configuration page (auth required) |
/gpio | GET | GPIO / PWM control page (auth required) |
/terminal | GET | WebSocket serial terminal (auth required) |
/ws/serial | WS | Bidirectional serial bridge |
/api/config | POST | Save configuration to NVS |
/api/status | GET | Device / Wi-Fi / USB status (JSON) |
/api/reset | POST | Erase NVS and restore cfg.toml defaults |
/api/reboot | POST | Reboot the device |
/api/gpio | POST | Set one digital output ON/OFF |
/api/pwm | POST | Set PWM duty cycle (0–100 %) |
/api/gpio_state | GET | Current GPIO / PWM state (JSON) |
/api/boot_log | GET | Boot history with reset reasons from NVS (JSON) |
| Item | Detail |
|---|---|
| Port | 22 (TCP) |
| Auth method | Password only (public-key authentication is not supported) |
| Username | Any string is accepted — only the password is checked |
| Password | Set via ssh_password in cfg.toml or Web UI (default: esp32) |
| Concurrent sessions | Up to 6 total SSH sessions (including command sessions) |
| Per-device console sharing | Up to 4 concurrent console sessions on the same target (usb0-usb3, com1, com2) |
Security note: Change the default password before deploying the device on a shared network.
The SSH server dispatches on the command passed after the host.
If no command is given, a usage summary is printed and the connection closes.
Connects the SSH session as a transparent terminal to a serial port.
ssh -tt <user>@<device_ip> console (usb0|usb1|usb2|usb3|com1|com2)| Argument | Description |
|---|---|
usb0 | First USB CDC device (plug order; alias: usb) |
usb1 | Second USB CDC device |
usb2 | Third USB CDC device |
usb3 | Fourth USB CDC device |
com1 | UART1 (pins configured by com1_tx_pin / com1_rx_pin) |
com2 | UART2 (pins configured by com2_tx_pin / com2_rx_pin) |
-tt flag forces pseudo-TTY allocation, which is required for correct
terminal behaviour.Connected to ESP32-S3 SSH-Serial-Bridge v0.1.1 [com1].
Disconnect: Enter then ~.Note: N other session(s) are also connected to this device — input/output is shared.com1, com2, usb0-usb3).Error: too many sessions already connected to this device (max 4).~.Examples:
# Connect to the first USB CDC device
ssh -tt admin@192.168.2.200 console usb0
# Connect to the second USB CDC device
ssh -tt admin@192.168.2.200 console usb1
# Connect to COM1 (UART1)
ssh -tt admin@192.168.2.200 console com1
# Connect to COM2 (UART2)
ssh -tt admin@192.168.2.200 console com2Controls GPIO4–GPIO9 output pins (mapped as power outlets 1–6).
ssh <user>@<device_ip> power <1-6> (on|off)| Argument | Description |
|---|---|
1–6 | Outlet number: 1 = GPIO4, 2 = GPIO5, … 6 = GPIO9 |
on | Set output HIGH |
off | Set output LOW |
Examples:
ssh admin@192.168.2.200 power 1 on # GPIO4 → HIGH
ssh admin@192.168.2.200 power 3 off # GPIO6 → LOWControls the dedicated DC Power output on GPIO12.
ssh <user>@<device_ip> dcpower (on|off)Examples:
ssh admin@192.168.2.200 dcpower on
ssh admin@192.168.2.200 dcpower offTurns the DC Power output off, waits briefly, then turns it back on — in a single SSH call.
ssh <user>@<device_ip> powercycleExample:
ssh admin@192.168.2.200 powercycleSets the PWM duty cycle on GPIO10 or GPIO11 (LEDC, 1 kHz, 14-bit).
ssh <user>@<device_ip> pwm <1|2> <0-100>| Argument | Description |
|---|---|
1 | Channel 1 — GPIO10 |
2 | Channel 2 — GPIO11 |
0–100 | Duty cycle in percent |
Examples:
ssh admin@192.168.2.200 pwm 1 50 # GPIO10 → 50 %
ssh admin@192.168.2.200 pwm 2 0 # GPIO11 → off
ssh admin@192.168.2.200 pwm 1 100 # GPIO10 → full onReboots the ESP32-S3 (equivalent to a power-on reset).
ssh <user>@<device_ip> rebootExample:
ssh admin@192.168.2.200 rebootStreams a new app image over SSH directly into the inactive OTA partition, then reboots into it. No filesystem, SCP, or SFTP support is required — the exec channel's stdin is piped straight into flash.
ssh <user>@<device_ip> update < firmware.binExample:
cat flash_images/app_ssh-bridge-board.bin | ssh admin@192.168.2.200 updateImportant:
flash_images/app_<board>.bin, produced by
build-flash-images.sh), not the merged full-flash image
(flash_images/flash_<board>.bin). The merged image includes the
bootloader and partition table baked in at offset 0 and will corrupt the
OTA partition if written this way.ota_0/ota_1). The update is written to
whichever slot isn't currently running, so the previous firmware is left
untouched until the new image is fully received and verified.ota_0/ota_1/otadata
(see partitions.csv). Boards flashed with an older single-partition image
must be reflashed once via USB/serial (cargo espflash flash or the merged
flash_<board>.bin image) before OTA updates over SSH will work.ESP32-S3 SSH-Serial-Bridge
Usage:
ssh -tt admin@host console (usb0|usb1|usb2|usb3|com1|com2) -- Serial console bridge
ssh admin@host power (1-6) (on|off) -- GPIO4-9 output control
ssh admin@host dcpower (on|off) -- DC Power output (GPIO12)
ssh admin@host powercycle -- DC Power off->on (GPIO12)
ssh admin@host pwm (1|2) (0-100) -- PWM GPIO10-11 duty %
ssh admin@host reboot -- Reboot the ESP32-S3
ssh admin@host update < firmware.bin -- OTA firmware updateThe USB Host driver auto-detects the connected adapter by VID/PID and applies
the appropriate initialisation sequence. The baud rate is set by cdc_baud
in cfg.toml (default: 115200).
Note:
cdc_enablemust be set to"true"incfg.toml(or via Web UI) to activate the USB Host driver. When disabled,usb0–usb3are unavailable as SSH console targets.
| Chip | VID | PID(s) | Ports | Notes |
|---|---|---|---|---|
| PL2303 | 067B | 2303, 23A3, 2304 | 1 | Prolific Technology |
| CP210x | 10C4 | EA60, EA61, EA70 | 1 | Silicon Labs |
| FT232R | 0403 | 6001 | 1 | FTDI |
| FT232H | 0403 | 6014 | 1 | FTDI |
| FT2232H/D | 0403 | 6010 | 2 | FTDI — maps to usb0 / usb1 |
| FT4232H | 0403 | 6011 | 4 | FTDI — maps to usb0–usb3 |
This firmware supports Raspberry Pi USB Gadget mode for direct serial access over USB:
| Device | VID | PID | Module | Notes |
|---|---|---|---|---|
| Raspberry Pi (g_cdc) | 0525 | a4a7 | g_cdc | CDC-ACM composite device (recommended) |
To use your Raspberry Pi as a USB serial gadget with this ESP32-S3 bridge:
Enable USB gadget mode on your Raspberry Pi:
# Add to /boot/config.txt (or /boot/firmware/config.txt on Ubuntu)
dtoverlay=dwc2Load the g_cdc module (recommended over g_serial):
Method A: Using cmdline.txt (Recommended)
# Edit /boot/cmdline.txt (or /boot/firmware/cmdline.txt on Ubuntu)
# Add modules-load=dwc2,g_cdc to the kernel command line
# Example:
console=serial0,115200 ... modules-load=dwc2,g_cdc ...Method B: Using /etc/modules
# Add to /etc/modules
dwc2
g_cdcEnable serial-getty service (required for the CDC device to respond):
sudo systemctl enable serial-getty@ttyGS0
sudo systemctl start serial-getty@ttyGS0Reboot your Raspberry Pi:
sudo rebootConnect the Pi to the ESP32-S3 USB port using a USB cable
Important: Use
g_cdcinstead ofg_serial. Theg_serialmodule has compatibility issues with the ESP-IDF USB Host stack and may not work reliably.g_cdcprovides better standards compliance and works seamlessly with this firmware.
After configuration, the Pi will appear as a CDC-ACM device and you can access its serial console via SSH to the ESP32-S3 bridge (target: usb0).
Multi-port FTDI adapters expose multiple ports, mapped to SSH console targets in channel order:
| SSH target | Description |
|---|---|
usb0 | Port 1 — all single-port adapters; FT2232 ch.A; FT4232 ch.A |
usb1 | Port 2 — FT2232 ch.B; FT4232 ch.B |
usb2 | Port 3 — FT4232 ch.C |
usb3 | Port 4 — FT4232 ch.D |
| Component / Library | Version | License | Purpose |
|---|---|---|---|
| ssh-serial-bridge (this project) | 0.1.1 | MIT | Firmware (Rust) |
| ssh_bridge component | 0.1.1 | MIT | SSH server C wrapper |
| esp-idf-hal | 0.45.2 | MIT / Apache-2.0 | ESP32-S3 hardware abstraction |
| esp-idf-svc | 0.51 | MIT / Apache-2.0 | Wi-Fi, HTTP server, SNTP, etc. |
| wolfSSH | commit 157cb01f | GPLv3 (or commercial) | SSH server protocol |
| wolfSSL / wolfCrypt | commit b7e7e755 | GPLv3 (or commercial) | Cryptography library |
| mipidsi | 0.8.0 | MIT | ST7789V display driver |
| embedded-graphics | 0.8.1 | MIT | Display rendering |
| @xterm/xterm | 6.0.0 (bundled) | MIT | Browser WebSocket terminal |
| @xterm/addon-fit | 0.11.0 (bundled) | MIT | xterm.js terminal fit addon |
Note on wolfSSH / wolfSSL licensing:
Both wolfSSH and wolfSSL are dual-licensed under GPLv3 (open source) or a commercial license (for use in proprietary products).
| Qty | Value | Footprint | References |
|---|---|---|---|
| 3 | 0.1uF | Capacitor_SMD:C_0603_1608Metric | C101, C201, C202 |
| 2 | 10K | Resistor_SMD:R_0603_1608Metric | R201, R202 |
| 2 | 4.7K 1% | Resistor_SMD:R_0603_1608Metric | R103, R206 |
| 2 | 47K 1% | Resistor_SMD:R_0603_1608Metric | R102, R204 |
| 2 | 51K | Resistor_SMD:R_0603_1608Metric | R110, R111 |
| 2 | 5K1 | Resistor_SMD:R_0603_1608Metric | R106, R107 |
| 2 | 75K | Resistor_SMD:R_0603_1608Metric | R104, R109 |
| 2 | USB4105-GF-A | Library:USB_C_5077CR-16-SMC2-BK-TR | J101, J102 |
| 1 | 1 | Library:SW_SKRPACE010_4mm_3mm | SW304 |
| 1 | 10uF | Capacitor_SMD:C_0805_2012Metric | C203 |
| 1 | 150 | Resistor_SMD:R_0603_1608Metric | R101 |
| 1 | 1K | Resistor_SMD:R_0603_1608Metric | R108 |
| 1 | 330 | Resistor_SMD:R_0603_1608Metric | R105 |
| 1 | 3V3 | TestPoint:TestPoint_Pad_D1.0mm | TP101 |
| 1 | AZ1117-CH3.3TRG1 | Package_TO_SOT_SMD:SOT-223-3_TabPin2 | U103 |
| 1 | CUHS20F60 | Diode_SMD:D_PowerDI-123 | D101 |
| 1 | Conn_01x04 | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J1 |
| 1 | Conn_01x10 | Connector_PinHeader_2.54mm:PinHeader_1x10_P2.54mm_Vertical | J2 |
| 1 | Conn_02x05_Odd_Even | Connector_PinHeader_2.54mm:PinHeader_2x05_P2.54mm_Vertical | J104 |
| 1 | ESP32-S3-WROOM-1-N16R8 | Library:ESP32-S3-WROOM-1_EXP | U201 |
| 1 | GND | TestPoint:TestPoint_Pad_D1.0mm | TP102 |
| 1 | LED BLUE | LED_SMD:LED_0603_1608Metric | D402 |
| 1 | LED RED | LED_SMD:LED_0603_1608Metric | D103 |
| 1 | MH2029-601Y | Inductor_SMD:L_0805_2012Metric | FB101 |
| 1 | ST7789V_TFT_DISPLAY_8P | Library:ST7789V TFT SPI DISPLAY 320x240 GMT020-02-8P | U101 |
| 1 | TLP3555A | Package_DIP:DIP-4_W7.62mm | U102 |
| 1 | USB_A | Library:USB_A_5075AR-04 | J105 |
| 1 | VBUS_OUT | TestPoint:TestPoint_Pad_D1.0mm | TP103 |

hnz1102/ssh-serial-bridge
Firmware for the ESP32-S3 that bridges an SSH connection (over Wi-Fi) to UART and USB CDC serial ports. Written in Rust (esp-idf-hal / esp-idf-svc) with a C component (wolfSSH) for the SSH server.


hnz1102/dcpower
DC Power Unit for Breadboard based on ESP32-S3 microcontroller and AP33772S USB Power Delivery (PD) Sink Controller.

hnz1102/EEW-display
ESP32-S3 firmware for a small earthquake-information display. It shows recent earthquakes and emergency earthquake warnings (緊急地震速報, EEW) from [P2P地震情報](https://www.p2pquake.net/), draws the epicenters on a Google map…




hnz1102/mini-current-meter
Mini Current Meter using INA228A ultra-precise digital power monitor

It measures 93 × 50 mm and has 2 copper layers, 1.6 mm thick.
37 parts, built around the ESP32-S3-WROOM-1-N16R8, AZ1117CH-3.3TRG1-50, TLP3555A(F and USB4105-GF-A. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the hnz1102/ssh-serial-bridge repository on GitHub, at the commit this page was made from: the board is hw/ssh-bridge-for-raspberrypi.kicad_pcb and its schematic hw/mini-ssh-serial-bridge/min-ssh-serial-bridge.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask hnz1102 before reusing the design.