From a12ee4cfc5cfbcb3d616d3fcef34b7aef9badbc9 Mon Sep 17 00:00:00 2001 From: Allan Eising Date: Mon, 1 Jul 2024 12:15:54 +0200 Subject: [PATCH] Initial commit --- Dockerfile | 9 ++++++++ LICENSE | 33 ++++++++++++++++++++++++++++ README.md | 29 +++++++++++++++++++++++++ action.yml | 45 ++++++++++++++++++++++++++++++++++++++ entrypoint.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 action.yml create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1a94054 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:3.20 + +RUN apk --update add git-crypt git-lfs openssh bash + +WORKDIR /gitea/workspace + +COPY entrypoint.sh . + +ENTRYPOINT ["/gitea/workspace.sh"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9e0b0be --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ +BSD 4-Clause License + +Copyright (c) 2020, Aleksandr Derbenev +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. All advertising materials mentioning features or use of this software must + display the following acknowledgement: + This product includes software developed by Aleksandr Derbenev. + +4. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..55a1d4f --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# gitea-action-git-crypt-ssh-deploy + +This action decrypts a repository that has been encrypted with git-crypt, and then deploys a docker-compose-based project. + +## Inputs + +* `ssh_private_key` - Private SSH key. Please keep this secure! +* `git_crypt_key` - Base64 encoded git-crypt key, see below. Must also be kept secure! +* `ssh_host` - Remote host to ssh to, where the project will be deployed. +* `ssh_port` - SSH port for the remote host. Defaults to 22. +* `ssh_user` - Username to use when connecting to the remote host. +* `docker_compose_project` - Name of the docker compose project. This will be used as the prefix by docker. +* `docker_compose_filename` - The filename of the compose file. Defaults to docker-compose.yml +* `docker_compose_down` - if set to `true`, the action will execute `docker compose down`. + +## Getting the git crypt key +The key can be extracted from an unlocked repository with the following command: + +``` +git-crypt export-key - | base64 +``` + +## Acknowledgement + +This action is a combination of these two existing github actions: + +- https://github.com/sliteteam/github-action-git-crypt-unlock +- https://github.com/matiasnu/github-action-ssh-docker-compose + diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..bb5cf59 --- /dev/null +++ b/action.yml @@ -0,0 +1,45 @@ +name: Git-Crypt-SSH-Deploy +description: Action to unlock git-crypt repository and deploy docker compose project. +author: "Allan Eising" +branding: + icon: "unlock" + color: "green" + +inputs: + ssh_private_key: + description: "Private SSH key used for logging into remote system." + required: true + git_crypt_key: + description: "Base64 encoded key to decrypt repository." + ssh_host: + description: Host to deploy to. + required: true + ssh_port: + description: SSH Port + default: 22 + required: true + ssh_user: + description: Remote user name. + required: true + docker_compose_project: + description: Compose project name + required: true + docker_compose_filename: + description: Compose file to use + default: docker-compose.yml + docker_compose_down: + description: Undeploy project instead of creating it ("true" or "false"). + default: "false" + +runs: + using: docker + image: Dockerfile + env: + SSH_PRIVATE_KEY: ${{ inputs.ssh_private_key }} + GIT_CRYPT_KEY: ${{ inputs.git_crypt_key }} + SSH_HOST: ${{ inputs.ssh_host }} + SSH_PORT: ${{ inputs.ssh_port }} + SSH_USER: ${{ inputs.ssh_user }} + DOCKER_COMPOSE_PRJECT: ${{ inputs.docker_compose_project }} + DOCKER_COMPOSE_FILENAME: ${{ inputs.docker_compose_filename }} + DOCKER_COMPOSE_DOWN: ${{ inputs.docker_compose_down }} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..cf35117 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +set -eu + + +log() { + echo ">> [local]" $@ +} + +cleanup() { + set +e + log "Killing ssh agent." + ssh-agent -k + log "Removing workspace archive." + rm -f /tmp/workspace.tar.bz2 +} + +trap cleanup EXIT + +unlock() { + log "Unlocking encrypted git repository" + echo "${GIT_CRYPT_KEY}" | base64 -d > ./git-crypt-key + git-crypt unlock ./git-crypt-key + rm ./git-crypt-key +} + + +compress_workdir() { + log "Packing workspace into archive to transfer to remove machine." + tar jcvf /tmp/workspace.tar.bz2 --exclude .git --exclude vendor . +} + +start_ssh_agent() { + log "Launching SSH agent" + eval $(ssh-agent -s) + ssh-add <(echo "$SSH_PRIVATE_KEY") +} + +compose_run() { + local remote_command="set -e ; log() { echo '>> [remote]' \$@ ; } ; cleanup() { log 'Removing workspace...'; rm -rf \"\$HOME/workspace\" ; } ; log 'Creating workspace directory...' ; mkdir -p \"\$HOME/workspace\" ; trap cleanup EXIT ; log 'Unpacking workspace...' ; tar -C \"\$HOME/workspace\" -xjv ; log 'Launching docker compose...' ; cd \"\$HOME/workspace\" ; docker compose -f \"$DOCKER_COMPOSE_FILENAME\" -p \"$DOCKER_COMPOSE_PROJECT\" pull ; docker compose -f \"$DOCKER_COMPOSE_FILENAME\" -p \"$DOCKER_COMPOSE_PREFIX\" up -d --remove-orphans --build" + + if "$DOCKER_COMPOSE_DOWN"; then + remote_command="set -e ; log() { echo '>> [remote]' \$@ ; } ; cleanup() { log 'Removing workspace...'; rm -rf \"\$HOME/workspace\" ; } ; log 'Creating workspace directory...' ; mkdir -p \"\$HOME/workspace\" ; trap cleanup EXIT ; log 'Unpacking workspace...' ; tar -C \"\$HOME/workspace\" -xjv ; log 'Launching docker compose...' ; cd \"\$HOME/workspace\" ; docker compose -f \"$DOCKER_COMPOSE_FILENAME\" -p \"$DOCKER_COMPOSE_PROJECT\" down" + fi + ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "$SSH_USER@$SSH_HOST" -p "$SSH_PORT" \ + "$remote_command" \ + < /tmp/workspace.tar.bz2 +} + +if [ -n "${RUN_DIR:-}" ]; then + cd ${RUN_DIR} + log "Running action from ${RUN_DIR}" +fi + +log "Starting deployment main function." +unlock +compress_workdir +start_ssh_agent +compose_run