[!WARNING]
The v3 branch is under heavy development. Expect breaking changes and
unstable APIs.

Tarantool CLI - command line utility for managing Tarantool packages and
Tarantool-based applications.
Contents
Intro
tt is tarantool's instance and environment management utility and is used to
develop, deploy, run and operate an application.
One of the basic concepts that tt works with is the "project": the
directory of a tarantool application, with its app.manifest.toml or its
instance templates, .templates/<name>/ with instances.yaml, config.yaml
or both. tt finds the project from the current directory upward. The
binaries the project runs on and the runtime artifacts of its instances are in
its .tarantool directory, apart from other applications. There is no
configuration file of the environment: tt.yaml of tt 2.x is not read.
The example of a typical project:
graph LR
%% Colors %%
classDef lime fill:#C7EA46,stroke:#000,color:#000
subgraph dot[Project]
manifest(app.manifest.toml):::lime
lock(app.manifest.lock):::lime
init(init.lua):::lime
rocks[.rocks]
templates[.templates] --> template_default[default]
template_default --> instances(instances.yaml):::lime
template_default --> cluster_config(config.yaml):::lime
root[.tarantool]
end
root --> bin
root --> include
root --> versions
root --> var
var --> run[run] --> app1[app] --> inst11[instance]
inst11 --> pid1(tt.pid):::lime
inst11 --> control1(tarantool.control):::lime
inst11 --> binary1(tarantool.sock):::lime
var --> log1[log] --> app2[app] --> inst12[instance] --> logfile1(tt.log):::lime
var --> lib1[lib] --> app3[app] --> inst13[instance] --> xlogs1(*.xlog,*.snap):::lime
bin --> binaries(tarantool<br/>tt<br/>tcm):::lime
Getting started
Installation
Install tt 3 from its GitHub release with one line, on Linux (x86_64 and
arm64) or on macOS with Apple silicon:
curl -fsSL https://raw.githubusercontent.com/tarantool/tt/v3/install.sh | sh
The script takes the newest stable tt 3 release, or the newest pre-release
while there is none, checks the archive against checksums.txt of the
release and puts tt into ~/.local/bin, or into /usr/local/bin when run
by root. wget -qO- <url> | sh works as well. Options go after sh -s --:
curl -fsSL https://raw.githubusercontent.com/tarantool/tt/v3/install.sh | sh -s -- --version 3.0.0-alpha.1 --dir /usr/local/bin
On Linux --openssl installs the tt-openssl build, whose TLS uses OpenSSL
instead of Go; --help lists the options. A binary installed this way needs
none of the macOS steps below: curl does not mark the file as downloaded.
--commit builds tt from a commit of the repository instead, with git
and Go: a hash, full or short, a branch or a tag. Such a build reports the
version git describe gives the commit, as mage build does, and runs on
Intel macOS too, which has no release build:
curl -fsSL https://raw.githubusercontent.com/tarantool/tt/v3/install.sh | sh -s -- --commit 1508ce93
[!NOTE]
The Gentoo and Homebrew packages below are of tt 2.x. To run a tt 3
that is not released yet, build it from source.
On Gentoo Linux, the TT can be installed from the Tarantool Gentoo
Overlay:
emerge tt
On MacOS, the TT can be installed from brew:
brew install tt
You can also install Tarantool CLI by downloading archive with pre-built
binary for your OS from GitHub's Releases page.
However, on MacOS to run that binary you will need to do additional
steps:
-
After first try to run binary, you will encounter an error:
-
To fix it, you should go to 'system settings->privacy and
security', then scroll down and find:
-
Click on 'Allow Anyway' and you should be able to use Tarantool Cli.
Build from source
Prerequisites
To run tests:
Build
git clone https://github.com/tarantool/tt
cd tt
By default, tt uses the pure-Go TLS backend and does not require OpenSSL.
Use the explicit default value to override another exported build mode:
mage build
TT_CLI_BUILD_SSL=default mage build
To use the dynamically linked OpenSSL backend:
TT_CLI_BUILD_SSL=openssl mage build
To build a statically linked binary with the OpenSSL backend, install the
OpenSSL static libraries and run:
TT_CLI_BUILD_SSL=openssl_static mage build
Dependencies
tt rocks runtime dependencies:
tt binary install && search runtime dependencies:
Run tests
Disable etcd service:
systemctl stop etcd
systemctl disable etcd
Create a virtual environment and install tests requirements:
python3 -m venv .venv
source .venv/bin/activate
pip install -r test/requirements.txt
Once inside the virtual environment, run default set of tests (excluding
slow tests):
mage test
To run full set of tests:
mage testfull
Commit changes
CI runs the same checks as these targets; run them before committing:
mage lint:golang
mage lint:python
mage codespell
mage lint:python runs ruff check and ruff format --check over test.
Add --fix to let Ruff fix and reformat the files: mage lint:python --fix.
Configuration
tt has no configuration file. tt.yaml of tt 2.x is not read by any
command, and neither is /etc/tarantool/tt.yaml. What it configured is set
elsewhere:
env.bin_dir, env.inc_dir: the binaries and headers tt binary install
puts into a scope (see Binaries). In a project the commands
run the tarantool and tcm of .tarantool/bin, and otherwise the first
on PATH.
env.output_history_max: the argument of \history in the tt connect
console, such as \history 15 (10 without one).
env.restart_on_failure: the restart field of the instance record.
app.*_dir: the runtime artifacts of an instance go under the root of the
scope of its application (see
Working with a set of instances).
repo.rocks: the rock servers of tt registry (see
Rock servers).
ee.credential_path: the --credentials-file flag of tt binary.
templates: tt create takes a template of your own by its path (see
Working with application templates).
modules.directory: TT_CLI_MODULES_PATH (see
External modules).
Binaries
tt binary install, search, list, switch, and uninstall for tt, tarantool,
tarantool-ee, tt-ee, tcm, and tarantool-sdk use --scope project (the default),
user, or system to choose the installation root. Executables are stored directly in
versions/<product>/<product>_<version>/, with Tarantool headers in its
include/tarantool/ directory. Active executable links are in bin/ and Tarantool
header links in include/. Each command uses only the selected scope, without
falling back to user/system installations. The project scope is .tarantool in
the project directory: the current directory or its nearest parent with
app.manifest.toml, or with instances.yaml or config.yaml in
.templates/<name>/, and the current directory outside a project.
TT_USER_ROOT and TT_SYSTEM_ROOT replace the default user and system roots
and must be absolute paths. For search, the scope only selects the
installed/active labels; it does not change the source of available versions.
tt binary install tarantool supports Community Edition releases starting
with Tarantool 3.0.
The first successful tt binary install in project scope creates
.env/activate.sh and .env/deactivate.sh in the project directory. Existing
scripts are preserved.
Run source .env/activate.sh to set TT_PROJECT_DIR to the installation's
project directory, prepend .tarantool/bin to PATH, and set
TT_CLI_TARANTOOL_PREFIX to the project's .tarantool directory. The prefix
selects the active headers in .tarantool/include/tarantool.
Run source .env/deactivate.sh to restore the previous PATH and Tarantool
prefix and unset the project variables. User and system installations do not
create these scripts.
Installing tarantool-sdk installs Tarantool Enterprise, tt Enterprise, TCM, and
headers from one SDK archive. The tt-ee product uses the executable name tt
and shares the active bin/tt link with ordinary tt. Its versions are stored
separately under versions/tt-ee/.
SDK components have sdk-<bundle-version> identities, separate from standalone
product versions. For example, an SDK component is stored in
versions/tarantool-ee/tarantool_sdk_<bundle-version>/ or
versions/tcm/tcm_sdk_<bundle-version>/ or
versions/tt-ee/tt_sdk_<bundle-version>/. An ownership record under
versions/tarantool-sdk/ identifies the components to remove together.
SDK installation uses the same version semantics as EE: an omitted version or
X, X.Y, or X.Y.Z selects the latest matching stable gc64 build; a complete
archive name selects an exact build. SDK installations and their components
retain the complete bundle version, including the revision.
tt binary switch sdk 3.7.1 selects all components
and headers of the matching SDK. Switch a component independently with
tt binary switch tcm sdk-3.7.1, or select a standalone TT/TCM version as usual.
Use tt binary switch tt-ee sdk-3.7.1 to select the SDK's tt Enterprise executable,
or tt binary switch tt <version> to select an ordinary tt version.
Switching or uninstalling an SDK requires an unambiguous installed version.
Automatic replacement of TCM and tt-ee installations compares each executable's own version,
independently of the SDK bundle version.
For user and system scopes, add <root>/bin to PATH to use the active binaries.
For project scope, run source .env/activate.sh. Uninstalling an SDK
removes its components while preserving independently selected versions.
Automatic selection of replacement components is optional: unusable candidates
are skipped, and a failed switch reports a warning without failing the removal.
Use tt binary search tarantool-sdk to find available SDK archives.
sdk and SDK are aliases for this search. SDK searches mark
complete SDK installations and report them as active when all components are selected.
tt binary search tarantool-ee uses the same archive catalog and marks standalone
Enterprise installations independently.
To install from local files, use:
tt binary install tt --local-repo <dir>: a Git clone of tt in <dir>/tt.
tt binary install tarantool --local-repo <dir>: a Git clone of Tarantool in
<dir>/tarantool.
tt binary install tarantool 3ee --local-dir <dir>: Tarantool Enterprise SDK
archives named tarantool-enterprise-sdk-*.tar.gz directly in <dir>.
tt binary install tt 2ee --local-dir <dir>: standalone tt Enterprise
archives named tt-ee-*.tar.gz directly in <dir>.
tt binary install tarantool-sdk --local-dir <dir>: the same SDK archives,
installing the entire supported component set.
tt binary install tcm --local-dir <dir>: TCM archives named tcm-*.tar.gz
directly in <dir>.
tt binary search <product> accepts the same product-specific flag and marks
installed/active versions in the selected scope. Put the source flag after the
product name. Both flags require an explicit directory. Relative paths are
resolved from the current directory. For EE and TCM, --local-dir replaces
--local-repo.
For tt binary install tarantool and tt binary install tt, append ee to
the version selector: Xee, X.Yee, or X.Y.Zee. These select the latest
matching stable Enterprise build. Tarantool EE selects gc64 builds by default.
Omitting the version selects Community Edition.
For tt binary install tcm, omit the version to select the latest stable build,
or specify X, X.Y, or X.Y.Z to select the latest matching stable build.
For example, tt binary install tarantool 3ee selects the
latest stable gc64 build in major version 3, and tt binary install tcm 1.3
selects the latest stable TCM build in minor version 1.3. These forms also work
with --local-dir. Complete Tarantool Enterprise build names, including
nogc64 or RC, also select Enterprise Edition. For tt Enterprise, append ee
to a version from tt binary search tt-ee to select that archive.
Standalone tarantool-ee release installations use the Tarantool version
without the gc64/nogc64 prefix, SDK revision, commit count, or hash, such as
3.8.1. Prerelease and debug variants remain separate, such as 3.8.1-rc1 or
debug-3.8.1.
For example, gc64-3.8.1-0-r93 and gc64-3.8.1-0-r94 both install into
versions/tarantool-ee/tarantool-ee_3.8.1/. Installing another revision preserves
the existing executable and headers unless --reinstall is specified.
These installed names also work with install, selecting the latest matching
archive revision, and with switch and uninstall. A full archive name resolves
to the same installed version. search continues to list full archive versions
and marks them using the corresponding standalone installation.
Use --dev to install development builds of Tarantool Enterprise, SDK, or TCM.
They keep the full archive version, including the revision, with a dev_ prefix.
For example, tt binary install tarantool 3.8.1ee --dev installs into
versions/tarantool-ee/tarantool-ee_dev_gc64-3.8.1-0-r94/ when that archive is selected.
Development builds coexist with releases and with other development revisions.
list, switch, and search --dev display dev_<full-version>; use that name
with install, switch, or uninstall to select the development build.
For example, tt binary switch tarantool dev_gc64-3.8.1-0-r94 selects that build.
SDK development components use sdk-dev_<full-version> identities and directories
such as versions/tarantool-ee/tarantool_sdk_dev_gc64-3.8.1-0-r94/.
Version selectors without dev_ match release installations independently.
For tt binary switch and tt binary uninstall, EE, tt-ee, and TCM accept X.Y.Z
to match installed versions in the selected scope; X and X.Y are not expanded.
For standalone EE, an exact installed name takes precedence. Otherwise exactly
one installation must match. For example, if both 3.8.1-rc1 and
debug-3.8.1 are installed, tt binary switch tarantool-ee 3.8.1 fails
with both names listed. Specify debug-3.8.1 to select that variant.
For tt-ee, TCM, and SDK components, different build variants, revisions, and
prereleases count as separate matches.
Ambiguous requests leave installations and active links unchanged.
For remote EE/TCM searches and EE/TCM/SDK downloads, use
--credentials-file <path> to read customer-zone credentials from a file:
the login on the first line and the password on the second. The file must not
be accessible to group or other users (chmod 0600 <path>). For example:
tt binary search tarantool-ee --credentials-file ./credentials
tt binary install tcm 1.3.1-0-g074b5ffa --credentials-file ./credentials
Without the flag, credentials come from TT_CLI_EE_USERNAME and
TT_CLI_EE_PASSWORD, or an interactive prompt.
tt rocks and tt package build build a rock with a C part against the
headers of the tarantool they run: the ones in .tarantool/include/tarantool
for the tarantool of the project, TT_CLI_TARANTOOL_PREFIX for another one,
and otherwise the install prefix that tarantool was built with.
Rock servers
tt registry list shows the rock servers the package commands query: the ones
--registry names, else TT_REGISTRIES (comma-separated), else
[platform].registries of app.manifest.toml in the current directory, else
the built-in defaults. tt rocks queries the servers of TT_REGISTRIES or of
the manifest too, in place of the servers LuaRocks queries by default; without
either, LuaRocks keeps its own. A relative directory is taken from the current
directory for TT_REGISTRIES and from the manifest's directory for the
manifest.
Migrating from instances.enabled
See the 2.x to 3.0 migration guide
for converting a tt 2.x environment, instances.enabled included, into
projects.
External modules
An external module is a directory in a modules directory, named after the
command it adds. It holds a manifest.yaml:
version: 1.0.0
help: Upload tt backups to an S3 bucket
main: main
version is the module's version, help its one-line description and main
the name of its executable in the directory. A module with no manifest is an
executable named main that prints the same version and help, as YAML,
when called with --description --version. When called with --help, the
module prints its full help to stdout.
help describes the module wherever tt lists it: among the commands of
tt --help and under its EXTERNAL COMMANDS, in shell completion and in
tt modules list. tt takes only the first line of it, so that each module
stays one line in these lists; a longer text belongs in the module's own
--help, which tt help <module> and tt <module> --help print.
Tarantool CLI already contains a basic set of modules. You can overload
these with external ones, or extend functionality with your own module.
Modules are looked for in the directories listed in the
TT_CLI_MODULES_PATH environment variable, separated by colons:
export TT_CLI_MODULES_PATH=/path/to/modules:/path/to/other/modules
A relative directory is taken from the working directory tt runs in, so list
absolute paths.
For example, you have an external cat module. When you type tt cat, the
external cat module will be launched, and every argument after cat goes
to it; with -V, tt logs that the module replaces the command. A module
named like a group of commands, such as cluster, takes over the whole
group, and a module answers to the aliases of the command it replaces. To
run the internal implementation, use the --internal (-I) flag. If there is
no executable file with the same name, the internal implementation will be
started. The modules, help, completion and version commands cannot be
replaced: a module named so is ignored with a warning.
You can use any external module that doesn't have any internal
implementation. For example, you have module named example-module.
Just type tt example-module to run it.
To see list of available modules, type tt -h.
Building a distribution of tt
A tt module is a Go module that is compiled into tt rather than run next to
it: its package exports a constructor, func New(sdk.Services) []sdk.Mount,
that returns the commands it adds (see the SDK). A
distribution of tt is the tt core and a set of such modules built into one
binary, described by tt.manifest.toml:
manifest_version = "0.1"
manifest_kind = "tt-distribution"
[package]
name = "tt"
[core]
tt = "v3"
[distribution]
title = "Tarantool CLI EE"
edition = "ee"
integrity = "rsa"
[dependencies]
aeon = "github.com/tarantool/tt/modules/aeon"
migrations = "./plugins/migrations"
foo = "github.com/acme/tt-foo@v1.2.0"
Only manifest_version and manifest_kind are required. Without [core]
the distribution is built on the core of the tt that builds it; tt takes
any Go version query (latest, a branch, a commit, a version) and path a
local checkout of the core instead. [distribution] sets how the binary
presents itself (title, edition), the integrity provider (none or
rsa), and whether it has tt's own commands (builtin) and external modules
(external_modules), both on by default. [build] sets the TLS
implementation (ssl: default, openssl or openssl_static, overridden
by TT_CLI_BUILD_SSL), extra build tags and ldflags.
A dependency is a local directory (./..., ../... or an absolute path), a
module path, or a module path with a version after @; the long form is a
table with module, version, path, package and symbol. A module of
the core's repository, such as aeon, is built at the commit of the core;
any other module without a version at its latest.
tt binary build tt # build ./tt from ./tt.manifest.toml
tt binary build tt --update # take the newest core and modules
tt binary build tt --locked -o tt # build exactly what the lock pins
The Go toolchain must be in PATH. The build generates a main module that
requires the core and the modules, compiles it with the build tags tt itself
is built with, runs tt version of the result and writes tt.manifest.lock
and tt.manifest.sum next to the manifest. Commit both: while the manifest
stays the same, the next build takes its versions from the lock, and
--locked fails when the lock or the Go modules differ. The lock pins what
the binary is built from, not how it is compiled: the TLS implementation,
the tags and the Go toolchain are the choice of each build, so one lock
builds every one of them, and a build that pins nothing new - by another tt,
say - leaves both files as they are.
A local module, a local core or a directory of [replace] has no version to
pin, so the lock records content_hash, a hash of its files by path and
content, as Go hashes a module for go.sum. They are the files the bundle of
--vendor copies: every regular file of its directory but those in VCS and
vendor directories and in nested modules, and those .gitignore ignores.
The .gitignore files are the module's own and those of the directories
above it up to the root of its git repository - outside a repository, up to
the manifest's directory when the module is in it. They are read as git reads
them, but without git, so a tarball of a checkout hashes as the checkout
does; .git/info/exclude and core.excludesFile, which differ from machine
to machine, are not read, and a file git tracks that .gitignore ignores
does not count. The files Go may build the module from count even when
ignored: the Go and cgo sources, go.mod, go.sum and the files
//go:embed embeds. --locked fails when the files changed; an ordinary
build records them again. A binary built in a checkout of the core, ./tt
say, is no change: the .gitignore of tt ignores it.
tt version of the result shows the version of the distribution and of the
tt core it is built on; tt version --modules lists its modules with the
versions Go recorded for their Go modules, (devel) for a local one:
$ ./tt version --modules
Tarantool CLI EE version 3.0.0, linux/amd64. commit: 1a2b3c4
Tarantool CLI core version 3.0.0. commit: 9031d7ad96d9 (v3.0.1-0.20261028190206-9031d7ad96d9)
aeon v0.0.0-20261028190206-9031d7ad96d9 github.com/tarantool/tt/modules/aeon
builtin v3.0.1-0.20261028190206-9031d7ad96d9 github.com/tarantool/tt/v3
migrations (devel) example.com/tt-ee/plugins/migrations
Replacing Go modules
A tt module is built with the dependencies its own go.mod names, but Go
applies the replace directives of the main module only, so a module that
depends on a library that is not published, or not at the version it needs,
cannot carry the replacement itself. [replace] puts it in the go.mod that
the build generates, before it runs go mod tidy:
[replace]
"gitlab.corp.mail.ru/tarantool/go-migration" = "../go-migration"
"github.com/tarantool/go-storage/v2" = "github.com/tarantool/go-storage/v2@v2.1.0-rc1"
"github.com/acme/old@v1.2.3" = "github.com/acme/new@main"
A key is the path of a Go module, with @version to replace that version
only, as in a go.mod. A value is either a local directory - it starts with
./, ../ or /, and is relative to the manifest - that holds the module
the key names, or module@version, where the version may be any query (a
branch, a commit, latest); the build resolves it to an exact version, as it
does for the modules, and the lock pins it. The core, the modules of its
repository and the tt modules listed in [dependencies] are not replaced
here, which is an error: the core has [core].path and --core, and a tt
module has path and version of its own. A replacement that no package of
the build comes from has no effect, and the build warns of it.
The lock records every entry in [replace]: a directory by content_hash,
computed as for a local module (see above), and a module by its exact version. --locked
fails when a replaced directory changed, like it does for a local module.
--vendor copies the replaced directories into local/replace/ of the
bundle, which go.mod replaces them with by a relative path, so the bundle
builds offline.
Building on another core
--core VALUE, or the TT_DIST_CORE environment variable (the flag wins),
builds a distribution on another core than [core] names, without editing
the manifest: a local checkout - an existing directory, or a path that starts
with ./, ../ or /, taken from the project directory - or else a version
query, as [core].tt takes. It is for building a distribution against
changes of the core not yet released, and for the CI of tt itself, which
builds the distributions from its working tree:
tt binary build tt --core ../tt
TT_DIST_CORE=. tt binary build tt --manifest dist/tt.manifest.toml
Such a build is a development one. Its core and the modules of the core's
repository are not taken from the lock, and the lock and the sum are not
written; the other modules still come from the lock while the manifest
matches it. --locked refuses it.
Offline build
--vendor DIR makes a bundle instead of a binary: everything a distribution
is built from, which the Go toolchain alone turns into the binary on a
machine with no network, no module cache and no tt.
tt binary build tt --locked --vendor dist/bundle
The bundle holds the generated go.mod, go.sum and main.go, vendor/
with every package the binary is built from (the core, the modules of its
repository, the tt modules, third-party modules, and the files they embed),
local/ with a copy of each local module - a local core, the path
dependencies and the directories of [replace] - which go.mod replaces them
with by a relative path, and the build parameters: build.env sets the tags,
the linker flags and cgo of each TLS implementation, the implementation the
bundle was made with, the toolchain and the version, and build.sh builds
with them. The bundle names no directory of the machine that made it, so it
can be moved anywhere; it is built once offline when it is made.
On the offline machine, with the Go toolchain build.env names
(TT_DIST_TOOLCHAIN) or a newer one in PATH:
sh bundle/build.sh # the TLS the bundle was made with
sh bundle/build.sh openssl_static ./tt # or default, openssl; and the output
build.sh is no more than:
cd bundle
. ./build.env
GOFLAGS=-mod=vendor GOPROXY=off GOWORK=off GOTOOLCHAIN=local \
CGO_ENABLED=$TT_DIST_CGO_DEFAULT \
go build -trimpath -tags "$TT_DIST_TAGS_DEFAULT" \
-ldflags "$TT_DIST_LDFLAGS_DEFAULT" -o tt .
The OpenSSL implementations need a C compiler and the OpenSSL headers on the
offline machine; on macOS build.sh takes TT_DIST_LDFLAGS_DARWIN_*.
Signed packages
A distribution built with integrity = "rsa" signs packages with an RSA
private key and runs them checked with the public key. tt itself checks
nothing: it has no integrity provider. The keys are PEM: the private one
PKCS#1 or PKCS#8, the public one PKIX or PKCS#1, as openssl makes them:
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
tt package pack --with-integrity-check private.pem signs the archive it
packs. The package gets two hashes files at its root, each with an
RSASSA-PSS signature next to it (.sig): hashes.json lists what Tarantool
loads - the Lua sources, the shared libraries, the cluster configs of the
templates and the scripts the instance records run - and env_hashes.json
every other file of the package: the manifest, the lock, VERSION, the
instances descriptions, the programs in .rocks/bin/. Every runtime the
archive bundles in _runtime/ gets an env_hashes.json of its own, listing
its executable, and the headers of tarantool, by the paths
tt package install lays them out at. A signed package runs only its own
files: a record of its templates that runs a script or a binary outside of
it, or a program it does not build into .rocks/bin/, fails the pack, as
does a Tarantool instance record with env and a var/ at the top of the
package (see the layout on Tarantool Enterprise below). A package is not
signed --without-deps, as its install fetches dependencies nobody signed.
tt --integrity-check public.pem package install installs only a signed
archive, into the user or the system scope: the version and each bundled
runtime are checked before they are put in place - their signatures, every
file they list, and that they list every file - so that a changed or an added
file is refused. A runtime installed there already, by tt binary or an
earlier install, must be the signed one: without hashes files of its own it
gets those of the archive and is checked with them.
tt --integrity-check public.pem instance start checks each application at
its own directory - the project, or the installed version - and at the
directories of the runtimes it runs on, whatever the directory tt runs in,
and runs only what they sign: the tarantool of the application, which must
be the signed one it bundles rather than one from PATH, the script of a
record, the binary of an external process, which is looked up in
.rocks/bin/ of the application only, and the tt that runs the watchdog,
which must be the bundled one. The watchdog checks them again every
--integrity-check-period seconds and stops the instance for good on a
failure. Tarantool gets hashes.json of the application to check what it
loads.
The pair of the host in <root>/etc/<app>/ is not part of a package, and
an application that runs from one is refused with the checks on; it runs
from a template of its package, --template. A signed install into the
project scope, whose install root the project shares with its guest
packages, and the signing of a project as it is developed are not supported
yet. The signatures have a random salt, so a signed archive is not reproduced
bit for bit, unlike an unsigned one.
tt gives an instance the paths of the layout - its data, its pid file, its
sockets and its log - through the TT_*_DEFAULT variables of its
environment. Tarantool Enterprise starts with an empty environment when it
checks integrity, so under --integrity-check they do not reach it, and it
falls back to the defaults of Tarantool, relative to its working directory,
the installed version: var/lib/<instance> for the data,
var/run/<instance>/tarantool.pid and var/run/<instance>/tarantool.control,
and var/log/<instance>/tarantool.log for a log file.
A signed install makes those defaults the layout. tt package install --integrity-check gives the version var/lib, var/run and var/log as
links to <root>/var/lib/<app>, <root>/var/run/<app> and
<root>/var/log/<app>, so a config that names no path keeps the data, the
pid file and the console socket of an instance in the layout of the root,
where tt finds them, as without the checks. Every version of the application
links the same directories, so the data outlives an upgrade, and removing a
version removes its links, not the data. The links are not part of what is
signed, and a signed package cannot have a var/ of its own: the pack
refuses it. tt instance start --integrity-check makes the links a version
lacks - one installed before tt made them - when it may write into it, and
refuses to start an instance whose version has something else there.
A config may still name the paths itself, in the cluster config of the
package or in its config storage; tt reads the data directories, the console
socket and the first unix socket of iproto.listen from the config of an
instance, with {{ instance_name }}, {{ replicaset_name }} and
{{ group_name }} substituted. In the system scope, whose root is
/opt/tarantool on Linux, for the package <app>:
snapshot:
dir: /opt/tarantool/var/lib/<app>/{{ instance_name }}
wal:
dir: /opt/tarantool/var/lib/<app>/{{ instance_name }}
vinyl:
dir: /opt/tarantool/var/lib/<app>/{{ instance_name }}
quiver:
dir: /opt/tarantool/var/lib/<app>/{{ instance_name }}
process:
pid_file: /opt/tarantool/var/run/<app>/{{ instance_name }}/tarantool.pid
console:
socket: /opt/tarantool/var/run/<app>/{{ instance_name }}/tarantool.control
iproto:
listen:
- uri: unix/:/opt/tarantool/var/run/<app>/{{ instance_name }}/tarantool.sock
quiver.dir is an option of Tarantool Enterprise, which Tarantool Community
refuses. process.work_dir is no way to move the defaults: Tarantool looks
for the modules of the application, app.file among them, in its working
directory, and finds none once it moves there.
What the checks take away with the environment stays away, as it did in tt
2:
- No iproto address by default: an instance listens on what
iproto.listen
of its config names, and tt connect --binary needs a unix socket there;
tt connect over the console socket works without one.
- The log goes to the standard error of the instance, which tt writes into
tt.log of the layout, where tt instance logs reads it; log.to: file
writes tarantool.log next to it.
- The
env of the record of a Tarantool instance does not reach it: the pack
of a signed package and tt instance start --integrity-check refuse a
record that sets it, and the values belong in the config. An external
process keeps its env: tt runs it.
- A record that runs its script is refused under the checks: tt starts it
through a launcher that takes the script and the paths of the instance from
the environment. The instance is configured by the cluster config instead.
CLI Args
Arguments of Tarantool CLI:
--internal | -I - use internal module.
--verbose | -V - verbose output.
--log-format text|json - the format of the log written to stderr.
--no-prompt - skip CLI interaction, using the default behavior.
--help | -h - help.
A distribution with an integrity provider adds --integrity-check and
--integrity-check-period (see Signed packages). The exit
codes of the commands are described by tt help errors.
Autocompletion
You can generate autocompletion for bash, zsh and fish shell:
. <(tt completion bash)
Enter tt, press tab and you will see a list of available commands with
descriptions. Also, autocomplete supports external modules.
For the target of the tt instance commands, autocompletion offers the
current project and the applications installed in the system scope, or in the
scope --scope names, before the : delimiter, and the instances of the pair
of that application after it, those the command can act on: stop offers the
running ones.
For tt create command it will show a list of built-in templates; a
template given by its path is completed as a file name.
TT usage
Working with packages
A package is a project described by app.manifest.toml: its name, the
versions of Tarantool and tt it runs on, its dependencies and the components
it is built from. tt new writes a skeleton of the manifest, and the
tt package commands do the rest:
tt new # app.manifest.toml in the current directory
tt package add checks '>=3.0.0' # declare a dependency, update the lock
tt package add luatest --dev # a dependency of the tests only
tt package build # .rocks/: the dependencies and the components
tt run # the tarantool of the project
tt test # build, then luatest over test/
tt package pack # _build/pack/<name>-<version>-<os>-<arch>.tt
tt package install <archive> --scope user
The versions the dependencies resolved to are in app.manifest.lock next to
the manifest; commit it. tt package add, remove and resolve keep the
versions the lock holds, and only tt package update takes newer ones from the
rock servers (see Rock servers). --locked makes build and
pack fail on a lock that is out of date instead of resolving it again.
tt package deps shows what the manifest declares and what it resolved to.
A component is the code of the package:
[components.app]
path = "."
include = ["init.lua", "kv/*.lua"]
tt package build puts its files into .rocks/share/tarantool/<name>/,
together with version.lua, so the code is require('<name>') and its version
require('<name>.version').version. The version is the one of VERSION next
to the manifest, else of the nearest v* tag of git. An installed version has
the files of the components and not the other files of the project, so the
cluster config of a package loads its code with app.module: <name> rather
than app.file, unless [package].include lists the file.
tt package pack builds the package and packs it into an archive. By default
the archive carries the dependencies and, in _runtime/, the tarantool and
the tt the package runs on, so its install needs no network;
--without-deps packs the package alone. tt package install installs an
archive into a project, where its packages share .rocks/, or into the user
or the system scope, where it becomes a version of an application,
<root>/versions/<name>/<name>_<version>/, that <root>/apps/<name> points
to: tt instance start <name>:<instance> --scope user runs it.
tt package list and tt package uninstall show and remove what is
installed.
Working with a set of instances
tt instance acts on the instances of an application on this host:
tt instance start | stop | restart | kill | status
tt instance logs | logrotate
tt instance check | clean
tt instance connect
tt connect is the same command as tt instance connect, with the same
flags; tt play takes the same targets. The top-level tt start, tt stop
and the rest of tt2 are gone, and tt log is tt instance logs.
A project is a directory with app.manifest.toml, or with instances.yaml or
config.yaml in .templates/<name>/; tt finds it from the current
directory or any directory inside it. The project runs from a pair of files in
.templates/default/: instances.yaml, what runs on this host, and
config.yaml, the cluster config tarantool -c gets:
.
├── .templates
│ └── default
│ ├── config.yaml
│ └── instances.yaml
├── app.manifest.toml
└── storage.lua
instances.yaml maps instance names to their records; every Tarantool
instance configured by the cluster config must be in the topology of
config.yaml. A description of instances that run their scripts and of
external processes alone needs no config.yaml, and one next to it is not
read:
storage-001:
storage-002:
restart: on-failure
The record "*", quoted, stands for every instance of the topology of
config.yaml that no other record names, each with the fields of "*"; a
record of its own replaces "*" for its instance whole. A template of
config.yaml alone runs every instance of its topology, as "*": {} would.
The pair of the host, <root>/etc/<app>/, needs its instances.yaml: it says
what runs on that host.
The application is named by [package].name of the manifest, or after the
project directory without one. A target is <app>:<instance>, <app>:*, or
a comma-separated list of them; no target is every instance of the current
project. <app>:... is the current project when it is called <app>, and
the application installed in the system scope otherwise: <root>/apps/<app>,
where <root> is /opt/tarantool or TT_SYSTEM_ROOT. An installed
application runs from the pair of the host, <root>/etc/<app>/, when there is
one. A bare <app> is refused: it is not an instance target.
Every tt instance command takes --scope project|user|system, which picks
the scope of the application outright, and --template <name>, which runs a
project or an installed version from .templates/<name>/ instead of
.templates/default/:
tt instance start # every instance of the project
tt instance start myapp:storage-1 --scope user
tt instance stop myapp:* --yes
tt instance logs myapp:storage-1 --follow
A command over several instances goes on after an instance it fails for and
exits with 3 when it failed for some of them only, with 1 when it failed for
every one of them, and with the code of the error of the instance when there
is one instance. stop, restart, kill and clean ask for a confirmation,
which --yes (-y) skips; -f is not a short form of any of their flags.
The confirmation is asked on a terminal only: without a terminal on the
standard input, in a script or a pipe, a command that needs one fails with
code 1 unless it is given --yes, and an answer piped into it is not read.
--no-prompt confirms nothing.
tt instance start runs every instance in the background under a watchdog of
tt, which restarts it as its restart field says. With --foreground, for
systemd, a container or a terminal, tt stays in the foreground instead, and
every instance runs under a watchdog of its own that does not restart it, in
a process group of its own and with its own pid file, as in the background:
tt instance stop, kill, logrotate and status act on one instance from
another terminal. The output of the instances goes to their tt.log and to
the standard output of tt, prefixed with the instance when there are
several. SIGINT, SIGTERM and SIGQUIT sent to tt stop every instance as a
stop of its watchdog does; Ctrl-C reaches every instance once, as tt passes
it on. An instance that ends does not stop the others: tt writes with what
code it exited and goes on. tt exits once all of them have ended: with 0
when they were stopped and stopped in time, a process killed by its stop
signal included; with 137 when one did not stop within its stop_timeout
and was killed; with the exit code of the first instance that ended on its
own with another code otherwise, 128 plus the signal for one killed by a
signal. An instance that runs already is an error before anything starts.
tt instance clean removes the data and the log of the instances, the files
of <root>/var/lib/<app>/<instance>/ and <root>/var/log/<app>/<instance>/,
and leaves a running instance alone.
The data, the logs and the pid files and sockets of an instance are in
<root>/var/lib/<app>/<instance>/, <root>/var/log/<app>/<instance>/ and
<root>/var/run/<app>/<instance>/; in a project <root> is .tarantool in
the project directory. The instance runs in the application directory.
A record with binary is an external process, which the instance commands
start, stop and show next to the Tarantool instances, under the same watchdog:
storage-001:
gateway:
binary: ./bin/gateway # or a program in PATH, such as python3
args: [--port, "8080"]
env: {GATEWAY_MODE: production}
workdir: ./gateway # <root>/var/lib/<app>/<instance>/ by default
stop_signal: SIGINT # SIGTERM by default
stop_timeout: 10s # 30s by default
logrotate_signal: SIGHUP # none by default
restart: on-failure # no by default
binary and workdir are relative to the application directory, also in the
pair of the host; a binary without a slash is looked up in PATH of tt,
and tt instance start reports one it cannot run, or a workdir that does
not exist, before it starts anything. Without workdir the process runs in
its data directory, <root>/var/lib/<app>/<instance>/, which
tt instance start creates. env goes on top of the environment of tt. The
process leads a process group of its own, which its stop signal and
tt instance kill reach whole, so that a wrapper script stops with the
program it runs. Its output goes to tt.log; its watchdog keeps tt.pid and
the pid of the process, process.pid, in the run directory.
tt instance status shows whether the process runs and nothing more;
tt instance logrotate reopens tt.log and sends the process
logrotate_signal, if the record has one; tt instance clean removes the log
and the data directory. tt connect, tt play, tt instance kill --dump and
the cluster commands refuse an external process: it is not a Tarantool
instance. The instances start in the order of instances.yaml, and none waits
for another to be ready.
A process whose watchdog was killed by something else than tt instance kill
runs on without it. tt instance status does not show it running and names it
in an alert, tt instance start refuses to start a second one, and
tt instance stop and tt instance kill stop it by process.pid.
A record with script is a Tarantool instance configured by its own Lua
script rather than by the cluster config, as the init.lua and
<instance>.init.lua applications of tt2 were:
legacy-001:
script: init.lua # relative to the application directory
env: {TT_MEMTX_MEMORY: "268435456"}
tarantool runs the script in the application directory. box.cfg takes the
data directory and the binary port of the layout from TT_WAL_DIR,
TT_MEMTX_DIR, TT_VINYL_DIR and TT_LISTEN for the options the script does
not pass; TT_LISTEN set in the environment of tt is kept. The console
socket is tarantool.control in the run directory, and the output goes to
tt.log. env of the record goes on top and may move the data with the same
variables; in the user and system scopes a relative path there is refused. A
relative path the script passes to box.cfg itself tt cannot check: in the
user and system scopes it is resolved against the installed version, and the
instance writes into the version, which an upgrade replaces. tt connect,
tt play, tt instance status and tt instance logrotate work as with any
Tarantool instance, tt instance check checks the syntax of the script, and
tt instance clean removes its data and log. tt cluster show and publish
refuse it: no cluster config configures it. The application targets of
tt replicaset leave it out next to instances of the cluster config. An
application of such instances alone keeps them, and tt replicaset acts on it
with the custom orchestrator without --custom, whatever the version of
Tarantool; --config and --custom still force an orchestrator.
Running instances under systemd
tt service systemd makes the systemd units that run the instances of an
application installed in the system scope, <root>/apps/<app>, from its pair:
the pair of the host in <root>/etc/<app>/, or else the default template of
the installed version. Units are made for the system scope only; the user
scope and projects are refused as not supported. <app> names the
application as the instance commands name it: inside a project of the same
name it is the project, and --scope system picks the installed one.
tt service systemd generate myapp # print the units
tt service systemd generate myapp --unit-dir ./units # write them into ./units
tt service systemd install myapp # into /etc/systemd/system
tt service systemd install myapp --run-as tt:tarantool
tt service systemd uninstall myapp
The template unit myapp@.service runs one instance of myapp:
[Unit]
Description=Tarantool application myapp, instance %i
After=network.target
[Service]
Type=simple
User=tarantool
Group=tarantool
Environment=TT_SYSTEM_ROOT=/opt/tarantool
Environment=TT_SYSTEMD_UNIT=%n
ExecStart=/opt/tarantool/bin/tt instance start --foreground --scope system myapp:%i
KillMode=mixed
KillSignal=SIGTERM
SendSIGKILL=yes
Restart=no
RestartSec=5s
TimeoutStopSec=35s
LimitNOFILE=65535
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
and every instance gets a drop-in, myapp@<instance>.service.d/tt.conf, with
what differs between the instances:
[Service]
Restart=on-failure
TimeoutStopSec=65s
tt instance start --foreground does not restart the instance: it exits
with the code of the instance, and systemd restarts it as Restart= says,
which is the restart field of the record: no, on-failure and always
are the values of systemd.
tt stops the instance itself: it sends the instance its stop signal and
kills it once its stop_timeout is up. So the stop signal of systemd goes
to tt alone (KillMode=mixed), and TimeoutStopSec= is the
stop_timeout of the record, 30 seconds by default, plus 5 seconds for tt
to kill the instance and exit: systemd kills nothing before tt does. A
stop in time ends the unit with 0, a kill with 137.
- Tarantool instances, instances with
script and external processes with
binary run under the same template.
TT_SYSTEM_ROOT is the root of the system scope the units are made in, so
that tt under systemd finds the application there. ExecStart= runs
<root>/bin/tt, the tt of the scope, which
tt binary install tt --scope system installs; without it the units run the
tt that makes them, with a warning.
- The instances run as the user and the group
--run-as <user>[:<group>]
names, tarantool:tarantool by default, the user the deb and rpm packages
of tt create; without a group the group is the user's name, and a numeric
id is taken as well. <root>/var must be writable by them. install
records the value with the units, and an install over them without the
flag keeps it; it warns when the host has no such user or group. Settings of
your own go into a drop-in of your own, myapp@.service.d/override.conf;
Restart= and TimeoutStopSec= come from instances.yaml.
- An application or instance name that a unit name would have to escape, a
user or a group that
User= and Group= would have to escape, and a root or
a path of tt that a unit would have to quote, are refused.
install writes the units into /etc/systemd/system, or the directory
--unit-dir names, and records in <root>/etc/<app>/systemd.yaml which
instances the units manage. It does not run systemctl, it prints what to
run:
systemctl daemon-reload
systemctl enable --now myapp@router-1.service myapp@storage-1.service
Run it again after the instances of the application change: it rewrites the
units and removes the drop-ins of the instances that are gone. It refuses a
unit file of the same name that it did not write, and an instance that runs
without a unit: stop it with tt instance stop first.
tt instance start, stop, restart and kill, and
tt replicaset rebootstrap, refuse the instances the units manage and print
the systemctl command to use instead: a watchdog of tt next to the unit
would supervise the instance twice, and a stop behind the back of the unit
would leave it out of step. The start the unit itself runs is told by
TT_SYSTEMD_UNIT, the name of the unit. tt instance status reads the same
pid files and shows the unit, in the UNIT column and the unit field of
-o json and -o yaml; logs, logrotate, check, clean and connect
work as with any instance.
uninstall removes the units and the record, from the directory they were
installed into, and needs only the record: it works for an application that
is gone. Without a record there is nothing to remove: it says the units are
not installed and exits with 0, so that it can be run again; a record that
cannot be read is an error. It refuses while an instance runs under its unit:
stop the units with systemctl disable --now first. A file it did not write
is left in place. generate writes the units only and records nothing: the instance
commands do not refuse the instances of units installed by hand.
Working with application templates
tt can create applications from templates.
A template is a built-in one, named by its name (tt create cluster), or a
template of your own, given by its path: a directory, or a .tgz or
.tar.gz archive, which may be named without its extension
(tt create ./templates/basic). A path is told from a name by a slash in
it, so a template in the current directory is given as ./<name>.
The application is created in the --name directory of the current
directory, or of the --dst directory.
The built-in templates are single_instance, cluster, vshard_cluster
and config_storage. Each of them creates a project that starts on
localhost as it is: the code of the application in the project directory,
and the pair it runs from, instances.yaml and config.yaml, in
.templates/default/:
$ tt create cluster --name app1
app1/
├── .templates
│ └── default
│ ├── config.yaml
│ └── instances.yaml
└── app.lua
app.file and the other paths of config.yaml are relative to the project
directory, the directory the instances run in; the data, logs and sockets go
to .tarantool/var/ there. The project is named after its directory;
vshard_cluster also writes app.manifest.toml, which names it --name with
_ replaced by -, and needs tt package build for its vshard
dependency before it starts. config_storage needs Tarantool Enterprise
Edition, which provides the config.storage role.
When the template writes app.manifest.toml, tt create refuses a --name
that does not make a package name there - lowercase letters, digits and
dashes, starting with a letter - and creates nothing: --name my_app gives
vshard_cluster the name my-app, --name My_App is refused.
A template of your own lays a project out the same way when it carries
.templates/<name>/instances.yaml and config.yaml; the files under
.templates/ are instantiated like any other.
Application template may contain:
*.tt.template - template files, that will be instantiated during
application creation.
MANIFEST.yaml - template manifest (see details below).
Template manifest MANIFEST.yaml has the following format:
description: Template description
vars:
- prompt: User name
name: user_name
default: admin
re: ^\w+$
- prompt: Retry count
default: "3"
name: retry_count
re: ^\d+$
pre-hook: ./hooks/pre-gen.sh
post-hook: ./hooks/post-gen.sh
include:
- init.lua
- .templates/default/instances.yaml
- .templates/default/config.yaml
follow-up-message: Run "tt instance start" in {{.name}}.
Where:
description (string) - template description.
vars - template variables used for instantiation.
prompt - user prompt for variable value input.
name - variable name.
default - default value of the variable.
re - regular expression used for value validation.
pre-hook (string) - executable to run before template
instantiation.
post-hook (string) - executable to run after template
instantiation.
include (list) - list of files to keep in application directory
after create.
follow-up-message (string) - message printed after the application
is created, with the variables instantiated in it.
There are pre-defined variables that can be used in template text:
name - application name. It is set to --name CLI argument value.
Don't include the .rocks directory in your application template. To
specify application dependencies, declare them in [dependencies] of
app.manifest.toml (see Working with packages).
Custom template
example
Working with tt daemon (experimental)
tt daemon module is used to manage tt daemon on a given machine.
This way instances can be operated remotely. Daemon can be configured
with tt_daemon.yaml config.
tt_daemon.yaml file format:
daemon:
run_dir: path
log_dir: path
log_file: string (file name)
listen_interface: string
port: num
pidfile: string (file name)
Where:
run_dir (string) - path to directory that stores various instance
runtime artifacts like console socket, PID file, etc. Default:
run.
log_dir (string) - directory that stores log files. Default:
log.
log_file (string) - name of file contains log of daemon process.
Default: tt_daemon.log.
listen_interface (string) - network interface the IP address
should be found on to bind http server socket. Default: loopback
(lo/lo0).
port (number) - port number to be used for daemon http server.
Default: 1024.
pidfile (string) - name of file contains pid of daemon process.
Default: tt_daemon.pid.
TT daemon
example
Tarantool reads its configuration from environment variables itself, and tt
adds nothing to it: an option of the cluster config from TT_<PATH>, the
path of the option in uppercase with _ for ., such as TT_IPROTO_LISTEN,
and a
box.cfg
parameter of an instance with script from TT_<NAME>, such as
TT_MEMTX_MEMORY. Set them for an instance in env of its record in
instances.yaml (see
Working with a set of instances).
Commands
Common description. For a detailed description, use tt help command .
instance - manage the instances of applications: start, stop,
restart, kill, status, logs, logrotate, check, clean and
connect.
connect - connect to the tarantool instance, as tt instance connect.
service systemd - generate, install and uninstall the systemd units of an
application of the system scope.
new - write a skeleton app.manifest.toml in the current directory.
create - create an application from a template.
package - build, pack, install, and manage manifest-based application
packages.
run - run the current package under its Tarantool.
test - build the current package and run its tests with luatest.
registry list - show the rock servers the packages are resolved against.
rocks - LuaRocks package manager.
binary - install, search, list, switch and uninstall tt, Tarantool, TCM
and SDK bundles; binary build tt builds a distribution of tt.
cluster - manage cluster configuration.
replicaset (rs) - manage replicasets.
backup - back up a Tarantool cluster for point-in-time recovery;
backup-id prints an identifier for a new backup.
restore - restore a Tarantool cluster from a backup.
cat - print into stdout the contents of .snap/.xlog files.
play - play the contents of .snap/.xlog files to another Tarantool
instance.
coredump - pack/unpack/inspect tarantool coredump.
aeon - connect to an Aeon instance.
tcm - manage Tarantool Cluster Manager.
daemon (experimental) - manage tt daemon.
modules - list external modules.
version - show Tarantool CLI version information.
completion - generate autocomplete for a specified shell.
help - display help for any command; tt help errors describes the exit
codes.