Compare commits
	
		
			194 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2ead5e3657 | ||
|   | a0a0326939 | ||
|   | b0a8f324e1 | ||
|   | 039c9e07bb | ||
|   | 48992f2e2c | ||
|   | 01a53594eb | ||
|   | d99ccf8c09 | ||
|   | 92737056c0 | ||
|   | 9817ef4a17 | ||
|   | 8faa84277b | ||
|   | 49751ff516 | ||
|   | 86aa40ddb7 | ||
|   | 66aa4d343b | ||
|   | 102c0d2e5f | ||
|   | e13c387332 | ||
|   | 1c1ad10f6d | ||
|   | 48531853a7 | ||
|   | b76e6173e8 | ||
|   | 6137f733fb | ||
|   | 43d4ebbb72 | ||
|   | a9e2fdf08d | ||
|   | cec69ef231 | ||
|   | a8952ebe2a | ||
|   | 8fdfeb034e | ||
|   | 7eaf76671a | ||
|   | 176437b548 | ||
|   | 25259c3d50 | ||
|   | bf84378588 | ||
|   | 362a7f1677 | ||
|   | ab698e59d8 | ||
|   | 703ffa3c1e | ||
|   | 8b84eaec3a | ||
|   | 2763143a97 | ||
|   | 3f1416813d | ||
|   | bb32884d53 | ||
|   | 25ce8cbbcb | ||
|   | 58164d0dc2 | ||
|   | d732991ab0 | ||
|   | b4a07ca594 | ||
|   | eaeb06998d | ||
|   | 06fa62e61c | ||
|   | 28428a13f5 | ||
|   | 5ade826485 | ||
|   | 8b6078208d | ||
|   | 036cad7df7 | ||
|   | 71d43ea0f7 | ||
|   | 43895f2cd5 | ||
|   | b6941ae5d5 | ||
|   | 0c7561b1a3 | ||
|   | 5a8776fd15 | ||
|   | 97f8d752b5 | ||
|   | 9c32aa61f8 | ||
|   | f0e5a23d53 | ||
|   | fc1c1fce51 | ||
|   | aa293c24bb | ||
|   | 378323e4c8 | ||
|   | 815c5743ac | ||
|   | a39b3cce7d | ||
|   | 15b64dc891 | ||
|   | e40b597081 | ||
|   | f05aefe351 | ||
|   | acd41e5091 | ||
|   | da612c8015 | ||
|   | 2eeab5bdba | ||
|   | 977b74a12d | ||
|   | 0b0e77098a | ||
|   | 40aad53c5a | ||
|   | c8594ae37d | ||
|   | aabaf1254d | ||
|   | f916346256 | ||
|   | 551964ebda | ||
|   | d2d6858859 | ||
|   | dd0f09ca07 | ||
|   | 1991c553ec | ||
|   | fe44be0b96 | ||
|   | c78141851a | ||
|   | 8a779a5b1a | ||
|   | 9b978f09f2 | ||
|   | 029f5b4aee | ||
|   | d134a26a1f | ||
|   | 2451745138 | ||
|   | 1f3c338936 | ||
|   | 8f94919856 | ||
|   | 2344d97573 | ||
|   | b9f6bf6223 | ||
|   | 4330a1ea48 | ||
|   | 55dabf81b4 | ||
|   | 8d9094f3b1 | ||
|   | 5ac43dd762 | ||
|   | a01d3ea1df | ||
|   | c7d850f6cd | ||
|   | f579d71942 | ||
|   | d87d276960 | ||
|   | 3130c7a2bc | ||
|   | 2b7de38eed | ||
|   | 334f9259f2 | ||
|   | 6268c80dd6 | ||
|   | 5f64c95280 | ||
|   | 3cd1bcf771 | ||
|   | 6a1b59d972 | ||
|   | e4a881008d | ||
|   | 51b83ba474 | ||
|   | 495830820f | ||
|   | b601429988 | ||
|   | ae2bb3c3dc | ||
|   | 7bf58514db | ||
|   | c1965ddd25 | ||
|   | d91a1af6f5 | ||
|   | 4a03da89e5 | ||
|   | 0d5a3d0e48 | ||
|   | db9be1d5f2 | ||
|   | 9a7da95c8c | ||
|   | f23dd5c681 | ||
|   | cc051b07ed | ||
|   | f9010ff7f1 | ||
|   | e1116226a0 | ||
|   | a8d82ec39b | ||
|   | f82e23f1a3 | ||
|   | ed1f3fc7c1 | ||
|   | dce9d565de | ||
|   | ea5c23a2b5 | ||
|   | c732d38392 | ||
|   | ba1d4fb0eb | ||
|   | c7671d858f | ||
|   | 1a8b3784ea | ||
|   | 29007ce6fb | ||
|   | e59c0ee97a | ||
|   | c7104ccac4 | ||
|   | 63dd9dd662 | ||
|   | 61e292b601 | ||
|   | 1d1b21ca96 | ||
|   | 9fb11fb1f5 | ||
|   | fd39ef0f18 | ||
|   | ffff33f8fe | ||
|   | 8bd4933b73 | ||
|   | bf84735fa9 | ||
|   | d09b6e0211 | ||
|   | 3ac4675689 | ||
|   | 269a4479eb | ||
|   | a2f91cbad1 | ||
|   | e2cbea5f00 | ||
|   | 5711a203b3 | ||
|   | b315fb5f98 | ||
|   | 682eb0ddda | ||
|   | 03b440e441 | ||
|   | 1cb5cd31c9 | ||
|   | c9eebc1cde | ||
|   | 6b00175bad | ||
|   | a912e225ec | ||
|   | ad6643f705 | ||
|   | 26dd2b3a38 | ||
|   | 122f35dca5 | ||
|   | 03b5d10ad6 | ||
|   | fcfb760891 | ||
|   | fd81fae289 | ||
|   | 242a8e2e57 | ||
|   | cfe9c45db6 | ||
|   | 73767290ca | ||
|   | e5c07fceef | ||
|   | d690bdebf8 | ||
|   | f478af9b34 | ||
|   | d520c19f4f | ||
|   | 0dee98b334 | ||
|   | 9085f3ea5b | ||
|   | 696aab4627 | ||
|   | a88f6f2013 | ||
|   | 6f091cd9e3 | ||
|   | aa1ecdd19a | ||
|   | bffdd4e1f4 | ||
|   | f4890bec77 | ||
|   | 9aaf218321 | ||
|   | a2d5832a97 | ||
|   | 49e81b4a32 | ||
|   | 04535147e0 | ||
|   | 533a062133 | ||
|   | ef697c0ac1 | ||
|   | 480ff5e05e | ||
|   | ccece0c886 | ||
|   | 7e0bb7cd75 | ||
|   | dc9ae8e2e3 | ||
|   | d0bd170212 | ||
|   | 54eb169e33 | ||
|   | 1a6f86cece | ||
|   | 917a1df2a4 | ||
|   | b87ddeff00 | ||
|   | 4f7d6491f3 | ||
|   | 1f7ce4dfab | ||
|   | 46adad98f2 | ||
|   | 215a0580d7 | ||
|   | b305709c8d | ||
|   | fd26aa3ca7 | ||
|   | c94d94aab3 | ||
|   | 592a3daf58 | ||
|   | 5942cfaf03 | 
							
								
								
									
										13
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # These are supported funding model platforms | ||||
|  | ||||
| github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] | ||||
| patreon: # Replace with a single Patreon username | ||||
| open_collective: ssh-action | ||||
| ko_fi: # Replace with a single Ko-fi username | ||||
| tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||||
| community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||||
| liberapay: # Replace with a single Liberapay username | ||||
| issuehunt: # Replace with a single IssueHunt username | ||||
| otechie: # Replace with a single Otechie username | ||||
| lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry | ||||
| custom: ['https://www.paypal.me/appleboy46'] | ||||
							
								
								
									
										41
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Create a report to help us improve | ||||
| title: "" | ||||
| labels: bug | ||||
| assignees: appleboy | ||||
| --- | ||||
|  | ||||
| ## Describe the bug | ||||
|  | ||||
| A clear and concise description of what the bug is. If applicable, add screenshots to help explain your problem. | ||||
|  | ||||
| ## Yaml Config | ||||
|  | ||||
| Please post your Yaml configuration file along with the output results. | ||||
|  | ||||
| ```yaml | ||||
| name: remote ssh command | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: executing remote ssh commands using password | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: ${{ secrets.USERNAME }} | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           script: whoami | ||||
| ``` | ||||
|  | ||||
| ## Related environment | ||||
|  | ||||
| Please provide the following information: | ||||
|  | ||||
| 1. Your hosting provider information, such as DigitalOcean, Linode, AWS, or GCP. | ||||
| 2. The version information of your host's SSH service. | ||||
| 3. The information from your host's SSH configuration file. | ||||
							
								
								
									
										45
									
								
								.github/main.workflow
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								.github/main.workflow
									
									
									
									
										vendored
									
									
								
							| @@ -1,45 +0,0 @@ | ||||
