Grant external access¶
Sometimes someone without an Otherix account needs to reach a specific VM
port: a contractor who needs SSH to one box, a partner who needs a database
port for an integration. You do not want to create a user, hand out a role, or
expose the VM on a public IP for that. An ingress-grant is the answer: a
scoped, optionally time-boxed, optionally source-IP-pinned credential to a named
set of (VM, port) targets, and nothing else.
The grant is delivered as a single shareable bundle. The recipient installs
a thin connector (otherix-ssh) and connects to the VM by name - no Otherix
account, no VPN, no inbound path to the guest. Access always flows through the
control plane broker, exactly like the first-party ingress
path.
Creating and managing grants requires the vm:ingress-grant permission.
Create a grant¶
The operator creates a grant with otherix ingress-grant create, naming the
VMs and ports the third party is allowed to reach:
otherix ingress-grant create acme-contractor \
--vm web01:22 \
--vm db01:5432,8080 \
--login deploy \
--ttl 168h \
--source-ip 203.0.113.10/32
The flags:
| Flag | Meaning |
|---|---|
--vm host:port[,port...] |
A VM and the ports it exposes to the grant. Repeatable - one VM per flag; list multiple ports comma-separated. Port 22 is SSH. |
--login |
Guest login the grant connects as, applied to every VM in the grant. Defaults to root. |
--ttl |
Relative lifetime, e.g. 168h (7 days) or 720h (30 days). Omit for a grant that never expires. |
--source-ip |
Pin the caller's source IP or CIDR (203.0.113.10/32, 198.51.100.0/24). A connection from any other address is refused (fail-closed). |
--user |
A free-form label recording who the grant is for. Not an Otherix user. |
The grant above lets the holder SSH to web01 and reach ports 5432 and 8080
on db01, as the deploy login, for seven days, and only from
203.0.113.10. A grant reaches the exact (VM, port) set you list and
nothing else.
create prints a bundle once, at creation time. Copy it now - it is shown
only this once and cannot be retrieved later. If you lose it, revoke the grant
and create a new one.
The bundle¶
The bundle is a one-time credential that packs everything the recipient needs into a single string:
- the control plane server URL,
- the TLS trust needed to reach it,
- the grant token, and
- the
(vm, ports, login)set the grant covers.
Its single-line form is otx_ingressbundle_<...>. You hand this one string to
the third party.
The bundle is a live credential
Anyone holding the bundle can reach the VMs and ports it names, as the pinned login, until it expires or you revoke it. Treat it like a password: share it over a secure channel (an encrypted message, a secrets manager), never a public paste or a plaintext email.
Recipient side: the otherix-ssh connector¶
The recipient needs no Otherix account and no otherix CLI - only the thin
otherix-ssh connector. Install it:
Then register the bundle once. otherix-ssh add accepts the bundle as a file
path or pasted inline:
otherix-ssh add ./acme-bundle.txt # from a file
otherix-ssh add otx_ingressbundle_... # or paste the single-line form
add stores the control plane URL, the TLS trust, and the grant token, and
writes an ssh_config fragment that routes *.otherix.local through
otherix-ssh proxy. After that, the recipient reaches a granted VM by name with
plain ssh:
The connection is brokered through the control plane to web01's port 22. The
login is fixed by the grant server-side (the --login you set at create time),
so the recipient does not choose it.
Overriding the host suffix
The connector uses the host suffix otherix.local by default (so
web01 becomes web01.otherix.local). Pass --suffix to otherix-ssh add
to use a different suffix if otherix.local collides with something on the
recipient's machine.
Recipient side: the raw token¶
If the recipient already has the otherix CLI, they can skip the connector and
use the bare grant token directly. Export it as OTHERIX_API_TOKEN and use the
normal ingress commands - the token's scope limits them to the granted targets:
export OTHERIX_API_TOKEN=<grant-token>
otherix ssh web01 # SSH to a granted VM
otherix forward db01 5432 # forward a granted port (local 5432 -> db01:5432)
See SSH access and Port forwarding for the full command surface those two share.
Manage grants¶
Once a grant exists, adjust its scope, inspect it, or shut it off:
otherix ingress-grant add-vm acme-contractor cache01:6379 # widen: add a target
otherix ingress-grant remove-vm acme-contractor db01 # narrow: drop a VM
otherix ingress-grant list # all grants
otherix ingress-grant get acme-contractor # one grant's scope + status
otherix ingress-grant revoke acme-contractor # kill switch - disable now
otherix ingress-grant delete acme-contractor # remove the record
Each command takes the grant's name or its id, and supports -o text|json|yaml.
revoke is the kill switch: it disables the grant immediately, so every bundle
and raw token issued from it stops working at once. Use it the moment access is
no longer needed or a bundle may have leaked. delete removes the grant record
entirely.
Scoping and security¶
An ingress-grant is a deliberately narrow tool. Keep it narrow:
- Grant the minimum ports. List only the
(VM, port)targets the third party actually needs. A grant can reach nothing outside that set. - Prefer a short
--ttl. A grant that expires on its own is one less thing to remember to revoke. Reach for168h/720hover an open-ended grant. - Pin
--source-ipwhen you can. If the third party connects from a known address or range, pin it. An off-network connection is then refused fail-closed, even with a valid bundle. - Revoke when done. When the engagement ends,
revokethe grant. Do not leave a live credential outstanding.