README
¶
Shed
Secure HTTP Execution Daemon
Overview
SHED is basically SSH - just over HTTPS.
SHED lets you securely execute any kernel command with an HTTP request (without a shell).
- Direct Kernel Execution (no shell)
- Bearer Token Auth (set in env var or arg)
- Structured JSON I/O
- Event Streaming
- Lightweight (9.1 MB Go Binary)
WARNING: This project is early phase and experimental. It has not been battle-tested like SSH. I wanted to get the concept out there. But, if you like the idea of a stateless remote execution architecture, feel free to test it out.
Usage
Startup
# Start with auto-generated token
shed
# Start with custom token
shed -token mysecret
# Start on a specific port
shed -port 8080
# Disable auth (usually not recommended)
shed -no-auth
On startup, shed prints the generated token. Use it in requests:
🏠 shed 0.1.0
Secure HTTP Execution Daemon
Listening on 0.0.0.0:7680
Token a1b2c3d4e5f6g7h8i9j10
Invocation
Headers
Authorization: Bearer <TOKEN>
Request Body
{
"command": ["ls", "-la", "/tmp"]
}
Response Body
{
"stdout": "total 0\ndrwxrwxrwt 2 root root 40 Feb 23 ...\n",
"stderr": "",
"stdout_lines": ["total 0", "drwxrwxrwt 2 root root 40 Feb 23 ..."],
"exit_code": 0,
"duration": "3ms"
}
Installation
- Install Go
-
Mac:
brew install go -
Linux:
sudo apt install golang-go -
Windows:
choco install golang
- Install Shed
go install github.com/oranda-io/shed@latest
- Add Go bins to your PATH:
export PATH=$PATH:$(go env GOPATH)/bin
Setup
Shed requires TLS and a bearer token by default. This creates a secure tunnel between the client and the server (much like SSH).
NOTE: You MAY run shed without a bearer token with
-no-authand without TLS with-insecure. Generally this is not recommended, but it can still be secure in some setups (e.g. private networking, ssl-proxy, etc).
TLS (self-signed)
TLS certs are required unless you use -insecure (not recommended).
TLS uses a public/private keypair. The certificate is what clients use to trust the server’s public key. With a self-signed cert, the server signs its own cert and clients must trust that exact cert.
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout key.pem -out cert.pem -days 365 \
-subj "/CN=localhost"
shed -tls-cert cert.pem -tls-key key.pem
NOTE: Clients should ideally trust the certificate (or a local dev CA). Avoid disabling TLS verification. With a local dev CA, you create a CA once and sign server certs; clients trust the CA instead.
Authentication (bearer token)
By default, shed generates a random 256-bit token on startup and prints it to stdout. Pass it as a Bearer token:
Authorization: Bearer <token>
This can be overridden by passing a token with the -token argument.
NOTE: Token comparison uses constant-time comparison to prevent timing attacks.
Tests
go test ./...
API
GET /health
Health check. No auth required.
curl https://localhost:7680/health
{ "status": "ok", "version": "0.1.0", "uptime": "2m30s" }
NOTE: The
/healthendpoint is always unauthenticated.
POST /exec
Execute a command. Returns stdout, stderr, and exit code as JSON.
curl -H "Authorization: Bearer TOKEN" \
-d '{"command": ["ls", "-la", "/tmp"]}' \
https://localhost:7680/exec
{
"stdout": "total 0\ndrwxrwxrwt 2 root root 40 Feb 23 ...\n",
"stderr": "",
"stdout_lines": ["total 0", "drwxrwxrwt 2 root root 40 Feb 23 ..."],
"exit_code": 0,
"duration": "3ms"
}
Request body:
| Field | Type | Description |
|---|---|---|
command |
string[] |
Command and arguments (required) |
stdin |
string |
Data to pipe to stdin |
env |
map<string,string> |
Additional environment variables |
cwd |
string |
Working directory |
timeout |
int |
Timeout in seconds (default: 30) |
split_lines |
bool |
Include stdout_lines / stderr_lines |
Commands are executed directly via execve — no shell is involved. This is faster and more secure than piping through /bin/sh.
POST /exec/stream
Same as /exec but streams output in real-time via Server-Sent Events.
curl -H "Authorization: Bearer TOKEN" \
-d '{"command": ["tail", "-f", "/var/log/syslog"]}' \
https://localhost:7680/exec/stream
event: stdout
data: Feb 23 12:00:01 host CRON[1234]: ...
event: stdout
data: Feb 23 12:00:02 host sshd[5678]: ...
event: exit
data: 0
Flags
-port Port to listen on (default: 7680)
-host Host to bind to (default: 0.0.0.0)
-token Auth token (env: SHED_TOKEN)
-tls-cert Path to TLS certificate (env: SHED_TLS_CERT)
-tls-key Path to TLS key (env: SHED_TLS_KEY)
-insecure Allow plain HTTP without TLS (NOT recommended)
-no-auth Disable authentication (NOT recommended)
-version Print version and exit
Motivation
Why reinvent SSH?
SSH is stateful - but the modern web is stateless (largely). With SSH, your client must maintain a persistent connection, manage reconnects, and handle the connection lifecycle. With HTTP, the lifecycle is abstracted.
SSH is streaming - but the modern web uses a request / response model (largely). With SSH, your client must hold the stream open, buffer, and parse the result to identify hangs / failures. With HTTP, the response length is known prior to send and delivery is deterministic.
SSH is plaintext - but the modern web is JSON (largely). With SSH, your client must parse the response into a form your app logic can understand. With HTTP, you are given the complete response readily available as JSON with stdout, stderr, and exit code as structured JSON properties.
Why reinvent Docker Exec?
Docker Exec is great when you have access to the Docker Host. However, if you only have access to the container (e.g. GitHub Codespaces), then you need an alternative.
Is SHED really SSH?
SSH is a huge, complex program (183,000 lines of C) that supports things like X11 Forwarding (run graphical apps from a remote server), SFTP (file transfer), TCP tunneling (secure tunnel for TCP traffic), agent forwarding, Kerberos authentication, FIDO tokens, and tons of other features that have accumulated over 30 years.
But, SSH started simple - remote execution. So, SHED is SSH in its simpler, original form.
Is SHED really as secure as SSH?
SSH started in 1995, because Telnet sent passwords in plaintext. SSL already existed, but it was designed for the request-response model. SSH was designed for persistent terminal sessions.
Interactive terminal sessions were the norm at the time, but as the web has evolved, the client-server model became the standard.
TLS establishes the same encrypted tunnel, and TLS has become the transport encryption standard. With TLS, SHED provides the same transport security as SSH.
The main difference is auth: SSH uses per-user keypairs by default. Keypairs provide "non-transferable identity", because if someone steals the public key, you're still safe.
SHED uses a bearer token, which is functionally equivalent to password auth in SSH. Both can be considered secure over an encrypted connection. mTLS (per-user client certificates) is on the roadmap for full parity.
Doesn't HTTP also hold a stateful connection?
Both HTTP and SSH hold a stateful TCP connection.
The difference is, HTTP makes the TCP connection disposable and abstracts this implementation detail.
In SSH, the connection is first-class. Managing it (e.g. opening / closing) is the developer's responsibility.
You may find an SSH client that mimics this, abstracts the stateful connection and presents a stateless interface - but you'd need to do this for every client.
HTTP already solves this at the protocol level, so every HTTP client presents a stateless interface.
Is this AI garbage?
I encountered this problem as a real human, identified the solution, and came up with the name "SHE".
I used Claude Opus 4.6 to do deep research on alternatives. It found a few, but they were bundled with more complex services.
I used Claude and Codex to assist development / testing, but I reviewed the AI generated output carefully and use this solution in my Mobile IDE.
Claude also added a "D" to the name for "Daemon", and SHED is just cute, so that's what I went with.
What is the actual use-case?
For me, it was executing remote commands on a docker container to which I did not have host access. The obvious alternative is SSH, but creating stateful sessions just to run simple commands felt like overkill. I couldn't use Docker Exec, because I didn't have host access.
Why support SSE if SSH already supports streaming?
HTTP is the standard for the modern web. All tools natively support HTTP (and most support SSE). With SSH, you need to install an SSH client to stream command output.
HTTP handles connection state for you. If the connection drops, then HTTP handles it. In SSH, if the connection drops, then your app code generally handles that.
Antipitch
Don't use SHED if you need:
- An interactive terminal (shed is one-way)
- File Transfer (scp/sftp)
- TCP Tunneling
- Port Forwarding
- Per-user OS-level isolation (at the moment, but this is on the roadmap)
License
MIT
Built by Oranda IO
Documentation
¶
There is no documentation for this package.