{"id":13557684,"url":"https://github.com/wagoodman/bridgy","last_synced_at":"2025-04-13T02:09:49.260Z","repository":{"id":50354065,"uuid":"98302540","full_name":"wagoodman/bridgy","owner":"wagoodman","description":"cloud inventory + ssh + tmux + sshfs","archived":false,"fork":false,"pushed_at":"2023-10-13T13:46:08.000Z","size":781,"stargazers_count":413,"open_issues_count":9,"forks_count":53,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-13T02:09:19.699Z","etag":null,"topics":["aws","ec2","inventory","ssh","sshfs","tmux"],"latest_commit_sha":null,"homepage":"","language":"Python","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/wagoodman.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":"2017-07-25T12:14:54.000Z","updated_at":"2025-04-05T00:57:09.000Z","dependencies_parsed_at":"2024-01-14T06:56:09.335Z","dependency_job_id":null,"html_url":"https://github.com/wagoodman/bridgy","commit_stats":{"total_commits":129,"total_committers":7,"mean_commits":"18.428571428571427","dds":0.07751937984496127,"last_synced_commit":"27a3d1e2702de95f05ac0b16eb5ea39013b88ee4"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbridgy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbridgy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbridgy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wagoodman%2Fbridgy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wagoodman","download_url":"https://codeload.github.com/wagoodman/bridgy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654090,"owners_count":21140236,"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":["aws","ec2","inventory","ssh","sshfs","tmux"],"created_at":"2024-08-01T12:04:29.363Z","updated_at":"2025-04-13T02:09:49.238Z","avatar_url":"https://github.com/wagoodman.png","language":"Python","funding_links":[],"categories":["Python","aws"],"sub_categories":[],"readme":"# bridgy\n\n![Image](https://api.travis-ci.org/wagoodman/bridgy.svg?branch=master)  [![PyPI version](https://badge.fury.io/py/bridgy.svg)](https://badge.fury.io/py/bridgy)\n(***WIP/beta***)\n\n**TL;DR**: bridgy = ssh + tmux + sshfs + cloud inventory search\n\nJust get me to my ec2 box with a simple search. Multiple matches? Just\nssh into all matching instances via tmux.\n\n![Image](demo.gif)\n\n**Features:**\n- [x] Custom inventory sources:\n  - [x] AWS (supports matching by tag, dns, or instance-id)\n  - [ ] GCP\n  - [x] New Relic\n  - [x] CSV\n  - [ ] Ansible inventory\n- [x] Search against multiple inventory sources simultaneously\n- [x] Connect to inventory sources via a bastion/jumpbox\n- [x] Fuzzy search against the inventory\n- [x] Prompt for single/multi selection for matched hosts in inventory\n- [x] Open multiple ssh connections via tmux (splits or tabs)\n- [x] Configure custom tmux layouts (via config)\n- [x] Seamless connection via bastion (via config)\n- [x] Setup sshfs mount to a remote dir\n- [x] Run custom command on login (via config)\n- [x] Run arbitrary ansible playbooks\n- [x] Push / pull files (via ansible fetch/copy task)\n- [ ] Ssh tunnel to hosts\n- [x] ECS support (exec to container, currently only via new relic inventory)\n- [x] Python3 support :)\n\n**(Want a feature? Just [create an issue](https://github.com/wagoodman/bridgy/issues/new?labels=enhancement) describing it)**\n\n## Installing\n\n**Linux**\n```bash\npip install --user bridgy\n\n# optionally support sshing into multiple systems at once\nsudo apt install tmux\n\n# optionally support remote mounts\nsudo apt install sshfs\n\n# put this into your ~/.bashrc (pip install --user does not put bins in the 'right' spot for everyone: https://github.com/pypa/pip/issues/3813)\nexport PATH=${HOME}/.local/bin:$PATH\n```\n**Note:** you may still need to add bridgy to your path!\n\n**OSX**\n```bash\nsudo easy_install pip\npip install --user bridgy --ignore-installed six\n\n# optionally support sshing into multiple systems at once\nbrew install tmux\n\n# optionally support remote mounts\nbrew cask install osxfuse\nbrew install sshfs\n\n# put this into your ~/.bash_profile (pip install --user does not put bins in the 'right' spot for everyone: https://github.com/pypa/pip/issues/3813)\nexport PATH=${HOME}/.local/bin:$PATH\n```\n\n**Windows**\n```\n¯\\_(ツ)_/¯\n```\n\n## Getting started\nAfter installing, create a configuration file by running\n```bash\n$ bridgy init\n```\nThis will create a default `~/.bridgy/config.yml` file for you. From there you need to configure inventory sources and other options:\n\n```yaml\nconfig-schema: 2\ninventory:\n  source:\n\n    - type: csv\n      name: on-site servers\n      # CSV files are placed in ~/.bridgy/inventory/csv\n      file: somefile.csv\n      # requires at least name and address\n      fields: name, address\n\n    # Inventory parameters to support querying AWS using boto profiles\n    - type: aws\n      name: test\n      profile: a-boto-profile-name\n      region: us-west-2\n\n\n# define ssh behavior and preferences\nssh:\n  user: awesome-user\n  options: -C -o ServerAliveInterval=255\n  command: sudo -i su - another-user -s /bin/bash\n  tmux: false\n```\nNow you can ssh into a system referenced from the given inventory sources:\n```bash\n# without tmux\n$ bridgy ssh someserver\n\n# with tmux (or set the ssh.tmux=true config option to always use tmux)\n$ bridgy ssh -t someserver\n```\nThat's just to get you started, there is plenty more you can do though!\n\nHave a special multi-pane tmux layout for every system you login to? Drop it in\nthe config, reference it by name:\n```yaml\ntmux:\n  layout:\n    logger:\n      - cmd: split-window -h\n      - cmd: split-window -h\n      - cmd: split-window -v\n        run: tail -f /var/log/messages\n      - cmd: set-window-option synchronize-panes on\n```\nthen...\n```bash\n$ bridgy ssh -tl logger awesomebox\n```\n\nWant to remotely mount a dir from your ec2 instance over ssh locally?\n\n```bash\n$ bridgy mount awesomebox:/appdir\n[?] What instances would you like to have mounted? (enter to select):\n \u003e o dev-myawesomeboxname                   (10.10.60.220)\n   o qa-myawesomeboxname                    (10.10.63.13)\n\nMounted dev-myawesomeboxname:/tmp at ~/.bridgy/mounts/dev-myawesomeboxname\n```\n\nNeed to connect to your boxes via a jumpbox? Drop in your bastion connection information in the config:\n```yaml\nbastion:\n  user: some-username\n  address: some-ip-or-host\n  # optional ssh arguments\n  options: -C -o ServerAliveInterval=255 -o FingerprintHash=sha256 -o TCPKeepAlive=yes -o ForwardAgent=yes -p 22222\n```\n\nNeed a different bastion for a given inventory source, override it:\n```yaml\ninventory:\n  source:\n\n    - type: csv\n      name: on-site servers\n      file: anawesome.csv\n      fields: name, address\n      # if you need to connect to aws hosts via a bastion, then\n      # provide all connectivity info in each inventory item\n      # (each inventory source bastion overrides the global bastion configuration)\n      bastion:\n        user: a-better-username\n        address: someotherhost.com\n        options: -C -o ServerAliveInterval=60\n\nbastion:\n  user: some-username\n  address: some-ip-or-host.com\n  options: -C -o ServerAliveInterval=255 -o FingerprintHash=sha256 -o TCPKeepAlive=yes -o ForwardAgent=yes -p 22222\n```\n\nThe same override functionality is available for ssh options and pattern matchers:\n```yaml\ninventory:\n  source:\n\n    - type: csv\n      name: on-site servers\n      include_pattern: .*meh_.*\n      file: anawesome.csv\n      fields: name, address\n      ssh:\n        user: a-better-username\n        options: -C -o ServerAliveInterval=60\n\nssh:\n  user: some-username\n  options: -C -o ServerAliveInterval=255\n```\n\nWant to perform arbitrary tasks? Drop an ansible playbook in config, reference it by name (`grab-files`):\n```yaml\nrun:\n  grab-files:\n    - hosts: app-srv-13, dev-srv\n      gather_facts: no\n      tasks:\n        - name: 'Get secrets.yml'\n          fetch:\n            src: /appdir/config/secrets.yml\n            dest: /tmp/prefix-{{ inventory_hostname }}.secrets.yml\n            fail_on_missing: yes\n            flat: yes\n        - name: 'Get production.rb'\n          fetch:\n            src: /appdir/config/environments/production.rb\n            dest: /tmp/prefix-{{ inventory_hostname }}.production.rb\n            fail_on_missing: yes\n            flat: yes\n        - name: 'Get database.yml'\n          fetch:\n            src: /appdir/config/database.yml\n            dest: /tmp/prefix-{{ inventory_hostname }}.database.yml\n            fail_on_missing: yes\n            flat: yes\n```\nthen...\n```bash\n$ bridgy run grab-files\n\nPLAY [app-srv-13, dev-srv] *****************************************************\n\nTASK [Get secrets.yml] ********************************************************\nok: [dev-srv]\nok: [app-srv-13]\n\nTASK [Get production.rb] ******************************************************\nok: [dev-srv]\nok: [app-srv-13]\n\nTASK [Get database.yml] *******************************************************\nok: [dev-srv]\nok: [app-srv-13]\n\n$ ls -1 /tmp | grep prefix\nprefix-dev-srv.database.yml\nprefix-dev-srv.production.rb\nprefix-dev-srv.secrets.yml\nprefix-app-srv-13.database.yml\nprefix-app-srv-13.production.rb\nprefix-app-srv-13.secrets.yml\n\n```\n\nWant to exec into a running container in ECS? (only via new relic inventory is supported)\n\n```bash\n$ bridgy exec awesome\n[?] What containers would you like to exec into? (enter to select):\n \u003e o dev-myawesomecontainer\n   o qa-myawesomecontainer\n```\n\n## Config Reference\nAn exhaustive list of options you can put in the config, with some example values:\n```yaml\nconfig-schema: 2\ninventory:\n\n  update_at_start: false      # update the inventory sources on each run\n  fuzzy_search: true          # allow for more that partial matching, you only need to get 'close'\n  exclude_pattern: '.*qa.*'   # exclude instances that match the given regex\n  include_pattern: '.*qa.*'   # include only instances that match the given regex\n\n  # in case you need to use this behind a proxy\n  http_proxy: http://someurl.com:80 \n  https_proxy: http://someurl.com:80 \n\n  source:\n\n    # Example with a CSV\n    - type: csv\n      name: On-site\n      # CSV files are placed in ~/.bridgy/inventory/csv\n      file: primary-site.csv\n      delimiter: '|'\n      # requires at least name and address\n      fields: index, name, address, other, random, fields\n\n    - type: aws\n      name: Offsite\n      # ~/.aws/* configs will be referenced by default, but can be overridden here: \n      access_key_id: AdfhjskfhdkfjfhskfTQ(fake)\n      secret_access_key: ZdhfjkshfkjdhfjshfkhfjsE5xx/dhfjksdhfksjf(fake)\n      session_token: someawesometoken(fake)\n      region: us-west-2\n\n    # Inventory parameters to support querying AWS using boto profiles\n    - type: aws\n      name: Offsite DR\n      profile: offsite-dr-servers\n      region: us-west-2\n\n    # All inventory parameters to support querying New Relic\n    - type: newrelic\n      name: web-production\n      account_number: ACCOUNT_NUMBER\n      insights_query_api_key: API_KEY\n\n    # You can always use a specific bastion for each inventory source if you want (that overrides the global bastion)\n    - type: aws\n      name: Offsite DR\n      profile: offsite-dr-servers\n      region: us-west-2\n      # the real bastion!...\n      bastion:\n        user: jumper\n        address: someothersystem.com\n        options: -C -o ServerAliveInterval=30 -o TCPKeepAlive=yes\n\n# define ssh behavior and preferences\nssh:\n  user: awesome-user\n  # Any valid ssh cli options you would specify to SSH (optional)\n  options: -C -o ServerAliveInterval=255\n  # Run a command upon logging into any host (optional)\n  command: sudo -i su - another_user -s /bin/bash\n  # Use Tmux to wrap all ssh sessions (optional)\n  tmux: true\n\n\n# This specifies any SSHFS options for mounting remote directories\nsshfs:\n  # Any sshfs option that you would specify to sshfs (optional)\n  # Tip: if you need to be another user on the remote system you can do so via sudo:\n  # options: -o sftp_server=\"/usr/bin/sudo /usr/lib/openssh/sftp-server\"\n  options: -o auto_cache,reconnect,no_readahead -C -o TCPKeepAlive=yes -o ServerAliveInterval=255 -o StrictHostKeyChecking=no\n\n# configure your bastion here if it applies to all of your inventory sources\nbastion:\n  # User to use when SSHing into the bastion host (optional)\n  user: johnybgoode\n  # Address of the bastion host\n  address: zest\n  # Any valid cli options you would specify to SSH (optional)\n  options: -C -o ServerAliveInterval=255\n\n\ntmux:\n  # You can make multiple panes to a single host by specifying a layout definition. Simply\n  # define each tmux command to run and an optional command to run in that pane.\n  # Use these layouts by name with the -l cli option (bridgy ssh -l somename host...)\n  layout:\n    # bridgy ssh -l example host...\n    example:\n      - cmd: split-window -h\n        #run: sleep 1\n      - cmd: split-window -h\n        #run: sleep 2\n      - cmd: split-window -v\n        #run: sleep 3\n\n    logger:\n      - cmd: split-window -h\n      - cmd: split-window -h\n        run: sh -c \"cd /webapps; exec sh\"\n      - cmd: split-window -v\n        run: sudo su - -c 'tail -f /webapps/app-*/log/production.log'\n\n# ansible specific configuration (for 'run' profiles)\nansible:\n  become_user: root\n  become_method: sudo\n\n# an example set of ansible tasks to run against select servers (bridgy run grab-files)\nrun:\n  grab-files:\n    - hosts: app-srv-13, dev-srv\n      gather_facts: no\n      tasks:\n        - name: 'Get secrets.yml'\n          fetch:\n            src: /appdir/config/secrets.yml\n            dest: /tmp/prefix-{{ inventory_hostname }}.secrets.yml\n            fail_on_missing: yes\n            flat: yes\n\n```\n\n## Usage\n```\n  bridgy init\n  bridgy ssh (-t | --tmux) [-adsuvw] [-l LAYOUT] [-i SOURCE] \u003chost\u003e...\n  bridgy ssh [-duv] [-i SOURCE] \u003chost\u003e\n  bridgy exec (-t | --tmux) [-adsuvw] [-l LAYOUT] [-i SOURCE] \u003ccontainer\u003e...\n  bridgy exec [-duv] [-i SOURCE] \u003ccontainer\u003e\n  bridgy list-inventory [-i SOURCE]\n  bridgy list-mounts\n  bridgy mount [-duv] [-i SOURCE] \u003chost\u003e:\u003cremotedir\u003e\n  bridgy unmount [-dv] [-i SOURCE] (-a | \u003chost\u003e...)\n  bridgy run \u003ctask\u003e\n  bridgy update [-v] [-i SOURCE] \n  bridgy (-h | --help)\n  bridgy --version\n\nSub-commands:\n  init          create the ~/.bridgy/config.yml\n  ssh           ssh into the selected host(s)\n  exec          exec into the selected container(s) (new relic + ecs only)\n  mount         use sshfs to mount a remote directory to an empty local directory\n  unmount       unmount one or more host sshfs mounts\n  list-mounts   show all sshfs mounts\n  run           execute the given ansible task defined as playbook yml in ~/.bridgy/config.yml\n  update        pull the latest inventory from your cloud provider\n\nOptions:\n  -a        --all            Automatically use all matched hosts.\n  -d        --dry-run        Show all commands that you would have run, but don't run them (implies --verbose).\n  -i SOURCE --source SOURCE  Search a subset of inventories by name (comma separated for multiple values)\n  -l LAYOUT --layout LAYOUT  Use a configured tmux layout for each host.\n  -s        --sync-panes     Synchronize input on all visible panes (tmux :setw synchronize-panes on).\n  -t        --tmux           Open all ssh connections in a tmux session.\n  -u        --update         pull the latest instance inventory from aws then run the specified command.\n  -w        --windows        Use tmux windows instead of panes for each matched host.\n  -h        --help           Show this screen.\n  -v        --verbose        Show debug information.\n  --version                  Show version.\n\nConfiguration Options are in ~/.bridgy/config.yml\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwagoodman%2Fbridgy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwagoodman%2Fbridgy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwagoodman%2Fbridgy/lists"}