Tomo is a friendly command-line tool for deploying Rails apps. It is a new alternative to Capistrano, Mina, and Shipit that aims for simplicity and developer happiness.
💻 Rich command-line interface with built-in bash completions
☁️ Multi-environment and role-based multi-host support
💎 Everything you need to deploy a basic Rails app out of the box
🔌 Easily extensible for polyglot projects (not just Rails!)
💡 Concise, helpful error messages
📚 Quality documentation
🔬 Minimal dependencies
- Quick start
- Reference documentation
- Code of conduct
- Contribution guide
Tomo is distributed as a ruby gem. To install:
$ gem install tomo
For instructions on setting up bash completions, run:
$ tomo completion-script
Configuring a project
Tomo is configured via a
.tomo/config.rb file in your project. To get started, you can use
tomo init to generate a configuration that works for a basic Rails app.
An abbreviated version looks like this:
# .tomo/config.rb plugin "git" plugin "bundler" plugin "rails" # ... host "firstname.lastname@example.org" set application: "my-rails-app" set deploy_to: "/var/www/%<application>" set git_url: "email@example.com:my-username/my-rails-app.git" set git_branch: "master" # ... setup do run "git:clone" run "git:create_release" run "bundler:install" run "rails:db_schema_load" # ... end deploy do run "git:create_release" run "core:symlink_shared" run "core:write_release_json" run "bundler:install" run "rails:assets_precompile" run "rails:db_migrate" run "core:symlink_current" # ... end
Check out the configuration docs for a complete reference.
Tomo gives you easy-to-use commands for three common use cases:
tomo setupprepares a remote host for its first deploy
tomo deployperforms a deployment
tomo runlets you invoke one-off tasks
tomo setup prepares the remote host for its first deploy by sequentially running the
setup list of tasks specified in
.tomo/config.rb. These tasks typically create directories, initialize data stores, install prerequisite tools, and perform other one-time actions that are necessary before a deploy can take place.
Out of the box, tomo will:
- Configure necessary environment variables, like
- Install Ruby, Bundler, Node, Yarn, and dependencies
- Create all necessary deployment directories
- Create the Rails database, load the schema, and insert seed data
tomo setup is typically run once, you can use
tomo deploy every time you want to deploy a new version of your app. The deploy command will sequentially run the deploy list of tasks specified in
.tomo/config.rb. You can customize this list to meet the needs of your app. By default, tomo runs these tasks:
- Create a release (using the git:create_release task)
- Build the project (e.g. bundler:install, rails:assets_precompile)
- Migrate data to the meet the requirements of the new release (e.g. rails:db_migrate)
- Make the new release the “current” one (core:symlink_current)
- Restart the app to use the new current release (e.g. puma:restart)
- Perform any cleanup (e.g. bundler:clean)
Tomo can also
run individual remote tasks on demand. You can use the
tasks command to see the list of tasks tomo knows about.
One of the built-in Rails tasks is
rails:console, which brings up a fully-interactive Rails console over SSH.
Tomo has many plugins built-in, but you can easily add your own to extend tomo with custom tasks. By convention, custom plugins are stored in
.tomo/plugins/. These plugins can define tasks as plain ruby methods. For example:
# .tomo/plugins/my-plugin.rb def hello remote.run "echo", "hello", settings[:application] end
remote.run to execute shell scripts on the remote host, similar to how you would use Ruby’s
system. Project settings are accessible via
settings, which is a plain Ruby hash.
Load your plugin in
config.rb like this:
# .tomo/config.rb plugin "./plugins/my-plugin.rb"
And run it!
Read the Writing Custom Tasks tutorial for an in-depth guide to extending tomo.
What does the
unsupported option "accept-new" error mean?
By default, tomo uses the “accept-new” value for the StrictHostKeyChecking option, which is supported by OpenSSH 7.6 and newer. If you are using an older version, this will cause an error. As a workaround, you can override tomo’s default behavior like this:
# Replace "accept-new" with something compatible with older versions of SSH set ssh_strict_host_key_checking: true # or false
Why does my deploy hang after starting puma?
Puma 4.1.0 has a bug where its output isn’t properly detached prior to daemonzing. This causes tomo to hang waiting for output. You may see something like this prior to the deploy freezing:
Puma starting in single mode... * Version 4.1.0 (ruby 2.6.4-p104), codename: Fourth and One * Min threads: 5, max threads: 5 * Environment: production * Daemonizing...
To fix, upgrade to puma 4.1.1 or newer.
This project is a labor of love and I can only spend a few hours a week maintaining it, at most. If you’d like to help by submitting a pull request, or if you’ve discovered a bug that needs my attention, please let me know. Check out CONTRIBUTING.md to get started. Happy hacking! —Matt
The gem is available as open source under the terms of the MIT License.
Code of conduct
Everyone interacting in the Tomo project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Interested in filing a bug report, feature request, or opening a PR? Excellent! Please read the short CONTRIBUTING.md guidelines before you dive in.