# up(1) up(1) is a batching, parallel task-runner. It's designed primarily to deploy servers, where you can think of up(1) as a partial replacement for Kubernetes, Nomad, Docker Swarm, and other deployment tools. Unlike those other tools, `up` is extremely small, simple, and as a result, more reliable and less prone to bugs. up(1) is deliberately similar to make(1) in its config syntax. It differs primarily in its ability to run tasks in batches and prompt before continuing, a small but important difference which enables up(1) to handle zero-downtime, blue-green, rolling deploys. ### Install ``` $ go get -u egt.run/up/cmd/up ``` ### Usage Like make(1), up(1) can be used to deploy anything. You'll describe your server architecture in a single file (`Upfile(5)`), then use the `up` command to bring everything online. Each Upfile contains one or more commands. All commands run locally, so remote commands can be executed using something like `ssh user@$server "echo 'hi'"` Variable substitution exists, and variables are identified by a `$`. Variables can represent a single thing, such as `$remote` representing `my_user@$server` or they can represent a series of commands, such as `$provision` representing 10 different commands to run. You'll define these commands yourself. Up gives you access to a reserved, always-available variable in your commands: `$server` represents the IP address in the inventory that `up` is currently executing commands on. You can also use environment variables, like the following: ```bash USER=dev up -t 100.0.0.1 deploy ``` You can access that variable in your Upfile using `$USER`. Running commands on the remote host is as simple as using whatever shell you've configured for your local system. See the below example Upfile designed for bash, which runs remote commands using ssh: ```bash remote=$UP_USER@$server deploy: # Your steps to compile and copy files to the remote server go here. # If any of the following lines have non-zero exits, up immediately # exits with status code 1. go build -o myserver git.sr.ht/~example/myserver rsync -chazP myserver $remote: rm myserver ssh $remote 'sudo service myserver restart' sleep 10 && $check_health update: ssh $remote 'sudo apt -y update && sudo apt -y upgrade' ssh $remote 'sudo snap refresh' ``` Using the example Upfile above, here's how we could deploy to staging: ``` up -t 100.0.0.1 deploy ``` Since `up` does these tasks by running arbitrary shell commands defined in your project-level `Upfile`, `up` works out-of-the-box with: * All cloud providers * Ansible * Containers (Docker, rkt, LXC, etc.) * Bash scripts * And any other tools with command-line interfaces If we want to deploy to staging and production, we'd write: ``` up -t 100.0.0.1,100.0.0.2 deploy ``` To update all of our debian servers, 2 at a time, and exit immediately if any fail, we can run: ``` up -t 100.0.0.1,100.0.0.2 -n 2 update ``` Run `up -h` for additional usage info. ### Composition with other tools Often in systems you'll have services deployed to dynamic IP addresses, so you won't want to hardcode IPs in your deployment scripts. You can use a service discovery mechanism to pass IPs to up and dynamically look up services by name. For instance, using [inv2ips](https://www.egt.run/inv2ips) (which outputs a comma-separated list of IP addresses) with an inventory.json file: ``` { "100.0.0.1": ["production", "app"], "100.0.0.2": ["production", "database"], "100.0.0.3": ["staging", "app"] } ``` We can run our deploy task on all production servers like so: ``` up -t $(inv2ips production) deploy # equivalent to: up -t 100.0.0.1,100.0.0.2 deploy ``` ### Features - [x] Define your system architecture in source control - [x] Run arbitrary shell commands to provision, start, and check the health of your servers - [x] Operate on individual environments, like production and staging - [x] Rolling, concurrent, agentless deploys - [x] Stateless. Up checks your infrastructure to determine its state on each run, so nothing is ever out-of-date ### Non-Features Like any good UNIX tool, `up` aims to do one thing and do it well. The following features are out of the scope of `up`: * Bin-packing * Logging * On-going monitoring * Restarting apps after crashes * Spinning up new servers via cloud providers * Scaling servers up or down with demand