Metadata-Version: 2.4
Name: certbot-dns-xynta
Version: 0.1.0
Summary: Xynta DNS Authenticator plugin for Certbot
Project-URL: Homepage, https://github.com/mbchristoff/xynta-certbot-plugin
Project-URL: Bug Reports, https://github.com/mbchristoff/xynta-certbot-plugin/issues
Project-URL: Source, https://github.com/mbchristoff/xynta-certbot-plugin
Author: mbchristoff
License-Expression: Apache-2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Security
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.10
Requires-Dist: acme>=2.0.0
Requires-Dist: certbot>=2.0.0
Requires-Dist: requests>=2.32.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: requests-mock>=1.11.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Description-Content-Type: text/markdown

# xynta-certbot-plugin

Xynta DNS Authenticator plugin for [Certbot](https://certbot.eff.org/).

This plugin automates the process of completing a `dns-01` challenge by creating,
and subsequently removing, TXT records in your Xynta DNS zone using the
[Xynta HostFact API](https://help.xynta.com/en/article/api-documentation-domains-module-s1808y/).

It enables you to obtain **wildcard certificates** (e.g. `*.example.com`) via
Let's Encrypt without any manual DNS interaction.

---

## Requirements

| Requirement | Version |
|---|---|
| Python | ≥ 3.10 |
| certbot | ≥ 2.0.0 |
| requests | ≥ 2.32.0 |

---

## Installation

```bash
pip install certbot-dns-xynta
```

If certbot is installed system-wide and you want to add the plugin to that
environment, either use `sudo pip install certbot-dns-xynta` or install both
certbot and the plugin together in a virtual environment:

```bash
python3 -m venv certbot-env
source certbot-env/bin/activate
pip install certbot certbot-dns-xynta
```

---

## Xynta API credentials

You need the **UserID** and **IP Hash** from your Xynta HostFact account.
These are found in the Xynta control panel under your API settings.

---

## Usage

### 1. Create a credentials file

Create a file (e.g. `/etc/letsencrypt/xynta.ini`) with the following content:

```ini
dns_xynta_api_url     = https://api.xynta.com/
dns_xynta_api_user_id = YOUR_USER_ID
dns_xynta_api_ip_hash = YOUR_IP_HASH
```

### 2. Secure the credentials file

```bash
chmod 600 /etc/letsencrypt/xynta.ini
```

### 3. Run certbot

**Single domain:**

```bash
certbot certonly \
  --authenticator dns-xynta \
  --dns-xynta-credentials /etc/letsencrypt/xynta.ini \
  -d example.com
```

**Wildcard certificate:**

```bash
certbot certonly \
  --authenticator dns-xynta \
  --dns-xynta-credentials /etc/letsencrypt/xynta.ini \
  -d example.com \
  -d "*.example.com"
```

**Custom DNS propagation wait (in seconds):**

```bash
certbot certonly \
  --authenticator dns-xynta \
  --dns-xynta-credentials /etc/letsencrypt/xynta.ini \
  --dns-xynta-propagation-seconds 300 \
  -d example.com \
  -d "*.example.com"
```

---

## Arguments

| Argument | Description |
|---|---|
| `--dns-xynta-credentials` | Path to the credentials INI file (required) |
| `--dns-xynta-propagation-seconds` | Seconds to wait for DNS propagation (default: 120) |

---

## Docker

Pre-built images are published to the GitHub Container Registry on every push:

```
ghcr.io/mbchristoff/xynta-certbot-plugin:latest   # latest build from main
ghcr.io/mbchristoff/xynta-certbot-plugin:main     # current main branch build
ghcr.io/mbchristoff/xynta-certbot-plugin:<branch> # sanitized branch-name build
```

Pull the latest image:

```bash
docker pull ghcr.io/mbchristoff/xynta-certbot-plugin:latest
```

### Environment variables

Configure the container entirely through environment variables — no credentials
file needs to be created on the host.

| Variable | Required | Default | Description |
|---|---|---|---|
| `XYNTA_API_USER_ID` | ✅ | — | Xynta HostFact API User ID |
| `XYNTA_API_IP_HASH` | ✅ | — | Xynta HostFact API IP Hash |
| `CERTBOT_EMAIL` | ✅ | — | Email address for Let's Encrypt account / recovery |
| `CERTBOT_DOMAINS` | ✅ | — | Comma-separated list of domains (e.g. `example.com,*.example.com`) |
| `XYNTA_API_URL` | ❌ | `https://api.xynta.com/` | Xynta API base URL |
| `CERTBOT_PROPAGATION_SECONDS` | ❌ | `120` | Seconds to wait for DNS propagation |
| `CERTBOT_STAGING` | ❌ | `false` | Set to `true` to use the Let's Encrypt staging environment (avoids rate limits during testing) |

### Using a `.env` file (recommended)

Copy `.env.example` to `.env`, fill in your values, and pass it to `docker run`:

```bash
cp .env.example .env
# edit .env with your credentials and domains
docker run --rm \
  --env-file .env \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/lib/letsencrypt:/var/lib/letsencrypt \
  ghcr.io/mbchristoff/xynta-certbot-plugin:latest
```

### Volumes

| Host path | Container path | Purpose |
|---|---|---|
| `/etc/letsencrypt` | `/etc/letsencrypt` | Issued certificates and certbot config |
| `/var/lib/letsencrypt` | `/var/lib/letsencrypt` | Certbot working directory (locks, accounts) |

### Run the container

**Single domain:**

```bash
docker run --rm \
  -e XYNTA_API_USER_ID=your-user-id \
  -e XYNTA_API_IP_HASH=your-ip-hash \
  -e CERTBOT_EMAIL=your-email@example.com \
  -e CERTBOT_DOMAINS=example.com \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/lib/letsencrypt:/var/lib/letsencrypt \
  ghcr.io/mbchristoff/xynta-certbot-plugin:latest
```

**Wildcard certificate:**

```bash
docker run --rm \
  -e XYNTA_API_USER_ID=your-user-id \
  -e XYNTA_API_IP_HASH=your-ip-hash \
  -e CERTBOT_EMAIL=your-email@example.com \
  -e "CERTBOT_DOMAINS=example.com,*.example.com" \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/lib/letsencrypt:/var/lib/letsencrypt \
  ghcr.io/mbchristoff/xynta-certbot-plugin:latest
```

**With custom propagation time:**

```bash
docker run --rm \
  -e XYNTA_API_USER_ID=your-user-id \
  -e XYNTA_API_IP_HASH=your-ip-hash \
  -e CERTBOT_EMAIL=your-email@example.com \
  -e "CERTBOT_DOMAINS=example.com,*.example.com" \
  -e CERTBOT_PROPAGATION_SECONDS=300 \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/lib/letsencrypt:/var/lib/letsencrypt \
  ghcr.io/mbchristoff/xynta-certbot-plugin:latest
```

After a successful run the certificates are stored on the host at
`/etc/letsencrypt/live/<domain>/`.

### Renewing certificates

Pass `renew` as the command to run `certbot renew` instead of `certbot certonly`.
Only the API credentials (`XYNTA_API_USER_ID`, `XYNTA_API_IP_HASH`) are required —
`CERTBOT_EMAIL` and `CERTBOT_DOMAINS` are not needed because certbot reads those
from the stored renewal configuration.

```bash
docker run --rm \
  --env-file .env \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/lib/letsencrypt:/var/lib/letsencrypt \
  ghcr.io/mbchristoff/xynta-certbot-plugin:latest renew
```

#### Cron example

Add this line to your crontab (`crontab -e`) to attempt renewal every day at 03:00:

```cron
0 3 * * * docker run --rm --env-file /path/to/.env -v /etc/letsencrypt:/etc/letsencrypt -v /var/lib/letsencrypt:/var/lib/letsencrypt ghcr.io/mbchristoff/xynta-certbot-plugin:latest renew >> /var/log/certbot-renew.log 2>&1
```

Certbot only renews certificates that expire within 30 days, so running daily is safe.

### Build the image locally

```bash
docker build -t xynta-certbot-plugin .
```

---

## Development

Install dev dependencies:

```bash
pip install -e ".[dev]"
```

Run tests:

```bash
pytest certbot_dns_xynta/
```

Run linter:

```bash
ruff check certbot_dns_xynta/
```

---

## Troubleshooting

### Plugin not found by certbot

If `certbot plugins` doesn't list `dns-xynta`, make sure both certbot and the
plugin are installed in the **same** Python environment:

```bash
# Check the active certbot
which certbot

# If using system certbot but plugin installed in a venv, install both together:
pip install certbot certbot-dns-xynta
```

### API errors

- Verify the `api_url` is correct (default: `https://api.xynta.com/`).
- Check that your `api_user_id` and `api_ip_hash` match the values in the Xynta
  control panel.
- Ensure the domain you are trying to certify is managed by your Xynta account.

---

## License

Apache License 2.0