Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .beads/knowledge/gotchas.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# Example entry:
{"id":"gotcha-example-001","type":"gotcha","fact":"Example: Truthy check on numeric values fails for explicit zero - if (value) is false when value === 0.","recommendation":"Use !== undefined or !== null instead of truthy checks when the value could legitimately be 0 or empty string.","confidence":"high","provenance":[{"source":"coderabbit","reference":"PR review","date":"2026-01-09"}],"tags":["javascript","type-coercion","validation"],"affectedFiles":["**/*.ts"],"affectedServices":[],"createdAt":"2026-01-09T00:00:00Z","updatedAt":"2026-01-09T00:00:00Z","usageCount":0,"helpfulCount":0,"outdatedReports":0}
{"id":"gotcha-pin-shellcheck-version","type":"gotcha","fact":"GitHub-hosted runners ship a preinstalled ShellCheck whose version drifts; different versions report different findings (SC2236 fired on the runner but not on local 0.11.0).","recommendation":"Pin ShellCheck in CI by downloading the official koalaman release; keep SHELLCHECK_VERSION in ci.yml in sync with local dev (currently v0.11.0).","confidence":"high","provenance":[{"source":"agent","reference":"discovered fixing CI in PR #11","date":"2026-05-18"}],"tags":["ci","shellcheck","lint"],"affectedFiles":[".github/workflows/ci.yml"],"affectedServices":[],"createdAt":"2026-05-18T00:00:00Z","updatedAt":"2026-05-18T00:00:00Z","usageCount":0,"helpfulCount":0,"outdatedReports":0}
{"id":"gotcha-certbot-latest-flag-drift","type":"gotcha","fact":"The container is built FROM certbot/certbot:latest, so certbot's CLI drifts with each rebuild. Two flags broke: --manual-public-ip-logging-ok was removed (certbot errors 'unrecognized arguments'), and the bare --dns-ionos plugin selector became an ambiguous prefix of --dns-ionos-credentials/--dns-ionos-propagation-seconds ('ambiguous option: --dns-ionos').","recommendation":"Select third-party DNS plugins with '--authenticator dns-<name>' (unambiguous), never the bare '--dns-<name>' selector (that convenience flag only exists for certbot's official plugins). Avoid deprecated certbot flags. Consider pinning the certbot image to a known tag instead of :latest to stop silent CLI drift on rebuild.","confidence":"high","provenance":[{"source":"agent","reference":"fixing certbot failures on ethicserver","date":"2026-06-09"}],"tags":["certbot","docker","dns-ionos","flags","letsencrypt"],"affectedFiles":["commands/proxy.sh","Dockerfile"],"affectedServices":[],"createdAt":"2026-06-09T00:00:00Z","updatedAt":"2026-06-09T00:00:00Z","usageCount":0,"helpfulCount":0,"outdatedReports":0}
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [2.3.1] — 2026-06-09

### Fixed

- `easy proxy certbot-ionos` — select the DNS plugin with `--authenticator
dns-ionos` instead of the bare `--dns-ionos` flag. On recent certbot the bare
flag is an ambiguous prefix of `--dns-ionos-credentials` /
`--dns-ionos-propagation-seconds` and the command aborted with
`ambiguous option: --dns-ionos`.
- `easy proxy certbot` — drop the `--manual-public-ip-logging-ok` flag, removed
from modern certbot. It caused `unrecognized arguments`. IP-logging consent is
no longer prompted, so the flag is obsolete.

## [2.3.0] — 2026-05-19

### Added
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# easy-proxy — CLAUDE.md

> Nginx reverse proxy CLI con Let's Encrypt SSL automation e multi-DNS provider.
> Stato: **ATTIVO** — v2.3.0
> Ultimo aggiornamento: 2026-05-18
> Stato: **ATTIVO** — v2.3.1
> Ultimo aggiornamento: 2026-06-09

---

