{"id":23477791,"url":"https://github.com/michael-yuji/cloudflare-sh","last_synced_at":"2026-04-10T03:02:07.280Z","repository":{"id":171734669,"uuid":"471667711","full_name":"michael-yuji/cloudflare-sh","owner":"michael-yuji","description":"Script friendly Cloudflare DNS cli tool in pure shell","archived":false,"fork":false,"pushed_at":"2022-03-19T17:36:53.000Z","size":44,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-28T08:51:15.215Z","etag":null,"topics":["cli","cloudflare","cloudflare-cli","shell","shell-script"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/michael-yuji.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}},"created_at":"2022-03-19T10:54:43.000Z","updated_at":"2025-01-02T14:25:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"6a42d5e0-4a7e-4da4-9aa9-4c347a2b5c19","html_url":"https://github.com/michael-yuji/cloudflare-sh","commit_stats":null,"previous_names":["michael-yuji/cloudflare-sh"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fcloudflare-sh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fcloudflare-sh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fcloudflare-sh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fcloudflare-sh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michael-yuji","download_url":"https://codeload.github.com/michael-yuji/cloudflare-sh/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248956515,"owners_count":21189358,"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":["cli","cloudflare","cloudflare-cli","shell","shell-script"],"created_at":"2024-12-24T18:33:41.098Z","updated_at":"2026-04-10T03:02:02.258Z","avatar_url":"https://github.com/michael-yuji.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cloudflare-sh\n\nThis script is designed to be use to manage DNS records of multiple accounts and multiple zones. It also prioritize scriptablility and portability, it provides cli interface to manage DNS records on cloudflare via cloudflare api with minimum footprint and dependencies. The output of this script in intended to be simple to parse and easy to use with other tools like `awk`\n\nPR Welcome! See code and bottom of this document for technical documentation.\n\n# Installation\n\nThe only dependencies are `jq` and `curl`, you need to install `jq` and `curl` for your specific operating system.\nAfter you have installed the dependencies, simply clone the directory or place the shell script somewhere under your `$PATH`. \n\n# Usage\n\n```\nUsage: cloudflare.sh [options] [CMD] [CMD ARGS...]\n\n  available commands:\n    apikey  - Manage api keys\n    zone    - Manage zones\n    dns     - Manage DNS\n    profile - Manage profiles\n```\n\nExample workflow\n\n```sh\n# register a new api key, since this is your first key, it will become the default now (you can change later)\ncloudflare.sh apikey new --keyname test --apikey \u003cyour-api-key\u003e\n\n# list DNS records in zone \"example.com\"\ncloudflare.sh dns list --zone_name example.com\n\n# list A records in zone \"example.com\" \ncloudflare.sh dns list --type A --zone_name example.com\n\n# Create an A record \"test.example.com\", points to 127.0.0.1\ncloudflare.sh dns --zone_name example.com create --type A --name test --content 127.0.0.1\n\n# Same as above, but different ordering, and set priority to 10\ncloudflare.sh dns create --zone_name example.com --type A --name test --content 127.0.0.1 --priority 10\n```\n\n### Api key / Profile management\nYou can use this script with and without storing your api keys with this tool, however storing it will make your life much easier and secure. In fact, you can store multiple api keys, and alias them to fit your need. The api keys are always store with `0400` permission so only the owner can read it.\n\nTo run any of the command with an explicit api key, you can simply add the `--apikey \u003ccloudflare-key\u003e` option.\n\n```\nUsage: apikey [CMD] [options...]\n\n  available commands:\n\n    list\n      list all profiles\n\n    new\n      Reqister and set a name for an api key\n        Required options:\n          --apikey  [KEY]  - the api key to store\n          --keyname [NAME] - the name of the api key to store as\n\n    set-default [NAME]\n      Set the api key with name [NAME] as the default api key, such that when\n        executing any other commands without either --apikey or --keyname, the\n        default api key will be used\n\n    remove [NAME]\n      Remove the api key stored as [NAME]\n```\n\nYour DNS records lives in a zone, and a zone lives in your account, natuarlly it becomes quite cumbersome when you just want to query / perform changes to some domain. This tool allows you to create different profiles, a profile stores a api key together with a zone, such that you can manage your domain without needing to explicitly specify the api key and zone id you will use.\n\n\n```\n Usage: profile [CMD] [options...]\n \n   available commands:\n \n   list\n      list all profiles\n \n   create [NAME]\n     Reqister and set a name for a profile\n       Optional options:\n         --keyname [NAME]    - the api key name for this profile\n         --zone_name [NAME] - the name of the zone to be set for this profile\n         --zone_id   [ID]   - the zone id to be set for this profile\n \n   update-zone [NAME]\n     Update the zone of a profile with [NAME]\n\n   update-key [NAME]\n     Update the apikey use by the profile with [NAME]\n\n   remove [NAME]\n     Remove the api key stored as [NAME]\n ```\n\nThis script by default stores your configuration under `$HOME/.cloudflare`, this directory will be created automatically when you use the script.\n\nTo register your api key\n```\n# Register our apikey aliased as `foo`\ncloudflare.sh apikey new --keyname foo --apikey \u003ccloudflare-api-key\u003e\n```\n\nIf this is your first api key, the tool automatiaclly set it as the default key so you never have to type in the api again.\n\nTo create a profile,\n\n```\ncloudflare.sh profile create your-profile-name --keyname your-apikey-name --zone_id \u003czone-id-of-the-zone\u003e\n```\n\nTo use a profile in place of api key and zone id, add `--profile your-profile-name` instead of `--keyname your-apikey-name` and `--zone_name example.com`.\n\nIn the case when multiple of these variables defined, the precedence are:\n\n`--apikey` (use a api key explicitly) \u003e `--keyname (use a api key by name)` \u003e `--profile (usa a profile)` \u003e `(default apikey)`\n\nSimilarly \n`--zone_id` \u003e `--zone_name` \u003e `--profile (use a profile)` \u003e `(default zone_id)`\n\n### Zone management\n\n```\nUsage: zone [CMD] [options...]'\n\n  available commands:\n\n  list\n     list all zones\n\n  set-default\n    Reqister and set as the default zone\n      Required options (either):\n        --zone_name [NAME] - the name of the zone to be set for this profile\n        --zone_id   [ID]   - the zone id to be set for this profile\n```\n\nCurrent the script only supports querying zones (as that's all I need now).\n\nTo query all zones under an account, if you have a default api key set, you can run\n```\ncloudflare.sh zone list\n```\n\nIf you have not register an api key, or just want to use with another apikey, you can run\n```\ncloudflare.sh --apikey \u003ccloudflare-api-key\u003e zone list\n```\n\nThe command(s) above should give you outputs with format\n```\n11111111110000000007777abcedfaaa example.org\n```\n\nWhere the first column is the zone-id and the last column is the zone name.\n\n### DNS management\n\n\n```\nUsage: dns [CMD] [options...]'\n\n  common options:\n    --apikey    [KEY]     - use alternate api key\n    --keyname   [NAME]    - the key name to an api key to use\n    --zone_id   [ZONEID]  - operate in another zone by id\n    --zone_name [NAME]    - operate in another zone by zone name\n\n  available commands:\n\n    list\n      List DNS records,\n        Optional options:\n          --direction [asc/desc]   - ordering of the records (default desc)\n          --type      [TYPE]       - list records with [TYPE]\n          --content   [DATA]       - filter by DNS data\n          --proxied   [true/false] - filter by if the cloudflare proxy enabled\n          --name      [NAME]       - filter by dns name\n\n    update RECORD_ID\n        Required and optional options as same as 'create' action\n\n    create\n        Required options:\n          --type    [TYPE]  - DNS record type, for example \"A\"\n          --name    [NAME]  - DNS record name, for example \"subdomain\"\n          --content [DATA]  - DNS data, for example \"127.0.0.1\"\n        Optional options:\n          --priority [PRIOV]      - DNS priority, for example 10 (default 10)\n          --proxied  [true/false] - Enable/disable cloudflare proxy (default false)\n          --ttl      [NUM]        - time to live, see cloudflare api for valid values (default 1 (auto))\n\n    delete RECORD_ID\n      - Delete a record by RECORD_ID\n\n```\n\n##### Listing records\n\nTo list DNS records under a zone (e.g. example.com), you can run the following command\n\n```\ncloudflare.sh dns list --zone_name example.com\n```\n\nThe output will be in the format of\n\n```\n\u003czone-id\u003e \u003cdns-data (e.g. files.example.com)\u003e \u003ctype (e.g. A)\u003e \u003cdata (e.g 127.0.0.1)\u003e\n```\n\nYou can also use `--zone_id` instead of `--zone_name` if you prefer to query dns records within a zone using a zone id instead of the name.\n\n##### Creating/Updating a record\n\nTo create a record, you can use one of the following (the example is to create an A record points to 127.0.0.1 for test.example.com)\n\nwith a profile:\n```cloudflare.sh --profile examplecom dns create --type A --name test --content \"127.0.0.1\"```\n\nwith default apikey and a specific zone name\n```cloudflare.sh --zone_name example.com dns create --type A --name test --content \"127.0.0.1\"```\n\nwith explicit apikey and explicit zone_id (... are the arguments to create dns records)\n```cloudflare.sh --apikey \u003ccloudflare-key\u003e --zone_id \u003czone_id\u003e dns create ...```\n\n\n\n## The Configuration directory\n\nThe layout of the configuration directory is like this:\n```\n.cloudflare\n  | - default\n  | - profiles/\n  |.   - profiles\n  | - keys/\n  |.   - your_api_key_name\n```\n\n# Technical Documentation\n\n## Calling Cloudflare api\nUse the api() function to call the cloudflare api, this will allows api keys\nto set automatically, and if there are any api failure it will set shell vars\nto aid debugging. The path must be the first argument of the api() function.\n\nUse check_success() function to check if a response succeed. The check_success\nfunction checks if the \"success\" field of the api returns true.\n\n# fatal failure handling\nUse the failure() function to fail the script with an error message, the \nerror message will be written to stderr.\n\n## The shell arguments\n\nThe way this script works first parse the arguments pass to the script, any\narguments starts with --, for example --foo will strip from the argument list, \nand a shell variable, in this case $foo will be contructed, the value of $foo\nwill be set to be the value of the next argument.\n\nFor example if `--foo bar` are in the argument list, a shell variable foo=bar\nwill be set.\n\nThis allows a good (but can be danger...) degree of flexibility in writing the\nscript. For example the script contains the logic that if $apikey is not set,\napikey will be derive from other variables, now when the user set --apikey \ndirectly it will alow us to bypass the deriving logic and save a lot of work.\n\nThis is also the reason why must functions does not need to take $1 $2 as arguments.\n\n## Directory structure\n\nWhen the script launched and after after the script parsed arguments, it will\nsource \"$CF_CONFIG/default\" and hence set the default variables, if the user\nset the $profile argument, the file in \"$CF_CONFIG/profiles/$profile\" will be\nsourced, and therefore any variables defined in both default and profile will\nbe shadowed by the values defined in the profile file.\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-yuji%2Fcloudflare-sh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichael-yuji%2Fcloudflare-sh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-yuji%2Fcloudflare-sh/lists"}