TNC, or truenas_incus_ctl
, is a tool for remote controlling a TrueNAS server using a familar CLI.
With the discussion on the CLI in the latest T3 video, I thought it was a good time to introduce a little project I’ve been working on.
truenas_incus_ctl
, or truenas_ctl
is a tool built for easily administering datasets, snapshots and network shares that are hosted on a TrueNAS server.
The latest version of the tool can be obtained from github:
It implements a simple to use command line interface, which is specifically designed to feel familiar to people who are used to using the zfs
and zpool
, commands.
The tool implements an automatic connection caching daemon to allow efficient login and quick connections to a remote (or local) truenas.
The tool was originally created as part of implementing an incus driver, hence the current name.
It effectively provides a remote CLI interface to a TrueNAS server, that can be used along side the existing WebUI.
Internally, the tool effectively combines and optimizes API calls to efficiently accomplish its goals in a blocking fashion, and is suitable for integrating into scripts.
You may find that the simplest way to accomplish some complex scripting goals would be to add any extra functionality required to the software, and then use the tool from your script!
Login
To login to the remote TrueNAS host first run the command:
sudo truenas_incus_ctl config login
Example:
$ sudo truenas_incus_ctl config login
[sudo] password for user:
Enter a name for this connection: example
Enter the TrueNAS hostname or IP address: server.example.com
Setting up connection to TrueNAS host: server.example.com
Choose authentication method (1 for API Key, 2 for Username/Password): 2
Testing connection to wss://server.example.com/api/current...
Enter your TrueNAS username: truenas_admin
Enter your TrueNAS password:
Generating API key...
API key successfully generated
Successfully connected to wss://server.example.com/api/current
Configuration for 'example' (connecting to server.example.com) saved to /root/.truenas_incus_ctl/config.json
This will create a “config” to store the API key which is created as part of logging in. You can further edit the configs, or specify different configs using the --config
global flag, see config --help
for additional commands
Dataset manipulation
You can then list your datasets with the following command
sudo truenas_incus_ctl dataset ls
Or a specific dataset/pool, and its children
sudo truenas_incus_ctl dataset ls -r pool/dataset
Like zfs
you can specify what columns to output
$ truenas_incus_ctl dataset ls dozer -o name,used
name | used
-------+-------
dozer | 63.3G
Help is available for any command, for example, dataset create
$ truenas_incus_ctl dataset create -h
Creates a dataset/zvol.
Usage:
truenas_incus_ctl dataset create <dataset>... [flags]
Flags:
--aclmode string Controls how an ACL is modified during chmod(2) and how inherited ACEs are modified by the file creation mode (inherit, passthrough, restricted, discard) (default "inherit")
--acltype string Controls whether ACLs are enabled and if so what type of ACL to use (inherit, posix, nfsv4, off) (default "inherit")
--allow-shrinking By default, shrinking a volume to a smaller size is not permitted. This flag disables this check.
--atime string Controls whether the access time for files is updated when they are read (inherit, on, off) (default "inherit")
--casesensitivity string (inherit, sensitive, insensitive) (default "inherit")
--checksum string (inherit, on, off, fletcher2, fletcher4, sha256, sha512, skein, edonr, blake3) (default "inherit")
--comments string User defined comments
--compression string Controls the compression algorithm used for this dataset
(on, off, gzip, gzip-1, gzip-9, lz4, lzjb, zle, zstd, zstd-1, zstd-2, zstd-3, zstd-4, zstd-5, zstd-6, zstd-7, zstd-8, zstd-9, zstd-10, zstd-11, zstd-12, zstd-13, zstd-14, zstd-15, zstd-16, zstd-17, zstd-18, zstd-19, zstd-fast, zstd-fast-1, zstd-fast-2, zstd-fast-3, zstd-fast-4, zstd-fast-5, zstd-fast-6, zstd-fast-7, zstd-fast-8, zstd-fast-9, zstd-fast-10, zstd-fast-20, zstd-fast-30, zstd-fast-40, zstd-fast-50, zstd-fast-60, zstd-fast-70, zstd-fast-80, zstd-fast-90, zstd-fast-100, zstd-fast-500, zstd-fast-1000) (default "off")
--copies int
-p, --create-parents Creates all the non-existing parent datasets
--deduplication string (inherit, on, verify, off) (default "inherit")
--exec string Controls whether processes can be executed from within this file system (inherit, on, off) (default "inherit")
--force-size
-h, --help help for create
--managedby string Manager of this dataset, must not be empty (default "truenas_incus_ctl")
-o, --option string Specify property=value,...
--quota string (default "0")
--quota-critical int Percentage (1-100 or 0)
--quota-warning int Percentage (1-100 or 0)
--readonly string (inherit, on, off) (default "inherit")
--recordsize string
--refquota string (default "0")
--refquota-critical int Percentage (1-100 or 0)
--refquota-warning int Percentage (1-100 or 0)
--refreservation string (default "0")
--reservation string (default "0")
--share-type string (inherit, generic, multiprotocol, nfs, smb, apps) (default "inherit")
--snapdev string Controls whether the volume snapshot devices are hidden or visible (hidden, visible) (default "hidden")
--snapdir string Controls whether the .zfs directory is disabled, hidden or visible (disabled, hidden, visible) (default "hidden")
-s, --sparse Creates a sparse volume with no reservation
--special-small-block-size string (default "0")
--sync string Controls the behavior of synchronous requests (standard, always, disabled) (default "standard")
-u, --user-props string Sets the specified properties
-b, --volblocksize string Volume block size (512, 1K, 2K, 4K, 8K, 16K, 32K, 64K, 128K) (default "512")
-V, --volsize string Creates a volume of the given size instead of a filesystem, should be a multiple of the block size. (default "0")
Global Flags:
--allow-insecure Allow self-signed or non-trusted SSL certificates
-K, --api-key string API key
-C, --config string Name of config to look up in config.json, defaults to first entry
-F, --config-file string Override config filename (~/.truenas_incus_ctl/config.json)
--daemon-socket string Override the default daemon socket path (~/tncdaemon.sock)
--debug Enable debug logs
-H, --host string Server hostname or URL
dataset create
, and the related update
command provides a powerful way to create datasets, and update the properties using the TrueNAS API without having to login to your WebUI to do it.
Once you get used to it… you may find yourself using it instead of the WebUI
A full suite of dataset commands is available
$ truenas_incus_ctl dataset -h
Edit or list datasets/zvols and their shares on a remote or local machine
Usage:
truenas_incus_ctl dataset [flags]
truenas_incus_ctl dataset [command]
Available Commands:
create Creates a dataset/zvol.
delete Deletes a dataset/zvol.
list Prints a table of all datasets/zvols, given a source and an optional set of properties.
promote Promote a clone dataset to no longer depend on the origin snapshot.
rename Rename a ZFS dataset
update Updates an existing dataset/zvol.
Snapshots
The tool has extensive snapshot support.
$ truenas_incus_ctl snapshot -h
Edit or list snapshots on a remote or local machine
Usage:
truenas_incus_ctl snapshot [flags]
truenas_incus_ctl snapshot [command]
Aliases:
snapshot, snap
Available Commands:
clone clone snapshot of ZFS dataset
create Take a snapshot of dataset, possibly recursive
delete Delete a snapshot of dataset, possibly recursive
list List all snapshots
rename Rename a ZFS snapshot
rollback Rollback to a given snapshot
Bulk Commands
Additionally, most commands support multiple parameters. Look for the ...
in the usage,
truenas_incus_ctl dataset create <dataset>... [flags]
Example to create two sparse 1GB zvols at once, and any parents:
$ truenas_incus_ctl dataset create -p -s -V 1G dozer/zvols-for-testing/zvol1 dozer/zvols-for-testing/zvol2
$ truenas_incus_ctl dataset ls -r -o name,type,volsize dozer/zvols-for-testing
name | type | volsize
-------------------------------+------------+---------
dozer/zvols-for-testing | filesystem |
dozer/zvols-for-testing/zvol1 | volume | 1G
dozer/zvols-for-testing/zvol2 | volume | 1G
$ truenas_incus_ctl dataset rm -r dozer/zvols-for-testing
$ truenas_incus_ctl dataset ls -r -o name,type,volsize dozer/zvols-for-testing
$
Output manipulation
Many commands support sophisticated output manipulation, for example, json output, parsable, table, no headers, or specifically choosing which columsn to enable or retrieve
eg, for dataset list
-a, --all Output all properties
--format string Output table format (csv, json, table, compact) (default "table")
-j, --json Equivalent to --format=json
-c, --no-headers Equivalent to --format=compact. More easily parsed by scripts
-o, --output string Output property list
-p, --parsable Show raw values instead of the already parsed values
-r, --recursive Retrieves properties for children
-s, --source string A comma-separated list of sources to display.
Those properties coming from a source other than those in this list are ignored.
Each source must be one of the following: local, default, inherited, temporary, received, or none.
The default value is all sources. (default "default")
-u, --user-properties Include user-properties
Command categories
This is the root help menu, and shows the major command categories, most categories will then have sub-commands, or perhaps even sub-commands for sub-commands
stux@incusdev:~/git/truenas_incus_ctl$ truenas_incus_ctl -h
Usage:
truenas_incus_ctl [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
config Manage local configuration settings
daemon
dataset Edit or list datasets/zvols and their shares on a remote or local machine
help Help about any command
list Prints a table of datasets/snapshots/shares, given a source and an optional set of properties.
replication Replicate a dataset from one pool to another, locally or across any network
service Control the operation of services on the server (eg. iSCSI)
share Create, list, update or delete NFS or iSCSI shares.
snapshot Edit or list snapshots on a remote or local machine
version Print the version of this program
Flags:
--allow-insecure Allow self-signed or non-trusted SSL certificates
-K, --api-key string API key
-C, --config string Name of config to look up in config.json, defaults to first entry
-F, --config-file string Override config filename (~/.truenas_incus_ctl/config.json)
--daemon-socket string Override the default daemon socket path (~/tncdaemon.sock)
--debug Enable debug logs
-h, --help help for truenas_incus_ctl
-H, --host string Server hostname or URL
Use "truenas_incus_ctl [command] --help" for more information about a command.
Shares
The tool excels at creating and managing shares.
$ truenas_incus_ctl share -h
Create, list, update or delete NFS or iSCSI shares.
Usage:
truenas_incus_ctl share [command]
Available Commands:
iscsi Manage iSCSI connections
nfs Create, list, update or delete NFS shares
iSCSI
The tool integrates with open-iscsi
on the local system to make creating, activating and using zvol based iscsi devices trivial.
open-iscsi
can be installed with apt install open-iscsi
After logging in, you can ensure iSCSI is configured and working with the following command:
sudo truenas_incus_ctl share iscsi setup --test
(iSCSI commands require sudo
)
You can then create a zvol if necessary, create a share, and activate it:
$ truenas_incus_ctl dataset create -p -s -V 1G dozer/zvols-for-testing/zvol1
$ truenas_incus_ctl share iscsi create dozer/zvols-for-testing/zvol1
created dozer/zvols-for-testing/zvol1
Now the zvol is created, and shared via iscsi, it can be activated. Activation requires sudo
$ sudo truenas_incus_ctl share iscsi activate dozer/zvols-for-testing/zvol1
activated /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lun-0
$ ls -l /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lun-0
lrwxrwxrwx 1 root root 9 Jul 12 04:31 /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lun-0 -> ../../sda
The remote zvol is now available on the local system as /dev/sda
, and can be formatted with a filesystem if desired
$ sudo mkfs.xfs /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lu
n-0
specified blocksize 4096 is less than device physical sector size 16384
switching to logical sector size 512
meta-data=/dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lun-0 isize=512 agcount=4, agsize=65536 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=1
= reflink=1 bigtime=1 inobtcount=1 nrext64=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=16384, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Discarding blocks...Done.
And that can now be mounted:
stux@incusdev:~/git/truenas_incus_ctl$ sudo mount /dev/sda /mnt
$ mount | grep sda
/dev/sda on /mnt type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
share iscsi locate
can be used to locate an activated volume
$ sudo /home/stux/go/bin/truenas_incus_ctl share iscsi locate dozer/zvols-for-testing/zvol1
located /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1-lun-0
You can then unmount, de-activate and destroy the share if you wish
$ sudo umount /mnt
$ sudo /home/stux/go/bin/truenas_incus_ctl share iscsi deactivate dozer/zvols-for-testing/zvol1
deactivated iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol1
$ sudo /home/stux/go/bin/truenas_incus_ctl share iscsi delete dozer/zvols-for-testing/zvol1
deleted dozer/zvols-for-testing/zvol1
Actually, you don’t need to deactivate
before deleting
, as the deactivation is implicit.
BUT, almost all operations can be combined and performed using the locate
command.
truenas_incus_ctl share iscsi locate -h
Locate the iscsi targets that map to the given datasets
Usage:
truenas_incus_ctl share iscsi locate <dataset>... [flags]
Flags:
--activate Activate any shares that could not be located
--create Create any shares that could not be activated or located, then activate them
--deactivate Deactivate any shares that could be located
--delete Deactivate and delete any shares that could be located
-h, --help help for locate
-i, --initiator string iSCSI initiator id or comment
--parsable Parsable (ie. minimal) output
-p, --portal string iSCSI portal [ip]:[port] or id (default ":")
--readonly If a share is to be created, ensure that its extent is read-only. Ignored for snapshots.
-t, --target-prefix string label to prefix the created target
--wait Wait until a target is deactivated before returning
If you specify --activate
to the locate
command, then it will activate the share if necessary to locate it. If you specify the --create
command then it will create the share if necessary to activate and then locate it.
So, at its simplest you can create and attach a remove zvol to your system with just 2 commands.
$ truenas_incus_ctl dataset create -p -s -V 1G dozer/zvols-for-testing/zvol3
$ sudo /home/stux/go/bin/truenas_incus_ctl share iscsi locate --create dozer/zvols-for-testing/zvol3
created dozer/zvols-for-testing/zvol3
activated /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol3-lun-0
$ ls -l /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol3-lun-0
lrwxrwxrwx 1 root root 9 Jul 12 04:47 /dev/disk/by-path/ip-192.168.0.32:3260-iscsi-iqn.2005-10.org.freenas.ctl:dozer:zvols-for-testing:zvol3-lun-0 -> ../../sda
I find myself just spinning up another zvol whenever I need a new disk on a system…
Replication
The tool exposes the full underlying one-shot replication support built into TrueNAS.
$ truenas_incus_ctl replication start -h
Start replicating a dataset from one pool to another, locally or across any network.
A replication specifier can either be "<host>:<dataset>" or just "<dataset>" if local.
Currently, only local to local replication is supported.
Usage:
truenas_incus_ctl replication start <sources>... <destination> <-n|-N|-R> <name filter> [flags]
Flags:
--allow-from-scratch
--aux-properties (default true)
--compressed (default true)
--compression string (lz4, pigz, plzip) (default "lz4")
-d, --direction string (push, pull) (default "push")
--embed
--encryption
--encryption-inherit
--encryption-key string
--encryption-key-format string (hex, passphrase) (default "passphrase")
--encryption-key-location string
-e, --exclude string
--exclude-mountpoint-property (default true)
-h, --help help for start
--hold-pending-snapshots
--large-block (default true)
--lifetime-unit string (hour, day, week, month, year) (default "hour")
--lifetime-value int
--logging-level string (debug, info, warning, error) (default "warning")
-R, --name-regex string
-N, --naming-schema-aux string
-n, --naming-schema-main string
--netcat-active-side string (local, remote) (default "local")
--netcat-active-side-listen-address string
--netcat-active-side-port-max int
--netcat-active-side-port-min int
--netcat-passive-side-connect-address string
--only-from-scratch
-o, --options string
--periodic-snapshot-tasks string
--properties-exclude string
--properties-override string
--readonly-policy string (set, require, ignore) (default "set")
-r, --recursive
--replicate
--restrict-schedule string
-p, --retention-policy string (source, custom, none) (default "none")
--retries int (default 5)
--speed-limit int
--ssh-credentials int
--sudo
Example
$ tnc repl start -R ".*" dozer/replication-test/src-zvol dozer/replication-test/dst-zvol dozer/repl-test -p none -d push -r
stux@incusdev:~/git/truenas_incus_ctl$ tnc list -r dozer/real-test
id
----------------------------------
dozer/repl-test
dozer/repl-test/dst-zvol
dozer/repl-test/dst-zvol@latest
dozer/repl-test/dst-zvol@latest2
dozer/repl-test/src-zvol
dozer/repl-test/src-zvol@latest
dozer/repl-test/src-zvol@latest2
Will replicate the source, and all its snapshtos to the destinationation zvol
This could be quite useful, and these replications show up in the GUI as active tasks.
Command Auto-Complete
The tool supports shell based tab completion, see completion -h
for more information
Call to action
There’s a lot in this tool, and I hope the community enjoys it, digs in and gives it a go.
Its fairly easy to add functionality in a modular fashion, so I’m hoping to receive more Pull Requests to add functionality!
Its much easier to use for the things it can do, than doing it through midclt
This has the potential to be a definitive scripting tool for TrueNAS
Enjoy.