tui-tools

tui-secure

The machine's security posture, with the command behind every verdict

A terminal UI (TUI) for systemctl, sshd, ufw, firewall-cmd and sbctl on Linux: the security posture of one Linux machine.

v0.2.3betasecurityMIT
The posture: one row per probe, its verdict, and the score across all of them
The posture: one row per probe, its verdict, and the score across all of them

A terminal UI for the security posture of one Linux machine. Eight probes — Secure Boot, the MAC layer, the firewall, sshd, pending updates, accounts, kernel hardening and listening ports — each answered ok, warn, bad or unknown, with a score across the lot.

Every verdict shows its work. Open a probe and you get the exact command that was run, the line it judged, the full raw output underneath, and a fix that names either the sibling tool that owns the change (tui-firewall, tui-update) or the command to run yourself.

It reads first and asks second. Nothing escalates beyond sudo -n, which never prompts, so a probe that needs root it cannot get degrades to unknown with the reason instead of hanging on a password. The fixes it offers are the one-liners it can preview in full: turning on ufw, firewalld or nftables, setting one kernel key or one sshd keyword through a drop-in, enabling the update timer, stopping the service behind an open port. A change that would leave nothing able to log in over ssh is refused.

Run tui-secure --demo to drive a sample machine: every key works, every command is built and previewed for real, and nothing touches your system.

Keys

KeyAction
enterOpen the probe: evidence, raw output and the fix
aApply an offered fix, previewed and confirmed first
rRe-run every probe
RRe-run the selected probe
/Filter the probes by name, verdict or summary
?Help
qQuit

Press ? inside the tool for the full help screen, which is generated from the same action table as the key map.

Compatibility

This tool is a face on the program below, so its version matters. Tested is not a claim: a version lands there only after the tool's own suite passed against it on a real machine in the lab, and the run is kept as evidence in the repository. At startup the tool probes the backend once and says what it found in its header — a version nobody has run against is shown as (untested) in the warning colour, one older than the minimum as (below minimum) in the error colour. Neither stops it: the backend still refuses what it cannot do, in its own words.

systemd

systemctl ≥ 245
Binary
systemctl
Minimum
245
Probed with
systemctl --version
Tested
255257259261

Needs a version this new

  • journal-grepsince 246

What changes on older versions

  • systemd <246

    journalctl --grep does not exist, so the denial and failed-login counts are read by filtering the journal here instead of in journalctl, which is slower on a large journal

openssh

sshd ≥ 8.2
Binary
sshd
Minimum
8.2
Probed with
ssh -V
Tested
9.69.910.210.5

Needs a version this new

  • sshd-test-configsince 8.2

What changes on older versions

  • openssh <8.2

    sshd -T predates several of the keywords this probe reads, so the settings come from parsing sshd_config and its drop-ins instead, which does not resolve Match blocks

ufw

ufw ≥ 0.36
Binary
ufw
Minimum
0.36
Probed with
ufw --version
Tested
0.36.2

What changes on older versions

  • ufw <0.36

    ufw status verbose prints no default policy line, so the incoming and outgoing policies are reported as unknown and only the active state is judged

firewalld

firewall-cmd ≥ 0.9
Binary
firewall-cmd
Minimum
0.9
Probed with
firewall-cmd --version
Tested
2.3.22.4.4

sbctl

Binary
sbctl
Probed with
sbctl version
Tested
No recorded run yet. The tool still runs and reports the version it found as untested.

What changes on older versions

  • sbctl >=0.1

    sbctl is optional: without it the Secure Boot probe reports what bootctl status knows and says nothing about enrolled keys or signed files

Maintain systemd, openssh, ufw, firewalld or sbctl? You are welcome to help shape this tool. About → maintainers

Guides

Written after the work, from a machine the commands were actually run on. Every guide that mentions tui-secure is listed here.

  • What a bug report sends, and what it never does

    The --report flag prints the block a maintainer needs to reproduce a bug, and leaves out your hostname, your user name and your home path by construction, not by asking you to trust it.

Install

Once per machine, then every tool in the family is one pacman away.

Add the repository
$ curl -fsSL https://pkgs.tui.tools/install.sh | sh
Or run the same thing yourself, one command at a time

A family whose whole promise is preview before you run is not going to insist you pipe a script into a shell. These are the commands that script runs.

The one-time setup, by hand
$ curl -fsSL -o /tmp/tui-tools.asc https://pkgs.tui.tools/pubkey.asc
  sudo pacman-key --add /tmp/tui-tools.asc
  sudo pacman-key --lsign-key \
    "$(gpg --show-keys --with-colons /tmp/tui-tools.asc | awk -F: '/^fpr:/{print $10; exit}')"
  printf '[tui-tools]\nServer = https://pkgs.tui.tools/arch/$arch\n' \
    | sudo tee -a /etc/pacman.conf
  sudo pacman -Sy
Arch Linux · tui-secure
$ sudo pacman -S tui-secure

