{"id":24624945,"url":"https://github.com/timball/sops-age-git-example","last_synced_at":"2026-04-17T05:31:50.020Z","repository":{"id":180028009,"uuid":"664370675","full_name":"timball/sops-age-git-example","owner":"timball","description":"testing encrypting passwd with sops and git","archived":false,"fork":false,"pushed_at":"2023-08-31T00:28:12.000Z","size":13,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T07:42:47.356Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timball.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-09T19:13:32.000Z","updated_at":"2023-07-25T23:53:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"f76907d3-b75b-46a9-9442-2bb742e43190","html_url":"https://github.com/timball/sops-age-git-example","commit_stats":null,"previous_names":["timball/sops-age-git-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/timball/sops-age-git-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timball%2Fsops-age-git-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timball%2Fsops-age-git-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timball%2Fsops-age-git-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timball%2Fsops-age-git-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timball","download_url":"https://codeload.github.com/timball/sops-age-git-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timball%2Fsops-age-git-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31916757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-25T04:12:14.260Z","updated_at":"2026-04-17T05:31:50.015Z","avatar_url":"https://github.com/timball.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# git + sops + age + secrets\n\n#### --timball@gmail.com\n#### Sun  9 Jul 21:41:48 EDT 2023\n\n## overview\nWe are trying to setup a repo with sane password storage and not be a big PITA to use. \nWhile it is debatable if we want to upload passwords to a git repot at all, we can\nall agree that we should never upload unencrypted passwords. \n\nIn these examples we'll be using `sops` and `age` to do the encryption. We wrote some bash scripts\nto run as git filters such that on the local filesystem files can be decrypted\nand will automatically be encrypted before being committed.\n\ngit commits and diffs should work as expected. \nAll secrets stored in git will be encrypted, but the local copies will be in clear text if you have the right key\n\nWe admit that using Hashicorp Vault, AWS KMS, or GCP KMS would be the better way to go, but this is for a quick and dirty. Maybe next repo I do is how to set this up w/ a cloud based secrets manager.\n\n## setup\n0. `git init` a repo or however you want to create a repo\n\n1. Create an `age` key, and export the public-key and make sure to put\n`age-key.txt` into `.gitignore` add public key to repo. NOTICE! This means that\nthe `secrets/age-key.txt` needs to be distributed out of band.\n```sh\n    $ age-keygen -o secrets/age-key.txt\n    $ age-keygen -y -o secrets/public-age-keys.txt secrets/age-key.txt\n    $ echo \"secrets/age-key.txt\" \u003e\u003e .gitignore\n    $ git add secrets/public-age-keys.txt\n    $ git commit -m \"add public key to secrets/\"\n```\n\n2. Copy scripts into a `bin/` directory and add to repo\n```sh\n    $ mkdir bin\n    $ wget https://raw.githubusercontent.com/timball/sops-test/main/bin/encrypt.sh -o bin/encrypt.sh\n    $ wget https://raw.githubusercontent.com/timball/sops-test/main/bin/decrypt.sh -o bin/decrypt.sh\n    $ chmod +x bin/*.sh\n    $ git add bin/*.sh\n    $ git commit -m \"add encrypt/decrypt sops filters scripts\" \n```\n\n3. add configs to git. This creates a filter named `sop`. The `%f` allows the\nscript to recieve the filename. This has to done to repo each time it's checked out\n```sh\n    $ git config --local filter.sops.smudge $(pwd)/bin/decrypt.sh %f\n    $ git config --local filter.sops.clean $(pwd)/bin/encrypt.sh %f\n    $ git config --local filter.sops.required true\n```\n\n4. setup `.gitattributes` for the files that need it\n```sh\n    $ echo 'secrets.json filter=sops' \u003e .gitattributes\n    $ git add .gitattributes\n    $ git commit -m \"add sops filter to secret.json in .gitattributes\"\n```\n\n5. add files and make sure that the in-line secrets are enumerated in\n`secrets/secrets.regex`. right now it is just one line that sops\n--encrypted-regex uses to decide what fields need to encrypted.\n```sh\n    $ echo \"passwd|API\" \u003e secrets/secrets.regex\n    $ git add secrets/secrets.regex\n    $ git add secrets.json\n    $ git commit -m \"add secrets.json and update secrets.regex\"\n```\n\n\n## key rotation\n:shrug: https://technotim.live/posts/rotate-sops-encryption-keys/\n1. seems to rotate keys on a local repo that has secrets files decrypted all one has to do is create a new key and public key file\n```sh\n    $ age-keygen -o secrets/age-key.txt\n    $ age-keygen -y -o secrets/public-age-keys.txt secrets/age-key.txt\n    $ touch \u003csecrets file\u003e\n```\n\n## git diff\nhttps://github.com/getsops/sops#showing-diffs-in-cleartext-in-git\n### the following didn't work and is preserved for future fiddling. As is `git diff` will spit still useful information.\n\n1. for each file that you need a sops differ modify .gitattributes accordingly. name \"sopsdiffer\" is arbitrary\n```\n    example.yaml diff=sopsdiffer\n```\n2. set a git config for the differ\n```sh\n    $ git config diff.sopsdiffer.textconv \"sops -d\"\n```\n\n3. test \n```sh\n    $ git diff example.yaml\n```\n\n## caveats\n`sops` can in-line encrypt secrets for ini, yaml, json, env files. All other files\nwill be completely encrypted. \n\nyou need to update .gitattributes w/ files you want to encrypt\n\nyou need to update secrets/secrets.regex w/ the individual regex parts you need\nneed to encrypt\n\nremeber that item #3 git config must be done for each checked out repo\n\n## appendix and non-throw-away-notes\n### testing SOPS w/ gnupg. DO NOT USE .gnupg, it will make your brain bleed.\n\nhttps://blog.gitguardian.com/a-comprehensive-guide-to-sops/\n\n1. create a gnupg key w/ no password\n2. create a ~/.sops.yaml \n3. edit/encrypte whole files w/ `sops \u003cfilename\u003e`\n4. do bits of file w/ `sops --encrypt --in-place --encrypted-regex 'passwd|APIKEY' example.yaml`\n5. still need to figure out how to deal w/ this at deploy time? `sops -d \u003cfile\u003e`\n6. maybe don't use gnupg and use `age` instead \n7. enc and decrypt using git pre-commit hooks for push and pull to make this automagic?\n    - https://github.com/yuvipanda/pre-commit-hook-ensure-sops\n\nWANTS:\npre-commit\nif $secret-file is new than $enc-file pass $secret-file thru `sop` and update $enc-file\n\npost-merge\nif $enc-file is newer than $secret-file then decrypt w/ `sop`\n\ngit status ignores files that have .enc. versions \naka if foo.enc.yaml exists then ignore example.yaml\n\n\n### use SOPS + age \nhttps://technotim.live/posts/secret-encryption-sops/\n\nhttps://devops.datenkollektiv.de/using-sops-with-age-and-git-like-a-pro.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimball%2Fsops-age-git-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimball%2Fsops-age-git-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimball%2Fsops-age-git-example/lists"}