# TinySSH review: a minimal SSHv2 server for constrained systems

> TinySSH is a compact C SSH server built around a restricted SSHv2 feature set and modern cryptography. It fits controlled shell-access deployments, but its lack of password authentication, forwarding, compression, and client environment variables is substantial.

**janmojzis/tinyssh** — TinySSH is small server (less than 100000 words of code)

- Repository: https://github.com/janmojzis/tinyssh
- Stars: 1,535 · Forks: 83
- Language: C
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/janmojzis-tinyssh

## TinySSH's restricted SSHv2 scope

TinySSH, implemented as the tinysshd server, provides remote shell access while deliberately excluding much of the SSH feature surface found in general-purpose servers. The README describes it as a minimalistic implementation of a subset of SSHv2. It does not implement SSH1, compression, port forwarding, agent forwarding, or X11 forwarding. Password and hostbased authentication are also absent because the project classifies them as unsafe features.

The target user is an administrator who needs SSH shell access but does not depend on those excluded capabilities. The code-size constraint is central to the project. The repository description calls TinySSH less than 100,000 words of code, and the README states that release 20261001 contains 74,260 words of code. The README labels 20261001 a beta release and describes beta as ready for production use, although it still describes stable as an expected future stage.

That narrow scope affects adoption more than conventional deployment options. A client configuration that expects a password prompt, forwarded port, X11 session, compressed stream, or transferred environment variable will not match TinySSH's documented behavior. Missing features are easy to classify. The environment-variable restriction is also explicit: TinySSH has rejected every client-supplied `env` channel request since version 20260906. This is a deliberate compatibility change rather than a missing convenience setting.

## Curve25519, sntrup761, Ed25519, and ChaCha20-Poly1305

TinySSH uses a compact modern algorithm set rather than negotiating the broad historical catalogue associated with SSH. For version 20261001, the README lists `curve25519-sha256`, `curve25519-sha256@libssh.org`, `sntrup761x25519-sha512@openssh.com`, and `sntrup761x25519-sha512` for `KexAlgorithms`. The documented cipher is `chacha20-poly1305@openssh.com`, and the host key algorithm is `ssh-ed25519`.

The README also lists `hmac-sha2-256` under `MACs`. It explains that this algorithm is advertised for protocol compatibility, while packet authentication comes from the `chacha20-poly1305@openssh.com` AEAD cipher. TinySSH implements the OpenSSH strict key-exchange extension `kex-strict-s-v00@openssh.com`.

Two documented command-line options can restrict the exchange set further. The Curve25519 algorithms can be disabled with `-S`. The post-quantum `sntrup761x25519-sha512@openssh.com` algorithm can be disabled with `-P`. These switches provide limited policy control, but the README does not document a file-based algorithm policy. A deployment that must enforce an organization-wide SSH cipher policy would need to establish separately whether TinySSH can satisfy it.

Older cryptography is intentionally unsupported. The README names RSA, DSA, HMAC-MD5, HMAC-SHA1, 3DES, and RC4 as examples that TinySSH does not implement. Client compatibility therefore needs an explicit check against the algorithms above, especially for embedded clients or old administrative systems.

## Fixed-size packet paths and authorization memory

The README states that TinySSH processes SSH packets with fixed-size buffers. This supports the project's compact design by avoiding a general-purpose allocation policy for ordinary packet handling. The repository layout is consistent with that architecture. It includes separate C modules and headers for packet reception and transmission, packet parsing, packet authentication, channel requests, channel opening, connection information, key exchange, and channel backends.

Authorization path resolution is different. The README says it uses dynamically allocated memory, and that an allocation failure rejects authorization. That boundary is explicit: memory-allocation failure does not cause the server to proceed with an unresolved or incomplete authorization path. The README does not describe any fallback path, retry policy, or operational setting for this case.

Repository files further show separate implementations for stream encryption, authentication, signature verification, X25519 scalar multiplication, Ed25519 signing, SHA-256, SHA-512, and sntrup761x25519 key establishment. This separation allows the server to combine its own cryptographic code with optional library implementations, but the README does not explain the build-time selection process in enough detail to assess which variant an installation uses.

Fixed buffers should not be read as a performance claim. The repository contains `_tinysshd-speed.c`, but neither the README nor the listed Makefile rules provide a benchmark procedure or results. Engineers evaluating constrained hardware therefore need to inspect their own deployment rather than infer throughput from the file name.

## Building and installing the tinysshd binaries

The README gives a short source build followed by a privileged installation. Run these commands from the repository root:

```bash
make
sudo make install
```

The first command builds the project. The second installs its files under the configured prefix, which defaults to `/usr/local` in the Makefile. The Makefile also recognizes `CC`, `CFLAGS`, `LDFLAGS`, `CPPFLAGS`, `DESTDIR`, `PREFIX`, and `INSTALL`, so a packager can supply its own build or installation variables. The README does not provide a dependency-install step.

After installation, create the server key directory and initialize its host key as follows:

```bash
mkdir -p /etc/tinyssh
tinysshd-makekey /etc/tinyssh/sshkeydir
```

The first command creates the parent directory under `/etc`. The second asks `tinysshd-makekey` to prepare the key directory. The README's launch examples then pass `/etc/tinyssh/sshkeydir` to `tinysshd`.

The Makefile identifies `tinysshd`, `tinysshd-makekey`, `tinysshd-printkey`, and `tinysshnoneauthd` as linked programs. The README does not document the role of `tinysshnoneauthd`, so it should not be substituted for the normal daemon without checking its source and intended deployment context.

## Starting TinySSH with tcpserver or BusyBox

