{"id":23104107,"url":"https://github.com/glueops/provisioner","last_synced_at":"2026-04-25T09:07:19.298Z","repository":{"id":264304225,"uuid":"892917390","full_name":"GlueOps/provisioner","owner":"GlueOps","description":"API to provision vms through libvirt","archived":false,"fork":false,"pushed_at":"2026-04-23T10:04:58.000Z","size":328,"stargazers_count":1,"open_issues_count":18,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-23T12:08:15.828Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GlueOps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-23T03:38:10.000Z","updated_at":"2026-02-26T06:34:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"211f7262-b71a-42e0-a57a-46e85d21c620","html_url":"https://github.com/GlueOps/provisioner","commit_stats":null,"previous_names":["glueops/provisioner"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/GlueOps/provisioner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlueOps%2Fprovisioner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlueOps%2Fprovisioner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlueOps%2Fprovisioner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlueOps%2Fprovisioner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GlueOps","download_url":"https://codeload.github.com/GlueOps/provisioner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlueOps%2Fprovisioner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32256257,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T04:23:17.126Z","status":"ssl_error","status_checked_at":"2026-04-25T04:21:53.360Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2024-12-17T00:31:28.922Z","updated_at":"2026-04-25T09:07:19.279Z","avatar_url":"https://github.com/GlueOps.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# provisioner\n\nFastAPI to provision virtualmachines using libvirt via SSH.\n\n# Provisioner\n\nThis project provides an API to provision virtual machines (VMs) through libvirt.\n\n### Prerequisites\n\n- Devbox\n- Docker\n\n### Devbox\n\nTo set up the development environment using Devbox, run:\n```sh\ndevbox shell\ndevbox run dev\n```\n\n\n### Deployment\n\n#### Setup tailscale ACLs\n\nHere is an example ACL that does the following:\n\n- Machines with `tag:app-prod-provisioner-api` can talk to `tag:app-prod-provisioner-nodes` and vice versa.\n- Users in `group:app-prod-provisioner-developers` can talk to `tag:app-prod-provisioner-api` and  `tag:app-prod-provisioner-nodes` \n- `tim.cook@glueops.dev` is part of `group:app-prod-provisioner-developers`\n- `tim.cook@glueops.dev` can access their own instances tagged with `tag:tim-cook` however because we are using a SVC Admin account to tag the machines `tim.cook` doesn't actually own the tag itself.\n\nThe goals of this ACL policy are to allow the provisioner API to access \"provisioner nodes\" via SSH (port 2222 since tailscale SSH takes over port 22). `tim.cook` needs to be able to administrate provisioner nodes so he is part of `group:app-prod-provisioner-developers` otherwise he can be kept out of this group. `tim.cook` also uses a workspace himself so he needs to have a tag himself. Any user that uses a developer workspace will need their own tag so that the [slack workspace bot](https://github.com/GlueOps/slackbot-developer-workspaces) can assign machines to them (e.g.  `tag:tim-cook`).\n\nWhen testing new policies/ACLs it's best to just create a separate tailnet/tailscale account for testing.\n\n```json\n{\n    \"acls\": [\n        {\n            \"action\": \"accept\",\n            \"dst\": [\n                \"tag:app-prod-provisioner-api:*\",\n                \"tag:app-prod-provisioner-nodes:*\"\n            ],\n            \"src\": [\n                \"group:app-prod-provisioner-developers\"\n            ]\n        },\n        {\n            \"action\": \"accept\",\n            \"dst\": [\n                \"tag:app-prod-provisioner-nodes:*\"\n            ],\n            \"src\": [\n                \"tag:app-prod-provisioner-api\"\n            ]\n        },\n        {\n            \"action\": \"accept\",\n            \"dst\": [\n                \"tag:tim-cook:*\"\n            ],\n            \"src\": [\n                \"tim.cook@glueops.dev\"\n            ]\n        }\n    ],\n    \"groups\": {\n        \"group:app-prod-provisioner-developers\": [\n            \"tim.cook@glueops.dev\"\n        ]\n    },\n    \"ssh\": [\n        {\n            \"action\": \"check\",\n            \"dst\": [\n                \"autogroup:self\"\n            ],\n            \"src\": [\n                \"autogroup:member\"\n            ],\n            \"users\": [\n                \"autogroup:nonroot\",\n                \"root\"\n            ]\n        },\n        {\n            \"action\": \"check\",\n            \"dst\": [\n                \"tag:tim-cook\"\n            ],\n            \"src\": [\n                \"autogroup:member\",\n                \"autogroup:admin\"\n            ],\n            \"users\": [\n                \"autogroup:nonroot\",\n                \"root\"\n            ]\n        },\n        {\n            \"action\": \"check\",\n            \"dst\": [\n                \"tag:app-prod-provisioner-api\",\n                \"tag:app-prod-provisioner-nodes\"\n            ],\n            \"src\": [\n                \"group:app-prod-provisioner-developers\"\n            ],\n            \"users\": [\n                \"autogroup:nonroot\",\n                \"root\"\n            ]\n        }\n    ],\n    \"tagOwners\": {\n        \"tag:tim-cook\": [\n            \"autogroup:admin\"\n        ],\n        \"tag:app-prod-provisioner-api\": [\n            \"group:app-prod-provisioner-developers\"\n        ],\n        \"tag:app-prod-provisioner-nodes\": [\n            \"group:app-prod-provisioner-developers\"\n        ]\n    }\n}\n```\n\n\n\n### Deploy Provisioner Nodes\n\n- Run `install-server.sh` on the provisioner nodes.\n- Ensure proper tailscale tags are assigned to provisioner nodes (e.g. `tag:app-nonprod-provisioner-nodes`)\n\n\n### Deploy Provisioner APIs\n\n- Deploy a debian host\n- Run `curl setup.glueops.dev | bash` and then add it to tailscale with the respective tag (e.g. `tag:app-nonprod-provisioner-api`)\n- Create a file called `provisioner/secrets`\n- Add these `env` variables to the `secrets` file\n```bash\nAPI_TOKEN\nSSH_HOST\nSSH_PORT\nSSH_PRIVATE_KEY_ED25519_BASE64_ENCODED\nSSH_USER\n```\n- Run with `docker run -it --env-file provisioner/secrets \u003ccontainer-image/tag\u003e`\n\n_NOTE: this will run within an interactive terminal so it's best to use tmux or similar so that it keeps running in the background. Alternatively you can remove `it` and just use `d` to have it run as a daemon in the background._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglueops%2Fprovisioner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglueops%2Fprovisioner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglueops%2Fprovisioner/lists"}