{"id":17550915,"url":"https://github.com/iancleary/local-ssh-config","last_synced_at":"2026-05-10T16:18:40.375Z","repository":{"id":37993005,"uuid":"502400720","full_name":"iancleary/local-ssh-config","owner":"iancleary","description":"⚡ CLI utility to update SSH Configs for VMs, particularly Multipass and Hyper-V on Windows⚡","archived":false,"fork":false,"pushed_at":"2023-03-28T13:23:37.000Z","size":209,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-07T21:38:54.066Z","etag":null,"topics":["cli","hyper-v","multipass","ssh","ubuntu-server","windows"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/local-ssh-config/","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/iancleary.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["iancleary"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-06-11T16:31:08.000Z","updated_at":"2023-07-09T05:51:10.000Z","dependencies_parsed_at":"2025-03-29T07:27:37.720Z","dependency_job_id":"c7778286-1f0d-41e8-9924-3266301f0942","html_url":"https://github.com/iancleary/local-ssh-config","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/iancleary/local-ssh-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iancleary%2Flocal-ssh-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iancleary%2Flocal-ssh-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iancleary%2Flocal-ssh-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iancleary%2Flocal-ssh-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iancleary","download_url":"https://codeload.github.com/iancleary/local-ssh-config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iancleary%2Flocal-ssh-config/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269970127,"owners_count":24505470,"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","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cli","hyper-v","multipass","ssh","ubuntu-server","windows"],"created_at":"2024-10-21T04:44:19.547Z","updated_at":"2026-05-10T16:18:35.354Z","avatar_url":"https://github.com/iancleary.png","language":"Python","funding_links":["https://github.com/sponsors/iancleary"],"categories":[],"sub_categories":[],"readme":"# local-ssh-config\n\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat\u0026labelColor=ef8336)](https://pycqa.github.io/isort/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://black.readthedocs.io/en/stable/)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white)](https://github.com/pre-commit/pre-commit)\n[![ci](https://github.com/iancleary/local-ssh-config/workflows/ci/badge.svg)](https://github.com/iancleary/local-ssh-config/actions/workflows/ci.yml)\n\nIan Cleary ([iancleary](https://github.com/iancleary))\n\n## Description\n\n**Welcome!** This is a CLI to generate/update SSH config files for your local virtual machines quickly.\n\n## Problem\n\nWindows doesn't maintain a static IP Address of Hyper-V Virtual Machines across reboots.  When using [multipass](https://multipass.run) with a Hyper-V backend, this applies as well for multipass.\n\nThis leads to ssh configuration, which is by ip address, to be stale every reboot.\n\n## Solution\n\nThis script updates my ssh config file for me\n\n- get IP address from PowerShell for hyper-v by name according to source ('hyper-v' directly, or 'multipass list')\n- write template config files to the `~/.ssh/config.d/` directory according to your `~/.config/local-ssh-config/settings.json` file.\n\nThis assumes you have:\n\n- a `~/.ssh/config.d/` folder\n- [`Include config.d/*` in your `~/.ssh/config`](https://superuser.com/questions/247564/is-there-a-way-for-one-ssh-config-file-to-include-another-one)\n- For Hyper-V Virtual Machines\n  - PowerShell installed\n  - Hyper-V enabled and The Hyper-V Manager Installed\n\n### Hyper-V Manager IP Address\n\n![Hyper-V Manager Networking Tab](docs/assets/hyper-v-manager-networking-tab.png)\n\n\u003e I currently use Ubuntu Servers, if you do too, [please install several `apt` packages in the Virtual Machine (so that Hyper-V can report the IP Address)](https://stackoverflow.com/a/72534742/13577666)\n\n🚨🚨 Hyper-V will not report the ip address until you do the above 🚨🚨\n\n\u003e Multipass or Virtual Box may report the IP address of an Ubuntu Guest. I'm not currently sure if it's a Hyper-V limitation or a Windows limitation.  \n\nAs this tool only currently supports Hyper-V, please consider this a warning of the required step.\n\n## Quickstart\n\n```sh\n❯ pipx install local-ssh-config --user\n❯ local-ssh-config --help\n```\n\nThat will output the following:\n\n```bash\nUsage: local_ssh_config [OPTIONS]\n\n  Creates an `~/.ssh/config.d/` directory, \n  checks to see if you include all files in that directory,\n  and then creates config files for each virtual machine specified\n  in your `~/.config/vm-ip-ssh-config/settings.json` file.\n\n  See https://github.com/iancleary/local-ssh-config/ for more information.\n\nArguments:\n  None\n\nOptions:\n  -f, --file TEXT       The JSON file containing the virtual machine\n                        configuration  [default: C:\\Users\\username\\.config\\vm-\n                        ip-ssh-config\\settings.json]\n  -v, --version         Show the application's version and exit.\n  --install-completion  Install completion for the current shell.\n  --show-completion     Show completion for the current shell, to copy it or\n                        customize the installation.\n  --help                Show this message and exit.\n```\n\n## Example Usage\n\nThe first and only argument is the name of the component to create.\n\n```bash\n$ local-ssh-config\n{'host': 'test.local', 'hostname': '0.0.0.0', 'user': 'test', 'identity_file': '~/.ssh/example_id_ed25519'}\n{'host': 'ubuntu.local', 'hostname': {'source': 'hyper-v', 'physical_address': '00-15-5d-95-fb-09'}, 'user': 'icleary', 'identity_file': '~/.ssh/github_id_rsa_ed25519'}\nHyper-V: Powershell (arp -a): Interface command executed successfully!\n-------------------------\n{'host': 'dev1.multipass.local', 'hostname': {'source': 'multipass', 'name': 'dev1'}, 'user': 'ubuntu'}\nMultipass-V: Powershell (multipass list): Interface command executed successfully!\n-------------------------\n\n✨ Creating ~/.ssh/config.d/ files\n✅ C:\\Users\\icleary\\.ssh\\config.d\\test.local\n✅ C:\\Users\\icleary\\.ssh\\config.d\\ubuntu.local\n✅ C:\\Users\\icleary\\.ssh\\config.d\\dev1.multipass.local\nSSH config updated! 🚀 ✨!\n\nThank you for using local-ssh-config.\n```\n\nThe path printed is the absolute path to the updated config files.\n\n\u003e This uses a directory `~/.ssh/config.d/` to allow for a single file per Host, to allow cleaner version tracking within a dotfile manager.\n\u003e See [`Include config.d/*` in your `~/.ssh/config`](https://superuser.com/questions/247564/is-there-a-way-for-one-ssh-config-file-to-include-another-one) for the include syntax\n\u003e [WINDOWS_MULTIPASS_DEFAULT_ID_RSA](https://github.com/canonical/multipass/issues/913#issuecomment-697235248) = \"%PROGRAMDATA%/Multipass/data/ssh-keys/id_rsa\"\n\n## Configuration\n\nConfiguration can be done through 2 different ways:\n\n- Creating a global `settings.json` in your home directory (`~/.config/local-ssh-config/settings.json`).\n- Creating a local `.local-ssh-config-config.json` in your project's root directory and including the path to that file with the `--f` or `-f` optionanl command-line argument.\n\nThe optional command line value takes precendence global settings file being the default.\n\n## API Reference\n\n### File\n\nControls the settings.json to load.\nDefaults to `~/.config/local-ssh-config/settings.json`\n\nUsage:\n\nCommand line: `--file \u003cvalue\u003e` or `-f \u003cvalue\u003e`\n\nJSON config:\n\nExample with single host, as dictionary\n\n```json\n{\n    \"host\": \"ubuntu.local\",\n    \"hostname\": {\n        \"source\": \"hyper-v\",\n        \"physical_address\": \"00-15-5d-95-fb-09\"\n    },\n    \"user\": \"icleary\",\n    \"identity_file\": \"~/.ssh/github_id_rsa_ed25519\"\n}\n```\n\nExample with single host, as list:\n\n```json\n[\n  {\n      \"host\": \"ubuntu.local\",\n      \"hostname\": {\n          \"source\": \"hyper-v\",\n          \"physical_address\": \"00-15-5d-95-fb-09\"\n      },\n      \"user\": \"icleary\",\n      \"identity_file\": \"~/.ssh/github_id_rsa_ed25519\"\n  }\n]\n```\n\n\u003e A single dictionary is converted to a list of hosts before looping through the files, so either structure is valid (your preference).\n\nExample with multiple hosts:\n\n```json\n[\n    {\n        \"host\": \"test.local\",\n        \"hostname\": \"0.0.0.0\",\n        \"user\": \"test\",\n        \"identity_file\": \"~/.ssh/example_id_ed25519\"\n    },\n    {\n        \"host\": \"ubuntu.local\",\n        \"hostname\": {\n            \"source\": \"hyper-v\",\n            \"physical_address\": \"00-15-5d-95-fb-09\"\n        },\n        \"user\": \"icleary\",\n        \"identity_file\": \"~/.ssh/github_id_rsa_ed25519\"\n    },\n    {\n        \"host\": \"dev1.multipass.local\",\n        \"hostname\": {\n            \"source\": \"multipass\",\n            \"name\": \"dev1\"\n        },\n        \"user\": \"ubuntu\"\n    }\n]\n```\n\n## Further information\n\n\u003e I will likely evolve this CLI as I learn more; I'm on my way 😊\n\n**Enjoy quickly updating your ssh configurations 🚀!**\n\n## Contributing\n\nI created this CLI for my opinionated uses and may not accept changes.  That said, I made this to solve a problem, and if you have the same problem, I hope it helps you! 😊\n\nSee [CONTRIBUTING.md](.github/CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiancleary%2Flocal-ssh-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiancleary%2Flocal-ssh-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiancleary%2Flocal-ssh-config/lists"}