{"id":28458871,"url":"https://github.com/jeffrom/polyester","last_synced_at":"2025-07-02T09:30:59.539Z","repository":{"id":148291910,"uuid":"385226752","full_name":"jeffrom/polyester","owner":"jeffrom","description":"bootstrap and manage linux environments using posix shell","archived":false,"fork":false,"pushed_at":"2021-09-17T20:16:56.000Z","size":688,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-07T00:41:18.967Z","etag":null,"topics":["devops","gitops","posix-sh"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeffrom.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":"2021-07-12T11:39:09.000Z","updated_at":"2021-09-17T20:16:59.000Z","dependencies_parsed_at":"2023-09-08T01:17:54.763Z","dependency_job_id":null,"html_url":"https://github.com/jeffrom/polyester","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jeffrom/polyester","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffrom%2Fpolyester","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffrom%2Fpolyester/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffrom%2Fpolyester/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffrom%2Fpolyester/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffrom","download_url":"https://codeload.github.com/jeffrom/polyester/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffrom%2Fpolyester/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263111287,"owners_count":23415421,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["devops","gitops","posix-sh"],"created_at":"2025-06-07T00:40:18.110Z","updated_at":"2025-07-02T09:30:59.522Z","avatar_url":"https://github.com/jeffrom.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# polyester\n\nBootstrap servers, apps, and secrets. Run applications with secrets mapped to environment variables. Template configuration files and scripts. Continuously deploy. Made for version control.\n\n## status\n\nPretty unstable!\n\n## usage\n\n### plans\n\nSince we're an ops tool, we need a magic directory structure:\n\n```\n.\n├── files\n├── plans\n│   ├── myapp\n│   │   ├── files\n│   │   └── templates\n│   └── myapp2\n├── templates\n│   └── systemd\n└── vars\n```\n\n### agent\n\nrun a collection of plans (default usage):\n\n```bash\n$ make \u0026\u0026 ./polyester apply testdata/basic\n```\n\nrun a single plan in a filesystem sandbox, w/ an overridden state directory:\n\n```bash\n$ make \u0026\u0026 ./polyester apply --dir-root /tmp/polytest --state-dir /tmp/polystate testdata/basic/plans/touchy/plan.sh\n```\n\nNormal usage entails running `polyester apply` on remote servers. To continuously update a git repository containing the polyester manifest, a cron could periodically run a script such as:\n\n```\n$ cd ~/repos/cluster \u0026\u0026 git pull \u0026\u0026 polyester apply\n```\n\n## how does it work\n\nThe key concepts are \"plans\" and \"operators\". Plans are sequences of operations, used to execute commands on an environment. Operations are run in order, by plan (which run concurrently). There is a caching strategy for operations where, if an operation's state changes, it and every subsequent operation is executed.\n\nThe primary domain language is POSIX shell (though others could be supported without a huge amount of effort). Shell scripts are evaluated to generate the execution plan by outputting it to an intermediate format in the local filesystem. This means variable scope and other behavior may not be what you expect because the script doesn't immediately execute, but rather constructs an intermediate plan.\n\nOperators idempotently execute operations and track state. In many cases they extend common linux tools. Some example operators:\n\n- useradd\n- touch\n- copy\n\nSee the `testdata/` directory for example plans.\n\n## development\n\nbuild it:\n\n```\n$ make\n```\n\nrun docker tests:\n\n```\n$ go test ./cmd/polyester -run TestDocker\n```\n\nOperators can be partially \"sandboxed\" using the --dir-root flag, which can be useful for debugging. For example, to override the state directory and use a filesystem sandbox:\n\n```\n$ ./polyester apply --dir-root /tmp/mysandbox --state-dir /tmp/mystate testdata/basic\n```\n\n## todo\n\n* operators\n  - more/better secret management (sops, ?)\n  - templating (maybe w/ gomplate)\n  - systemd operators to reenable, reinstall, restart units on state changes (maybe shell is enough).\n  - apt add source\n  - certbot\n* shell plan script improvements\n  - validate operator calls in shell scripts pre-execution\n  - handling variables / scope in shell script plans\n* planner improvements\n  - improve dryrun contract -- ie planner passes --dry-run to commands that have it otherwise execution is skipped.\n  - use remote, versioned git repo / tar / exported plans\n  - prune old / unused state files\n* output formats\n  - nice readable apply summaries, what changed etc\n  - json log for debugging, introspection, integration testing\n  - operations interface (maybe just stringer) to control its argument formatting\n* testing\n  - parameterize base docker image to run against various distros \u0026 oses\n  - generic table test for operation idempotency\n  - replace github repo in docker basic test w/ a proper test fixture repo on the local fs\n* docs\n  - write some\n  - templatized operation docs using go generate / gomplate / operation.Info\n  - example repo / article\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffrom%2Fpolyester","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffrom%2Fpolyester","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffrom%2Fpolyester/lists"}