{"id":17364323,"url":"https://github.com/bytehunt/x4","last_synced_at":"2025-04-15T01:05:15.493Z","repository":{"id":257811741,"uuid":"858950621","full_name":"bytehunt/x4","owner":"bytehunt","description":"💭 Execute shell commands to server(s) via ssh protocol","archived":false,"fork":false,"pushed_at":"2024-10-28T20:54:46.000Z","size":147,"stargazers_count":5,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T01:04:59.245Z","etag":null,"topics":["cicd-json-pipeline","libssh2","rustlang","ssh","ssh-commands"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/x4","language":"Rust","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/bytehunt.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}},"created_at":"2024-09-17T20:14:34.000Z","updated_at":"2024-11-11T01:57:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"040345d0-d88a-4318-96a2-ea0534dcabaf","html_url":"https://github.com/bytehunt/x4","commit_stats":{"total_commits":73,"total_committers":3,"mean_commits":"24.333333333333332","dds":0.0273972602739726,"last_synced_commit":"7402585918f5302e3742882fe8206775a7af83c8"},"previous_names":["pwnwriter/x4","bytehunt/x4"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytehunt%2Fx4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytehunt%2Fx4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytehunt%2Fx4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytehunt%2Fx4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bytehunt","download_url":"https://codeload.github.com/bytehunt/x4/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248986313,"owners_count":21194025,"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":["cicd-json-pipeline","libssh2","rustlang","ssh","ssh-commands"],"created_at":"2024-10-15T20:05:34.910Z","updated_at":"2025-04-15T01:05:15.451Z","avatar_url":"https://github.com/bytehunt.png","language":"Rust","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/db6ea484-be58-4e68-bfcf-e868291867e7\" width=\"200\" height=\"200\" alt=\"server image\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  A lightweight implementation of \u003ccode\u003elibssh2\u003c/code\u003e to execute shell commands on remote servers with rich configuration via \u003ccode\u003ejson\u003c/code\u003e.\n\u003c/p\u003e\n\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/pwnwriter/x4/releases\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/release/pwnwriter/x4?style=flat\u0026labelcolor=f38ba8\u0026color=585b70\u0026logo=github\u0026logocolor=white\" alt=\"release version\"\u003e\n  \u003c/a\u003e\n  \n  \u003ca href=\"https://crates.io/crates/x4/\"\u003e\n    \u003cimg src=\"https://img.shields.io/crates/v/x4?style=flat\u0026labelcolor=b4befe\u0026color=eba0ac\u0026logo=rust\u0026logocolor=white\" alt=\"crates.io version\"\u003e\n  \u003c/a\u003e\n  \n  \u003ca href=\"https://github.com/pwnwriter/x4/actions?query=workflow%3a%22continuous+deployment%22\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/pwnwriter/x4/nix-build.yml?style=flat\u0026labelcolor=eba0ac\u0026color=74c7ec\u0026label=nix-build\u0026logo=github%20actions\u0026logocolor=white\" alt=\"github actions status\"\u003e\n  \u003c/a\u003e\n  \n  \u003ca href=\"https://github.com/pwnwriter/x4/blob/main/license\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-mit-white.svg\" alt=\"mit license\"\u003e\n  \u003c/a\u003e\n  \n\u003c/div\u003e\n\n\u003cbr\u003e\u003c/br\u003e\n\n\n\u003c!--toc:start--\u003e\n- [Features and todos](#features-and-todos)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usages](#usages)   \n- [Configuration](#configuration)\n  - [Options](#options)\n    - [Examples](#examples)\n- [Development](#development)\n- [Support my work](#support-my-work)\n  \u003c!--toc:end--\u003e\n\n---\n\n\u003e [!TIP]\n\u003e Here's a blogpost on how i use [**x4 to deploy a website on aws ec2 instance**](/.github/guide.md)\n\n\n## Features and todos\n- [x] retrieve the password from environment variables\n- [x] retrieve the password by executing a shell command\n    \n    usages `pass` password manager to get the `user` password and `ssh`'s into the server\n    \n    https://github.com/user-attachments/assets/2a85e2ab-c762-41e0-855d-fa8e6d15f5e0\n\n- [x] format `stderr` and `stdout` outputs for better readability\n- [x] check pipeline configuration\n\n    ![configuration-check](https://github.com/user-attachments/assets/ad24647c-ebbc-42af-8681-865dae15d678)\n\n- [ ] Implement file upload and download functionality\n- [ ] Allow connections through a proxy server\n- [ ] Implement unit tests for critical features\n- [ ] Current configuration is with `json` but with `lua` ? planned yes!! \n- [ ] Better code, docs and more\n- [ ] More ways to get the json value fields, like password ?\n- [ ] You tell more.\n\n\n## Requirements \n- **ssh connection**: must have ssh connections using one of the following authentication methods:\n  - **password authentication**: using the `username` and `password`.\n  - **keypair**: public key authentication.\n  - No extra deps will be required for runtime\n\n\n## Installation\n    \n  \u003cdetails\u003e \u003csummary\u003e\u003ccode\u003eBinary \u003c/code\u003e\u003c/summary\u003e\n    \u0026nbsp;\n   \n   -  **manual**: you can directly download the binary from [**releases**](https://github.com/pwnwriter/x4/releases) of your arch and run it.\n   - **one liner**: run this one liner script \n\n```bash\nwget -qo- \"$(curl -qfssl \"https://api.github.com/repos/pwnwriter/x4/releases/latest\" | jq -r '.assets[].browser_download_url' | grep -ei \"$(uname -m).*$(uname -s).*musl\" | grep -v \"\\.sha\")\" | tar -xzf - --strip-components=1 \u0026\u0026 ./x4 -h\n```  \n  \u003c/details\u003e\n  \u003cdetails\u003e \u003csummary\u003e\u003ccode\u003esource \u003c/code\u003e\u003c/summary\u003e\n  \u0026nbsp;\n \n  ```bash\n  git clone --depth=1 https://github.com/pwnwriter/x4 --branch=main\n  cd x4\n  cargo build --release \n  ```\n  then go to `release` dir and `./x4` or move the `binary` to your any `$path` for instant access from anywhere.\n\n\u003c/details\u003e\n\n\n\u003e [!NOTE]  \n\u003e This requires a working setup of `rust/cargo` and `binstall`.\n\n\u003cdetails open\u003e \u003csummary\u003e\u003ccode\u003ecargo \u003c/code\u003e\u003c/summary\u003e\n\n- using [crates.io](https://crates.io/crates/x4)\n    \n  \n  ```bash\n  cargo install x4\n  ```\n\n- using [binstall](https://github.com/cargo-bins/cargo-binstall)\n\n  ```bash\n  cargo binstall x4\n  ```\n\n\u003c/details\u003e\n\n\n\u003cdetails open\u003e \u003csummary\u003e\u003ccode\u003eon nix  \u003c/code\u003e\u003c/summary\u003e\n\u0026nbsp;\n  \n- Source build\n\n    ```\n    nix run github:pwnwriter/x4\n    ```\n\n- With flakes:\n\n    ```\n    nix profile install nixpkgs#x4\n    ```\n\n- Without flakes:\n\n  ```\n   nix-env -ia nixpkgs.x4\n  ```\n\n\u003c/details\u003e\n\n\n## Usages\n\n```yaml\nUsage: x4 [OPTIONS]\n\nOptions:\n  -p, --pipeline \u003cPIPELINE\u003e              Path to your pipeline file\n      --check-pipeline \u003cCHECK_PIPELINE\u003e  Check the configuration of the specified pipeline\n  -h, --help                             Print help\n  -V, --version                          Print version\n\n```\n\n## Configuration\n\n### Options\n\nThe configuration JSON supports the following key values for server definitions:\n\n| Key          | Description                                                 | Example Value                             |\n|--------------|-------------------------------------------------------------|-------------------------------------------|\n| `description`| A brief description of the server's purpose or role.      | My hot EC2 instance                        |\n| `name`       | A unique identifier for the server.                        | ec2                                       |\n| `host`       | The hostname or IP address of the server.                  | fawn.pwnwriter.me                        |\n| `port`       | The SSH port to connect to the server. Defaults to `22`.   | 22                                        |\n| `user`       | The username used for SSH authentication.                  | fawn                                      |\n| `password`   | Method of authentication for SSH: use an environment variable (prefix with `env:`) or a command (prefix with `cmd:`). See [Password Retrieval](#password-retrieval) for details. | `env:wolf_pass` or `cmd:pass uni/server/wolf` |\n| `commands`   | An array of commands to execute once the SSH connection is established. | `[pnpm run build \u0026\u0026 pnpm start]`         |\n\n---\n\n#### Password Retrieval\n\nThe `password` field allows for secure handling of sensitive information using either environment variables or commands.\n\n- **Using Environment Variables**: \n  To set your password as an environment variable in your shell, run:\n  ```bash\n  export wolf_pass='my_secure_password'\n  ```\n  You can then reference this variable in your configuration like so:\n  ```json\n  \"password\": \"env:wolf_pass\"\n  ```\n\n- **Using Commands**: \n  If you use the `pass` password manager, you can retrieve your password with a command. For instance:\n  ```json\n  \"password\": \"cmd:pass uni/server/wolf\"\n  ```\n  This command will execute `pass` to get the password stored under `uni/server/wolf`.\n\n\n### Examples\n\n- Single server Configuration with `cmd` for `password`\n\n```json\n{\n  \"servers\": [\n    {\n      \"description\": \"using a cmd to get password for SSH authentication and default 22 port\",\n      \"name\": \"ec2\",\n      \"host\": \"fawn.pwnwriter.me\",\n      \"user\": \"wolf\",\n      \"password\": \"cmd:pass personal/server/root\",\n      \"commands\": [\n        \"ping -c 3 google.com\",\n        \"ls\"\n      ]\n    }\n  ]\n}\n```\n\n- More than one server configuration\n\n```json\n{\n  \"servers\": [\n    {\n      \"description\": \"using a cmd to get password for SSH authentication and default 22 port\",\n      \"name\": \"ec201\",\n      \"host\": \"fawn.pwnwriter.me\",\n      \"user\": \"wolf\",\n      \"password\": \"cmd:pass personal/server/root\",\n      \"commands\": [\n        \"mkdir -p from_many_at_wolf\",\n        \"cat /etc/os-release\"\n      ]\n    },\n    {\n      \"description\": \"using a private key for SSH authentication and default 22 port\",\n      \"name\": \"ec2\",\n      \"host\": \"fawn.pwnwriter.me\",\n      \"user\": \"fawn\",\n      \"private_key\": \"/Users/pwnwriter/.local/share/ssh/wynwood.pem\",\n      \"commands\": [\n        \"mkdir from_many_at_fawn\",\n        \"mkdir from_manyyyy\"\n      ]\n    }\n  ]\n}\n```\n\n\n## Development\n\nif you are using nix, \n\nget into the development shell \n\n`nix develop` or use \n\n`direnv allow` to enter a shell with all required deps. \n\n`nix build/run` to build and run the app. \n\n`nix run github:pwnwriter/x4 -- --help` \n\n## Support my work\n\nI do open source work in my free time, and I really enjoy it! If any of my applications have helped you in any way, please consider supporting me via Ko-fi. Your support enables me to continue developing and improving my projects.\n\n\n\u003ca href=\"https://ko-fi.com/pwnwriter\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Ko--fi-Support%20Me%20%F0%9F%92%96-FF5E5B?style=flat-square\u0026logo=ko-fi\" alt=\"Support me on Ko-fi\" width=\"250\"/\u003e\n\u003c/a\u003e\n\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/footers/gray0_ctp_on_line.svg?sanitize=true\" /\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003ecopyright \u0026copy; 2024 \u003ca href=\"https://pwnwriter.me\" target=\"_blank\"\u003e pwnwriter.me\u003ca\u003e 🍃\u003c/a\u003e \n","funding_links":["https://ko-fi.com/pwnwriter"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytehunt%2Fx4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbytehunt%2Fx4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytehunt%2Fx4/lists"}