Upgrades then arrive with the rest of your system updates.

What it can do to your machine

  • Preview, then confirm

    Every change is shown as an exact command line and confirmed before it runs. The dialog and the runner receive the same value, so the preview cannot drift from what executes.

  • Escalates for actions

    Most probes read unprivileged. Escalation is sudo -n, which never prompts: it covers the reads only root can do (ufw status, sshd -T, /etc/shadow, sudo -l, the nftables ruleset) and the offered fixes. A probe that cannot escalate reports unknown with the reason.

  • No daemon, no state of its own

    Nothing keeps running after you quit, and nothing is installed to run later. The system is the source of truth; the tool re-reads it after every change.

  • Opens network connections

    The update probe runs the distribution's own update check (checkupdates, apt-get -s upgrade, dnf check-update), which contacts the configured package repositories. tui-secure itself opens no connection.

  • Static binary

    Released statically linked, with no runtime dependencies to install.

  • Signed release, with provenance

    checksums.txt carries a keyless cosign signature from this repository's release workflow, every archive has a CycloneDX SBOM, and every archive, package and the checksum file carry SLSA build provenance. The security page shows the three commands that check it.

Reporting

Report a security issue privately, through GitHub's private vulnerability reporting on the repository's Security tab. The family-wide policy, and what counts as in scope, is on the security page.

Downloads

v0.2.3 · 2026-09-26
FileSizeSHA-256
checksums.txt1 KB—
checksums.txt.sigstore.json10 KB—
provenance.intoto.jsonl12 KB—
tui-secure-0.2.3-1-aarch64.pkg.tar.zst1.7 MBba4b8d6cefa0967bb768c5a2d49826449b36aa097ebfed4b7c4764555d10d428
tui-secure-0.2.3-1-x86_64.pkg.tar.zst1.9 MB23611c42201d06f38f4136c1cd405548a3496054c1a5a23fb126b4124b8456d0
tui-secure-0.2.3-1.aarch64.rpm1.7 MB4ecacabb11aa60db76d19ce87a531e9ba4d29313ae89a6b196073e4f03e5c8ba
tui-secure-0.2.3-1.x86_64.rpm1.9 MBae2547d03a1307b507005f70ddf044ae69e982e788d07707de0f56ebef8cb180
tui-secure_0.2.3_amd64.deb1.9 MB817e8dee52eaed43af484137a387e76d84496057d2ebbc8e71ec7119c595df9c
tui-secure_0.2.3_arm64.deb1.7 MBe1106bc5d6ad366b8f61cf1346972d3be95416264ecb504ad0c53ae1db293789
tui-secure_0.2.3_linux_amd64.tar.gz1.9 MBc94e97970bd190c8724350b653436a225fc445fe52e7523d7a945c18153893b7
tui-secure_0.2.3_linux_amd64.tar.gz.cyclonedx.json23 KB70cbbb8400105aa521f3a4957bb7956ec3131e34b9c406be4a6d702ed3f4a880
tui-secure_0.2.3_linux_arm64.tar.gz1.7 MB4fa353a9110150c879576cc8ec19bc4b258a2c3fbbb14898d7110f78a750aa8a
tui-secure_0.2.3_linux_arm64.tar.gz.cyclonedx.json23 KBd74df1f5eaae881222ee475e0f763902fb9312ecc302126440da3f35db06357b

Every release ships a checksums.txt. Download it next to the archive and run sha256sum -c checksums.txt --ignore-missing. See verifying a download.

Releases

v0.2.3

2026-09-26
## tui-secure v0.2.3

tui-secure 0.2.3: tui-kit v0.4.4; ufw enable confirmed by the tool

