{"id":13430358,"url":"https://github.com/pressly/sup","last_synced_at":"2025-04-13T22:28:30.533Z","repository":{"id":27746828,"uuid":"31234749","full_name":"pressly/sup","owner":"pressly","description":"Super simple deployment tool - think of it like 'make' for a network of servers","archived":false,"fork":false,"pushed_at":"2023-12-24T11:13:37.000Z","size":23788,"stargazers_count":2493,"open_issues_count":56,"forks_count":178,"subscribers_count":64,"default_branch":"master","last_synced_at":"2025-04-06T19:07:52.364Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://pressly.github.io/sup","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pressly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-02-23T23:04:21.000Z","updated_at":"2025-04-06T08:35:59.000Z","dependencies_parsed_at":"2022-07-08T10:51:21.894Z","dependency_job_id":"ed1a4be6-b57a-4b5b-a311-02bf8252a795","html_url":"https://github.com/pressly/sup","commit_stats":{"total_commits":221,"total_committers":22,"mean_commits":"10.045454545454545","dds":"0.33484162895927605","last_synced_commit":"17c751e8ca547e2ef7fb5b6b2017543cd7172a05"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pressly%2Fsup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pressly%2Fsup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pressly%2Fsup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pressly%2Fsup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pressly","download_url":"https://codeload.github.com/pressly/sup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248790391,"owners_count":21162003,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T02:00:52.667Z","updated_at":"2025-04-13T22:28:30.476Z","avatar_url":"https://github.com/pressly.png","language":"Go","readme":"Stack Up\n========\n\nStack Up is a simple deployment tool that performs given set of commands on multiple hosts in parallel. It reads Supfile, a YAML configuration file, which defines networks (groups of hosts), commands and targets.\n\n# Demo\n\n[![Sup](https://github.com/pressly/sup/blob/gif/asciinema.gif?raw=true)](https://asciinema.org/a/19742?autoplay=1)\n\n*Note: Demo is based on [this example Supfile](./example/Supfile).*\n\n# Installation\n\n    $ go get -u github.com/pressly/sup/cmd/sup\n\n# Usage\n\n    $ sup [OPTIONS] NETWORK COMMAND [...]\n\n### Options\n\n| Option            | Description                      |\n|-------------------|----------------------------------|\n| `-f Supfile`      | Custom path to Supfile           |\n| `-e`, `--env=[]`  | Set environment variables        |\n| `--only REGEXP`   | Filter hosts matching regexp     |\n| `--except REGEXP` | Filter out hosts matching regexp |\n| `--debug`, `-D`   | Enable debug/verbose mode        |\n| `--disable-prefix`| Disable hostname prefix          |\n| `--help`, `-h`    | Show help/usage                  |\n| `--version`, `-v` | Print version                    |\n\n## Network\n\nA group of hosts.\n\n```yaml\n# Supfile\n\nnetworks:\n    production:\n        hosts:\n            - api1.example.com\n            - api2.example.com\n            - api3.example.com\n    staging:\n        # fetch dynamic list of hosts\n        inventory: curl http://example.com/latest/meta-data/hostname\n```\n\n`$ sup production COMMAND` will run COMMAND on `api1`, `api2` and `api3` hosts in parallel.\n\n## Command\n\nA shell command(s) to be run remotely.\n\n```yaml\n# Supfile\n\ncommands:\n    restart:\n        desc: Restart example Docker container\n        run: sudo docker restart example\n    tail-logs:\n        desc: Watch tail of Docker logs from all hosts\n        run: sudo docker logs --tail=20 -f example\n```\n\n`$ sup staging restart` will restart all staging Docker containers in parallel.\n\n`$ sup production tail-logs` will tail Docker logs from all production containers in parallel.\n\n### Serial command (a.k.a. Rolling Update)\n\n`serial: N` constraints a command to be run on `N` hosts at a time at maximum. Rolling Update for free!\n\n```yaml\n# Supfile\n\ncommands:\n    restart:\n        desc: Restart example Docker container\n        run: sudo docker restart example\n        serial: 2\n```\n\n`$ sup production restart` will restart all Docker containers, two at a time at maximum.\n\n### Once command (one host only)\n\n`once: true` constraints a command to be run only on one host. Useful for one-time tasks.\n\n```yaml\n# Supfile\n\ncommands:\n    build:\n        desc: Build Docker image and push to registry\n        run: sudo docker build -t image:latest . \u0026\u0026 sudo docker push image:latest\n        once: true # one host only\n    pull:\n        desc: Pull latest Docker image from registry\n        run: sudo docker pull image:latest\n```\n\n`$ sup production build pull` will build Docker image on one production host only and spread it to all hosts.\n\n### Local command\n\nRuns command always on localhost.\n\n```yaml\n# Supfile\n\ncommands:\n    prepare:\n        desc: Prepare to upload\n        local: npm run build\n```\n\n### Upload command\n\nUploads files/directories to all remote hosts. Uses `tar` under the hood.\n\n```yaml\n# Supfile\n\ncommands:\n    upload:\n        desc: Upload dist files to all hosts\n        upload:\n          - src: ./dist\n            dst: /tmp/\n```\n\n### Interactive Bash on all hosts\n\nDo you want to interact with multiple hosts at once? Sure!\n\n```yaml\n# Supfile\n\ncommands:\n    bash:\n        desc: Interactive Bash on all hosts\n        stdin: true\n        run: bash\n```\n\n```bash\n$ sup production bash\n#\n# type in commands and see output from all hosts!\n# ^C\n```\n\nPassing prepared commands to all hosts:\n```bash\n$ echo 'sudo apt-get update -y' | sup production bash\n\n# or:\n$ sup production bash \u003c\u003c\u003c 'sudo apt-get update -y'\n\n# or:\n$ cat \u003c\u003cEOF | sup production bash\nsudo apt-get update -y\ndate\nuname -a\nEOF\n```\n\n### Interactive Docker Exec on all hosts\n\n```yaml\n# Supfile\n\ncommands:\n    exec:\n        desc: Exec into Docker container on all hosts\n        stdin: true\n        run: sudo docker exec -i $CONTAINER bash\n```\n\n```bash\n$ sup production exec\nps aux\nstrace -p 1 # trace system calls and signals on all your production hosts\n```\n\n## Target\n\nTarget is an alias for multiple commands. Each command will be run on all hosts in parallel,\n`sup` will check return status from all hosts, and run subsequent commands on success only\n(thus any error on any host will interrupt the process).\n\n```yaml\n# Supfile\n\ntargets:\n    deploy:\n        - build\n        - pull\n        - migrate-db-up\n        - stop-rm-run\n        - health\n        - slack-notify\n        - airbrake-notify\n```\n\n`$ sup production deploy`\n\nis equivalent to\n\n`$ sup production build pull migrate-db-up stop-rm-run health slack-notify airbrake-notify`\n\n# Supfile\n\nSee [example Supfile](./example/Supfile).\n\n### Basic structure\n\n```yaml\n# Supfile\n---\nversion: 0.4\n\n# Global environment variables\nenv:\n  NAME: api\n  IMAGE: example/api\n\nnetworks:\n  local:\n    hosts:\n      - localhost\n  staging:\n    hosts:\n      - stg1.example.com\n  production:\n    hosts:\n      - api1.example.com\n      - api2.example.com\n\ncommands:\n  echo:\n    desc: Print some env vars\n    run: echo $NAME $IMAGE $SUP_NETWORK\n  date:\n    desc: Print OS name and current date/time\n    run: uname -a; date\n\ntargets:\n  all:\n    - echo\n    - date\n```\n\n### Default environment variables available in Supfile\n\n- `$SUP_HOST` - Current host.\n- `$SUP_NETWORK` - Current network.\n- `$SUP_USER` - User who invoked sup command.\n- `$SUP_TIME` - Date/time of sup command invocation.\n- `$SUP_ENV` - Environment variables provided on sup command invocation. You can pass `$SUP_ENV` to another `sup` or `docker` commands in your Supfile.\n\n# Running sup from Supfile\n\nSupfile doesn't let you import another Supfile. Instead, it lets you run `sup` sub-process from inside your Supfile. This is how you can structure larger projects:\n\n```\n./Supfile\n./database/Supfile\n./services/scheduler/Supfile\n```\n\nTop-level Supfile calls `sup` with Supfiles from sub-projects:\n```yaml\n restart-scheduler:\n    desc: Restart scheduler\n    local: \u003e\n      sup -f ./services/scheduler/Supfile $SUP_ENV $SUP_NETWORK restart\n db-up:\n    desc: Migrate database\n    local: \u003e\n      sup -f ./database/Supfile $SUP_ENV $SUP_NETWORK up\n```\n\n# Common SSH Problem\n\nif for some reason sup doesn't connect and you get the following error,\n\n```bash\nconnecting to clients failed: connecting to remote host failed: Connect(\"myserver@xxx.xxx.xxx.xxx\"): ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain\n```\n\nit means that your `ssh-agent` dosen't have access to your public and private keys. in order to fix this issue, follow the below instructions:\n\n- run the following command and make sure you have a key register with `ssh-agent`\n\n```bash\nssh-add -l\n```\n\nif you see something like `The agent has no identities.` it means that you need to manually add your key to `ssh-agent`.\nin order to do that, run the following command\n\n```bash\nssh-add ~/.ssh/id_rsa\n```\n\nyou should now be able to use sup with your ssh key.\n\n\n# Development\n\n    fork it, hack it..\n\n    $ make build\n\n    create new Pull Request\n\nWe'll be happy to review \u0026 accept new Pull Requests!\n\n# License\n\nLicensed under the [MIT License](./LICENSE).\n","funding_links":[],"categories":["Software Packages","Go","软件包","Go Tools","Tools","others","Other Software","tools","軟件包","Go 工具"],"sub_categories":["Other Software","其他软件","其他软件库和软件包","其他軟件"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpressly%2Fsup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpressly%2Fsup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpressly%2Fsup/lists"}