TinySSH's launch model delegates listening to an external service wrapper. The README gives a `tcpserver` command that listens on TCP port 22 and starts `tinysshd` for accepted connections:

```bash
tcpserver -HRDl0 0.0.0.0 22 /usr/sbin/tinysshd -v /etc/tinyssh/sshkeydir &
```

Here, `0.0.0.0` requests listening on all IPv4 interfaces, while the key directory is `/etc/tinyssh/sshkeydir`. The exact meaning of every `tcpserver` flag is outside TinySSH and is not documented in the project README. Operators should review the flags against their local `tcpserver` documentation rather than assuming that the example defines a portable policy.

The README also provides a BusyBox `tcpsvd` example:

```bash
busybox tcpsvd 0 22 tinysshd -v /etc/tinyssh/sshkeydir &
```

This form relies on BusyBox and on `tinysshd` being discoverable in the command path. It differs from the preceding example in both listening utility and executable path. The README does not provide a BusyBox build recipe or list the applets required beyond the shown `tcpsvd` invocation.

Both examples run the listener in the background with `&`. The README does not document log routing, process supervision, restart behavior, or shutdown handling for these two forms. A production service should preserve the documented listening command while supplying the missing lifecycle management from the host system's service configuration.

## TinySSH under inetd and systemd socket activation

For inetd systems, the README places an SSH service entry in `/etc/inetd.conf`:

```bash
ssh stream tcp nowait root /usr/sbin/tinysshd tinysshd -l -v /etc/tinyssh/sshkeydir
```

This entry asks inetd to handle the socket and invoke the server. The command includes `-l` and `-v`, but the README does not define these flags. The extra `tinysshd` shown after the executable path appears in the documented line, so it should not be silently removed when converting the example into a configuration.

The systemd example is split between a socket unit and a templated service unit. The socket listens on port 22 and accepts connections:

```ini
[Socket]
ListenStream=22
Accept=yes
```

The service prepares the key directory quietly, loads optional environment settings, and starts TinySSH:

```ini
[Service]
ExecStartPre=-/usr/sbin/tinysshd-makekey -q /etc/tinyssh/sshkeydir
EnvironmentFile=-/etc/default/tinysshd
ExecStart=/usr/sbin/tinysshd $TINYSSHDOPTS -- /etc/tinyssh/sshkeydir
```

The service also sets `KillMode=process`, accepts exit status 111, connects standard input to the socket, and sends standard error to the journal. The socket unit checks that `/etc/tinyssh/disable_tinysshd` does not exist. The README does not document the contents of `/etc/default/tinysshd`, so deployments must define only settings appropriate to the installed version.

## Environment requests, legacy clients, and maintenance boundaries

Since version 20260906, TinySSH rejects client-supplied environment variables carried in `env` channel requests. The README warns specifically about OpenSSH `SendEnv` and `SetEnv`. A required value must instead exist on the server. This change can alter application startup when a shell expects per-session configuration sent by the client.

TinySSH is therefore the wrong server for workflows that require environment transfer. It is also the wrong choice when users depend on password authentication or when infrastructure requires SSH1, port forwarding, agent forwarding, X11 forwarding, or compression. Unlike OpenSSH, whose client options are referenced in the compatibility warning, TinySSH implements a much smaller protocol surface. The tradeoff is reduced feature scope rather than a drop-in SSH replacement.

The repository is not archived, and its last push was on 2026-10-16. Releases 20261001, 20260906, and 20260601 were published on 2026-10-01, 2026-09-06, and 2026-06-01, respectively. These dates show continued repository and release activity, but they do not prove compatibility with a particular distribution.

The project uses a custom license in `LICENSE.md`. GitHub's repository classification does not summarize its permissions or conditions, and the README does not replace that document. Integrators must inspect `LICENSE.md` before redistribution. The README also does not document a rollback procedure, upgrade migration guide, supported operating-system matrix, or service-account setup checklist.

## Conclusion

Adopt TinySSH when a compact SSH server with a deliberately restricted feature set fits the deployment and systemd, tcpserver, BusyBox, or inetd is available. Do not adopt it for password-based access, port forwarding, agent forwarding, X11 forwarding, compression, or client-supplied environment variables. Before deployment, verify the custom LICENSE.md terms, the required client algorithms, and the operating-system service configuration.

## FAQ

### How do I install TinySSH?

The README documents building the source with `make` and installing it with `sudo make install`. It then shows creating `/etc/tinyssh/sshkeydir` with `tinysshd-makekey`.

### Does TinySSH support password authentication?

No. The README explicitly lists password authentication and hostbased authentication as unsafe features that TinySSH does not implement.

### Can TinySSH accept environment variables from an SSH client?

No. Since version 20260906, TinySSH rejects client-supplied environment variables in `env` channel requests. The README says required variables must be set on the server instead.

### Which SSH algorithms does TinySSH support?

For version 20261001, the README lists four key exchanges, `chacha20-poly1305@openssh.com` as the cipher, and `ssh-ed25519` for host keys. It also advertises `hmac-sha2-256` for protocol compatibility.

### Can TinySSH run under systemd?

Yes. The README provides socket and service units that listen on port 22, prepare the key directory, read `/etc/default/tinysshd`, and launch `tinysshd` with `/etc/tinyssh/sshkeydir`.

## Sources

- [Issues](https://github.com/janmojzis/tinyssh/issues)
- [janmojzis/tinyssh on GitHub](https://github.com/janmojzis/tinyssh)
- [README](https://github.com/janmojzis/tinyssh/blob/master/README.md)
- [Releases](https://github.com/janmojzis/tinyssh/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/janmojzis-tinyssh
