Project: PlatformIO Remote Build Node
1. Overview
We utilize an i9-13900K Server as a centralized build and flash node for embedded devices (ESP32/Arduino/Uno R4). This architecture offloads heavy compilation tasks to the high-power server while allowing the user to plug embedded devices into a lightweight remote laptop (MacBook Pro) for flashing.
2. Architecture
- Host Hardware (Compiler): i9-13900K Server (Linux/Ubuntu 24.04+)
- IP:
100.83.197.77(Tailscale) or192.168.0.11(LAN) - Hostname:
code-server-1,code-server-1.story-pinecone.ts.net
- IP:
- Client Hardware (Agent): MacBook Pro (or other remote system)
- Role: USB Passthrough & UI Frontend
- Protocol: VS Code Remote (SSH) + PlatformIO Remote Agent
- Network: Tailscale Mesh VPN (for seamless DNS and connectivity anywhere)
3. Server-Side Setup (The "Brain")
Perform these steps once on the Linux Server.
A. Dependencies (Fixing the Python Mismatch)
Modern Ubuntu defaults to Python 3, but PlatformIO often looks for a generic python command. We must install compatibility layers.
sudo apt update
sudo apt install -y python3-venv python3-pip python-is-python3
B. Path Configuration
PlatformIO installs into a private directory. We must add this to the global PATH so the VS Code extension can find it.
# Add to .bashrc
echo 'export PATH=$PATH:~/.platformio/penv/bin' >> ~/.bashrc
source ~/.bashrc
C. Version Control (Git) Setup
Since the code resides on the server, Git must be configured on the Linux host.
1. Install Git (On Server)
Open the VS Code terminal (connected to code-server-1) and run:
sudo apt update
sudo apt install -y git
2. Configure Identity
Tell Git who you are (this attaches your name to commits):
git config --global user.name "Patrick Campanale"
git config --global user.email "[email protected]"
3. Authenticate with GitHub/GitLab (SSH Keys)
Since the server is headless, we cannot use browser-based login easily. We will use an SSH Deploy Key.
- Generate a Key on the Server:
ssh-keygen -t ed25519 -C "code-server-git" # Press Enter 3 times to accept defaults and no passphrase - Display the Key:
cat ~/.ssh/id_ed25519.pub - Add to GitHub:
- Copy the output (starts with
ssh-ed25519...). - Go to GitHub.com > Settings > SSH and GPG Keys.
- Click New SSH Key, name it "Code Server", and paste the key.
- Copy the output (starts with
4. VS Code Integration
You do not need to install anything extra.
- The Source Control tab (Git Icon) in VS Code on your Mac will automatically detect the Git repo on the Linux server.
- You can stage, commit, and push using the Mac's GUI, and it will execute the commands on the server remotely.
4. Client-Side Setup (The Mac)
Perform these steps on any new MacBook/Laptop you want to use.
A. Tailscale & DNS (Split Tunneling)
We utilize a Split DNS configuration. This ensures that the Mac uses its own local Wi-Fi for general internet access (fast, low latency) and only uses the VPN tunnel when connecting to the server.
- Tailscale Admin Console:
- Global Nameservers: (Optional) Can include the Pi-hole IP, but it is not strictly required for this node to function.
- Override local DNS: Disabled. (This ensures we do not force all mobile traffic back to the home network).
- Mac Client Settings:
- Click the Tailscale Icon in the menu bar.
- Ensure "Use Tailscale DNS" is CHECKED.
- Why: This enables MagicDNS, allowing the Mac to resolve
code-server-1by name instantly, without routing your Netflix/Web traffic through the home lab.
B. SSH Configuration
Edit ~/.ssh/config to ensure stable connections:
Host code-server-1
HostName code-server-1
User pcamp96
ForwardAgent yes
ServerAliveInterval 15
ConnectTimeout 60
Run ssh-copy-id code-server-1 to enable password-less login.
C. The "Always-On" Flash Agent
To avoid opening a terminal to run pio remote agent start, we install a macOS Launch Agent.
- Create the Service File:
Run this in Mac Terminal to create~/Library/LaunchAgents/org.platformio.agent.plist:cat <<EOF > ~/Library/LaunchAgents/org.platformio.agent.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>org.platformio.agent</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/pio</string> <string>remote</string> <string>agent</string> <string>start</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string> </dict> </dict> </plist> EOF - Load the Service:
launchctl load ~/Library/LaunchAgents/org.platformio.agent.plist
5. VS Code Configuration (The "Golden" Config)
These settings fix the "Grey Screen" and "Timeout" errors in the PlatformIO extension and streamline the workflow.
A. Remote Settings (settings.json)
Open Remote Settings (JSON) and paste this configuration. This forces the UI to use a fixed port (8008) and bypasses the broken internal browser.
{
"platformio-ide.useBuiltinPIOHome": false, // Force external browser (Safari/Chrome)
"platformio-ide.useBuiltinPython": false, // Use System Python (fixes crash)
"platformio-ide.pioHomeServerHttpHost": "0.0.0.0", // Bind to all interfaces
"platformio-ide.pioHomeServerHttpPort": 8008, // Lock to Port 8008
"platformio-ide.customPATH": "/home/pcamp96/.platformio/penv/bin" // Hard-code executable path
}
B. Manual Port Forwarding
Because auto-detection can fail, we manually forward the fixed port.
- Open Ports tab in VS Code (bottom panel).
- Click Forward a Port.
- Add 8008.
C. The "Unlock" Task (Timeout Fix)
If VS Code crashes, Port 8008 may get stuck ("Timeout Error"). We add a task to "nuke" the zombie process. Create/Edit .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Unlock PIO Home",
"type": "shell",
"command": "pkill -9 -f pio || true; pkill -9 -f python || true",
"presentation": { "reveal": "silent", "close": true }
}
]
}
D. Custom Key Binding (One-Click Remote Upload)
The default PlatformIO: Upload command attempts to flash devices connected to the Server's USB ports. Since our devices are connected to the Client Mac, we must create a custom task to trigger the Remote Upload command.
1. Define the "Remote Flash" Task
We must explicitly define the upload command as a task, so VS Code can see it. Open .vscode/tasks.json and ensure it looks like this (combining both the Unlock task and the Flash task):
{
"version": "2.0.0",
"tasks": [
{
"label": "Remote Flash",
"type": "shell",
"command": "pio remote run -t upload",
"problemMatcher": ["$platformio"]
},
{
"label": "Unlock PIO Home",
"type": "shell",
"command": "pkill -9 -f pio || true; pkill -9 -f python || true",
"presentation": { "reveal": "silent", "close": true }
}
]
}
2. Bind the Key
Now we bind a keyboard shortcut to trigger that specific task.
- Open the Command Palette (
Cmd + Shift + P). - Type and select: Preferences: Open Keyboard Shortcuts (JSON).
(Note: Select the one without "Default" in the name). - Add this entry inside the square brackets
[ ... ]:{ "key": "cmd+shift+e", "command": "workbench.action.tasks.runTask", "args": "Remote Flash" } - Save the file.
3. Usage
Press Cmd + Shift + E while editing any file. The terminal will open automatically, compile the code on the server, and push the firmware to the device plugged into your Mac.
6. Daily Workflow & Automation
A. Flashing Devices
No terminal required.
- Connect Device to Mac.
- VS Code: Press
Cmd + Shift + E(Custom keybinding forplatformio.remote.upload). - Code compiles on i9 Server -> Flashes to Mac USB.
B. Toggling the Agent (Apple Shortcut)
Since the agent holds the USB port, it must be disabled to use other tools (like Arduino IDE). Create an Apple Shortcut containing this script to toggle the service:
PLIST="$HOME/Library/LaunchAgents/org.platformio.agent.plist"
if launchctl list | grep -q "org.platformio.agent"; then
launchctl unload "$PLIST"
echo "Agent Stopped 🔴"
else
launchctl load "$PLIST"
echo "Agent Started 🟢"
fi
7. Troubleshooting
Issue: "Timeout Error" or "Could not start PIO Home Server".
Cause: The previous session left a "zombie" process holding Port 8008.
Fix: Run the "Unlock PIO Home" task in VS Code (or run pkill -9 -f pio in terminal).
Issue: "Grey/Black Screen" when opening PIO Home.
Cause: VS Code is not forwarding the port.
Fix: Manually forward port 8008 in VS Code.
No comments to display
No comments to display