Commands
The yaml top-level map can be any string.
The top-level name must be unique.
Example Config
commands:
stop-docker-container:
cmd: docker
Args:
- compose
- -f /some/path/to/docker-compose.yaml
- down
# if host is not defined, command will be run locally
# The host has to be defined in either the config file or the SSH Config files
host: some-host
hooks
error:
- some-other-command-when-failing
success:
- success-command
final:
- final-command
backup-docker-container-script:
cmd: /path/to/local/script
# script file is input as stdin to SSH
type: scriptFile # also can be script
environment:
- FOO=BAR
- APP=$VAR
Values available for this section (case-sensitive):
name |
notes |
type |
required |
cmd |
Defines the command to execute |
string |
yes |
Args |
Defines the arguments to the command |
[]string |
no |
environment |
Defines evironment variables for the command |
[]string |
no |
type |
May be scriptFile , script , or package . Runs script from local machine on remote. Package is the only one that can be run on local and remote hosts. |
string |
no |
getOutput |
Command(s) output is in the notification(s) |
bool |
no |
host |
If not specified, the command will execute locally. |
string |
no |
scriptEnvFile |
When type is scriptFile or script , this file is prepended to the input. |
string |
no |
shell |
Run the command in the shell |
string |
no |
hooks |
Hooks are used at the end of the individual command. Must have at least error , success , or final . |
map[string][]string |
no |
cmd
cmd must be a valid command or script to execute.
Args
args must be arguments to cmd as they would be passed on the command-line:
Define them in an array:
Args:
- arg1
- arg2
- arg3
getOutput
Get command output when a notification is sent.
Is not required. Can be true
or false
.
host
Info
If any host
is not defined or left blank, the command will run on the local machine.
Host may or may not be defined in the hosts
section.
Info
If any host
from the commands section does not match any object in the hosts
section, the Host
is assumed to be this value. This value will be used to search in the default SSH config files.
For example, say that I have a host defined in my SSH config with the Host
defined as web-prod
.
If I assign a value to host as host: web-prod
and don’t specify this value in the hosts
object, web-prod will be used as the Host
in searching the SSH config files.
shell
If shell is defined, the command will run in the specified shell.
Make sure to escape any shell input.
scriptEnvFile
Path to a file.
When type is script
or scriptFile
, the script is appended to this file.
This is useful for specifying environment variables or other things so they don’t have to be included in the script.
type
May be scriptFile
or script
. Runs script from local machine on remote host passed to the SSH session as standard input.
If type
is script
, cmd
is used as the script.
If type
is scriptFile
, cmd must be a script file.
If type
is package
, there are additional fields that must be specified.
environment
The environment variables support expansion:
- using escaped values
$VAR
or ${VAR}
For now, the variables have to be defined in an .env
file in the same directory as the config file.
If using it with host specified, the SSH server has to be configured to accept those env variables.
If the command is run locally, the OS’s environment is added.
hooks
Hooks are run after the command is run.
Errors are run if the command errors, success if it returns no error. Final hooks are run regardless of error condition.
Values for hooks are as follows:
command:
hook:
# these commands are defined elsewhere in the file
error:
- errcommand
success:
- successcommand
final:
- donecommand
packages
See the dedicated page for package configuration.
Command Lists
Command lists are for executing commands in sequence and getting notifications from them.
The top-level object key can be anything you want but not the same as another.
Lists can go in a separate file. Command lists should be in a separate file if:
- key ‘cmd-lists.file’ is found
- hosts.yml or hosts.yaml is found in the same directory as the backy config file
test2:
name: test2
order:
- test
- test2
notifications:
- mail.prod-email
- matrix.sysadmin
cron: "0 * * * * *"
key |
description |
type |
required |
order |
Defines the sequence of commands to execute |
[]string |
yes |
getOutput |
Command(s) output is in the notification(s) |
bool |
no |
notifications |
The notification service(s) and ID(s) to use on success and failure. Must be service.id . See the notifications documentation page for more |
[]string |
no |
name |
Optional name of the list |
string |
no |
cron |
Time at which to schedule the list. Only has affect when cron subcommand is run. |
string |
no |
Order
The order is an array of commands to execute in order. Each command must be defined.
getOutput
Get command output when a notification is sent.
Is not required. Can be true
or false
. Default is false
.
Notifications
An array of notification IDs to use on success and failure. Must match any of the notifications
object map keys.
Name
Name is optional. If name is not defined, name will be the object’s map key.
Cron mode
Backy also has a cron mode, so one can run backy cron
and start a process that schedules jobs to run at times defined in the configuration file.
Adding cron: 0 0 1 * * *
 to a cmd-lists