| workflow "Remote ssh commands" { | ||||
|   on = "push" | ||||
|   resolves = [ | ||||
|     "Executing remote ssh commands", | ||||
|     "Support Private Key", | ||||
|     "Multiple Commands", | ||||
|   ] | ||||
| } | ||||
|  | ||||
| action "Executing remote ssh commands" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "PASSWORD", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "whoami", | ||||
|   ] | ||||
| } | ||||
|  | ||||
| action "Support Private Key" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "KEY", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "'ls -al'", | ||||
|   ] | ||||
| } | ||||
|  | ||||
| action "Multiple Commands" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "KEY", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "'whoami'", | ||||
|     "--script", "'ls -al'", | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										33
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| name: Goreleaser | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     tags: | ||||
|       - "*" | ||||
|  | ||||
| permissions: | ||||
|   contents: write | ||||
|  | ||||
| jobs: | ||||
|   goreleaser: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Setup go | ||||
|         uses: actions/setup-go@v5 | ||||
|         with: | ||||
|           go-version: "^1" | ||||
|  | ||||
|       - name: Run GoReleaser | ||||
|         uses: goreleaser/goreleaser-action@v6 | ||||
|         with: | ||||
|           # either 'goreleaser' (default) or 'goreleaser-pro' | ||||
|           distribution: goreleaser | ||||
|           version: latest | ||||
|           args: release --clean | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
							
								
								
									
										724
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										724
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,724 @@ | ||||
| name: testing main branch | ||||
|  | ||||
| on: [push] | ||||
|  | ||||
| jobs: | ||||
|   default-user-name-password: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh by username and password | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             whoami | ||||
|  | ||||
|       - name: ssh commands from a file | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           script_path: testdata/test.sh | ||||
|  | ||||
|   check-ssh-key: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_rsa.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_rsa.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_rsa >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_rsa | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh by private key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|       - name: wrong password but correct key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: "abcdef" | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|       - name: correct password but wrong key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           key: password | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|   support-key-passphrase: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_passphrase.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_passphrase | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh key passphrase | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       - name: missing ssh key passphrase | ||||
|         uses: ./ | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       # https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271 | ||||
|       - name: Multiline SSH commands interpreted as single lines | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             ls \ | ||||
|               -lah | ||||
|           use_insecure_cipher: true | ||||
|  | ||||
|   multiple-server: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_passphrase.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_passphrase | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server-01 \ | ||||
|           --hostname=openssh-server-01 \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server-01 sh -c "hostname -i" > ip01.txt | ||||
|           echo "REMOTE_HOST_01<<EOF" >> $GITHUB_ENV | ||||
|           cat ip01.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip01.txt | ||||
|           echo "======================================" | ||||
|  | ||||
|           docker run -d \ | ||||
|           --name=openssh-server-02 \ | ||||
|           --hostname=openssh-server-02 \ | ||||
|           -p 2223:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server-02 sh -c "hostname -i" > ip02.txt | ||||
|           echo "REMOTE_HOST_02<<EOF" >> $GITHUB_ENV | ||||
|           cat ip02.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip02.txt | ||||
|           echo "======================================" | ||||
|  | ||||
|           sleep 2 | ||||
|  | ||||
|       # https://github.com/appleboy/ssh-action/issues/85 | ||||
|       - name: Deployment to multiple hosts with different ports | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: "${{ env.REMOTE_HOST_01 }}:2222,${{ env.REMOTE_HOST_02 }}:2222" | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             whoami | ||||
|  | ||||
|   support-ed25519-key: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_ed25519.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_ed25519 | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: testing id_ed25519 key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|   testing-with-env: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_ed25519.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_ed25519 | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=true \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: testing id_ed25519 key | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       - name: pass environment | ||||
|         uses: ./ | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO | ||||
|           script: | | ||||
|             echo "I am $FOO, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|  | ||||
|       - name: pass multiple environment | ||||
|         uses: ./ | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|           BAR: "FOO" | ||||
|           SHA: ${{ github.sha }} | ||||
|           PORT: ${{ secrets.PORT }} | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO,BAR,SHA,PORT | ||||
|           script: | | ||||
|             echo "I am $FOO, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|             echo "sha: $SHA" | ||||
|             echo "port: $PORT" | ||||
|  | ||||
|       - name: custom envs format | ||||
|         uses: ./ | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|           AAA: "BBB" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO,BAR,AAA | ||||
|           envs_format: export TEST_{NAME}={VALUE} | ||||
|           script: | | ||||
|             echo "I am $TEST_FOO, thanks" | ||||
|             echo "I am $TEST_BAR, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|             echo "I am $TEST_AAA, thanks" | ||||
|  | ||||
|       - name: pass all ENV variables to script | ||||
|         uses: ./ | ||||
|         env: | ||||
|           INPUT_FOO: "BAR" | ||||
|           INPUT_AAA: "BBB" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           allenvs: true | ||||
|           script: | | ||||
|             echo "I am $INPUT_FOO, thanks" | ||||
|             echo "I am $INPUT_AAA, thanks" | ||||
|             echo "$GITHUB_BASE_REF" | ||||
|             echo "$GITHUB_REF" | ||||
|  | ||||
|       - name: pass secret variable in shell | ||||
|         uses: ./ | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: cd ${{ secrets.PORT }} | ||||
|  | ||||
|       - name: switch to root user | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           request_pty: true | ||||
|           command_timeout: 30s | ||||
|           script: | | ||||
|             whoami && echo 'hello world' && touch todo.txt | ||||
|             sudo whoami | ||||
|  | ||||
|   testing06: | ||||
|     name: testing ipv6 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Set up WARP | ||||
|         uses: fscarmen/warp-on-actions@v1.1 | ||||
|         with: | ||||
|           stack: dual | ||||
|  | ||||
|       - name: testing ipv6 for command | ||||
|         run: | | ||||
|           curl -m 9 --ipv6 --verbose https://google.com | ||||
|  | ||||
|       - name: testing ipv6 | ||||
|         uses: ./ | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|           host: 2402:1f00:8000:800::2628 | ||||
|           username: ubuntu | ||||
|           password: ${{ secrets.OVH_PASSWORD }} | ||||
|           protocol: tcp6 | ||||
|           port: 22 | ||||
|           command_timeout: 30s | ||||
|           script: | | ||||
|             whoami | ||||
|  | ||||
|   testing07: | ||||
|     name: some special character | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: checkout | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Set Environment Variables | ||||
|         run: | | ||||
|           PASS='3HUS$?8kLu)}' | ||||
|           printf "PASS=${PASS}" >> $GITHUB_ENV | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD='${{ env.PASS }}'  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh by username and password | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: ${{ env.PASS }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             whoami | ||||
|  | ||||
|   testing-capturing-output: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - id: stdout | ||||
|         name: ssh command with stdout | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           capture_stdout: true | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             whoami | ||||
|  | ||||
|       - name: check stdout | ||||
|         run: | | ||||
|           echo "stdout: ${{ steps.stdout.outputs.stdout }}" | ||||
|  | ||||
|   testing-script-stop: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - id: stdout01 | ||||
|         name: ssh command with stdout 01 | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           capture_stdout: true | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             echo "TMP TESTING IF" | ||||
|             if [[ "2" == "1" ]]; then | ||||
|               echo "True" | ||||
|             else | ||||
|               echo "False" | ||||
|             fi | ||||
|  | ||||
|       - name: check stdout 01 | ||||
|         run: | | ||||
|           echo "stdout: ${{ steps.stdout01.outputs.stdout }}" | ||||
|           if echo "${{ steps.stdout01.outputs.stdout }}" | grep -q "True"; then | ||||
|             echo "Output contains 'True'" | ||||
|             exit 1 | ||||
|           fi | ||||
|           if echo "${{ steps.stdout01.outputs.stdout }}" | grep -q "False"; then | ||||
|             echo "Output contains 'False'" | ||||
|           fi | ||||
|  | ||||
|       - id: stdout02 | ||||
|         name: ssh command with stdout 01 | ||||
|         uses: ./ | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           capture_stdout: true | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             echo "TMP TESTING IF" | ||||
|             if [[ "1" == "1" ]]; then | ||||
|               echo "True" | ||||
|             else | ||||
|               echo "False" | ||||
|             fi | ||||
|  | ||||
|       - name: check stdout 02 | ||||
|         run: | | ||||
|           echo "stdout: ${{ steps.stdout02.outputs.stdout }}" | ||||
|           if echo "${{ steps.stdout02.outputs.stdout }}" | grep -q "False"; then | ||||
|             echo "Output contains 'False'" | ||||
|             exit 1 | ||||
|           fi | ||||
|           if echo "${{ steps.stdout02.outputs.stdout }}" | grep -q "True"; then | ||||
|             echo "Output contains 'True'" | ||||
|           fi | ||||
|  | ||||
|   testing-script-error: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: test script error | ||||
|         uses: ./ | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           capture_stdout: true | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             ls /nonexistent | ||||
							
								
								
									
										467
									
								
								.github/workflows/stable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										467
									
								
								.github/workflows/stable.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,467 @@ | ||||
| name: testing stable version | ||||
|  | ||||
| on: [push] | ||||
|  | ||||
| jobs: | ||||
|   default-user-name-password: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh by username and password | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             #!/usr/bin/env bash | ||||
|             set -e | ||||
|             whoami | ||||
|  | ||||
|       - name: ssh commands from a file | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           port: 2222 | ||||
|           script_path: testdata/test.sh | ||||
|  | ||||
|   check-ssh-key: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_rsa.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_rsa.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_rsa >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_rsa | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh by private key | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|       - name: wrong password but correct key | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: "abcdef" | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|       - name: correct password but wrong key | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: password | ||||
|           key: password | ||||
|           port: 2222 | ||||
|           script: whoami | ||||
|  | ||||
|   support-key-passphrase: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_passphrase.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_passphrase | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: ssh key passphrase | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       - name: missing ssh key passphrase | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       # https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271 | ||||
|       - name: Multiline SSH commands interpreted as single lines | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             ls \ | ||||
|               -lah | ||||
|           use_insecure_cipher: true | ||||
|  | ||||
|   multiple-server: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_passphrase.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_passphrase >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_passphrase | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server-01 \ | ||||
|           --hostname=openssh-server-01 \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server-01 sh -c "hostname -i" > ip01.txt | ||||
|           echo "REMOTE_HOST_01<<EOF" >> $GITHUB_ENV | ||||
|           cat ip01.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip01.txt | ||||
|           echo "======================================" | ||||
|  | ||||
|           docker run -d \ | ||||
|           --name=openssh-server-02 \ | ||||
|           --hostname=openssh-server-02 \ | ||||
|           -p 2223:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server-02 sh -c "hostname -i" > ip02.txt | ||||
|           echo "REMOTE_HOST_02<<EOF" >> $GITHUB_ENV | ||||
|           cat ip02.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip02.txt | ||||
|           echo "======================================" | ||||
|  | ||||
|           sleep 2 | ||||
|  | ||||
|       # https://github.com/appleboy/ssh-action/issues/85 | ||||
|       - name: Deployment to multiple hosts with different ports | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: "${{ env.REMOTE_HOST_01 }}:2222,${{ env.REMOTE_HOST_02 }}:2222" | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           passphrase: 1234 | ||||
|           script: | | ||||
|             whoami | ||||
|  | ||||
|   support-ed25519-key: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_ed25519.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_ed25519 | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=false \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_PASSWORD=password  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: testing id_ed25519 key | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|   testing-with-env: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: add public key to env | ||||
|         run: | | ||||
|           echo "PUBLIC_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= public key =========" | ||||
|           cat testdata/.ssh/id_ed25519.pub | ||||
|           echo "============================" | ||||
|           echo "PRIVATE_KEY<<EOF" >> $GITHUB_ENV | ||||
|           cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= private key =========" | ||||
|           cat testdata/.ssh/id_ed25519 | ||||
|           echo "============================" | ||||
|  | ||||
|       - name: create new ssh server | ||||
|         run: | | ||||
|           docker run -d \ | ||||
|           --name=openssh-server \ | ||||
|           --hostname=openssh-server \ | ||||
|           -p 2222:2222 \ | ||||
|           -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ | ||||
|           -e SUDO_ACCESS=true \ | ||||
|           -e PASSWORD_ACCESS=true  \ | ||||
|           -e USER_NAME=linuxserver.io \ | ||||
|           --restart unless-stopped \ | ||||
|           lscr.io/linuxserver/openssh-server:latest | ||||
|           docker exec openssh-server sh -c "hostname -i" > ip.txt | ||||
|           echo "REMOTE_HOST<<EOF" >> $GITHUB_ENV | ||||
|           cat ip.txt >> $GITHUB_ENV | ||||
|           echo "EOF" >> $GITHUB_ENV | ||||
|           echo "======= container ip address =========" | ||||
|           cat ip.txt | ||||
|           echo "======================================" | ||||
|           sleep 2 | ||||
|  | ||||
|       - name: testing id_ed25519 key | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           script: | | ||||
|             whoami | ||||
|             ls -al | ||||
|  | ||||
|       - name: pass environment | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO | ||||
|           script: | | ||||
|             echo "I am $FOO, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|  | ||||
|       - name: pass multiple environment | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|           BAR: "FOO" | ||||
|           SHA: ${{ github.sha }} | ||||
|           PORT: ${{ secrets.PORT }} | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO,BAR,SHA,PORT | ||||
|           script: | | ||||
|             echo "I am $FOO, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|             echo "sha: $SHA" | ||||
|             echo "port: $PORT" | ||||
|  | ||||
|       - name: custom envs format | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         env: | ||||
|           FOO: "BAR" | ||||
|           AAA: "BBB" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           envs: FOO,BAR,AAA | ||||
|           envs_format: export TEST_{NAME}={VALUE} | ||||
|           script: | | ||||
|             echo "I am $TEST_FOO, thanks" | ||||
|             echo "I am $TEST_BAR, thanks" | ||||
|             echo "I am $BAR, thanks" | ||||
|             echo "I am $TEST_AAA, thanks" | ||||
|  | ||||
|       - name: pass all ENV variables to script | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         env: | ||||
|           INPUT_FOO: "BAR" | ||||
|           INPUT_AAA: "BBB" | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           allenvs: true | ||||
|           script: | | ||||
|             echo "I am $INPUT_FOO, thanks" | ||||
|             echo "I am $INPUT_AAA, thanks" | ||||
|             echo "$GITHUB_BASE_REF" | ||||
|             echo "$GITHUB_REF" | ||||
|  | ||||
|       - name: switch to root user | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ env.REMOTE_HOST }} | ||||
|           username: linuxserver.io | ||||
|           key: ${{ env.PRIVATE_KEY }} | ||||
|           port: 2222 | ||||
|           request_pty: true | ||||
|           command_timeout: 30s | ||||
|           script: | | ||||
|             whoami && echo 'hello world' && touch todo.txt | ||||
|             sudo whoami | ||||
							
								
								
									
										28
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| builds: | ||||
|   - # If true, skip the build. | ||||
|     # Useful for library projects. | ||||
|     # Default is false | ||||
|     skip: true | ||||
|  | ||||
| changelog: | ||||
|   use: github | ||||
|   groups: | ||||
|     - title: Features | ||||
|       regexp: "^.*feat[(\\w)]*:+.*$" | ||||
|       order: 0 | ||||
|     - title: "Bug fixes" | ||||
|       regexp: "^.*fix[(\\w)]*:+.*$" | ||||
|       order: 1 | ||||
|     - title: "Enhancements" | ||||
|       regexp: "^.*chore[(\\w)]*:+.*$" | ||||
|       order: 2 | ||||
|     - title: "Refactor" | ||||
|       regexp: "^.*refactor[(\\w)]*:+.*$" | ||||
|       order: 3 | ||||
|     - title: "Build process updates" | ||||
|       regexp: ^.*?(build|ci)(\(.+\))??!?:.+$ | ||||
|       order: 4 | ||||
|     - title: "Documentation updates" | ||||
|       regexp: ^.*?docs?(\(.+\))??!?:.+$ | ||||
|       order: 4 | ||||
|     - title: Others | ||||
							
								
								
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,16 +0,0 @@ | ||||
| FROM appleboy/drone-ssh:1.5.0-linux-amd64 | ||||
|  | ||||
| # Github labels | ||||
| LABEL "com.github.actions.name"="SSH Commands" | ||||
| LABEL "com.github.actions.description"="Executing remote ssh commands" | ||||
| LABEL "com.github.actions.icon"="terminal" | ||||
| LABEL "com.github.actions.color"="gray-dark" | ||||
|  | ||||
| LABEL "repository"="https://github.com/appleboy/ssh-action" | ||||
| LABEL "homepage"="https://github.com/appleboy" | ||||
| LABEL "maintainer"="Bo-Yi Wu <appleboy.tw@gmail.com>" | ||||
| LABEL "version"="0.0.1" | ||||
|  | ||||
| ADD entrypoint.sh /entrypoint.sh | ||||
| RUN chmod +x /entrypoint.sh | ||||
| ENTRYPOINT ["/entrypoint.sh"] | ||||
							
								
								
									
										499
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										499
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,131 +1,428 @@ | ||||
| # 🚀 SSH for GitHub Actions | ||||
|  | ||||
| [GitHub Action](https://developer.github.com/actions/) for executing remote ssh commands. | ||||
| English | [繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md) | ||||
|  | ||||
| <img src="./images/ssh-workflow.png"> | ||||
| A [GitHub Action](https://github.com/features/actions) for executing remote SSH commands. | ||||
|  | ||||
|  | ||||
|  | ||||
| [](https://github.com/appleboy/ssh-action/actions/workflows/main.yml) | ||||
|  | ||||
| This project is built with [Golang](https://go.dev) and [drone-ssh](https://github.com/appleboy/drone-ssh). 🚀 | ||||
|  | ||||
| ## Input variables | ||||
|  | ||||
| Refer to [action.yml](./action.yml) for more detailed information. | ||||
|  | ||||
| | Input Parameter           | Description                                                                              | Default Value | | ||||
| | ------------------------- | ---------------------------------------------------------------------------------------- | ------------- | | ||||
| | host                      | SSH host address                                                                         |               | | ||||
| | port                      | SSH port number                                                                          | 22            | | ||||
| | passphrase                | SSH key passphrase                                                                       |               | | ||||
| | username                  | SSH username                                                                             |               | | ||||
| | password                  | SSH password                                                                             |               | | ||||
| | protocol                  | SSH protocol version (tcp, tcp4, tcp6)                                                   | tcp           | | ||||
| | sync                      | Enable synchronous execution if multiple hosts are specified                             | false         | | ||||
| | use_insecure_cipher       | Include more ciphers with use_insecure_cipher                                            | false         | | ||||
| | cipher                    | Allowed cipher algorithms. If unspecified, sensible defaults are used                    |               | | ||||
| | timeout                   | Timeout duration for SSH to host                                                         | 30s           | | ||||
| | command_timeout           | Timeout duration for SSH command                                                         | 10m           | | ||||
| | key                       | Content of SSH private key. e.g., raw content of ~/.ssh/id_rsa                           |               | | ||||
| | key_path                  | Path of SSH private key                                                                  |               | | ||||
| | fingerprint               | SHA256 fingerprint of the host public key                                                |               | | ||||
| | proxy_host                | SSH proxy host                                                                           |               | | ||||
| | proxy_port                | SSH proxy port                                                                           | 22            | | ||||
| | proxy_protocol            | SSH proxy protocol version (tcp, tcp4, tcp6)                                             | tcp           | | ||||
| | proxy_username            | SSH proxy username                                                                       |               | | ||||
| | proxy_password            | SSH proxy password                                                                       |               | | ||||
| | proxy_passphrase          | SSH proxy key passphrase                                                                 |               | | ||||
| | proxy_timeout             | Timeout for SSH to proxy host                                                            | 30s           | | ||||
| | proxy_key                 | Content of SSH proxy private key                                                         |               | | ||||
| | proxy_key_path            | Path of SSH proxy private key                                                            |               | | ||||
| | proxy_fingerprint         | SHA256 fingerprint of the proxy host public key                                          |               | | ||||
| | proxy_cipher              | Allowed cipher algorithms for the proxy                                                  |               | | ||||
| | proxy_use_insecure_cipher | Include more ciphers with use_insecure_cipher for the proxy                              | false         | | ||||
| | script                    | Execute commands                                                                         |               | | ||||
| | script_path               | Execute commands from a file                                                             |               | | ||||
| | envs                      | Pass environment variables to the shell script                                           |               | | ||||
| | envs_format               | Flexible configuration of environment value transfer                                     |               | | ||||
| | debug                     | Enable debug mode                                                                        | false         | | ||||
| | allenvs                   | Pass the environment variables with prefix value of `GITHUB_` and `INPUT_` to the script | false         | | ||||
| | request_pty               | Request a pseudo-terminal from the server                                                | false         | | ||||
|  | ||||
| **Note:** Users can add `set -e` in their shell script to achieve similar functionality to the removed `script_stop` option. | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| Executing remote ssh commands. | ||||
| Executing remote SSH commands. | ||||
|  | ||||
| ``` | ||||
| action "Executing remote ssh commands" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "PASSWORD", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "whoami", | ||||
|   ] | ||||
| } | ||||
| ```yaml | ||||
| name: remote ssh command | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: executing remote ssh commands using password | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           script: whoami | ||||
| ``` | ||||
|  | ||||
| ## Environment variables | ||||
| output: | ||||
|  | ||||
| * HOST - ssh server host | ||||
| * PORT - ssh server port | ||||
| * USERNAME - ssh server username | ||||
| * PASSWORD - ssh server password | ||||
| * KEY - ssh server private key | ||||
| * SCRIPT - execute the scripts | ||||
| ```sh | ||||
| ======CMD====== | ||||
| whoami | ||||
| ======END====== | ||||
| linuxserver.io | ||||
| =============================================== | ||||
| ✅ Successfully executed commands to all hosts. | ||||
| =============================================== | ||||
| ``` | ||||
|  | ||||
| ### Setting up a SSH Key | ||||
|  | ||||
| Follow the steps below to create and use SSH Keys. | ||||
| It is best practice to create SSH Keys on your local machine, not on a remote machine. | ||||
| Log in with the username specified in GitHub Secrets and generate an RSA Key-Pair: | ||||
|  | ||||
| ### Generate rsa key | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### Generate ed25519 key | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| Add the newly generated key to the Authorized keys. Read more about authorized keys [here](https://www.ssh.com/ssh/authorized_keys/). | ||||
|  | ||||
| ### Add rsa key into Authorized keys | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| ### Add ed25519 key into Authorized keys | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| Copy the Private Key content and paste it into GitHub Secrets. | ||||
|  | ||||
| ### Copy rsa Private key | ||||
|  | ||||
| Before copying the private key, install the `clip` command as shown below: | ||||
|  | ||||
| ```bash | ||||
| # Ubuntu | ||||
| sudo apt-get install xclip | ||||
| ``` | ||||
|  | ||||
| Copy the private key: | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_rsa | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_rsa | ||||
| ``` | ||||
|  | ||||
| Starting from and including the comment section `-----BEGIN OPENSSH PRIVATE KEY-----` and ending at and including the comment section `-----END OPENSSH PRIVATE KEY-----`, copy the private key and paste it into GitHub Secrets. | ||||
|  | ||||
| ### Copy ed25519 Private key | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_ed25519 | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_ed25519 | ||||
| ``` | ||||
|  | ||||
| See detailed information about [SSH login without a password](http://www.linuxproblem.org/art_9.html). | ||||
|  | ||||
| **Note**: Depending on your version of SSH, you might also need to make the following changes: | ||||
|  | ||||
| - Put the public key in `.ssh/authorized_keys2` | ||||
| - Change the permissions of `.ssh` to 700 | ||||
| - Change the permissions of `.ssh/authorized_keys2` to 640 | ||||
|  | ||||
| ### If you are using OpenSSH | ||||
|  | ||||
| If you are currently using OpenSSH and are getting the following error: | ||||
|  | ||||
| ```bash | ||||
| ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey] | ||||
| ``` | ||||
|  | ||||
| Ensure that your chosen key algorithm is supported. On Ubuntu 20.04 or later, you must explicitly allow the use of the ssh-rsa algorithm. Add the following line to your OpenSSH daemon file (either `/etc/ssh/sshd_config` or a drop-in file under `/etc/ssh/sshd_config.d/`): | ||||
|  | ||||
| ```bash | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| Alternatively, `ed25519` keys are accepted by default in OpenSSH. You can use this instead of rsa if needed: | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### Example | ||||
|  | ||||
| Executing remote ssh commands. | ||||
| #### Executing remote ssh commands using password | ||||
|  | ||||
| ``` | ||||
| action "Executing remote ssh commands" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "PASSWORD", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--host", "foo.com" | ||||
|     "--user", "bar", | ||||
|     "--script", "whoami", | ||||
|   ] | ||||
| } | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using password | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     password: ${{ secrets.PASSWORD }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| Using private key | ||||
| #### Using private key | ||||
|  | ||||
| ``` | ||||
| action "Support Private Key" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "KEY", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "'ls -al'", | ||||
|   ] | ||||
| } | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using ssh key | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| Multiple Commands | ||||
| #### Multiple Commands | ||||
|  | ||||
| ``` | ||||
| action "Multiple Commands" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "HOST", | ||||
|     "KEY", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--user", "actions", | ||||
|     "--script", "'whoami'", | ||||
|     "--script", "'ls -al'", | ||||
|   ] | ||||
| } | ||||
| ```yaml | ||||
| - name: multiple command | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: | | ||||
|       whoami | ||||
|       ls -al | ||||
| ``` | ||||
|  | ||||
| <img src="./images/multiple-command-result.png"> | ||||
|  | ||||
|  | ||||
| Multiple Hosts | ||||
| #### Commands from a file | ||||
|  | ||||
| ``` | ||||
| action "Multiple Hosts" { | ||||
|   uses = "appleboy/ssh-action@master" | ||||
|   secrets = [ | ||||
|     "KEY", | ||||
|   ] | ||||
|   args = [ | ||||
|     "--host", "foo.com", | ||||
|     "--host", "bar.com", | ||||
|     "--user", "actions", | ||||
|     "--script", "'whoami'", | ||||
|     "--script", "'ls -al'", | ||||
|   ] | ||||
| } | ||||
| ```yaml | ||||
| - name: file commands | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script_path: scripts/script.sh | ||||
| ``` | ||||
|  | ||||
| see the detail of `drone-ssh` command | ||||
| #### Multiple Hosts | ||||
|  | ||||
| ``` | ||||
|    --ssh-key value                           private ssh key [$PLUGIN_SSH_KEY, $PLUGIN_KEY, $SSH_KEY, $KEY] | ||||
|    --key-path value, -i value                ssh private key path [$PLUGIN_KEY_PATH, $SSH_KEY_PATH, $PATH] | ||||
|    --username value, --user value, -u value  connect as user (default: "root") [$PLUGIN_USERNAME, $PLUGIN_USER, $SSH_USERNAME, $USERNAME] | ||||
|    --password value, -P value                user password [$PLUGIN_PASSWORD, $SSH_PASSWORD, $PASSWORD] | ||||
|    --host value, -H value                    connect to host [$PLUGIN_HOST, $SSH_HOST, $HOST] | ||||
|    --port value, -p value                    connect to port (default: 22) [$PLUGIN_PORT, $SSH_PORT, $PORT] | ||||
|    --sync                                    sync mode [$PLUGIN_SYNC, $SYNC] | ||||
|    --timeout value, -t value                 connection timeout (default: 0s) [$PLUGIN_TIMEOUT, $SSH_TIMEOUT, $TIMEOUT] | ||||
|    --command.timeout value, -T value         command timeout (default: 1m0s) [$PLUGIN_COMMAND_TIMEOUT, $SSH_COMMAND_TIMEOUT, $COMMAND_TIMEOUT] | ||||
|    --script value, -s value                  execute commands [$PLUGIN_SCRIPT, $SSH_SCRIPT, $SCRIPT] | ||||
|    --script.stop                             stop script after first failure [$PLUGIN_SCRIPT_STOP, $STOP] | ||||
|    --proxy.ssh-key value                     private ssh key of proxy [$PLUGIN_PROXY_SSH_KEY, $PLUGIN_PROXY_KEY, $PROXY_SSH_KEY] | ||||
|    --proxy.key-path value                    ssh private key path of proxy [$PLUGIN_PROXY_KEY_PATH, $PROXY_SSH_KEY_PATH] | ||||
|    --proxy.username value                    connect as user of proxy (default: "root") [$PLUGIN_PROXY_USERNAME, $PLUGIN_PROXY_USER, $PROXY_SSH_USERNAME] | ||||
|    --proxy.password value                    user password of proxy [$PLUGIN_PROXY_PASSWORD, $PROXY_SSH_PASSWORD] | ||||
|    --proxy.host value                        connect to host of proxy [$PLUGIN_PROXY_HOST, $PROXY_SSH_HOST] | ||||
|    --proxy.port value                        connect to port of proxy (default: "22") [$PLUGIN_PROXY_PORT, $PROXY_SSH_PORT] | ||||
|    --proxy.timeout value                     proxy connection timeout (default: 0s) [$PLUGIN_PROXY_TIMEOUT, $PROXY_SSH_TIMEOUT] | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com,bar.com" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| ## Secrets | ||||
| The default value of `port` is `22`. | ||||
|  | ||||
| * `PASSWORD` - ssh server password | ||||
| * `KEY` - ssh server private key | ||||
| #### Multiple hosts with different port | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com:1234,bar.com:5678" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### Synchronous execution on multiple hosts | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: "foo.com,bar.com" | ||||
| +     sync: true | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### Pass environment variable to shell script | ||||
|  | ||||
| ```diff | ||||
|   - name: pass environment | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
| +   env: | ||||
| +     FOO: "BAR" | ||||
| +     BAR: "FOO" | ||||
| +     SHA: ${{ github.sha }} | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     envs: FOO,BAR,SHA | ||||
|       script: | | ||||
|         echo "I am $FOO" | ||||
|         echo "I am $BAR" | ||||
|         echo "sha: $SHA" | ||||
| ``` | ||||
|  | ||||
| _Inside `env` object, you need to pass every environment variable as a string, passing `Integer` data type or any other may output unexpected results._ | ||||
|  | ||||
| #### How to connect remote server using `ProxyCommand`? | ||||
|  | ||||
| ```bash | ||||
| +--------+       +----------+      +-----------+ | ||||
| | Laptop | <-->  | Jumphost | <--> | FooServer | | ||||
| +--------+       +----------+      +-----------+ | ||||
| ``` | ||||
|  | ||||
| in your `~/.ssh/config`, you will see the following. | ||||
|  | ||||
| ```bash | ||||
| Host Jumphost | ||||
|   HostName Jumphost | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   IdentityFile ~/.ssh/keys/jump_host.pem | ||||
|  | ||||
| Host FooServer | ||||
|   HostName FooServer | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   ProxyCommand ssh -q -W %h:%p Jumphost | ||||
| ``` | ||||
|  | ||||
| #### How to convert to YAML format of GitHubActions | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh proxy command | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     proxy_host: ${{ secrets.PROXY_HOST }} | ||||
| +     proxy_username: ${{ secrets.PROXY_USERNAME }} | ||||
| +     proxy_key: ${{ secrets.PROXY_KEY }} | ||||
| +     proxy_port: ${{ secrets.PROXY_PORT }} | ||||
|       script: | | ||||
|         mkdir abc/def | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### Protecting a Private Key | ||||
|  | ||||
| The purpose of the passphrase is usually to encrypt the private key. | ||||
| This makes the key file by itself useless to an attacker. | ||||
| It is not uncommon for files to leak from backups or decommissioned hardware, and hackers commonly exfiltrate files from compromised systems. | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     passphrase: ${{ secrets.PASSPHRASE }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### Using host fingerprint verification | ||||
|  | ||||
| Setting up SSH host fingerprint verification can help to prevent Person-in-the-Middle attacks. Before setting this up, run the command below to get your SSH host fingerprint. Remember to replace `ed25519` with your appropriate key type (`rsa`, `dsa`, etc.) that your server is using and `example.com` with your host. | ||||
|  | ||||
| In modern OpenSSH releases, the _default_ key types to be fetched are `rsa` (since version 5.1), `ecdsa` (since version 6.0), and `ed25519` (since version 6.7). | ||||
|  | ||||
| ```sh | ||||
| ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2 | ||||
| ``` | ||||
|  | ||||
| Now you can adjust you config: | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     fingerprint: ${{ secrets.FINGERPRINT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| ## Q&A | ||||
|  | ||||
| ### Command not found (npm or other command) | ||||
|  | ||||
| See the [issue comment](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) about interactive vs non interactive shell. Thanks @kocyigityunus for the solution. | ||||
|  | ||||
| If you are running a command in a non-interactive shell, like ssh-action, on many Linux distros, | ||||
|  | ||||
| `/etc/bash.bashrc` file has a specific command that returns only, so some of the files didn't run and some specific commands doesn't add to path, | ||||
|  | ||||
| ```sh | ||||
| # /etc/bash.bashrc | ||||
| # System-wide .bashrc file for interactive bash(1) shells. | ||||
|  | ||||
| # To enable the settings / commands in this file for login shells as well, | ||||
| # this file has to be sourced in /etc/profile. | ||||
|  | ||||
| # If not running interactively, don't do anything | ||||
| [ -z "$PS1" ] && return` | ||||
| ``` | ||||
|  | ||||
| comment out the line that returns early, and everything should work fine. Alternatively, you can use the real paths of the commands you want to use. | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| We would love for you to contribute to `appleboy/ssh-action`, pull requests are welcome! | ||||
|  | ||||
| ## License | ||||
|  | ||||
| The scripts and documentation in this project are released under the [MIT License](LICENSE) | ||||
|   | ||||
							
								
								
									
										403
									
								
								README.zh-cn.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										403
									
								
								README.zh-cn.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,403 @@ | ||||
| # 🚀 用于 GitHub Actions 的 SSH | ||||
|  | ||||
| [English](./README.md) | [繁體中文](./README.zh-tw.md) | 简体中文 | ||||
|  | ||||
| 一个用于执行远程 SSH 命令的 [GitHub Action](https://github.com/features/actions)。 | ||||
|  | ||||
|  | ||||
|  | ||||
| [](https://github.com/appleboy/ssh-action/actions/workflows/main.yml) | ||||
|  | ||||
| 该项目使用 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 构建。🚀 | ||||
|  | ||||
| ## 输入变量 | ||||
|  | ||||
| 有关更详细的信息,请参阅 [action.yml](./action.yml)。 | ||||
|  | ||||
| | 输入参数                  | 描述                                                  | 默认值 | | ||||
| | ------------------------- | ----------------------------------------------------- | ------ | | ||||
| | host                      | SSH 主机地址                                          |        | | ||||
| | port                      | SSH 端口号                                            | 22     | | ||||
| | passphrase                | SSH 密钥密码短语                                      |        | | ||||
| | username                  | SSH 用户名                                            |        | | ||||
| | password                  | SSH 密码                                              |        | | ||||
| | protocol                  | SSH 协议版本(tcp, tcp4, tcp6)                       | tcp    | | ||||
| | sync                      | 如果指定了多个主机,则启用同步执行                    | false  | | ||||
| | use_insecure_cipher       | 使用不安全的密码算法                                  | false  | | ||||
| | cipher                    | 允许的密码算法。如果未指定,则使用适当的默认值        |        | | ||||
| | timeout                   | SSH 连接到主机的超时时间                              | 30s    | | ||||
| | command_timeout           | SSH 命令的超时时间                                    | 10m    | | ||||
| | key                       | SSH 私钥的内容,例如 ~/.ssh/id_rsa 的原始内容         |        | | ||||
| | key_path                  | SSH 私钥的路径                                        |        | | ||||
| | fingerprint               | 主机公钥的 SHA256 指纹                                |        | | ||||
| | proxy_host                | SSH 代理主机                                          |        | | ||||
| | proxy_port                | SSH 代理端口                                          | 22     | | ||||
| | proxy_protocol            | SSH 代理协议版本(tcp, tcp4, tcp6)                   | tcp    | | ||||
| | proxy_username            | SSH 代理用户名                                        |        | | ||||
| | proxy_password            | SSH 代理密码                                          |        | | ||||
| | proxy_passphrase          | SSH 代理密钥密码短语                                  |        | | ||||
| | proxy_timeout             | SSH 连接到代理主机的超时时间                          | 30s    | | ||||
| | proxy_key                 | SSH 代理私钥的内容                                    |        | | ||||
| | proxy_key_path            | SSH 代理私钥的路径                                    |        | | ||||
| | proxy_fingerprint         | 代理主机公钥的 SHA256 指纹                            |        | | ||||
| | proxy_cipher              | 代理允许的密码算法                                    |        | | ||||
| | proxy_use_insecure_cipher | 使用不安全的密码算法                                  | false  | | ||||
| | script                    | 执行命令                                              |        | | ||||
| | script_path               | 从文件执行命令                                        |        | | ||||
| | envs                      | 传递环境变量到 shell 脚本                             |        | | ||||
| | envs_format               | 环境变量传递的灵活配置                                |        | | ||||
| | debug                     | 启用调试模式                                          | false  | | ||||
| | allenvs                   | 将带有 `GITHUB_` 和 `INPUT_` 前缀的环境变量传递给脚本 | false  | | ||||
| | request_pty               | 请求伪终端                                            | false  | | ||||
|  | ||||
| **注意:** 用户可以在他们的 shell 脚本中添加 `set -e` 以实现类似于已删除的 `script_stop` 选项的功能。 | ||||
|  | ||||
| ## 使用方法 | ||||
|  | ||||
| 执行远程 SSH 命令。 | ||||
|  | ||||
| ```yaml | ||||
| name: remote ssh command | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: executing remote ssh commands using password | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           script: whoami | ||||
| ``` | ||||
|  | ||||
| 输出: | ||||
|  | ||||
| ```sh | ||||
| ======CMD====== | ||||
| whoami | ||||
| ======END====== | ||||
| linuxserver.io | ||||
| =============================================== | ||||
| ✅ Successfully executed commands to all hosts. | ||||
| =============================================== | ||||
| ``` | ||||
|  | ||||
| ### 设置 SSH 密钥 | ||||
|  | ||||
| 请按照以下步骤创建和使用 SSH 密钥。 | ||||
| 最佳做法是在本地机器上创建 SSH 密钥,而不是在远程机器上。 | ||||
| 使用 GitHub Secrets 中指定的用户名登录并生成 RSA 密钥对: | ||||
|  | ||||
| ### 生成 RSA 密钥 | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### 生成 ed25519 密钥 | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| 将新生成的密钥添加到已授权的密钥中。详细了解已授权的密钥请点[此处](https://www.ssh.com/ssh/authorized_keys/)。 | ||||
|  | ||||
| ### 将 RSA 密钥添加到已授权密钥中 | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| ### 将 ed25519 密钥添加到已授权密钥中 | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| 复制私钥内容,然后将其粘贴到 GitHub Secrets 中。 | ||||
|  | ||||
| ### 复制 RSA 私钥内容 | ||||
|  | ||||
| 在复制私钥之前,按照以下步骤安装 `clip` 命令: | ||||
|  | ||||
| ```bash | ||||
| # Ubuntu | ||||
| sudo apt-get install xclip | ||||
| ``` | ||||
|  | ||||
| 复制私钥: | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_rsa | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_rsa | ||||
| ``` | ||||
|  | ||||
| 从包含注释部分 `-----BEGIN OPENSSH PRIVATE KEY-----` 开始,到包含注释部分 `-----END OPENSSH PRIVATE KEY-----` 结束,复制私钥并将其粘贴到 GitHub Secrets 中。 | ||||
|  | ||||
| ### 复制 ed25519 私钥内容 | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_ed25519 | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_ed25519 | ||||
| ``` | ||||
|  | ||||
| 有关无需密码登录 SSH 的详细信息,请[见该网站](http://www.linuxproblem.org/art_9.html)。 | ||||
|  | ||||
| **注意**:根据您的 SSH 版本,您可能还需要进行以下更改: | ||||
|  | ||||
| - 将公钥放在 `.ssh/authorized_keys2` 中 | ||||
| - 将 `.ssh` 的权限更改为 700 | ||||
| - 将 `.ssh/authorized_keys2` 的权限更改为 640 | ||||
|  | ||||
| ### 如果你使用的是 OpenSSH | ||||
|  | ||||
| 如果您正在使用 OpenSSH,并出现以下错误: | ||||
|  | ||||
| ```bash | ||||
| ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey] | ||||
| ``` | ||||
|  | ||||
| 请确保您所选择的密钥算法得到支持。在 Ubuntu 20.04 或更高版本上,您必须明确允许使用 ssh-rsa 算法。请在 OpenSSH 守护进程文件中添加以下行(它可以是 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 中的一个附加文件): | ||||
|  | ||||
| ```bash | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| 或者,`ed25519` 密钥在 OpenSSH 中默认被接受。如果需要,您可以使用它来替代 RSA: | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### 示例 | ||||
|  | ||||
| #### 使用密码执行远程 SSH 命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using password | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     password: ${{ secrets.PASSWORD }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| #### 使用私钥 | ||||
|  | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using ssh key | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| #### 多个命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: multiple command | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: | | ||||
|       whoami | ||||
|       ls -al | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
| #### 从文件执行命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: file commands | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script_path: scripts/script.sh | ||||
| ``` | ||||
|  | ||||
| #### 多台主机 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com,bar.com" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| 默认的 `port` 值是 `22`。 | ||||
|  | ||||
| #### 多个不同端口的主机 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com:1234,bar.com:5678" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 在多台主机上同步执行 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: "foo.com,bar.com" | ||||
| +     sync: true | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 将环境变量传递到 shell 脚本 | ||||
|  | ||||
| ```diff | ||||
|   - name: pass environment | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
| +   env: | ||||
| +     FOO: "BAR" | ||||
| +     BAR: "FOO" | ||||
| +     SHA: ${{ github.sha }} | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     envs: FOO,BAR,SHA | ||||
|       script: | | ||||
|         echo "I am $FOO" | ||||
|         echo "I am $BAR" | ||||
|         echo "sha: $SHA" | ||||
| ``` | ||||
|  | ||||
| _在 `env` 对象中,您需要将每个环境变量作为字符串传递,传递 `Integer` 数据类型或任何其他类型可能会产生意外结果。_ | ||||
|  | ||||
| #### 如何使用 `ProxyCommand` 连接远程服务器? | ||||
|  | ||||
| ```bash | ||||
| +--------+       +----------+      +-----------+ | ||||
| | Laptop | <-->  | Jumphost | <--> | FooServer | | ||||
| +--------+       +----------+      +-----------+ | ||||
| ``` | ||||
|  | ||||
| 在您的 `~/.ssh/config` 文件中,您会看到以下内容。 | ||||
|  | ||||
| ```bash | ||||
| Host Jumphost | ||||
|   HostName Jumphost | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   IdentityFile ~/.ssh/keys/jump_host.pem | ||||
|  | ||||
| Host FooServer | ||||
|   HostName FooServer | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   ProxyCommand ssh -q -W %h:%p Jumphost | ||||
| ``` | ||||
|  | ||||
| #### 如何将其转换为 GitHubActions 的 YAML 格式? | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh proxy command | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     proxy_host: ${{ secrets.PROXY_HOST }} | ||||
| +     proxy_username: ${{ secrets.PROXY_USERNAME }} | ||||
| +     proxy_key: ${{ secrets.PROXY_KEY }} | ||||
| +     proxy_port: ${{ secrets.PROXY_PORT }} | ||||
|       script: | | ||||
|         mkdir abc/def | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 保护私钥 | ||||
|  | ||||
| 密码短语通常用于加密私钥。这使得密钥文件本身对攻击者无用。文件泄露可能来自备份或停用的硬件,黑客通常可以从受攻击系统中泄露文件。 | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     passphrase: ${{ secrets.PASSPHRASE }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 使用主机指纹验证 | ||||
|  | ||||
| 设置 SSH 主机指纹验证可以帮助防止中间人攻击。在设置之前,运行以下命令以获取 SSH 主机指纹。请记得将 `ed25519` 替换为您适当的密钥类型(`rsa`、 `dsa`等),而 `example.com` 则替换为您的主机。 | ||||
|  | ||||
| 在现代 OpenSSH 版本中,默认提取的密钥类型是 `rsa`(从版本 5.1 开始)、`ecdsa`(从版本 6.0 开始)和 `ed25519`(从版本 6.7 开始)。 | ||||
|  | ||||
| ```sh | ||||
| ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2 | ||||
| ``` | ||||
|  | ||||
| 现在您可以调整您的配置: | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     fingerprint: ${{ secrets.FINGERPRINT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| ## 贡献 | ||||
|  | ||||
| 我们非常希望您为 `appleboy/ssh-action` 做出贡献,欢迎提交请求! | ||||
|  | ||||
| ## 授权方式 | ||||
|  | ||||
| 本项目中的脚本和文档采用 [MIT 许可证](LICENSE) 发布。 | ||||
							
								
								
									
										399
									
								
								README.zh-tw.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								README.zh-tw.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,399 @@ | ||||
| # 🚀 GitHub Actions 的 SSH | ||||
|  | ||||
| [English](./README.md) | 繁體中文 | [简体中文](./README.zh-cn.md) | ||||
|  | ||||
| [GitHub Action](https://github.com/features/actions) 用於執行遠端 SSH 命令。 | ||||
|  | ||||
|  | ||||
|  | ||||
| [](https://github.com/appleboy/ssh-action/actions/workflows/main.yml) | ||||
|  | ||||
| 此專案使用 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 建立。🚀 | ||||
|  | ||||
| ## 輸入變數 | ||||
|  | ||||
| 請參閱 [action.yml](./action.yml) 以獲取更詳細的信息。 | ||||
|  | ||||
| | 輸入參數                  | 描述                                                  | 預設值 | | ||||
| | ------------------------- | ----------------------------------------------------- | ------ | | ||||
| | host                      | SSH 主機地址                                          |        | | ||||
| | port                      | SSH 埠號                                              | 22     | | ||||
| | passphrase                | SSH 金鑰密碼                                          |        | | ||||
| | username                  | SSH 使用者名稱                                        |        | | ||||
| | password                  | SSH 密碼                                              |        | | ||||
| | protocol                  | SSH 協議版本 (tcp, tcp4, tcp6)                        | tcp    | | ||||
| | sync                      | 如果有多個主機,啟用同步執行                          | false  | | ||||
| | use_insecure_cipher       | 包含更多不安全的加密算法                              | false  | | ||||
| | cipher                    | 允許的加密算法。如果未指定,則使用合理的預設值        |        | | ||||
| | timeout                   | SSH 連接主機的超時時間                                | 30s    | | ||||
| | command_timeout           | SSH 命令的超時時間                                    | 10m    | | ||||
| | key                       | SSH 私鑰的內容。例如,~/.ssh/id_rsa 的原始內容        |        | | ||||
| | key_path                  | SSH 私鑰的路徑                                        |        | | ||||
| | fingerprint               | 主機公鑰的 SHA256 指紋                                |        | | ||||
| | proxy_host                | SSH 代理主機                                          |        | | ||||
| | proxy_port                | SSH 代理埠號                                          | 22     | | ||||
| | proxy_protocol            | SSH 代理協議版本 (tcp, tcp4, tcp6)                    | tcp    | | ||||
| | proxy_username            | SSH 代理使用者名稱                                    |        | | ||||
| | proxy_password            | SSH 代理密碼                                          |        | | ||||
| | proxy_passphrase          | SSH 代理金鑰密碼                                      |        | | ||||
| | proxy_timeout             | SSH 連接代理主機的超時時間                            | 30s    | | ||||
| | proxy_key                 | SSH 代理私鑰的內容                                    |        | | ||||
| | proxy_key_path            | SSH 代理私鑰的路徑                                    |        | | ||||
| | proxy_fingerprint         | 代理主機公鑰的 SHA256 指紋                            |        | | ||||
| | proxy_cipher              | 代理允許的加密算法                                    |        | | ||||
| | proxy_use_insecure_cipher | 包含更多不安全的加密算法                              | false  | | ||||
| | script                    | 執行命令                                              |        | | ||||
| | script_path               | 從文件中執行命令                                      |        | | ||||
| | envs                      | 將環境變數傳遞給 shell 腳本                           |        | | ||||
| | envs_format               | 環境值傳遞的靈活配置                                  |        | | ||||
| | debug                     | 啟用調試模式                                          | false  | | ||||
| | allenvs                   | 將帶有 `GITHUB_` 和 `INPUT_` 前綴的環境變數傳遞給腳本 | false  | | ||||
| | request_pty               | 從伺服器請求偽終端                                    | false  | | ||||
|  | ||||
| **注意:** 用戶可以在他們的 shell 腳本中添加 `set -e` 以實現類似於已刪除的 `script_stop` 選項的功能。 | ||||
|  | ||||
| ## 用法 | ||||
|  | ||||
| 執行遠端 SSH 命令 | ||||
|  | ||||
| ```yaml | ||||
| name: remote ssh command | ||||
| on: [push] | ||||
| jobs: | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: executing remote ssh commands using password | ||||
|         uses: appleboy/ssh-action@v1.2.2 | ||||
|         with: | ||||
|           host: ${{ secrets.HOST }} | ||||
|           username: linuxserver.io | ||||
|           password: ${{ secrets.PASSWORD }} | ||||
|           port: ${{ secrets.PORT }} | ||||
|           script: whoami | ||||
| ``` | ||||
|  | ||||
| 畫面輸出 | ||||
|  | ||||
| ```sh | ||||
| ======CMD====== | ||||
| whoami | ||||
| ======END====== | ||||
| linuxserver.io | ||||
| =============================================== | ||||
| ✅ Successfully executed commands to all hosts. | ||||
| =============================================== | ||||
| ``` | ||||
|  | ||||
| ### 設置 SSH 金鑰 | ||||
|  | ||||
| 請在創建 SSH 金鑰並使用 SSH 金鑰時遵循以下步驟。最佳做法是在本地機器上創建 SSH 金鑰而不是遠端機器上。請使用 Github Secrets 中指定的用戶名登錄。生成 RSA 金鑰: | ||||
|  | ||||
| ### 生成 RSA 金鑰 | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### 生成 ed25519 金鑰 | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| 將新生成的金鑰添加到已授權的金鑰中。詳細了解已授權的金鑰請點擊[此處](https://www.ssh.com/ssh/authorized_keys/). | ||||
|  | ||||
| ### 將 RSA 金鑰添加到已授權金鑰中 | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| ### 將 ed25519 金鑰添加到已授權金鑰中 | ||||
|  | ||||
| ```bash | ||||
| cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys' | ||||
| ``` | ||||
|  | ||||
| 複製私鑰內容,然後將其粘貼到 Github Secrets 中。 | ||||
|  | ||||
| ### 複製 rsa 私鑰內容 | ||||
|  | ||||
| 在複製私鑰之前,請按照以下說明安裝 `clip` 命令: | ||||
|  | ||||
| ```bash | ||||
| # Ubuntu | ||||
| sudo apt-get install xclip | ||||
| ``` | ||||
|  | ||||
| 複製私鑰: | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_rsa | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_rsa | ||||
| ``` | ||||
|  | ||||
| 從包含註釋部分 `-----BEGIN OPENSSH PRIVATE KEY-----` 開始,到包含註釋部分 `-----END OPENSSH PRIVATE KEY-----` 結束,複製私鑰並將其粘貼到 GitHub Secrets 中。 | ||||
|  | ||||
| ### 複製 ed25519 私鑰內容 | ||||
|  | ||||
| ```bash | ||||
| # macOS | ||||
| pbcopy < ~/.ssh/id_ed25519 | ||||
| # Ubuntu | ||||
| xclip < ~/.ssh/id_ed25519 | ||||
| ``` | ||||
|  | ||||
| 有關無需密碼登錄 SSH 的詳細信息,請[參見該網站](http://www.linuxproblem.org/art_9.html)。 | ||||
|  | ||||
| **注意**:根據您的 SSH 版本,您可能還需要進行以下更改: | ||||
|  | ||||
| - 將公鑰放在 `.ssh/authorized_keys2` 中 | ||||
| - 將 `.ssh` 的權限更改為 700 | ||||
| - 將 `.ssh/authorized_keys2` 的權限更改為 640 | ||||
|  | ||||
| ### 如果你使用的是 OpenSSH | ||||
|  | ||||
| 如果您正在使用 OpenSSH,並出現以下錯誤: | ||||
|  | ||||
| ```bash | ||||
| ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey] | ||||
| ``` | ||||
|  | ||||
| 請確保您所選擇的密鑰演算法得到支援。在 Ubuntu 20.04 或更高版本上,您必須明確允許使用 SSH-RSA 演算法。請在 OpenSSH 守護進程文件中添加以下行(它可以是 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 中的一個附著文件): | ||||
|  | ||||
| ```bash | ||||
| CASignatureAlgorithms +ssh-rsa | ||||
| ``` | ||||
|  | ||||
| 或者,`Ed25519` 密鑰在 OpenSSH 中默認被接受。如果需要,您可以使用它來替代 RSA。 | ||||
|  | ||||
| ```bash | ||||
| ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" | ||||
| ``` | ||||
|  | ||||
| ### Example | ||||
|  | ||||
| #### 使用密碼執行遠端 SSH 命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using password | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     password: ${{ secrets.PASSWORD }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| #### 使用私鑰 | ||||
|  | ||||
| ```yaml | ||||
| - name: executing remote ssh commands using ssh key | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: whoami | ||||
| ``` | ||||
|  | ||||
| #### 多個命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: multiple command | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script: | | ||||
|       whoami | ||||
|       ls -al | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
| #### 從文件中執行命令 | ||||
|  | ||||
| ```yaml | ||||
| - name: file commands | ||||
|   uses: appleboy/ssh-action@v1.2.2 | ||||
|   with: | ||||
|     host: ${{ secrets.HOST }} | ||||
|     username: ${{ secrets.USERNAME }} | ||||
|     key: ${{ secrets.KEY }} | ||||
|     port: ${{ secrets.PORT }} | ||||
|     script_path: scripts/script.sh | ||||
| ``` | ||||
|  | ||||
| #### 多台主機 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com,bar.com" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 多個不同端口的主機 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
| -     host: "foo.com" | ||||
| +     host: "foo.com:1234,bar.com:5678" | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 在多個主機上同步執行 | ||||
|  | ||||
| ```diff | ||||
|   - name: multiple host | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: "foo.com,bar.com" | ||||
| +     sync: true | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 將環境變量傳遞到 Shell 腳本 | ||||
|  | ||||
| ```diff | ||||
|   - name: pass environment | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
| +   env: | ||||
| +     FOO: "BAR" | ||||
| +     BAR: "FOO" | ||||
| +     SHA: ${{ github.sha }} | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     envs: FOO,BAR,SHA | ||||
|       script: | | ||||
|         echo "I am $FOO" | ||||
|         echo "I am $BAR" | ||||
|         echo "sha: $SHA" | ||||
| ``` | ||||
|  | ||||
| _在 `env` 對象中,您需要將每個環境變量作為字符串傳遞,傳遞 `Integer` 數據類型或任何其他類型可能會產生意外結果。_ | ||||
|  | ||||
| #### 如何使用 `ProxyCommand` 連接遠程服務器? | ||||
|  | ||||
| ```bash | ||||
| +--------+       +----------+      +-----------+ | ||||
| | Laptop | <-->  | Jumphost | <--> | FooServer | | ||||
| +--------+       +----------+      +-----------+ | ||||
| ``` | ||||
|  | ||||
| 在您的 `~/.ssh/config` 文件中,您會看到以下內容。 | ||||
|  | ||||
| ```bash | ||||
| Host Jumphost | ||||
|   HostName Jumphost | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   IdentityFile ~/.ssh/keys/jump_host.pem | ||||
|  | ||||
| Host FooServer | ||||
|   HostName FooServer | ||||
|   User ubuntu | ||||
|   Port 22 | ||||
|   ProxyCommand ssh -q -W %h:%p Jumphost | ||||
| ``` | ||||
|  | ||||
| #### 如何將其轉換為 GitHubActions 的 YAML 格式? | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh proxy command | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     proxy_host: ${{ secrets.PROXY_HOST }} | ||||
| +     proxy_username: ${{ secrets.PROXY_USERNAME }} | ||||
| +     proxy_key: ${{ secrets.PROXY_KEY }} | ||||
| +     proxy_port: ${{ secrets.PROXY_PORT }} | ||||
|       script: | | ||||
|         mkdir abc/def | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 如何保護私鑰? | ||||
|  | ||||
| 密碼短語通常用於加密私鑰。這使得攻擊者無法單獨使用密鑰文件。文件泄露可能來自備份或停用的硬件,黑客通常可以從受攻擊系統中洩露文件。因此,保護私鑰非常重要。 | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     passphrase: ${{ secrets.PASSPHRASE }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| #### 使用主機指紋驗證 | ||||
|  | ||||
| 設置 SSH 主機指紋驗證可以幫助防止中間人攻擊。在設置之前,運行以下命令以獲取 SSH 主機指紋。請記得將 `ed25519` 替換為您的適當金鑰類型(`rsa`、 `dsa`等),而 `example.com` 則替換為您的主機。 | ||||
|  | ||||
| 現代 OpenSSH 版本中,需要提取的**默認金鑰**類型是 `rsa`(從版本 5.1 開始)、`ecdsa`(從版本 6.0 開始)和 `ed25519`(從版本 6.7 開始)。 | ||||
|  | ||||
| ```sh | ||||
| ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2 | ||||
| ``` | ||||
|  | ||||
| 現在您可以調整您的配置: | ||||
|  | ||||
| ```diff | ||||
|   - name: ssh key passphrase | ||||
|     uses: appleboy/ssh-action@v1.2.2 | ||||
|     with: | ||||
|       host: ${{ secrets.HOST }} | ||||
|       username: ${{ secrets.USERNAME }} | ||||
|       key: ${{ secrets.KEY }} | ||||
|       port: ${{ secrets.PORT }} | ||||
| +     fingerprint: ${{ secrets.FINGERPRINT }} | ||||
|       script: | | ||||
|         whoami | ||||
|         ls -al | ||||
| ``` | ||||
|  | ||||
| ## 貢獻 | ||||
|  | ||||
| 我們非常希望您為 `appleboy/ssh-action` 做出貢獻,歡迎提交請求! | ||||
|  | ||||
| ## 授權方式 | ||||
|  | ||||
| 本項目中的腳本和文檔采用 [MIT](LICENSE) 許可證 發布。 | ||||
							
								
								
									
										137
									
								
								action.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								action.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| name: "SSH Remote Commands" | ||||
| description: "Executing remote ssh commands" | ||||
| author: "Bo-Yi Wu" | ||||
| inputs: | ||||
|   host: | ||||
|     description: "SSH host address or IP to connect to." | ||||
|   port: | ||||
|     description: "SSH port number for the connection." | ||||
|     default: "22" | ||||
|   passphrase: | ||||
|     description: "Passphrase to decrypt the SSH private key if protected." | ||||
|   username: | ||||
|     description: "SSH username for authentication on the remote server." | ||||
|   password: | ||||
|     description: "SSH password for authentication (use secrets for sensitive data)." | ||||
|   protocol: | ||||
|     description: 'IP protocol version to use. Options: "tcp" (default), "tcp4" (IPv4 only), or "tcp6" (IPv6 only).' | ||||
|     default: "tcp" | ||||
|   sync: | ||||
|     description: "When true, executes commands synchronously across multiple hosts (one after another)." | ||||
|   use_insecure_cipher: | ||||
|     description: "Enable additional legacy ciphers that might be less secure but more compatible with older systems." | ||||
|   cipher: | ||||
|     description: "Specify custom cipher algorithms for encryption. Leave empty to use secure defaults." | ||||
|   timeout: | ||||
|     description: "Maximum time to wait when establishing the SSH connection, e.g., '30s', '1m'." | ||||
|     default: "30s" | ||||
|   command_timeout: | ||||
|     description: "Maximum execution time for the remote commands before terminating, e.g., '10m', '1h'." | ||||
|     default: "10m" | ||||
|   key: | ||||
|     description: "Raw content of the SSH private key for authentication (use secrets for sensitive data)." | ||||
|   key_path: | ||||
|     description: "Path to the SSH private key file on the runner." | ||||
|   fingerprint: | ||||
|     description: "SHA256 fingerprint of the host public key for verification to prevent MITM attacks." | ||||
|   proxy_host: | ||||
|     description: "Proxy server hostname or IP if connecting through an SSH jump host." | ||||
|   proxy_port: | ||||
|     description: "SSH port number for the proxy connection." | ||||
|     default: "22" | ||||
|   proxy_username: | ||||
|     description: "Username for authentication on the proxy server." | ||||
|   proxy_password: | ||||
|     description: "Password for authentication on the proxy server (use secrets for sensitive data)." | ||||
|   proxy_protocol: | ||||
|     description: 'IP protocol version for proxy. Options: "tcp" (default), "tcp4" (IPv4 only), or "tcp6" (IPv6 only).' | ||||
|     default: "tcp" | ||||
|   proxy_passphrase: | ||||
|     description: "Passphrase to decrypt the proxy SSH private key if protected." | ||||
|   proxy_timeout: | ||||
|     description: "Maximum time to wait when establishing the proxy SSH connection, e.g., '30s', '1m'." | ||||
|     default: "30s" | ||||
|   proxy_key: | ||||
|     description: "Raw content of the SSH proxy private key for authentication (use secrets for sensitive data)." | ||||
|   proxy_key_path: | ||||
|     description: "Path to the SSH proxy private key file on the runner." | ||||
|   proxy_fingerprint: | ||||
|     description: "SHA256 fingerprint of the proxy host public key for verification." | ||||
|   proxy_cipher: | ||||
|     description: "Specify custom cipher algorithms for proxy connection encryption." | ||||
|   proxy_use_insecure_cipher: | ||||
|     description: "Enable additional legacy ciphers for proxy connections (less secure but more compatible)." | ||||
|   script: | ||||
|     description: "Commands to execute on the remote server (inline script string)." | ||||
|   script_path: | ||||
|     description: "Path to a local file containing commands to execute on the remote server." | ||||
|   envs: | ||||
|     description: "Environment variables to expose to the remote script, format: key=value,key2=value2." | ||||
|   envs_format: | ||||
|     description: "Format specification for environment variable transfer (for advanced usage)." | ||||
|   debug: | ||||
|     description: "Set to true to enable verbose logging for troubleshooting connection issues." | ||||
|   allenvs: | ||||
|     description: "When true, passes all GitHub Actions environment variables to the remote script." | ||||
|   request_pty: | ||||
|     description: "Request a pseudo-terminal from the server (required for interactive commands or sudo)." | ||||
|   capture_stdout: | ||||
|     description: "When true, captures and returns standard output from the commands as action output." | ||||
|     default: "false" | ||||
|  | ||||
| outputs: | ||||
|   stdout: | ||||
|     description: "Standard output of the executed commands when capture_stdout is enabled." | ||||
|     value: ${{ steps.entrypoint.outputs.stdout }} | ||||
|  | ||||
| runs: | ||||
|   using: "composite" | ||||
|   steps: | ||||
|     - name: Set GitHub Path | ||||
|       run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH | ||||
|       shell: bash | ||||
|       env: | ||||
|         GITHUB_ACTION_PATH: ${{ github.action_path }} | ||||
|     - id: entrypoint | ||||
|       name: Run entrypoint.sh | ||||
|       run: entrypoint.sh | ||||
|       shell: bash | ||||
|       env: | ||||
|         GITHUB_ACTION_PATH: ${{ github.action_path }} | ||||
|         INPUT_HOST: ${{ inputs.host }} | ||||
|         INPUT_PORT: ${{ inputs.port }} | ||||
|         INPUT_PROTOCOL: ${{ inputs.protocol }} | ||||
|         INPUT_USERNAME: ${{ inputs.username }} | ||||
|         INPUT_PASSWORD: ${{ inputs.password }} | ||||
|         INPUT_PASSPHRASE: ${{ inputs.passphrase }} | ||||
|         INPUT_KEY: ${{ inputs.key }} | ||||
|         INPUT_KEY_PATH: ${{ inputs.key_path }} | ||||
|         INPUT_FINGERPRINT: ${{ inputs.fingerprint }} | ||||
|         INPUT_PROXY_HOST: ${{ inputs.proxy_host }} | ||||
|         INPUT_PROXY_PORT: ${{ inputs.proxy_port }} | ||||
|         INPUT_PROXY_USERNAME: ${{ inputs.proxy_username }} | ||||
|         INPUT_PROXY_PASSWORD: ${{ inputs.proxy_password }} | ||||
|         INPUT_PROXY_PASSPHRASE: ${{ inputs.proxy_passphrase }} | ||||
|         INPUT_PROXY_KEY: ${{ inputs.proxy_key }} | ||||
|         INPUT_PROXY_KEY_PATH: ${{ inputs.proxy_key_path }} | ||||
|         INPUT_PROXY_FINGERPRINT: ${{ inputs.proxy_fingerprint }} | ||||
|         INPUT_TIMEOUT: ${{ inputs.timeout }} | ||||
|         INPUT_PROXY_TIMEOUT: ${{ inputs.proxy_timeout }} | ||||
|         INPUT_COMMAND_TIMEOUT: ${{ inputs.command_timeout }} | ||||
|         INPUT_SCRIPT: ${{ inputs.script }} | ||||
|         INPUT_SCRIPT_FILE: ${{ inputs.script_path }} | ||||
|         INPUT_ENVS: ${{ inputs.envs }} | ||||
|         INPUT_ENVS_FORMAT: ${{ inputs.envs_format }} | ||||
|         INPUT_DEBUG: ${{ inputs.debug }} | ||||
|         INPUT_ALL_ENVS: ${{ inputs.allenvs }} | ||||
|         INPUT_REQUEST_PTY: ${{ inputs.request_pty }} | ||||
|         INPUT_USE_INSECURE_CIPHER: ${{ inputs.use_insecure_cipher }} | ||||
|         INPUT_CIPHER: ${{ inputs.cipher }} | ||||
|         INPUT_PROXY_USE_INSECURE_CIPHER: ${{ inputs.proxy_use_insecure_cipher }} | ||||
|         INPUT_PROXY_CIPHER: ${{ inputs.proxy_cipher }} | ||||
|         INPUT_SYNC: ${{ inputs.sync }} | ||||
|         INPUT_CAPTURE_STDOUT: ${{ inputs.capture_stdout }} | ||||
|  | ||||
| branding: | ||||
|   icon: "terminal" | ||||
|   color: "gray-dark" | ||||
| @@ -1,7 +1,77 @@ | ||||
| #!/bin/sh | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -eu | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| set -o pipefail | ||||
|  | ||||
| export GITHUB="true" | ||||
|  | ||||
| sh -c "/bin/drone-ssh $*" | ||||
| GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}" | ||||
| DRONE_SSH_RELEASE_URL="${DRONE_SSH_RELEASE_URL:-https://github.com/appleboy/drone-ssh/releases/download}" | ||||
| DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.8.1}" | ||||
|  | ||||
| function detect_client_info() { | ||||
|   if [ -n "${SSH_CLIENT_OS-}" ]; then | ||||
|     CLIENT_PLATFORM="${SSH_CLIENT_OS}" | ||||
|   else | ||||
|     local kernel | ||||
|     kernel="$(uname -s)" | ||||
|     case "${kernel}" in | ||||
|     Darwin) | ||||
|       CLIENT_PLATFORM="darwin" | ||||
|       ;; | ||||
|     Linux) | ||||
|       CLIENT_PLATFORM="linux" | ||||
|       ;; | ||||
|     Windows) | ||||
|       CLIENT_PLATFORM="windows" | ||||
|       ;; | ||||
|     *) | ||||
|       echo "Unknown, unsupported platform: ${kernel}." >&2 | ||||
|       echo "Supported platforms: Linux, Darwin and Windows." >&2 | ||||
|       echo "Bailing out." >&2 | ||||
|       exit 2 | ||||
|       ;; | ||||
|     esac | ||||
|   fi | ||||
|  | ||||
|   if [ -n "${SSH_CLIENT_ARCH-}" ]; then | ||||
|     CLIENT_ARCH="${SSH_CLIENT_ARCH}" | ||||
|   else | ||||
|     local machine | ||||
|     machine="$(uname -m)" | ||||
|     case "${machine}" in | ||||
|     x86_64* | i?86_64* | amd64*) | ||||
|       CLIENT_ARCH="amd64" | ||||
|       ;; | ||||
|     aarch64* | arm64*) | ||||
|       CLIENT_ARCH="arm64" | ||||
|       ;; | ||||
|     *) | ||||
|       echo "Unknown, unsupported architecture (${machine})." >&2 | ||||
|       echo "Supported architectures x86_64, i686, arm64." >&2 | ||||
|       echo "Bailing out." >&2 | ||||
|       exit 3 | ||||
|       ;; | ||||
|     esac | ||||
|   fi | ||||
| } | ||||
|  | ||||
| detect_client_info | ||||
| DOWNLOAD_URL_PREFIX="${DRONE_SSH_RELEASE_URL}/v${DRONE_SSH_VERSION}" | ||||
| CLIENT_BINARY="drone-ssh-${DRONE_SSH_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}" | ||||
| TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}" | ||||
| echo "Will download ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}" | ||||
| curl -fsSL --retry 5 --keepalive-time 2 "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o ${TARGET} | ||||
| chmod +x ${TARGET} | ||||
|  | ||||
| echo "======= CLI Version =======" | ||||
| sh -c "${TARGET} --version" # print version | ||||
| echo "===========================" | ||||
| if [[ "$INPUT_CAPTURE_STDOUT" == 'true' ]]; then | ||||
|   echo 'stdout<<EOF' >>$GITHUB_OUTPUT          # use heredoc for multiline output | ||||
|   sh -c "${TARGET} $*" | tee -a $GITHUB_OUTPUT # run the command | ||||
|   echo 'EOF' >>$GITHUB_OUTPUT | ||||
| else | ||||
|   sh -c "${TARGET} $*" # run the command | ||||
| fi | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 104 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/output-result.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								images/output-result.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 193 KiB | 
							
								
								
									
										7
									
								
								testdata/.ssh/id_ed25519
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								testdata/.ssh/id_ed25519
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| -----BEGIN OPENSSH PRIVATE KEY----- | ||||
| b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW | ||||
| QyNTUxOQAAACDoi7FltQCqpWporKh61nJUPIeazUYdzdstncoeU5XS2AAAAKBF5e2SReXt | ||||
| kgAAAAtzc2gtZWQyNTUxOQAAACDoi7FltQCqpWporKh61nJUPIeazUYdzdstncoeU5XS2A | ||||
| AAAEBrsLG1vSg08yaQgYM46KQW93Lz2ZikS1tTMH35gfHhpOiLsWW1AKqlamisqHrWclQ8 | ||||
| h5rNRh3N2y2dyh5TldLYAAAAFnlvdXJfZW1haWxAZXhhbXBsZS5jb20BAgMEBQYH | ||||
| -----END OPENSSH PRIVATE KEY----- | ||||
							
								
								
									
										1
									
								
								testdata/.ssh/id_ed25519.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								testdata/.ssh/id_ed25519.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOiLsWW1AKqlamisqHrWclQ8h5rNRh3N2y2dyh5TldLY your_email@example.com | ||||
							
								
								
									
										39
									
								
								testdata/.ssh/id_passphrase
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								testdata/.ssh/id_passphrase
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| -----BEGIN OPENSSH PRIVATE KEY----- | ||||
| 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 | ||||
| h55pSap77CEhEhE5FPZKuH9f7/E= | ||||
| -----END OPENSSH PRIVATE KEY----- | ||||
							
								
								
									
										1
									
								
								testdata/.ssh/id_passphrase.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								testdata/.ssh/id_passphrase.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuWKQh09Vlv3IRu/+oK18ws72VQS7PCXJaIEp1L+7HqC/6+plizaVgd9SjAg0UJSqvp+WfpU5I53hevE0Ip3s71Tsoeu1azWoi2Mbq3ycZ5ysh4htZZklKBkYsyW+2EdITPcmhA8rF+KiDRyuvk7fDo08G3YWgbCScY6VkLA06ReThCehAY54WNvgbx7lyvCWj1qYG0XjM7mTQHr3QN0JHJNdFaG3MCi1rTG2hK/owOlzcesIbzfM1VMIQG5HT4vNg/ULP0BTZ7pGtdvWlvR/660KQwc1tBxLqxI1dYoCgiS/gMyPxhOtNKTvhR/NR7e2sp/StkXURIxTHhj0KjKbnpXTQ2IndnesHAG9kDJ7c31SXastWpbXWhCIdRZk+KQsnmwobZlw3w1vfx2Dm7M2ZCcCgG/ArUPjY44nGOWO5Nz98QHyz3IocsKJXrGVo/3YpNNu72jkw7UGVMqh1dAe3ZMaCAC5pAAa0HKvkid7jdXawL2b//+vsAPSHdnEjP58= mtk10671@NB22040567 | ||||
							
								
								
									
										27
									
								
								testdata/.ssh/id_rsa
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								testdata/.ssh/id_rsa
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| -----BEGIN RSA PRIVATE KEY----- | ||||
| MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26 | ||||
| VbfAF0hIJji7ltvnYnqCU9oFfvEM33cTn7T96+od8ib/Vz25YU8ZbstqtIskPuwC | ||||
| bv3K0mAHgsviJyRD7yM+QKTbBQEgbGuW6gtbMKhiYfiIB4Dyj7AdS/fk3v26wDgz | ||||
| 7SHI5OBqu9bv1KhxQYdFEnU3PAtAqeccgzNpbH3eYLyGzuUxEIJlhpZ/uU2G9ppj | ||||
| /cSrONVPiI8Ahi4RrlZjmP5l57/sq1ClGulyLpFcMw68kP5FikyqHpHJHRBNgU57 | ||||
| 1y0Ph33SjBbs0haCIAcmreWEhGe+/OXnJe6VUQIDAQABAoIBAH97emORIm9DaVSD | ||||
| 7mD6DqA7c5m5Tmpgd6eszU08YC/Vkz9oVuBPUwDQNIX8tT0m0KVs42VVPIyoj874 | ||||
| bgZMJoucC1G8V5Bur9AMxhkShx9g9A7dNXJTmsKilRpk2TOk7wBdLp9jZoKoZBdJ | ||||
| jlp6FfaazQjjKD6zsCsMATwAoRCBpBNsmT6QDN0n0bIgY0tE6YGQaDdka0dAv68G | ||||
| R0VZrcJ9voT6+f+rgJLoojn2DAu6iXaM99Gv8FK91YCymbQlXXgrk6CyS0IHexN7 | ||||
| V7a3k767KnRbrkqd3o6JyNun/CrUjQwHs1IQH34tvkWScbseRaFehcAm6mLT93RP | ||||
| muauvMECgYEA9AXGtfDMse0FhvDPZx4mx8x+vcfsLvDHcDLkf/lbyPpu97C27b/z | ||||
| ia07bu5TAXesUZrWZtKA5KeRE5doQSdTOv1N28BEr8ZwzDJwfn0DPUYUOxsN2iIy | ||||
| MheO5A45Ko7bjKJVkZ61Mb1UxtqCTF9mqu9R3PBdJGthWOd+HUvF460CgYEA7QRf | ||||
| Z8+vpGA+eSuu29e0xgRKnRzed5zXYpcI4aERc3JzBgO4Z0er9G8l66OWVGdMfpe6 | ||||
| CBajC5ToIiT8zqoYxXwqJgN+glir4gJe3mm8J703QfArZiQrdk0NTi5bY7+vLLG/ | ||||
| knTrtpdsKih6r3kjhuPPaAsIwmMxIydFvATKjLUCgYEAh/y4EihRSk5WKC8GxeZt | ||||
| oiZ58vT4z+fqnMIfyJmD5up48JuQNcokw/LADj/ODiFM7GUnWkGxBrvDA3H67WQm | ||||
| 49bJjs8E+BfUQFdTjYnJRlpJZ+7Zt1gbNQMf5ENw5CCchTDqEq6pN0DVf8PBnSIF | ||||
| KvkXW9KvdV5J76uCAn15mDkCgYA1y8dHzbjlCz9Cy2pt1aDfTPwOew33gi7U3skS | ||||
| RTerx29aDyAcuQTLfyrROBkX4TZYiWGdEl5Bc7PYhCKpWawzrsH2TNa7CRtCOh2E | ||||
| R+V/84+GNNf04ALJYCXD9/ugQVKmR1XfDRCvKeFQFE38Y/dvV2etCswbKt5tRy2p | ||||
| xkCe/QKBgQCkLqafD4S20YHf6WTp3jp/4H/qEy2X2a8gdVVBi1uKkGDXr0n+AoVU | ||||
| ib4KbP5ovZlrjL++akMQ7V2fHzuQIFWnCkDA5c2ZAqzlM+ZN+HRG7gWur7Bt4XH1 | ||||
| 7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA== | ||||
| -----END RSA PRIVATE KEY----- | ||||
							
								
								
									
										1
									
								
								testdata/.ssh/id_rsa.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								testdata/.ssh/id_rsa.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDh7YP+o83TynNNpz5rxmaU/XOIk5eTjkLKcw+29rSu0r9EHbpVt8AXSEgmOLuW2+dieoJT2gV+8QzfdxOftP3r6h3yJv9XPblhTxluy2q0iyQ+7AJu/crSYAeCy+InJEPvIz5ApNsFASBsa5bqC1swqGJh+IgHgPKPsB1L9+Te/brAODPtIcjk4Gq71u/UqHFBh0USdTc8C0Cp5xyDM2lsfd5gvIbO5TEQgmWGln+5TYb2mmP9xKs41U+IjwCGLhGuVmOY/mXnv+yrUKUa6XIukVwzDryQ/kWKTKoekckdEE2BTnvXLQ+HfdKMFuzSFoIgByat5YSEZ7785ecl7pVR drone-scp@localhost | ||||
							
								
								
									
										50
									
								
								testdata/.ssh/test
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								testdata/.ssh/test
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| -----BEGIN OPENSSH PRIVATE KEY----- | ||||
| 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 | ||||
| l4njcaMpg4tpQMHtCBOicGyV0= | ||||
| -----END OPENSSH PRIVATE KEY----- | ||||
							
								
								
									
										1
									
								
								testdata/.ssh/test.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								testdata/.ssh/test.pub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDz6aZ1jY2onnuj2YNHJ/HhfvIu0B973v/+pFFOavnTUOhEEKEy3TASu+s9CkHrYZAtRc+QYIkNZI31mhHBhotdeP/7GoO2UirkFtrzyQKPNJxEcv0RBoG9ssN8jex0PyK6DHIYYFnIWadVBEEOh/H+rK7j7u2/big3oTzYBuFrCwmYFcz5na99MzFeAUhazF44gVBma+zO+1quGeqF51UDIg1SMGvX8I7LNEqrKEBaIUQJKFQcxlOWlRLQsjJCymrOujsXsRrXHAQWcnxDcNevv2ZMOUl0ybvv9yH0BiGbRBd1Hy8/QPILbAQaqu0oQE7fubN8Q8lqb3Jg0loID4x/5GPhSY8WAXpuLcXTOrb93SnCw1JsAgJDNqpuuRFy3BSZ7wBOr1jfeIoo7xk14OHiUjJ0uXDL9cLMkcw6ElWz81mrD2VCkXUz+qFyjJ+G7aGWRtctZoOzKln4yfNfUmwW8/8ra3QnmrMZ2xW2Ylw3ZhO+tLi7jINHYFb54bAdLVPUU1ctIuJns2qkWnjJCxxMiynIqCif20/OU1n8CTJuOWiURmRdmvKOH4PE3JxC2Qnk/3tV3Cf8hp1CH5VjBZ9AjGj5MDMHXyu34VY2WvYo5QyzfS3ySPoT8kCO0G0xpvjwCMHOK+G2RP4kqb/KKZguiKdgintBXuskTlJmD7kcMQ== deploy@easyssh | ||||
							
								
								
									
										3
									
								
								testdata/test.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								testdata/test.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -e | ||||
| whoami | ||||
		Reference in New Issue
	
	Block a user