From 5018c2e0dffcb3229e7aec44ce9fcad796748819 Mon Sep 17 00:00:00 2001 From: Max Mehl Date: Fri, 18 Sep 2026 18:46:20 +0200 Subject: [PATCH] init --- .sops.yaml | 3 +++ .woodpecker.yml | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile.app | 6 +++++ Dockerfile.db | 5 ++++ compose.yaml | 15 ++++++++++++ secrets.prod.env | 9 ++++++++ 6 files changed, 98 insertions(+) create mode 100644 .sops.yaml create mode 100644 .woodpecker.yml create mode 100644 Dockerfile.app create mode 100644 Dockerfile.db create mode 100644 compose.yaml create mode 100644 secrets.prod.env diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..b978c51 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,3 @@ +creation_rules: + - path_regex: secrets\.prod\.env$ + age: age14r2lmce367dmp4gl9lcf0tkdttc3aaqql4ymphpj5lcqeg9vjpzqz3pqp9 diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..1b0947a --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,60 @@ +steps: + - name: build-db + image: woodpeckerci/plugin-docker-buildx + settings: + repo: registry.ci.poc.mehl.mx/poc/dummy-service-db + dockerfile: Dockerfile.db + tag: ${CI_COMMIT_SHA:0:8} + registry: registry.ci.poc.mehl.mx + username: + from_secret: zot_username + password: + from_secret: zot_password + + - name: build-app + image: woodpeckerci/plugin-docker-buildx + settings: + repo: registry.ci.poc.mehl.mx/poc/dummy-service-app + dockerfile: Dockerfile.app + tag: ${CI_COMMIT_SHA:0:8} + registry: registry.ci.poc.mehl.mx + username: + from_secret: zot_username + password: + from_secret: zot_password + + - name: publish-deployment-artifact + image: alpine:3.20 + environment: + REGISTRY: registry.ci.poc.mehl.mx + IMAGE_TAG: ${CI_COMMIT_SHA:0:8} + SOURCE_COMMIT: ${CI_COMMIT_SHA} + ZOT_USERNAME: + from_secret: zot_username + ZOT_PASSWORD: + from_secret: zot_password + commands: + - apk add --no-cache oras + - mkdir -p /tmp/deploy-bundle + - cp compose.yaml secrets.prod.env /tmp/deploy-bundle/ + - echo "IMAGE_TAG=${IMAGE_TAG}" > /tmp/deploy-bundle/release.env + - echo "SOURCE_COMMIT=${SOURCE_COMMIT}" >> /tmp/deploy-bundle/release.env + - echo "REGISTRY=${REGISTRY}" >> /tmp/deploy-bundle/release.env + - oras login "${REGISTRY}" -u "${ZOT_USERNAME}" -p "${ZOT_PASSWORD}" + - cd /tmp/deploy-bundle && oras push "${REGISTRY}/poc/deploy/dummy-service:${IMAGE_TAG}" compose.yaml secrets.prod.env release.env + + - name: trigger-deployment + image: woodpeckerci/plugin-trigger + settings: + repositories: + - mxmehl/deployments + deploy: production + params: + - ARTIFACT=registry.ci.poc.mehl.mx/poc/deploy/dummy-service:${CI_COMMIT_SHA:0:8} + - TARGET=target1 + token: + from_secret: woodpecker_trigger_token + +when: + branch: ${CI_REPO_DEFAULT_BRANCH} + event: push diff --git a/Dockerfile.app b/Dockerfile.app new file mode 100644 index 0000000..4b4c750 --- /dev/null +++ b/Dockerfile.app @@ -0,0 +1,6 @@ +# Dummy "app" container for the PoC. Not a real application - proves that +# both the shared DB_PASSWORD and its own APP_PASSWORD secret reach it +# correctly, by logging (masked) evidence on startup, then staying up. +FROM alpine:3.20 + +CMD ["sh", "-c", "for v in DB_PASSWORD APP_PASSWORD; do val=$(eval echo \\$$v); if [ -n \"$val\" ]; then echo \"$v: received (redacted)\"; else echo \"$v: MISSING\"; fi; done; sleep infinity"] diff --git a/Dockerfile.db b/Dockerfile.db new file mode 100644 index 0000000..990d8cf --- /dev/null +++ b/Dockerfile.db @@ -0,0 +1,5 @@ +# Dummy "database" container for the PoC. Not a real database - just proves +# that a secret env var (DB_ROOT_PASSWORD) reaches this container correctly. +FROM alpine:3.20 + +CMD ["sh", "-c", "if [ -n \"$DB_ROOT_PASSWORD\" ]; then echo 'DB_ROOT_PASSWORD: received (redacted)'; else echo 'DB_ROOT_PASSWORD: MISSING'; fi; sleep infinity"] diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..3284682 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,15 @@ +services: + db: + image: ${REGISTRY:?err}/poc/dummy-service-db:${IMAGE_TAG:?err} + restart: unless-stopped + environment: + DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?err} + + app: + image: ${REGISTRY:?err}/poc/dummy-service-app:${IMAGE_TAG:?err} + restart: unless-stopped + depends_on: + - db + environment: + DB_PASSWORD: ${DB_PASSWORD:?err} + APP_PASSWORD: ${APP_PASSWORD:?err} diff --git a/secrets.prod.env b/secrets.prod.env new file mode 100644 index 0000000..ba4cba1 --- /dev/null +++ b/secrets.prod.env @@ -0,0 +1,9 @@ +DB_ROOT_PASSWORD=ENC[AES256_GCM,data:v7SL0WSvL2nRy1JUi0lHnx23V58Mzw==,iv:GnTwZeQA9XL5oAXO0rrSjkQrwsS2ITOZ9BzWKkDEUMI=,tag:DluClErQnXzppkWzUODpBA==,type:str] +DB_PASSWORD=ENC[AES256_GCM,data:DhvyDY8LuglX2cd2UujygUZXuSw=,iv:qEFuyR4orvPf0HvsGUCiOftyCKGCMXu7I7dFI4SLZaw=,tag:3o/OD4eaj1uDxKv9ORJUFA==,type:str] +APP_PASSWORD=ENC[AES256_GCM,data:VuGscm+j9ADALZGWp3vO+xnK9S5b,iv:Xk215wjl6KKzs58jR1wj/GNtkreIu2uoVOMXKI2EfFY=,tag:SIabyKRgtYdxXaA95l0bww==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4NUsxM3JiTHBkWTdPclYv\nY1FvL0ZBcEIrTlhPb25teTlzdHg1NkY3WlRvCnNFYW8vSGV5Y3I0OGtCai9SREs2\nMGlzMGRxL0Q2YmdIUFJLbTFET2VqbUEKLS0tIEsvMC9WeXBrU3VhemtUMGd0NERo\nZ2VsVmxHUWVXUkJtd3JFUEtzcXkxeXcKBJiGxzToQOlpq/nNt9S4lwvh70SZ5t5f\nPeXW49a4/oXAvLuDcJtN8QmqQgCNbgnqhZZGvMxfuyELHNPolHhhVw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_0__map_recipient=age14r2lmce367dmp4gl9lcf0tkdttc3aaqql4ymphpj5lcqeg9vjpzqz3pqp9 +sops_lastmodified=2026-09-18T15:44:35Z +sops_mac=ENC[AES256_GCM,data:BWdvcGLzhrFpgs/J41t5NA4SlvxZi75LQ5VWJlkS0hK2LvmO6JV2ojl8mtHkl+8ObR4yBd2PI4Aq4MO6+z4KVNWMQIiKIg/nfjUhFaaeNpt7LBpItX6HzAcfDST4O6Nh0Wcudx46sHwolHM7dy5GlD4Es0dGNWDRnUozPnpNyaM=,iv:V4GNwdu+4PT6yM2FsJfTNqyxKX4E5fb73R+0gMg6kSc=,tag:24hDwSkbBmvO+4wL8dvUPg==,type:str] +sops_unencrypted_suffix=_unencrypted +sops_version=3.13.3