object will schedule the list at 1 in the morning. See https://crontab.guru/ for reference.
Tip
Note: Backy uses the second field of cron, so add anything except * to the beginning of a regular cron expression.
cmd-lists:
 docker-container-backup: # this can be any name you want
  # all commands have to be defined
  order:
   - stop-docker-container
   - backup-docker-container-script
   - shell-cmd
   - hostname
   - start-docker-container
  notifications:
   - matrix.id
  name: backup-some-container
  cron: "0 0 1 * * *"
 hostname:
  name: hostname
  order:
   - hostname
  notifications:
  - mail.prod-email
Packages
This is dedicated to package
commands. The command type
field must be package
. Package is a type that allows one to perform package operations. There are several additional options available when type
is package
:
name |
notes |
type |
required |
packageName |
The name of a package to be modified. |
string |
yes |
packageManager |
The name of the package manger to be used. |
string |
yes |
packageOperation |
The type of operation to be perform. |
string |
yes |
packageVersion |
The version of a package to be modified. |
string |
no |
example
The following is an example of a package command:
update-docker:
type: package
shell: zsh
packageName: docker-ce
packageManager: apt
packageOperation: install
host: debian-based-host
packageOperation
The following package operations are supported:
packageManager
The following package managers are recognized:
package command args
You can add additional arguments using the standard Args
key. This is useful for adding more packages.
Development
The PackageManager interface provides an easy to enforce functions and options. There are two interfaces, PackageManager
and ConfigurablePackageManager
in the directory pkg/pkgman
. Go’s import-cycle “feature” caused me to implement functional options using a third interface. PackageManagerOption
is a function that takes an interface.
PackageManager
// PackageManager is an interface used to define common package commands. This shall be implemented by every package.
type PackageManager interface {
Install(pkg, version string, args []string) (string, []string)
Remove(pkg string, args []string) (string, []string)
Upgrade(pkg, version string) (string, []string) // Upgrade a specific package
UpgradeAll() (string, []string)
// Configure applies functional options to customize the package manager.
Configure(options ...pkgcommon.PackageManagerOption)
}
There are a few functional options that should be implemented using the ConfigurablePackageManager
interface:
// ConfigurablePackageManager defines methods for setting configuration options.
type ConfigurablePackageManager interface {
SetUseAuth(useAuth bool)
SetAuthCommand(authCommand string)
}
Notifications
Notifications can be sent on command list completion and failure.
The supported platforms for notifications are email (SMTP) and Matrix.
Notifications are defined by service, with the current form following below. Ids must come after the service.
notifications:
mail:
prod-email:
host: yourhost.tld
port: 587
senderaddress: email@domain.tld
to:
- admin@domain.tld
username: smtp-username@domain.tld
password: your-password-here
matrix:
matrix:
home-server: your-home-server.tld
room-id: room-id
access-token: your-access-token
user-id: your-user-id
Sections recognized are mail
and matrix
There must be a section with an id (eg. mail.test-svr
) following one of these sections.
mail
key |
description |
type |
host |
Specifies the SMTP host to connect to |
string |
port |
Specifies the SMTP port |
uint16 |
senderaddress |
Address from which to send mail |
string |
to |
Recipients to send emails to |
[]string |
username |
SMTP username |
string |
password |
SMTP password |
string |
matrix
key |
description |
type |
home-server |
Specifies the Matrix server connect to |
string |
room-id |
Specifies the room ID of the room to send messages to |
string |
access-token |
Matrix access token |
string |
user-id |
Matrix user ID |
string |
To get your access token (assumes you are using Element) :
- Log in to the account you want to get the access token for. Click on the name in the top left corner, then “Settings”.
- Click the “Help & About” tab (left side of the dialog).
- Scroll to the bottom and click on
<click to reveal>
part of Access Token.
- Copy your access token to a safe place.
To get the room ID:
- On Element or a similar client, navigate to the room.
- Navigate to the settings from the top menu.
- Click on Advanced, the room ID is there.
Info
Make sure to quote the room ID, as YAML spec defines tags using !
.