Skip to content

Repository files navigation

et.rs

GitHub release AUR version Homebrew tap

A Rust port of Eternal Terminal — a remote shell that automatically reconnects without interrupting the session.

Wire-compatible with upstream protocol version 6: an et.rs client can talk to a C++ etserver, and a C++ et client can talk to an et.rs server, in both terminal and port-forwarding modes. How we track upstream (Rust rewrite, not a C++ git fork): docs/upstream-factory.md.

Windows is a first-class target. Upstream has no native server there, so hosting a session on Windows meant running the POSIX server inside WSL and landing in a WSL shell. et.rs runs the server and the per-session terminal natively on Windows using ConPTY, so et gives you a real cmd.exe or PowerShell — no WSL involved.

Install

Homebrew (macOS, Linux)

brew install minpeter/tap/et-rs

Installs et plus the etserver, etterminal, htm, and htmd role symlinks. The formula conflicts with the upstream et formula — et.rs is a drop-in replacement, so uninstall one before installing the other. Upgrade later with brew upgrade et-rs.

AUR (Arch Linux)

yay -S et-rs-bin
# or
paru -S et-rs-bin

Installs the prebuilt release binary (x86_64, aarch64) with the role symlinks. Conflicts with the eternal-terminal package for the same drop-in-replacement reason.

Prebuilt binaries

Every release ships archives (with .sha256 checksums) for Linux (gnu/musl, x86_64/aarch64), macOS (x86_64/aarch64), and Windows (x86_64). The tarballs already contain the role symlinks:

curl -LO "https://github.com/minpeter/et.rs/releases/latest/download/et-VERSION-TARGET.tar.gz"
sudo tar -xzf et-VERSION-TARGET.tar.gz -C /usr/local/bin --strip-components=1

To run the server on boot (Linux):

# /etc/systemd/system/et.service
[Unit]
Description=EternalTerminal server (et.rs)
After=network.target

[Service]
ExecStart=/usr/local/bin/etserver
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now et    # and open 2022/tcp in your firewall

Build from source

cargo build --release                                  # host
cargo build --release --target x86_64-pc-windows-gnu -p et   # et.exe

Requires protoc (Protocol Buffers compiler) on the build host.

Roles

One binary provides every role, selected by argv[0] (busybox-style symlinks) or by a leading subcommand:

Upstream binary et.rs invocation Windows
et et <host> / et client <host> yes
etserver etserver / et server yes
etterminal etterminal / et terminal yes
htm htm / et htm yes
htmd htmd / et htmd yes
ln -s et etserver && ln -s et etterminal && ln -s et htm && ln -s et htmd

Usage

et user@host
et -c 'uptime' user@host:2022
et -t 8080:80 -r 9000:9000 user@host          # forward and reverse tunnels
et -f user@host                                # forward the ssh-agent socket
et --jumphost jump.example --jport 2022 \
   --jserverfifo /tmp/etserver.fifo1 dst:2022  # ET-native jumphost relay
etserver --daemon --pidfile /var/run/etserver.pid
htm                                            # headless terminal multiplexer

Connecting to a Windows host

# on the Windows machine (needs Windows 10 1809+ for ConPTY)
et.exe server --daemon --port 2022 --pidfile "%LOCALAPPDATA%\etserver\etserver.pid"
netsh advfirewall firewall add rule name="et" dir=in action=allow protocol=TCP localport=2022
# from anywhere
et user@windows-host:2022                               # auto-detects cmd.exe login shell
et --winserver user@windows-host:2022                   # explicitly force cmd.exe bootstrap
et --remote-shell powershell user@windows-host:2022     # PowerShell session

Bare clients run a credential-free %ComSpec% SSH probe before bootstrap. An expanded cmd.exe path selects the Windows bootstrap (no printf, CRLF lines, & separator) and defaults --terminal-path to et.exe; a literal %ComSpec% preserves POSIX behavior. --winserver remains the explicit override. The session shell follows %COMSPEC%, or ET_SHELL if set on the server. OpenSSH on Windows must be reachable.

Connecting from Ghostty

Ghostty identifies itself as TERM=xterm-ghostty, but many remote hosts do not have that terminfo entry and stock shell profiles may not recognize it as color-capable. ET sends TERM=xterm-256color for Ghostty clients so remote prompts and applications retain broadly supported 256-color behavior. Ghostty's standard COLORTERM=truecolor hint is also forwarded to POSIX sessions so applications that use it for 24-bit color detection do not downgrade. Other terminal types are forwarded unchanged.

Feature set

  • Protocol v6 handshake, crypto_secretbox (XSalsa20-Poly1305) framing, sequence numbers, and catch-up buffers, pinned to upstream bytes by golden fixtures in fixtures/wire.json.
  • Reconnecting client and server sessions with backed reader/writer replay.
  • SSH bootstrap (IDPASSKEY handshake), remote PTY, window resize, keepalives, --command execution, and --no-terminal mode.
  • Forward, reverse, Unix-socket, port-range, environment-variable named-pipe, and ssh-style (bind_address:port:host:hostport, bracketed IPv6) tunnels.
  • SSH-agent forwarding via a server-created socket exported as SSH_AUTH_SOCK.
  • ET-native jumphost relay (client, etserver JUMPHOST_INIT dispatch, and etterminal --jump).
  • etserver INI configuration, daemon mode with pid file, log files honouring --logdir, --logtostdout, --silent, --verbose, and log rollover.
  • Headless terminal multiplexer (htm/htmd) with upstream's base64 IPC framing, JSON state, tabs/splits/panes, and pane buffer replay.
  • Native Windows server and terminal: ConPTY shells, a loopback router authenticated with a per-server token, job-object breakaway so sessions survive the bootstrap ssh, and a console client that maps keys (including navigation keys upstream drops) to ANSI sequences.
  • No telemetry: --telemetry is accepted for compatibility and ignored.
  • #![forbid(unsafe_code)] across every crate.

Windows notes

  • The router is a loopback TCP listener; its address and a CSPRNG token live in the --serverfifo endpoint file under %LOCALAPPDATA%\etserver, which takes the place of Unix socket permissions.
  • HTM runs native ConPTY panes on Windows 10 1809+; use et.exe htm from an HTM-capable terminal emulator. It is a protocol relay, not a standalone pane UI. The pane shell is SHELL, then COMSPEC, then cmd.exe; its home is USERPROFILE.
  • HTM IPC uses an authenticated loopback endpoint at %LOCALAPPDATA%\et-htm\htm.ipc. The endpoint inherits the user-private application directory ACL, like the router. --socket on both HTM roles selects an isolated endpoint; on Windows it must remain below that user's LOCALAPPDATA tree, without junctions or parent traversal. Do not grant other users access to this directory or its token files. htm -x shuts down only the selected authenticated daemon, not named fleet processes.
  • HTM first requests Windows job breakaway. If the host denies it, HTM reports the restriction and starts a detached, handle-isolated daemon within the host job. It survives the launching htm client, but not termination of that host job. The stricter etserver/etterminal SSH-bootstrap breakaway policy is unchanged.
  • Unix-socket tunnels remain POSIX-only.
  • Inbound connections need a firewall rule; the server does not modify firewall state itself.

Tests

cargo test --workspace

License

Apache-2.0

About

Single telemetry-free EternalTerminal (Rust port)

Resources

Stars

19 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages