From 9a01d83f0af7dc5c21dc145a10f0a2980f9ee2dc Mon Sep 17 00:00:00 2001 From: Rui Hu Date: Mon, 9 Jun 2025 14:59:16 +0800 Subject: [PATCH] first demo --- .forgejo/workflows/render-and-commit.yaml | 55 +++++++++++++++++++++++ .gitignore | 2 + README.md | 18 +++++++- gomplate-ci.yaml | 7 +++ gomplate.yaml | 7 +++ prod-config.enc.yaml | 37 +++++++++++++++ render-stack.sh | 36 +++++++++++++++ templates/docker-stack.base.yml | 10 +++++ 8 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 .forgejo/workflows/render-and-commit.yaml create mode 100644 .gitignore create mode 100644 gomplate-ci.yaml create mode 100644 gomplate.yaml create mode 100644 prod-config.enc.yaml create mode 100755 render-stack.sh create mode 100644 templates/docker-stack.base.yml diff --git a/.forgejo/workflows/render-and-commit.yaml b/.forgejo/workflows/render-and-commit.yaml new file mode 100644 index 0000000..ba00af3 --- /dev/null +++ b/.forgejo/workflows/render-and-commit.yaml @@ -0,0 +1,55 @@ +name: "Render stack" +on: + push: + pull_request: +env: + DEBIAN_FRONTEND: noninteractive + TZ: UTC + DOCKER_HOST: "tcp://docker:2375" + DOCKER_TLS_VERIFY: "" + +jobs: + stack-test: + runs-on: general + container: + image: ubuntu:24.04 + services: + docker: + image: docker:dind + cmd: + - "dockerd" + - "-H" # we need this one to offer a docker socket to the job + - "tcp://0.0.0.0:2375" + - "-H" # we need this one to offer a docker socket on disk + - "unix:///var/run/docker.sock" + - "--tls=false" + steps: + # need to setup node and git + - run: | + apt-get update + apt-get install -y nodejs git curl jq sops age + # check out code + - uses: actions/checkout@v4 + with: + submodules: false + # setup docker + - name: set up docker cli + run: | + apt-get install -y ca-certificates curl dnsutils + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null + apt-get update + apt-get install docker-ce-cli docker-buildx-plugin docker-compose-plugin + # render stack + - name: Render stack + run: | + ./render-stack.sh + + - name: Cat + run: | + cat compose.prod.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b9d7b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +compose.prod.yaml diff --git a/README.md b/README.md index 8eee5e7..43f6724 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ # deployment-source -Demo repo for deployment. This one is the source repo that contains the dynamic templates. \ No newline at end of file +Demo repo for deployment, for clevermicro repos and swarm-cd. This repo will demo how to render the stack file with encrypted secrects and how to commit to the target repo and make PR. This is all down by the pipeline. + +The encrypted file is `prod-config.enc.yaml`. Currently it is encrypted by SOPS with AGE, here is the recipient list: + ++ age1kj66pvftzmz7t7klnghacleymtmj2szckkc50dvq8yldqp2gavpsegrfvl (Rui Hu) ++ age18rl4xxj6m55u44k82vwleurx5d5xhf5vj84n3ewg9rj5nh69rsjsjzqw66 (test key, the private key is `AGE-SECRET-KEY-1DEACUTGUPQWVPR29MVM3LV8JMW8RXS8A4UC2QGERN3VAQ225Z6XQN36C5D`, this is only for testing!!!) ++ age18ust9l2rx59n9t6h9chpqvhm3j5kc9p75rpxefm83w95s7fqq59qxjzfuj (pipeline runner) + +For VSC, use extension: https://marketplace.visualstudio.com/items/?itemName=signageos.signageos-vscode-sops to automatically +decrypt the sops file, by placing your private age key in `~/.config/sops/age/keys.txt` (one private key per line, with `#` for comments). +This is similar to `sops prod-config.enc.yaml` but instead of vm, you got vsc. + +The script to render the stack file: `render-stack.sh`, it will call gomplate and renders the final stack file to `compose.prod.yaml` + +Runner env var: + ++ `SOPS_AGE_KEY`: The private key for container \ No newline at end of file diff --git a/gomplate-ci.yaml b/gomplate-ci.yaml new file mode 100644 index 0000000..b2e0513 --- /dev/null +++ b/gomplate-ci.yaml @@ -0,0 +1,7 @@ +inputDir: ./templates/ +outputDir: ./ +leftDelim: (( +rightDelim: )) +# allow others to read and write, workaround for docker permission +chmod: 666 + diff --git a/gomplate.yaml b/gomplate.yaml new file mode 100644 index 0000000..3fd1798 --- /dev/null +++ b/gomplate.yaml @@ -0,0 +1,7 @@ +inputDir: /data/templates/ +outputDir: /data/ +leftDelim: (( +rightDelim: )) +# allow others to read and write, workaround for docker permission +chmod: 666 + diff --git a/prod-config.enc.yaml b/prod-config.enc.yaml new file mode 100644 index 0000000..88d356c --- /dev/null +++ b/prod-config.enc.yaml @@ -0,0 +1,37 @@ +whoami: + port: + http: ENC[AES256_GCM,data:0ac7Wg==,iv:auZwIXo9vvoLEtLGZYwyA/7xAaswdqIX8E/NYnFa3xQ=,tag:jke5bY+XLAxhjJwo0yr78A==,type:int] + deployReplica: ENC[AES256_GCM,data:Nw==,iv:a2rBG4vu7ikoXLfWrVLk27leX9RIb4DhWR5HrbHQO5w=,tag:viN9V+fFnS18UpjdHA7Wkg==,type:int] +sops: + age: + - recipient: age1kj66pvftzmz7t7klnghacleymtmj2szckkc50dvq8yldqp2gavpsegrfvl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRjVyaitIZGlGU3QrMFdy + Mm8zQ3JORVZ0anNsZDJWZkh3WWVFSy94ZkRjCkRoaGtXSmd6UEFvMEFMRW1BbVBz + dW5iY1RNVmZNVnNNdFR4UHBwcDNOUUkKLS0tIE9ZTGJUUWMxT0NhZGdkbk83Rnd3 + UlhqYmdwV0dJcG92aTZ1SmovT2cveVUKgHGFMXTzan0dgfPo95388lrH1hMCbkos + jKG8JZ22qZCWEWR3a6tiN1/aQZ6UJMfoFXQN0dcuwZ7gV4LmEQpW7Q== + -----END AGE ENCRYPTED FILE----- + - recipient: age18rl4xxj6m55u44k82vwleurx5d5xhf5vj84n3ewg9rj5nh69rsjsjzqw66 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqK2YzQ2xHbmViblNlT2JF + RDdrTVkyQzYwSlZVOXRmeVNzOXBoc2QyWmhjClhaWUxac3NqRUtwMFR3K0tiQjZV + RnVmcVY0RG1iRFJ5SHU4NmtHc1dzQVkKLS0tIHozK2ZURmM1SEdveFQzYUtoRDVv + SCtUbTFxWEVFbno4MldHaTNOUHdYRzQKz5lYkbOMNmKxIao0Kcx1s3xd6zJ4s+Kf + xm5hzijlg78arsIGOJxmmrP/lkeQWLysWaF8IauAh0goZKymOjTh7A== + -----END AGE ENCRYPTED FILE----- + - recipient: age18ust9l2rx59n9t6h9chpqvhm3j5kc9p75rpxefm83w95s7fqq59qxjzfuj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOeWtDcDdIS3NvMDN3Q2li + ZFF5Z3BoUG9TemFGWGlleCs4ZUVIUzVnL1hnCnFacitvQkhPZEVwOFM1Mml2TmxH + YVV1RkZQSGRmV05qelMza0MwUTZyTG8KLS0tIFRUc3RSZmFOY2V1NHBVR2p4bFBm + ZTFsTFpwcjBIaEp5UmJqYWdKNTlyVncK88IrSaBnVz34oiWpeyvYHLFDJ11wH31Y + gf3nlORVIe1MhMMkBgukOVJ8P1aiKN5ZUgdXz+dD2Ze5hG0q5HF/LQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-09T06:56:22Z" + mac: ENC[AES256_GCM,data:njQcK5UjACvRac8oUezgK2v4FtSNL0JgBmqMmvNuYTnPsv5oZItURfXI+6AByFjyquLr25u9rW6zaCtSSecJhz1BSKTRnw5gRGleI75RDV4eCu9CCTR5u/Vpd/bbbAhagzAxzuXDCuCp1aMo6kUqb7EIHaM5QSb6f7HALb85MZw=,iv:bsu/yEfAr0ZTEZRYD3tymkx61JPg8mKXTRKL1HeW1+o=,tag:tP89H0eBK2hbWEtRYFhVRA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/render-stack.sh b/render-stack.sh new file mode 100755 index 0000000..09e12b0 --- /dev/null +++ b/render-stack.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e + +RENDER_PROFILE=prod + +sops decrypt $RENDER_PROFILE-config.enc.yaml > $RENDER_PROFILE-config.yaml + +dockerContext=$(docker context inspect default | jq -r .[0].Endpoints.docker.Host) +if [[ $dockerContext == unix://* ]]; then # docker daemon runs on the same machine + # use gomplate to render profiles + docker run --rm -v .:/data hairyhenderson/gomplate:v4.3.1 --config /data/gomplate.yaml -c config=/data/$RENDER_PROFILE-config.yaml + # invoke twice to fix file permission issue + docker run --rm -v .:/data hairyhenderson/gomplate:v4.3.1 --config /data/gomplate.yaml -c config=/data/$RENDER_PROFILE-config.yaml +else # docker won't work, possibly in ci + curl -o /usr/local/bin/gomplate -sSL https://github.com/hairyhenderson/gomplate/releases/download/v4.3.1/gomplate_linux-amd64 + chmod 755 /usr/local/bin/gomplate + /usr/local/bin/gomplate --config gomplate-ci.yaml -c config=$RENDER_PROFILE-config.yaml +fi + +rm -f $RENDER_PROFILE-config.yaml + +# check each profile to make sure they exists +# and convert to the cli +CONFIG_FILES=("-c" "docker-stack.base.yml") +# preview the full stack +echo "Stack config preview:" +cmd=(docker stack config "${CONFIG_FILES[@]}") +if "${cmd[@]}"; then + echo "The above config will be used" +else + echo "Command failed!" + exit 1 +fi + +"${cmd[@]}" > compose.$RENDER_PROFILE.yaml +rm -f docker-stack.*.yml diff --git a/templates/docker-stack.base.yml b/templates/docker-stack.base.yml new file mode 100644 index 0000000..605402d --- /dev/null +++ b/templates/docker-stack.base.yml @@ -0,0 +1,10 @@ +version: "3.8" + +services: + whoami: + image: traefik/whoami + ports: + - "((.config.whoami.port.http)):80" + deploy: + mode: replicated + replicas: ((.config.whoami.deployReplica))