Expand Down
4 changes: 2 additions & 2 deletions commands/proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ function __easy_command_proxy {
echo "Invalid Domain. Set environment variable EASY_LETSENCRYPT_DOMAIN"
return 1
fi
docker exec -it "${EASY_PROXY_NAME}" sudo certbot --email "${EASY_LETSENCRYPT_EMAIL}" --agree-tos --manual-public-ip-logging-ok certonly --manual --preferred-challenges dns -d "${EASY_LETSENCRYPT_DOMAIN},*.${EASY_LETSENCRYPT_DOMAIN}"
docker exec -it "${EASY_PROXY_NAME}" sudo certbot --email "${EASY_LETSENCRYPT_EMAIL}" --agree-tos certonly --manual --preferred-challenges dns -d "${EASY_LETSENCRYPT_DOMAIN},*.${EASY_LETSENCRYPT_DOMAIN}"
return $?
fi
if [[ "certbot-ionos" == "$2" ]]; then
Expand Down Expand Up @@ -154,7 +154,7 @@ chmod 600 /etc/letsencrypt/ionos.ini"
--non-interactive \
--agree-tos \
--email "${EASY_LETSENCRYPT_EMAIL}" \
--dns-ionos \
--authenticator dns-ionos \
--dns-ionos-credentials /etc/letsencrypt/ionos.ini \
-d "${domain}" -d "*.${domain}"

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ethiclab/easy-cli",
"version": "2.3.0",
"version": "2.3.1",
"description": "Nginx reverse proxy with Let's Encrypt SSL automation, multi-DNS provider support (IONOS, Route53, Cloudflare, DigitalOcean)",
"files": [
"easy",
Expand Down
4 changes: 2 additions & 2 deletions test/dispatcher.bats
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ setup() { easy_setup; }
@test "easy --version prints the package.json version" {
run easy --version
[ "$status" -eq 0 ]
[ "$output" = "2.3.0" ]
[ "$output" = "2.3.1" ]
}

@test "easy --version works without the runtime env vars set" {
unset EASY_LETSENCRYPT_DIR EASY_DOMAINS_DIR
run easy --version
[ "$status" -eq 0 ]
[ "$output" = "2.3.0" ]
[ "$output" = "2.3.1" ]
}

@test "easy with no command prints usage and fails" {
Expand Down
22 changes: 22 additions & 0 deletions test/proxy.bats
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,25 @@ setup() { easy_setup; }
[ "$status" -eq 1 ]
[[ "$output" == *"IONOS API credentials not found"* ]]
}

@test "easy proxy certbot-ionos selects the plugin with --authenticator (not the ambiguous --dns-ionos)" {
export DOCKER_LOG="$BATS_TEST_TMPDIR/docker.log"
mock_docker_running_record
export EASY_LETSENCRYPT_EMAIL="test@example.com"
export IONOS_API_KEY="key" IONOS_API_SECRET="secret"
run easy proxy certbot-ionos example.com
[ "$status" -eq 0 ]
# The bare --dns-ionos selector is ambiguous on modern certbot; must use --authenticator.
grep -q -- "--authenticator dns-ionos" "$DOCKER_LOG"
! grep -Eq -- "--dns-ionos( |$)" "$DOCKER_LOG"
}

@test "easy proxy certbot does not pass the removed --manual-public-ip-logging-ok flag" {
export DOCKER_LOG="$BATS_TEST_TMPDIR/docker.log"
mock_docker_running_record
export EASY_LETSENCRYPT_EMAIL="test@example.com"
export EASY_LETSENCRYPT_DOMAIN="example.com"
run easy proxy certbot
[ "$status" -eq 0 ]
! grep -q -- "--manual-public-ip-logging-ok" "$DOCKER_LOG"
}
14 changes: 14 additions & 0 deletions test/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ MOCK
chmod +x "$MOCK_BIN/docker"
}

# Mock `docker`: the proxy is running AND every invocation is logged to
# $DOCKER_LOG. Lets a test assert the exact certbot flags passed via `docker exec`.
mock_docker_running_record() {
cat > "$MOCK_BIN/docker" <<'MOCK'
#!/usr/bin/env bash
echo "$*" >> "${DOCKER_LOG:-/dev/null}"
case "$1" in
ps) echo "deadbeefcafe1234" ;;
*) exit 0 ;;
esac
MOCK
chmod +x "$MOCK_BIN/docker"
}

# Mock `pass` so credential lookups always miss (no stored secrets).
mock_pass_empty() {
printf '#!/usr/bin/env bash\nexit 1\n' > "$MOCK_BIN/pass"
Expand Down
Loading