{"id":13564452,"url":"https://github.com/krtab/agnos","last_synced_at":"2025-05-15T10:06:10.702Z","repository":{"id":37177067,"uuid":"430111149","full_name":"krtab/agnos","owner":"krtab","description":"Obtain (wildcard) certificates from let's encrypt using dns-01 without the need for API access to your DNS provider.","archived":false,"fork":false,"pushed_at":"2025-04-08T17:35:11.000Z","size":6187,"stargazers_count":319,"open_issues_count":9,"forks_count":11,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-15T10:05:06.706Z","etag":null,"topics":["acme","acme-dns","acme-v2","certificate","dns","dns-01","lets-encrypt","letsencrypt","ssl"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/krtab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2021-11-20T13:31:30.000Z","updated_at":"2025-05-14T02:07:09.000Z","dependencies_parsed_at":"2024-01-13T19:40:46.296Z","dependency_job_id":"8056ceeb-4bc9-4508-b8fb-5846cb482ee5","html_url":"https://github.com/krtab/agnos","commit_stats":{"total_commits":96,"total_committers":4,"mean_commits":24.0,"dds":0.34375,"last_synced_commit":"5432ae23491d942d90d576a6726910f4288cd899"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krtab%2Fagnos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krtab%2Fagnos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krtab%2Fagnos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krtab%2Fagnos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krtab","download_url":"https://codeload.github.com/krtab/agnos/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319720,"owners_count":22051073,"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":["acme","acme-dns","acme-v2","certificate","dns","dns-01","lets-encrypt","letsencrypt","ssl"],"created_at":"2024-08-01T13:01:31.598Z","updated_at":"2025-05-15T10:06:05.675Z","avatar_url":"https://github.com/krtab.png","language":"Rust","readme":"[![Crates.io badge](https://img.shields.io/crates/v/agnos?style=flat-square)](https://crates.io/crates/agnos)\n[![github release badge badge](https://img.shields.io/github/v/release/krtab/agnos?style=flat-square)](https://github.com/krtab/agnos/releases/latest)\n![github downloads badge](https://img.shields.io/github/downloads/krtab/agnos/total?style=flat-square)\n\u003cbr/\u003e\n\u003cimg src=\"resources/Banner-optimized.png\" alt=\"drawing\" width=\"372\"/\u003e\n\u003cbr/\u003e\n[\u003cimg src=\"resources/red-iron.png\" alt=\"This project is proudly sponsored by Red Iron, the Rust division of OCamlPro\" width=\"372\"/\u003e](https://red-iron.eu/)\n\n\n\u003c!-- TOC ignore:true --\u003e\n# Presentation\n\nFor an introduction to the ACME protocol and its DNS verification part, you can refer to our beta release [blog post](https://ocamlpro.com/blog/2022_10_05_agnos_0.1.0-beta).\n\nAgnos is a single-binary program allowing you to easily obtain certificates (including wildcards) from [Let's Encrypt](https://letsencrypt.org/) using [DNS-01](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) challenges. It answers Let's Encrypt DNS queries on its own, bypassing the need for API calls to your DNS provider.\n\n\u003c!-- TOC ignore:true --\u003e\n## Why\n\n\nDNS-01 is summarized by Let's Encrypt documentation as such:\n\n\u003e \u003c!-- TOC ignore:true --\u003e\n\u003e ### Pros\n\u003e\n\u003e - You can use this challenge to issue certificates containing wildcard domain names.\n\u003e - It works well even if you have multiple web servers.\n\u003e\n\u003e \u003c!-- TOC ignore:true --\u003e\n\u003e ### Cons\n\u003e\n\u003e - Keeping API credentials on your web server is risky.\n\u003e - Your DNS provider might not offer an API.\n\u003e - Your DNS API may not provide information on propagation times.\n\nBy serving its own DNS answers, agnos:\n\n- Nullify the need for API and API credentials\n- Nullify all concerns regarding propagation times\n\nHence, **agnos removes virtually all downsides of dns-01 challenges**.\n\n\u003c!-- TOC ignore:true --\u003e\n## How\n\n\nAgnos leverages let's encrypt capability to follow DNS `NS` records. It requires you to add to your DNS zone:\n\n1. An `A` (or `AAAA`) record pointing to the public-facing IP address of the server on which agnos will run. On this server, UDP port 53 (the one used by DNS) should be open and free.\n2. For each domain you will want to validate, an `NS` record for the corresponding `_acme-challenge` sub-domain, indicating that agnos should be used as a name server for this specific domain.\n\n\u003c!-- TOC ignore:true --\u003e\n# Table of content\n\n\u003c!-- TOC --\u003e\n\n1. [Installation](#installation)\n    1. [Released binary](#released-binary)\n    1. [Archlinux AUR package](#archlinux-aur-package)\n    1. [Packaging on other systems](#packaging-on-other-systems)\n    1. [Building](#building)\n    1. [Setting capabilities to not run agnos as root](#setting-capabilities-to-not-run-agnos-as-root)\n1. [Usage](#usage)\n    1. [Let's Encrypt accounts](#lets-encrypt-accounts)\n    1. [Agnos configuration](#agnos-configuration)\n        1. [General](#general)\n        1. [Accounts](#accounts)\n        1. [Certificates](#certificates)\n    1. [Configuration of your DNS provider](#configuration-of-your-dns-provider)\n    1. [Running agnos](#running-agnos)\n    1. [Systemd units](#systemd-units)\n1. [Developers](#developers)\n    1. [Integration testing](#integration-testing)\n1. [User feedback requested](#user-feedback-requested)\n\n\u003c!-- /TOC --\u003e\n\n# Installation\n\nThese instructions are given for a Linux system but a similar process will likely work on all Unixes, and maybe windows.\n\n## Released binary\n\nPre-compiled binaries for Linux/amd64 are available for every tagged [release](https://github.com/krtab/agnos/releases). Be aware that they are statically built using musl and vendoring their own openssl so that they can easily be installed even on older distributions.\n\n## Archlinux AUR package\n\nAgnos is available in the [AUR](https://aur.archlinux.org/packages/agnos). You can install it using: `yay -S agnos`. \n\n## Packaging on other systems\n\nIf you have packaged agnos for another system, feel free to open a PR to add it to the list.\n\n## Building\n\nAgnos is written in Rust. To build it you will need to have the rust toolchain installed. On most distributions, this should be done using [rustup](https://rustup.rs).\n\nOnce you have obtained the source, the following command will build the binaries and put them in the root directory of the repo.\n\n```bash\ncd agnos/\nmake build-release\n```\n\nor more explicitly:\n\n```bash\ncargo build --locked --bins --release\nstrip target/release/agnos\nstrip target/release/agnos-generate-accounts-keys\nln target/release/agnos agnos\nln target/release/agnos-generate-accounts-keys agnos-generate-accounts-keys\n```\n\n## Setting capabilities to not run agnos as root\n\nBecause agnos listen on the low-numbered port 53, it requires special privileges. Running it as root will do, but if you (understandably) don't want to do that, the following command is for you:\n\n```bash\n# as root\nsetcap 'cap_net_bind_service=+ep' agnos\n# agnos is the file of the binary as compiled above\n```\n\n# Usage\n\n## Let's Encrypt accounts\n\nLet's Encrypt accounts are identified by an e-mail address and a private RSA key. To generate such a key, use the following command:\n\n```shell\nopenssl genrsa 2048 \u003e /path/to/store/the/key.pem\n```\n\nor if you prefer a larger key:\n\n```shell\nopenssl genrsa 4096 \u003e /path/to/store/the/key.pem\n```\n\nAlternatively, you can use the provided `agnos-generate-accounts-keys` binary to automatically generate private keys for the accounts listed in the configuration file.\n\n```bash\nagnos-generate-accounts-keys --key-size 4096 your_config.toml\n```\n\n## Agnos configuration\n\nAgnos is configured via a single [TOML](https://toml.io/) file. A commented example is available in [config_example.toml](https://github.com/krtab/agnos/blob/main/config_example.toml).\n\nIt is advised to use absolute rather than relative paths in the configuration file.\n\nThere are three \"levels\" in the configuration:\n\n### 1. General\n\nThe general configuration level is where the IP address to listen on is provided.\n\n```toml\ndns_listen_addr = \"1.2.3.4:53\"\n```\n\n### 2. Accounts\n\nSeveral Let's Encrypt accounts can be specified. For each account, an e-mail address and the path to the account RSA private key must be provided.\n\n```toml\n[[accounts]]\nemail= \"contact@doma.in\"\nprivate_key_path = \"priv_key.pem\"\n```\n\n### 3. Certificates\n\nFor each account, several certificates can be ordered. Each certificate can cover multiple domains. On disk, a certificate is represented by two files: the full certificate chain, and the private key of the certificate (different from the account private key). This certificate private key is regenerated on each certificate renewal by default but if one is already present on disk, it can be reused by setting the `reuse_private_key` option to true\nIn the configuration file, `accounts.certificates` is a TOML [array of tables](https://toml.io/en/v1.0.0#array-of-tables) meaning that several certificates can be attached to one account by writing them one after the other.\n\n```toml\n# A first certificate ordered for that account.\n[[accounts.certificates]]\ndomains =  [\"doma.in\",\"*.doma.in\"]\nfullchain_output_file = \"fullchain_A.pem\"\nkey_output_file = \"cert_key_A.pem\"\n# Renew certificate 30 days in advance of its expiration\n# (this is the default value and can be omitted).\nrenewal_days_advance = 30\n# Regenerate a private key for the certificate on each renewal\n# (this is the default value and can be omitted).\nreuse_private_key = false \n\n# A second certificate ordered for that account.\n[[accounts.certificates]]\nrenewal_days_advance = 21 # Renew certificate 21 days in advance of its expiration.\ndomains =  [\"examp.le\",\"another.examp.le\",\"and.a.completely.different.one\"]\nfullchain_output_file = \"fullchain_B.pem\"\nkey_output_file = \"cert_key_B.pem\"\n# Re-use the existing private key.\n# If no key is present at `key_output_file`, a new one will be generated.\nreuse_private_key = true\n```\n\n## Configuration of your DNS provider\n\nSay that we have the following domains we want to obtain a certificate (or multiple certificates) for: \n- `doma.in`\n- its wildcard variant: `*.doma.in`\n- `examp.le`\n- and `another.examp.le`. \n\nNotice here that we are not requesting a certificate for `*.examp.le` but only for one subdomain: `another.examp.le`.\n\nLet's encrypt DNS-01 challenge is going to ask for TXT DNS records on the following three domains: \n- `_acme-challenge.doma.in` (for both `doma.in` and its wildcard)\n- `_acme-challenge.examp.le`\n- `_acme-challenge.another.examp.le`\n\nLet's assume that agnos is going to run on a server whose public-facing IP address is `1.2.3.4`. The goal is to indicate that the three `_acme_challenge` domains cited above are managed by agnos using `NS` DNS records. `NS` records usually point to domain names, so we will also set an `A` record on `agnos-ns.doma.in` to point to `1.2.3.4` (here `agnos-ns.doma.in` is entirely arbitrary, it could be another, completely independent domain, you control, like `my-agnos.com`).\n\nWe create the following records:\n\nIn the zone of `doma.in`\n```\nagnos-ns.doma.in            A       1.2.3.4\n_acme-challenge.doma.in     NS      agnos-ns.doma.in\n```\n\nIn the zone of `examp.le`\n```\n_acme-challenge.examp.le            NS      agnos-ns.doma.in\n_acme-challenge.another.examp.le    NS      agnos-ns.doma.in\n```\n\n**Note:** Though it may seem cumbersome, this must only be done once from your DNS provider web interface. Once it is done, you will never have to touch a `TXT` record.\n\n## Running agnos\n\n`agnos` takes a single command line argument, the path to its configuration file, and two optional flags: `--no-staging` to use Let's Encrypt production server, and `--debug` to display more debug information. Help is available via `agnos --help`.\n\nWhen running, it checks whether the certificates of the full chain are going to expire in the next 30 days (by default), and only renew them in that case, so it is suitable to be used in a cron job.\n\n## Systemd units\n\nA systemd unit and timers are provided in the `systemd` folder of this repo.\n\n# Developers\n\nPRs and issues are very welcome.\n\nBuild using usual `cargo` commands.\n\n## Integration testing\n\nIntegration testing is done using nix-shell. Launch it with `nix-shell integration-testing/shell.nix --pure --run agnos-test-script`.\n\n# User feedback requested\n\nIf you are using agnos, please consider telling me about your user experience here: https://github.com/krtab/agnos/issues/62.\n\n","funding_links":[],"categories":["Rust","others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrtab%2Fagnos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrtab%2Fagnos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrtab%2Fagnos/lists"}