tui-secure 0.2.3 moves to tui-kit v0.4.4: every probe and fix now runs in its own session without a controlling terminal, so a step that would prompt fails at once instead of hanging behind the UI, and a failed step reports its meaningful line, cleaned of escape codes. Command previews are POSIX shell-quoted, the README screenshots are re-rendered with continuous box borders, and the README banner now carries the kit's stability markers.
Enabling ufw is now confirmed by the tool alone. Without a terminal, ufw's own "Command may disrupt existing ssh connections. Proceed (y|n)?" could no longer be answered over ssh, so the fix runs `ufw --force enable`, as tui-firewall does. The question ufw used to ask moved into the confirm dialog, with its answer read first: the plan reads `ufw show added` and the default incoming policy (read-only) and checks the ssh port this session came in on, or the one sshd listens on. The dialog says plainly whether that port is allowed and by which rule. When it is not, is allowed only from some sources, or the rules could not be read, the warning is in the dialog's red title before `y`.
Validated in an ubuntu:24.04 container with ufw 0.36.2, driven through tmux: with `ufw allow 22/tcp` the dialog says ssh stays reachable, names the rule, and `y` leaves ufw active; with only `ufw allow 80/tcp` the title reads "Enable ufw: ssh port 22 is NOT allowed", `n` cancels, and ufw stays inactive.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* be29a96df1ce4d39255cea7622e4a51550bf0e99 0.2.3: tui-kit v0.4.4; ufw enable confirmed by the tool (#21)
* 010c5589760c596c5bcc28605cc37fd0b3f22547 Bump anchore/sbom-action/download-syft (#3)
* 8d879e949a0b8dc269f8f5fdb9b093d51f3525b5 Bump anchore/sbom-action/download-syft in the github-actions group (#19)
* 2031a51f55eb1e0700f979c5e01a45eb9bfc0748 Bump the github-actions group with 4 updates (#20)
* 9e576ce95f69ed643b178ff15964b597fcbda9ed README: link the tool's page on tui.tools (#18)
* 6e31ba3402a9516804a20a4d9cd3fbe5a7ad55ce README: point the install snippet at the current release (#17)

v0.2.2

2026-09-02
## tui-secure v0.2.2

Offer the sshd fix the row says is missing, and count the kernel fixes it has.

Also: tui-kit v0.3.0 — dialogs wrap and scroll instead of clipping the
command preview, and the picker filters as you type.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* 7d750eb5603b43ea6e0a966a5cffb5b854161219 Bump tui-kit to v0.3.0 (#16)
* c05ce5371986bce81e7c59fd24a13fe9884a641b Offer the sshd fix the row says is missing, and count the kernel fixes it has (#15)

v0.2.1

2026-09-02
## tui-secure v0.2.1

v0.2.1

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* 9b637fb7afd8b7c18249de291c754140ce151aba Say which binary the smoke tests, and unmap loopback before judging reach (#14)

v0.2.0

2026-09-01
## tui-secure v0.2.0

Manage, not view (wave 2): apply what it diagnoses, author what it manages; lab-validated.

Built by this repository's CI on the tag itself. Each archive ships a
CycloneDX SBOM, `checksums.txt` carries a keyless cosign signature, and
every file has SLSA build provenance — see the README's "Verify a
download" for the two commands that check them.

The commits in this release:

## Changelog
* c5a191d091e4947e57b91fe844de39ed8e828376 A code of conduct that fits on one screen (#9)
* 4b57e20142a7fac45d875f55f8676bfe99a52209 Add --report, and a bug form that asks for it (#10)
* 2dac58457540acc789a7fc5376e4df7248cad741 Apply what it diagnoses: sshd enforce, firewall enable parity (#12)
* 3ef24068d59c29e9f3800d53859cd99923b2d671 Carry the OpenSSF Best Practices badge (#7)
* ffb5783b67e339861b058f6aebd57f78febca4b7 Do not search the distro line for the host name (#11)
* d63ad90fe05d8ce7dc193a7cf3eee7730ee39a50 Fetch the tag annotation before releasing (#5)
* 1fae5ffa4f0e31ab2b2eafdc6a467208c0cd2152 Pin what CI runs, fuzz the parsers, and say the releases are signed (#2)
* 0c4754496b6e6742db60fa0f64f9c78a34851758 Print the whole tag message, not only its body (#6)
* fd1832b11e5d72c47a601b490674111b73670940 Say beta once (#4)
* 3e2504de4d96d2245d929d3f6e94b8f9abc04bbb Take tui-kit v0.2.8: hashed pip install, provenance bundle on the release (#8)

v0.1.2

2026-08-30
## Changelog
* a6db62ae259503283f6003ae802d95d7ab84fda4 Drop cross-repo dispatch; the package repo and the site poll releases
* 18863b793ca7df03f4eef7d3da6642e51f4f877f Gate the release on a security job, and sign what it publishes (#1)
* 9b78d4e93303b38f0d081ea2bf1d14f41666331f Stop telling readers the packages are unpublished

v0.1.1

2026-08-30
## Changelog
* 23296ec4701a65c4cca4b00c3cb0ccfb57e7964d Packages are available from pkgs.tui.tools
* a9a974009f517847df38208adfee279cfbd4e2cb Re-pin the kit at v0.2.3
* 2002cc75b4a739eb15550fe7ddcf33076254a2ba Record the first real-machine compatibility run
* cc619794049ce563e93019913e448735ae35a015 Ship the tool as a .deb, an .rpm and a pacman package

v0.1.0

2026-08-30
## Changelog
* 5dc90ba63ada888548d488933f2a156290368403 Give it a face: the branding, six frames and the README
* c88b946d7742b36472d82684d08e29c36b8a4117 Initial commit
* ba9c696b4571b6f1d361b32ff47bb01fc10130ca Point the install line at v0.1.0
* aac2efff07610fc50ec9b580163f67e9dd524803 Prove it against a real machine, and record which one
* 95ec8cf975f35dff981e890546967345579d41a8 Read the machine's posture: the model, the backend and its probes
* 1e2288fb487f499f895d7e66a01c376cbecafb83 Start tui-secure from the family template
* 970ac953a060e0e4752f796b52322e06e0fa7f73 The screens: the posture, one probe in full, and one confirm dialog