Files
threshold/README.md
T
shadowdaoandClaude Sonnet 5.5 d07030a10b Make in-place upgrade from HashiCorp Boundary seamless
Linux packages: migrate /etc/boundary.d to /etc/threshold.d without
clobbering, reuse the boundary service user, carry over service
enablement with a boundary.service alias, provide a boundary command.
Docker: accept /boundary/config.hcl, boundary command, /boundary symlink.
CLI: deprecation notice when invoked as boundary (stderr only).
Dev mode: also create *.threshold.dev aliases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 11:12:29 -07:00

195 lines
9.8 KiB
Markdown

# Threshold
Threshold provides simple and secure access to hosts and services. It is a
community-maintained fork of HashiCorp Boundary Community Edition (CE).
## About this fork
Threshold is a community fork of [HashiCorp Boundary Community Edition](https://github.com/hashicorp/boundary).
HashiCorp (an IBM company) archived the upstream Boundary CE repository on
2026-10-09 and announced that no further CE releases, maintenance updates, bug
fixes or security patches are planned. Threshold continues maintenance of the
Community Edition code base so that existing self-managed deployments can keep
receiving fixes.
- Threshold is licensed under the [Business Source License 1.1](LICENSE), the
same license as the upstream code. The original license text and all
copyright headers are preserved. See [NOTICE](NOTICE) for attribution.
- **Threshold is not affiliated with, endorsed by, or sponsored by HashiCorp or
IBM.** "Boundary", "HashiCorp" and "HCP Boundary" are trademarks of their
respective owners and are used here only to describe the origin of this
project.
- Upstream project: <https://github.com/hashicorp/boundary>
- This repository: <https://repo.anhonesthost.net/CyberCoveLLC/threshold>
### Compatibility with Boundary CE
This is the first phase of the rebrand and is designed to keep existing
Boundary CE deployments working:
- The command-line binary is now `threshold` (built from `cmd/threshold`).
- The wire protocol, HTTP API paths (`/v1`), database schema, plugin protocol
and configuration file format are unchanged.
- The Go module path is `repo.anhonesthost.net/CyberCoveLLC/threshold` (with `/api` and `/sdk`
submodules); protobuf code has been regenerated for it.
- Release versions are still reported on the wire with the upstream
`Boundary v` prefix so mixed clusters keep working. `Threshold v` is also
accepted when parsing.
### Environment variable and path fallbacks
Threshold prefers `THRESHOLD_*` environment variables, and transparently falls
back to the legacy `BOUNDARY_*` name when the `THRESHOLD_*` variable is not set.
For example `THRESHOLD_ADDR`, `THRESHOLD_TOKEN`, `THRESHOLD_SCOPE_ID`,
`THRESHOLD_KEYRING_TYPE`, `THRESHOLD_TOKEN_NAME`, `THRESHOLD_CONNECT_*`,
`THRESHOLD_SKIP_CACHE_DAEMON` and the other CLI and server variables are read
first, then `BOUNDARY_ADDR`, `BOUNDARY_TOKEN`, and so on. A `THRESHOLD_*` variable that is
set to a non-empty value always wins. Existing scripts and deployments that
only set `BOUNDARY_*` variables do not need to change.
Notes:
- `env://VAR` references inside configuration files and flags (for example
`url = "env://BOUNDARY_POSTGRES_URL"` or `url = "env://THRESHOLD_POSTGRES_URL"`
as used by the bundled container config) name an environment variable
literally and are not rewritten; keep using whichever variable name you export.
- `threshold connect -exec` exports both `THRESHOLD_PROXIED_{PORT,IP,ADDR}` and
the legacy `BOUNDARY_PROXIED_{PORT,IP,ADDR}` variables to the child process.
- The container image entrypoint mirrors any `BOUNDARY_*` variables to the
matching `THRESHOLD_*` variable when it is unset.
Other fallbacks:
| Item | New | Legacy fallback |
|------|-----|-----------------|
| Client cache directory | `~/.threshold` | `~/.boundary` is used if it exists and `~/.threshold` does not |
| Keyring entry (macOS Keychain / Windows Credential Manager) | `Threshold Auth Token` | `HashiCorp Boundary Auth Token` is read if the new entry is not found, and removed on `threshold logout` |
| Keyring prefix (`pass`, libsecret) | `Threshold` | `HashiCorp_Boundary` is read if the new entry is not found, and removed on `threshold logout` |
Tokens are always written using the new names.
## Upgrading from Boundary
Threshold is designed as an in-place replacement for HashiCorp Boundary CE:
the same database, the same configuration files, and a binary that can still be
invoked as `boundary`.
### Compatibility guarantees
These are unchanged from upstream Boundary CE, so a mixed fleet of Boundary and
Threshold controllers and workers interoperates, and you can upgrade (and roll
back) one node at a time:
- **Database schema**: the schema migrations are untouched and the
`boundary_schema_version` table keeps its name. Threshold runs against an
existing Boundary database as-is (`threshold database migrate` applies the
same migrations Boundary would).
- **Wire protocol**: protobuf packages, gRPC service names and the `/v1` HTTP
API paths are unchanged (only Go import paths were renamed). Versions are
still reported to peers with the `Boundary v` prefix.
- **Plugin protocol**: the plugin magic cookie
(`HASHICORP_BOUNDARY_PLUGIN` / `boundary-plugin`) is unchanged, so existing
`boundary-plugin-*` binaries keep working.
- **Configuration file format** (HCL) is unchanged.
Do not run `database migrate` from a newer Threshold than your other nodes
understand; as with Boundary, upgrade controllers before workers and follow the
usual rolling-upgrade guidance for schema migrations.
### Linux packages (deb/rpm)
1. Back up `/etc/boundary.d` and take a database backup.
2. Install the Threshold package. Do not `purge` the old `boundary` package
(removal is fine); purging runs its scripts, which may delete the `boundary`
user that Threshold will reuse. Installing Threshold while the old package is
still installed is supported.
3. The package scripts then, automatically:
- **copy** `/etc/boundary.d` to `/etc/threshold.d` (`boundary.hcl` becomes
`threshold.hcl`, `boundary.env` becomes `threshold.env`; subdirectories such
as TLS material are copied as-is). Existing files in `/etc/threshold.d` are
never overwritten and the originals are never modified or deleted;
- keep reading `/etc/boundary.d/boundary.env` as a fallback environment file
(`threshold.env` takes precedence), so `BOUNDARY_*` variables keep working;
- reuse the existing `boundary` service user and group instead of creating a
`threshold` user (through a managed systemd drop-in,
`/etc/systemd/system/threshold.service.d/10-legacy-boundary-user.conf`), so
ownership of your data, log and key directories keeps working;
- if `boundary.service` was enabled and/or running, stop and disable it,
enable `threshold.service`, and start it if the old service was running.
If `threshold.service` fails to start, the old service is restored;
- make `systemctl restart boundary` (and `status`, `stop`, ...) address
`threshold.service` via a `boundary.service` alias symlink in
`/etc/systemd/system`, and provide `/usr/bin/boundary` as a symlink to
`threshold` if no such file exists. The `boundary` command prints a
one-line deprecation notice to **stderr** only (silence it with
`THRESHOLD_NO_DEPRECATION_NOTICE=1`); stdout, flags and exit codes are
identical to `threshold`.
4. Verify: `systemctl status threshold`, `threshold version`.
What is **not** migrated automatically:
- Paths *inside* your configuration files are not rewritten. A config that
refers to `/etc/boundary.d/...` or `/var/lib/boundary` keeps working because
those locations are left in place; update them at your own pace.
- A custom `/etc/systemd/system/boundary.service` unit (a regular file) is left
alone and the legacy service is not touched; migrate it by hand.
- If `/usr/bin/boundary` is still the old binary from the Boundary package, it is
left alone. After removing the old package: `ln -s threshold /usr/bin/boundary`.
- Distribution-specific package-manager behavior such as `--force-confnew` (dpkg)
can replace `/etc/threshold.d` defaults; your originals remain in
`/etc/boundary.d`.
- Data directories, the database, KMS keys and the client cache are not moved
(the client cache directory is covered by the table above).
Rollback: stop `threshold.service`, remove the `boundary.service` alias
symlink (`/etc/systemd/system/boundary.service`) and the drop-in, reinstall the
old Boundary package, and `systemctl enable --now boundary`. Because the
database schema is unchanged and `/etc/boundary.d` was never modified, nothing
else needs to be restored. If you ran a Threshold release that applied schema
migrations newer than your Boundary version, restore the database backup
instead.
### Container image
The image's configuration directory moved from `/boundary` to `/threshold`
(default command: `threshold server -config /threshold/config.hcl`). For
compatibility the image:
- contains `/boundary` as a symlink to `/threshold`, so existing
`-v "$(pwd)":/boundary/` mounts land in the right place;
- falls back to `/boundary/config.hcl` (printing a deprecation warning) when
`-config /boundary/config.hcl` is requested, or when the stock demo config is
still in place and a config exists at `/boundary/config.hcl`;
- accepts `boundary ...` as the command and `BOUNDARY_*` environment variables
(mirrored to `THRESHOLD_*`).
Plan to switch your mounts, `-config` arguments and environment variables to
the `/threshold` and `THRESHOLD_*` names; the compatibility paths print
warnings and may be removed in a future major release.
### Other installs (binary / zip)
Replace the `boundary` binary with `threshold` (or keep the file name
`boundary`, which behaves identically). Existing `BOUNDARY_*` variables,
`~/.boundary` and stored credentials are picked up as described above.
### Development mode
`threshold dev` creates the `ssh.threshold.dev` and `postgres.threshold.dev`
aliases and, for compatibility, the legacy `ssh.boundary.dev` and
`postgres.boundary.dev` aliases pointing at the same targets.
## Building
```
make build # builds bin/threshold (requires the embedded UI, see Makefile)
make build-no-ui # builds bin/threshold without the embedded admin UI
```
The embedded admin UI is built from the upstream `boundary-ui` project and is
not part of this repository.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).