{"id":13588861,"url":"https://github.com/apoprotsky/portctl","last_synced_at":"2026-01-12T06:31:49.040Z","repository":{"id":60938382,"uuid":"542877351","full_name":"apoprotsky/portctl","owner":"apoprotsky","description":"Portainer CLI tool to manage Docker Swarm resources","archived":false,"fork":false,"pushed_at":"2023-06-15T13:00:26.000Z","size":59,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T06:35:20.153Z","etag":null,"topics":["cli","docker-swarm","hashicorp-vault","portainer","v","vault","vlang","vlang-cli"],"latest_commit_sha":null,"homepage":"","language":"V","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/apoprotsky.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":"2022-09-29T02:14:42.000Z","updated_at":"2024-08-10T05:26:37.000Z","dependencies_parsed_at":"2024-05-03T03:01:01.364Z","dependency_job_id":"1c144119-4978-4675-a3db-1d68faaf5e35","html_url":"https://github.com/apoprotsky/portctl","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/apoprotsky/portctl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apoprotsky%2Fportctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apoprotsky%2Fportctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apoprotsky%2Fportctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apoprotsky%2Fportctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apoprotsky","download_url":"https://codeload.github.com/apoprotsky/portctl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apoprotsky%2Fportctl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28336316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["cli","docker-swarm","hashicorp-vault","portainer","v","vault","vlang","vlang-cli"],"created_at":"2024-08-01T15:06:59.648Z","updated_at":"2026-01-12T06:31:49.025Z","avatar_url":"https://github.com/apoprotsky.png","language":"V","funding_links":[],"categories":["V","Applications"],"sub_categories":["Command-line"],"readme":"`portctl` (`Port`ainer `C`on`t`ro`l`) is a command line interface tool for managing `Docker Swarm` resources through `Portainer API` integrated with `Hashicorp Vault`\n\n# How to use\n\nLet's deploy standalone `RabbitMQ` as stack in `Docker Swarm`\n\nStart environment using `Docker` or `Podman`:\n```sh\ndocker run -it --rm --name portctl apoprotsky/portctl /bin/sh\n```\n\nConfigure parameters to work with `Portainer API` and `Hashicorp Vault`\n```sh\nexport PORTAINER_API=https://portainer.example.com\nexport PORTAINER_TOKEN=ptr_U+portainertoken\nexport VAULT_ADDR=https://vault.example.com\nexport VAULT_TOKEN=hvs.vaulttoken\nexport RABBITMQ_VERSION=3.9.8-management-alpine\n```\n\nCreate template file `rabbitmq.conf` for `Docker Swarm` secret where\n`default_pass` will be filed from field `password` of `Hashicorp Vault` secret `kv/rabbitmq`\n```ini\ndefault_user = rabbitmq\ndefault_pass = {{ vault:kv/rabbitmq.password }}\ndefault_vhost = /\ncluster_formation.peer_discovery_backend = classic_config\ncluster_formation.classic_config.nodes.1 = rabbit@server\n```\n\nCreate template file `stack.env` for `Docker Swarm` stack variables where\n`RABBITMQ_VERSION` and `RABBITMQ_CONFIG` will be filled from environment variables and\n`RABBITMQ_ERLANG_COOKIE` will be filed from field `cookie` of `Hashicorp Vault` secret `kv/rabbitmq`\n```ini\nRABBITMQ_VERSION={{ env:RABBITMQ_VERSION }}\nRABBITMQ_ERLANG_COOKIE={{ vault:kv/rabbitmq.cookie }}\nRABBITMQ_CONFIG={{ env:RABBITMQ_CONFIG }}\n```\n\nPrepare `Docker Swarm` stack file `stack.yml`\n```yml\nversion: '3'\nservices:\n  server:\n    image: rabbitmq::${RABBITMQ_VERSION}\n    environment:\n      RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE}\n    hostname: server\n    volumes:\n      - rabbitmq:/var/lib/rabbitmq\n    secrets:\n      - source: rabbitmq.conf\n        target: /etc/rabbitmq/rabbitmq.conf\nvolumes:\n  rabbitmq:\nsecrets:\n  rabbitmq.conf:\n    external: true\n    name: ${RABBITMQ_CONFIG}\n```\n\nGet list of available `Portainer` endpoints to choose where to deploy new stack\n```sh\nportctl endpoints list\nexport PORTAINER_ENDPOINT=endpoint_name_from_list\n```\n\nDeploy `Docker Swarm` secret and save its name to environment variable `RABBITMQ_CONFIG`\n```sh\nexport RABBITMQ_CONFIG=`portctl secrets apply --name rabbitmq.conf --file rabbitmq.conf`\n```\n\nDeploy prepared stack\n```sh\nportctl stacks apply --name rabbitmq --file stack.yml --vars stack.env\n```\n\nView list of stacks\n```sh\nportctl stacks list\n```\n\n# Features\n\nNoticeable:\n- Render templates for `Docker Swarm` secrets, configs or stack variables file using environment variables or `Hashicorp Vault` KV secrets\n- Postfix (`-` followed by five symbols from `base58` string of `md5` hash of data) is adding to `Docker Swarm` secrets and configs names on creation to make them unique\n- Apply commands try to delete staled `Docker Swarm` configs and secrets. Configs and secrets consider as staled if its name is not equal current and resource are below first [TaskHistoryRetentionLimit](https://docs.docker.com/engine/reference/commandline/swarm_init/#--task-history-limit) items in list ordered by date.\n\nList:\n- `Portainer` endpoints, services, stacks for `Docker Swarm`\n- `Docker Swarm` configs, secrets\n\nCreate:\n- `Portainer` stacks for `Docker Swarm`\n- `Docker Swarm` configs, secrets\n\nUpdate:\n- `Portainer` stacks for `Docker Swarm`\n\nDelete:\n- `Portainer` stacks for `Docker Swarm`\n- `Docker Swarm` configs, secrets\n\n# Environment for development\n\nFor using `make watch` need to install `fswatch` utility\n\n```sh\nbrew install fswatch\n```\n\n# Additional infromation\n\nPortainer API\n\nhttps://app.swaggerhub.com/apis/portainer/portainer-ce\n\nDocker API\n\nhttps://docs.docker.com/engine/api/latest\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapoprotsky%2Fportctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapoprotsky%2Fportctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapoprotsky%2Fportctl/lists"}