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 @@ -4,3 +4,4 @@
{"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}
{"id":"gotcha-reinstall-breaks-bind-mount","type":"gotcha","fact":"easy proxy create bind-mounts ${EASY_DIR}/easyhome -> /usr/local/share/easy (EASY_DIR = dirname of the resolved 'easy' binary, i.e. the npm install dir). Running 'npm install -g' while the proxy container is up rewrites that directory, so the live container's bind mount points at the replaced inode and nginx -s reload fails: open() \"/usr/local/share/easy/nginx.conf\" failed (No such file or directory).","recommendation":"After upgrading the CLI with npm install -g, recreate the container so it re-binds to the fresh easyhome: 'easy proxy destroy && easy proxy create' (or 'easy proxy restart', which re-resolves the bind source). A plain reload is not enough. If backends live on Docker networks, set EASY_PROXY_NETWORK or run 'easy proxy recover' after recreating.","confidence":"high","provenance":[{"source":"agent","reference":"reload failure on ethicserver after upgrading to 2.3.1","date":"2026-06-09"}],"tags":["docker","bind-mount","npm","reload","nginx","upgrade"],"affectedFiles":["commands/proxy.sh","easy"],"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.2] — 2026-06-09

### Fixed

- `easy proxy certbot-ionos` — write `ionos.ini` in the format the current
`certbot-dns-ionos` plugin requires: `dns_ionos_prefix`, `dns_ionos_secret`
and `dns_ionos_endpoint` (https://api.hosting.ionos.com). The old
`dns_ionos_api_key` / `dns_ionos_api_secret` keys were dropped upstream and
certbot aborted with "Missing properties in credentials configuration file".
The stored credentials are unchanged — `ionos/api-key` is the public prefix,
`ionos/api-secret` is the secret. The endpoint can be overridden with
`IONOS_API_ENDPOINT`.

## [2.3.1] — 2026-06-09

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# easy-proxy — CLAUDE.md

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

---
Expand Down
13 changes: 10 additions & 3 deletions commands/proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,17 @@ function __easy_command_proxy {
return 1
fi

# Create credentials file in container
# IONOS Remote API endpoint — standard value covers all accounts; overridable.
local ionos_endpoint="${IONOS_API_ENDPOINT:-https://api.hosting.ionos.com}"

# Create credentials file in container. The certbot-dns-ionos plugin expects
# prefix/secret/endpoint keys (the IONOS API key is "<prefix>.<secret>", so the
# stored api-key is the public prefix and api-secret is the secret). The older
# dns_ionos_api_key / dns_ionos_api_secret keys were dropped upstream.
docker exec "${EASY_PROXY_NAME}" /bin/sh -c "cat > /etc/letsencrypt/ionos.ini <<'EOF'
dns_ionos_api_key = ${api_key}
dns_ionos_api_secret = ${api_secret}
dns_ionos_prefix = ${api_key}
dns_ionos_secret = ${api_secret}
dns_ionos_endpoint = ${ionos_endpoint}
EOF
chmod 600 /etc/letsencrypt/ionos.ini"

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.1",
"version": "2.3.2",
"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.1" ]
[ "$output" = "2.3.2" ]
}

@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.1" ]
[ "$output" = "2.3.2" ]
}

@test "easy with no command prints usage and fails" {
Expand Down
14 changes: 14 additions & 0 deletions test/proxy.bats
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ setup() { easy_setup; }
! grep -Eq -- "--dns-ionos( |$)" "$DOCKER_LOG"
}

@test "easy proxy certbot-ionos writes ionos.ini in the prefix/secret/endpoint format" {
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 ]
# Modern certbot-dns-ionos requires these keys; the legacy api_key/api_secret are gone.
grep -q -- "dns_ionos_prefix = key" "$DOCKER_LOG"
grep -q -- "dns_ionos_secret = secret" "$DOCKER_LOG"
grep -q -- "dns_ionos_endpoint = https://api.hosting.ionos.com" "$DOCKER_LOG"
! grep -q -- "dns_ionos_api_key" "$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
Expand Down
Loading