smith

module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2026 License: Apache-2.0

README

smith

Project status: early development. Smith is currently being built for personal use and experimentation. Interfaces, configuration and internal architecture may change without notice.

Smith turns a fresh VPS into a ready-to-use remote development machine and manages coding agents across the repositories on it.

Install

smith ships as a single static binary. Grab the latest release with the one-liner for your platform — it fetches the v0.1.0 archive, unpacks it in the current directory, and leaves the smith binary alongside its LICENSE and README. Move it onto your PATH afterwards (e.g. sudo mv smith /usr/local/bin/).

Fetch with curl, not your browser. smith is unsigned. A browser stamps every download with a quarantine flag, so macOS Gatekeeper then refuses to run it; curl and wget don't set that flag, so a curled binary runs untouched. The commands below are the supported path for exactly this reason. If you did download through a browser, see Gatekeeper below.

macOS (Apple silicon):

curl -L https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_darwin_arm64.tar.gz | tar xz

macOS (Intel):

curl -L https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_darwin_amd64.tar.gz | tar xz

Linux (x86-64):

curl -L https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_linux_amd64.tar.gz | tar xz

Linux (ARM64):

curl -L https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_linux_arm64.tar.gz | tar xz

Windows (x86-64) — download the zip, then extract it (modern tar on Windows 10+ handles zips):

curl -L -O https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_windows_amd64.zip
tar -xf smith_0.1.0_windows_amd64.zip

Confirm it: smith version should print 0.1.0.

Verify the checksum

The curl | tar one-liners are the fast path. To verify first, download the archive to disk instead of piping it, check it against checksums.txt, then unpack — shown here for macOS Apple silicon (substitute your archive name):

curl -L -O https://github.com/byranZA/smith/releases/download/v0.1.0/smith_0.1.0_darwin_arm64.tar.gz
curl -L -O https://github.com/byranZA/smith/releases/download/v0.1.0/checksums.txt

shasum -a 256 -c checksums.txt --ignore-missing   # macOS
sha256sum   -c checksums.txt --ignore-missing      # Linux

tar xzf smith_0.1.0_darwin_arm64.tar.gz

--ignore-missing verifies just the archive you downloaded and skips the rest. Expect a single ... : OK line.

Install with go install

