{"id":17602602,"url":"https://github.com/skycoder42/dynssh","last_synced_at":"2026-02-21T12:03:40.401Z","repository":{"id":178217807,"uuid":"618507700","full_name":"Skycoder42/dynssh","owner":"Skycoder42","description":"A small server utility to dynamically update the SSH configuration for a remote host with dynamic IPs","archived":false,"fork":false,"pushed_at":"2026-01-02T10:59:35.000Z","size":171,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-08T12:15:13.356Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Skycoder42.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-24T16:07:34.000Z","updated_at":"2026-01-02T10:55:09.000Z","dependencies_parsed_at":"2024-02-08T18:30:22.135Z","dependency_job_id":"bf768723-9708-4bfb-bebd-fbb8e2ffda01","html_url":"https://github.com/Skycoder42/dynssh","commit_stats":null,"previous_names":["skycoder42/dynssh"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/Skycoder42/dynssh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skycoder42%2Fdynssh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skycoder42%2Fdynssh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skycoder42%2Fdynssh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skycoder42%2Fdynssh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Skycoder42","download_url":"https://codeload.github.com/Skycoder42/dynssh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skycoder42%2Fdynssh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29680147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T11:29:27.227Z","status":"ssl_error","status_checked_at":"2026-02-21T11:29:20.292Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-10-22T13:09:03.615Z","updated_at":"2026-02-21T12:03:35.391Z","avatar_url":"https://github.com/Skycoder42.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dynssh\n[![Continuous integration](https://github.com/Skycoder42/dynssh/actions/workflows/ci.yaml/badge.svg)](https://github.com/Skycoder42/dynssh/actions/workflows/ci.yaml)\n[![Weekly - Docker image update](https://github.com/Skycoder42/dynssh/actions/workflows/docker_weekly.yaml/badge.svg)](https://github.com/Skycoder42/dynssh/actions/workflows/docker_weekly.yaml)\n[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/skycoder42/dynssh?label=Docker\u0026color=blue)](https://hub.docker.com/r/skycoder42/dynssh)\n\nA small server utility to dynamically update the SSH configuration for a remote host with dynamic IPs.\n\n## Table of contents\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n  * [Server Arguments](#server-arguments)\n  * [API usage](#api-usage)\n  * [Authentication](#authentication)\n\n\u003csmall\u003e\u003ci\u003e\u003ca href='https://ecotrust-canada.github.io/markdown-toc/'\u003eTable of contents generated with markdown-toc\u003c/a\u003e\u003c/i\u003e\u003c/small\u003e\n\n## Features\nThe primary goal of this tool is to make it possible to have a SSH configuration with a host alias for a remote server\nthat has a dynamic IP address, but no public name. That remote server can regularly notify the dynssh server with\nit's changed IP address so the host configuration gets updated with the new IP.\n\nThe main features are:\n\n- A minimal HTTP server that provides a DYNDNS-like endpoint, but for updating the SSH configuration.\n- Updates the `HostName` parameter of a `Host` in the SSH config file\n- This allows you to define an SSH host alias for a server with a dynamic IP address, without giving that server a\npublic name on the internet\n- Uses API-Key Authentication plus SSH server key validation to ensure only authentic updates are accepted\n\n## Installation\n1. Via docker/podman:\n    ```bash\n    podman run \\  # or docker run\n      -v \"$HOME/.config/dynssh:/etc/dynssh:ro\" \\\n      -v \"$HOME/.ssh:/etc/ssh\" \\\n      -p 127.0.0.1:8080:80 \\\n      docker.io/skycoder42/dynssh [\u003coptions\u003e]\n    ```\n2. From the releases page: https://github.com/Skycoder42/dynssh/releases/latest\n3. Install as global dart tool: `dart pub global activate dynssh`\n4. Compile it yourself:\n    ```bash\n    dart pub get\n    dart run build_runner build\n    dart compile exe bin/dynssh.dart -o bin/dynssh\n    sudo install bin/dynssh /usr/local/bin/dynssh\n    ```\n\n## Usage\nSimply start the server and use the provided HTTP endpoint to send update requests to it.\n\n\u003e **Important:** The server itself does not support HTTPS, but should never be run with just a HTTP connection. Instead,\n\u003e you should run it only on localhost (e.g `dynssh -H 127.0.0.1`) and use a reverse proxy like nginx or apache to\n\u003e provide a HTTPS gateway to expose the server to the internet.\n\n### Server Arguments\n```\nUsage:\n-H, --host=\u003chost\u003e             The host address to listen to.\n                              (defaults to \"0.0.0.0\")\n-p, --port=\u003cport\u003e             The port to listen to.\n                              (defaults to \"80\")\n-k, --api-key-path=\u003cpath\u003e     The path to the API-Key json file.\n                              (defaults to \"$HOME/.config/dynssh/api-keys.json\")\n-d, --ssh-directory=\u003cpath\u003e    The path to the ssh directory where configuration files are stored.\n                              (defaults to \"$HOME/.ssh\")\n-l, --log-level=\u003clevel\u003e       Customize the logging level. Listed from most verbose (all) to least verbose (off)\n                              [all, finest, finer, fine, config, info (default), warning, severe, shout, off]\n-h, --help                    Prints usage information.\n```\n\nThe API-Key JSON file has the following format:\n```json\n{\n  \"apiKeys\": {\n    \"\u003chostname1\u003e\": \"\u003capi-key1\u003e\",\n    \"\u003chostname2\u003e\": \"\u003capi-key2\u003e\",\n  }\n}\n```\nWith the `\u003chostnameX\u003e` being the the domain name and `\u003capi-keyX\u003e` the API key for that domain. There are no formal\nrequirements for the API Keys themselves, but recommendation is to use a long, random, base64 key. You can, for example,\nuse `openssl` to generate such a key:\n\n```bash\nopenssl rand -base64 48\n```\n\n### API usage\nThe server only provides a single endpoint:\n```\nPOST \u003chost\u003e/dynssh/update?hostname=\u003chostname\u003e\u0026myip=\u003cipAddress\u003e\n```\n\nThis endpoint is modeled after the [DYNDNS Update API](https://help.dyn.com/remote-access-api/perform-update/) and thus\nshould be able to be used as drop in replacement in any dyndns client to instead report to dynssh.\n\nThe `hostname` and `myip` parameters are always required. `hostname` must be the alias of the host as defined in the SSH\nconfig file to change the IP address for. The `myip` parameter is used to specify the new IP address for that host.\n\n### Authentication\nIn addition to those parameters you must also authenticate against the server. This uses HTTP Basic auth with the\n`hostname` as username and the API-Key as password, i. e. `base64UrlEncode(hostname ':' apiKey)`. Thus, for each\nupdatable hostname there must be an entry with the corresponding API Key in the API Key JSON file.\n\nIn addition to that, the server will verify that the SSH host keys will not have changed, meaning it will query the new\nIP address for it's host keys and compare them with the currently verified host keys of the old IP address. The update\nwill only be accepted if those keys have not changed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskycoder42%2Fdynssh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskycoder42%2Fdynssh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskycoder42%2Fdynssh/lists"}