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>
195 lines
9.8 KiB
Markdown
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).
|