If you have the Go toolchain (1.26+, matching smith's go.mod), build and install from the module tag directly:

go install github.com/byranZA/smith/cmd/smith@v0.1.0

This resolves the tag, builds from source, and stamps the version from the module path — smith version still reports 0.1.0, with no ldflags involved. The binary lands in $(go env GOBIN) (or $(go env GOPATH)/bin); make sure that's on your PATH.

Build from source

To build from a checkout instead:

make build   # produces ./bin/smith

A binary built this way reports smith version as dev — it carries no release tag. Use curl or go install for a version-stamped build.

Gatekeeper (macOS)

If you downloaded through a browser and macOS refuses to open smith — "smith cannot be opened because the developer cannot be verified" — clear the quarantine flag the browser set, then run it:

xattr -d com.apple.quarantine ./smith

Or just re-fetch with the curl one-liner above, which never sets the flag in the first place.

Windows / SmartScreen

The Windows story is weaker than the macOS one. SmartScreen keys off reputation as well as Mark-of-the-Web, so a freshly published unsigned binary can be flagged even when fetched with curl, and reputation only builds with downloads over time. If SmartScreen blocks it, choose More info → Run anyway.

Compatibility

smith is v0.x — there is no compatibility promise. Flags, config, and behavior may change between releases without notice. Pin to an exact tag rather than tracking latest.

Provisioning a VPS

smith machine setup takes a fresh box and makes it a secure, reachable development machine: it creates a smith user with your SSH key, enables a default-deny firewall, hardens SSH (no root login, no passwords), and turns on fail2ban and automatic security updates. Re-running is safe — every step checks before it changes anything.

Prerequisites

You'll need the smith binary on your PATH — see Install above.

The box you're provisioning must be:

  • A fresh Ubuntu 24.04 LTS or newer.
  • Reachable over SSH as root, or as a user with passwordless sudo. Smith connects non-interactively, so ssh <login>@<host> must log you in with no prompt at all — including no key passphrase (load a passphrase-protected key into ssh-agent first). This is the same access you used to reach the box; smith reuses it, copying that login's authorized_keys onto the new smith user.
Provision (public)

Point smith at the box as <login>@<host>:

smith machine setup root@203.0.113.10
# or a sudo-capable user:
smith machine setup ubuntu@203.0.113.10

When it finishes, the box is reachable as the smith user over hardened public SSH. Confirm it:

smith machine status 203.0.113.10

status connects as smith and reports how the box has drifted from what setup established (it never changes anything — pass a bare <host>, not <login>@<host>).

Provision over Tailscale

To reach the box over a tailnet instead of the public internet, use --access tailscale. This requires the machine you're running smith from to already be a member of the tailnet (the tailscale CLI installed and running), plus a Tailscale auth key passed as a reference — env:VAR or file:/path, never a bare literal.

First, add two entries to your tailnet ACL policy. An auth key can join a node but can't edit policy, so smith can't add these for you:

// declares tag:smith so the enrolled node's key never expires
"tagOwners": { "tag:smith": ["autogroup:admin"] },

// grants your identity SSH access to tag:smith (replace <your-identity>)
"ssh": [
  { "action": "accept", "src": ["<your-identity>"], "dst": ["tag:smith"], "users": ["smith"] }
]

Without the first, the box enrolls but never reaches Running; without the second, it enrolls but the SSH probe is denied. (Prefer to run first? smith prints these personalized to your identity and stops so you can add them.)

Then provision:

smith machine setup ubuntu@203.0.113.10 \
  --access tailscale \
  --tailscale-auth-key env:TS_AUTHKEY

Omit --tailscale-auth-key on an interactive terminal and smith prompts for it without echoing. Smith only closes public SSH once it has verified the box is reachable over the tailnet, so a policy that isn't ready yet never locks you out.

After a successful tailscale setup, smith prints the tailnet name to use from then on:

smith machine setup smith@smith-<host>   # re-run over the tailnet
smith machine status smith-<host>        # check status over the tailnet
Tailscale notes
  • Access is keyless after enrollment. Once the box is on the tailnet you no longer manage an SSH key to reach it — Tailscale authenticates you by identity and the ACL rule decides access. The box's public SSH (port 22) is closed, so the tailnet is the only way in.
  • Authorization follows you, not one machine. The ACL src is your tailnet user login, which matches every device you own on the tailnet. Any of your machines that's on the tailnet can ssh smith@smith-<host> or run smith machine status smith-<host> — no key, no per-machine setup. To run machine setup from another machine it also needs the tailscale CLI and to be a running tailnet member.
  • The first provision still uses your SSH key. A brand-new box isn't on the tailnet yet, so the initial --access tailscale run reaches it over public SSH as your bootstrap login (key-based) to install and enroll Tailscale, then closes public 22. The keyless model applies to everything after that.

Directories

Path Synopsis
cmd
smith command
Command smith turns a fresh VPS into a provisioned, secured, reachable remote development machine and manages coding agents on it.
Command smith turns a fresh VPS into a provisioned, secured, reachable remote development machine and manages coding agents on it.
internal
bootstrap
Package bootstrap is the Go side of the on-box provisioning harness.
Package bootstrap is the Go side of the on-box provisioning harness.
cli
Package cli is the cobra command surface for smith.
Package cli is the cobra command surface for smith.
connection
Package connection is the one exec boundary smith uses to reach a box: a thin wrapper over the system ssh and scp binaries.
Package connection is the one exec boundary smith uses to reach a box: a thin wrapper over the system ssh and scp binaries.
marker
Package marker models smith's on-box bootstrap marker: the /etc/smith/bootstrap.json ledger that records what setup did to a box.
Package marker models smith's on-box bootstrap marker: the /etc/smith/bootstrap.json ledger that records what setup did to a box.
osgate
Package osgate is the OS support gate: it decides whether a box's operating system is one smith supports.
Package osgate is the OS support gate: it decides whether a box's operating system is one smith supports.
secret
Package secret resolves a secret reference into its value without the secret ever touching a command line.
Package secret resolves a secret reference into its value without the secret ever touching a command line.
status
Package status is the read-only, state-oriented half of smith's setup/status seam: `smith machine status <host>` reads the on-box marker, re-probes the box's live facts, and reports how the box has drifted from what setup established — without ever changing it.
Package status is the read-only, state-oriented half of smith's setup/status seam: `smith machine status <host>` reads the on-box marker, re-probes the box's live facts, and reports how the box has drifted from what setup established — without ever changing it.
tailscale
Package tailscale drives smith's --access=tailscale layer: it joins the box to the operator's tailnet as a keyless Tailscale SSH node tagged tag:smith, then closes public SSH — but only after a live ssh-over-tailnet probe from the admin machine proves the new door opens.
Package tailscale drives smith's --access=tailscale layer: it joins the box to the operator's tailnet as a keyless Tailscale SSH node tagged tag:smith, then closes public SSH — but only after a live ssh-over-tailnet probe from the admin machine proves the new door opens.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL