Install

Install the proxy

Linux and macOS, amd64 and arm64. The script is POSIX sh. It does not call sudo.

install.sh

install.sh
curl -fsSL https://tablebelt.com/install.sh | sh
tablebelt init
tablebelt run

The script detects linux or darwin, and x86_64/amd64 or aarch64/arm64. Anything else prints a Docker hint and exits 1. It downloads tablebelt_<os>_<arch>.tar.gz and checksums.txt from the latest GitHub release, checks sha256 with sha256sum or shasum -a 256, and stops on a mismatch.

Install location: TABLEBELT_INSTALL_DIR if you set it, otherwise /usr/local/bin when that directory is writable, otherwise $HOME/.local/bin (created, with a PATH hint). If the directory you asked for is not writable, the script prints the sudo command and exits 1.

pin a version
curl -fsSL https://tablebelt.com/install.sh | env TABLEBELT_VERSION=v1.0.0 sh

That uses /releases/download/vX.Y.Z/ instead of /releases/latest/download/. TABLEBELT_DOWNLOAD_BASE overrides the releases root. It is for tests. Leave it unset.

Check the archive yourself

Goreleaser writes <sha256>  <filename> (two spaces). sha256sum -c reads that format.

checksums.txt
curl -fsSL https://github.com/ksred/tablebelt/releases/latest/download/checksums.txt -o checksums.txt
curl -fsSL https://github.com/ksred/tablebelt/releases/latest/download/tablebelt_linux_amd64.tar.gz -o tablebelt_linux_amd64.tar.gz
sha256sum -c --ignore-missing checksums.txt

Homebrew

Homebrew
brew install ksred/tap/tablebelt

Docker

Image ghcr.io/ksred/tablebelt:1 (also :latest and a version tag), amd64 and arm64. Default command is run. It listens on 5439 and the admin API on 5440.

Docker
docker run --rm ghcr.io/ksred/tablebelt:1 version

Other operating systems use this image. There is no native binary for them.

Compose

Publish the proxy only on the host loopback. Inside the container the process binds all interfaces, so set allow_plaintext_remote or terminate TLS. The upstream DSN stays in the environment, not in the image.

compose.yaml
services:
  tablebelt:
    image: ghcr.io/ksred/tablebelt:1
    command: ["run"]
    environment:
      TABLEBELT_UPSTREAM_DSN: postgres://tablebelt_admin:replace-me@db.internal:5432/app?sslmode=require
      TABLEBELT_LISTEN_ADDR: 0.0.0.0:5439
      TABLEBELT_LISTEN_ALLOW_PLAINTEXT_REMOTE: "true"
    ports:
      - "127.0.0.1:5439:5439"
      - "127.0.0.1:5440:5440"
    volumes:
      - ./tablebelt.yaml:/etc/tablebelt/tablebelt.yaml:ro

systemd

This unit is the proxy, tablebelt run. It is not the landing page API.

tablebelt.service
[Unit]
Description=Tablebelt Postgres proxy
After=network-online.target
Wants=network-online.target

[Service]
User=tablebelt
Group=tablebelt
EnvironmentFile=/etc/tablebelt/tablebelt.env
ExecStart=/usr/local/bin/tablebelt run --config /etc/tablebelt/tablebelt.yaml
Restart=on-failure
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Put the upstream DSN in /etc/tablebelt/tablebelt.env as TABLEBELT_UPSTREAM_DSN. Own tablebelt.yaml and the token files as the tablebelt user, mode 0600 for secrets. Then:

enable
sudo systemctl enable --now tablebelt

Next

tablebelt init, then tablebelt run. Point the agent at the printed URL. Host notes are on Hosts. Agent files are on Agents.