From 30639737441dc8ea33a5b1c9ffb53c9517713922 Mon Sep 17 00:00:00 2001
From: fratoro <7229526+fratoro@users.noreply.github.com>
Date: Tue, 9 Dec 2025 16:49:12 +0100
Subject: [PATCH 01/11] Update dns_cyon to use unique user-agent and all
cookies
---
dnsapi/dns_cyon.sh | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh
index a585e772..882ebc48 100644
--- a/dnsapi/dns_cyon.sh
+++ b/dnsapi/dns_cyon.sh
@@ -101,6 +101,8 @@ _cyon_load_parameters() {
# This header is required for curl calls.
_H1="X-Requested-With: XMLHttpRequest"
export _H1
+ _H3="User-Agent: cyon-dns-acmesh/1.0"
+ export _H3
}
_cyon_print_header() {
@@ -125,7 +127,11 @@ _cyon_print_header() {
}
_cyon_get_cookie_header() {
- printf "Cookie: %s" "$(grep "cyon=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'cyon=[^;]*;' | tr -d ';')"
+ # Extract all cookies from the response headers (case-insensitive)
+ _cookies="$(grep -i "^set-cookie:" "$HTTP_HEADER" | sed 's/^[Ss]et-[Cc]ookie: //' | sed 's/;.*//' | tr '\n' '; ' | sed 's/; $//')"
+ if [ -n "$_cookies" ]; then
+ printf "Cookie: %s" "$_cookies"
+ fi
}
_cyon_login() {
@@ -155,6 +161,13 @@ _cyon_login() {
_get "https://my.cyon.ch/" >/dev/null
+ # Update cookie after loading main page (only if new cookies are set)
+ _new_cookies="$(_cyon_get_cookie_header)"
+ if [ -n "$_new_cookies" ]; then
+ _H2="$_new_cookies"
+ export _H2
+ fi
+
# todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request.
# 2FA authentication with OTP?
@@ -184,6 +197,13 @@ _cyon_login() {
fi
_info " success"
+
+ # Update cookie after 2FA (only if new cookies are set)
+ _new_cookies="$(_cyon_get_cookie_header)"
+ if [ -n "$_new_cookies" ]; then
+ _H2="$_new_cookies"
+ export _H2
+ fi
fi
_info ""
@@ -205,7 +225,17 @@ _cyon_change_domain_env() {
domain_env="$(printf "%s" "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/')"
_debug "Changing domain environment to ${domain_env}"
- gloo_item_key="$(_get "https://my.cyon.ch/domain/" | tr '\n' ' ' | sed -E -e "s/.*data-domain=\"${domain_env}\"[^<]*data-itemkey=\"([^\"]*).*/\1/")"
+ domain_page_response="$(_get "https://my.cyon.ch/domain/")"
+ _debug domain_page_response "${domain_page_response}"
+
+ # Check if we got an error response (JSON) instead of HTML
+ if printf "%s" "${domain_page_response}" | grep -q '"iserror":true'; then
+ _err " $(printf "%s" "${domain_page_response}" | _cyon_get_response_message)"
+ _err ""
+ return 1
+ fi
+
+ gloo_item_key="$(printf "%s" "${domain_page_response}" | tr '\n' ' ' | sed -E -e "s/.*data-domain=\"${domain_env}\"[^<]*data-itemkey=\"([^\"]*).*/\1/")"
_debug gloo_item_key "${gloo_item_key}"
domain_env_url="https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/${gloo_item_key}"
From 70bc5a6fbac33463e2e22dcb21e29b639dd33ffd Mon Sep 17 00:00:00 2001
From: fratoro <7229526+fratoro@users.noreply.github.com>
Date: Tue, 9 Dec 2025 22:57:26 +0100
Subject: [PATCH 02/11] Update dns_cyon to use unique user-agent and all
cookies
---
dnsapi/dns_cyon.sh | 2 --
1 file changed, 2 deletions(-)
diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh
index 882ebc48..0c74be2a 100644
--- a/dnsapi/dns_cyon.sh
+++ b/dnsapi/dns_cyon.sh
@@ -168,8 +168,6 @@ _cyon_login() {
export _H2
fi
- # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request.
-
# 2FA authentication with OTP?
if [ -n "${CY_OTP_Secret}" ]; then
_info " - Authorising with OTP code..."
From 5ad2bea129b6a497aae30e50f64ac387a629d0f6 Mon Sep 17 00:00:00 2001
From: Denis Kurz
Date: Sat, 10 Jan 2026 01:03:37 +0100
Subject: [PATCH 03/11] fix typos
---
dnsapi/dns_dynv6.sh | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh
index 0c9491f8..a68b5fb9 100644
--- a/dnsapi/dns_dynv6.sh
+++ b/dnsapi/dns_dynv6.sh
@@ -107,7 +107,7 @@ _get_domain() {
return 0
fi
done
- _err "Either their is no such host on your dnyv6 account or it cannot be accessed with this key"
+ _err "Either there is no such host on your dynv6 account, or it cannot be accessed with this key"
return 1
}
@@ -179,8 +179,8 @@ _dns_dynv6_rm_http() {
fi
}
+#Usage: _get_zone_id $record
#get the zoneid for a specifc record or zone
-#usage: _get_zone_id §record
#where $record is the record to get the id for
#returns _zone_id the id of the zone
_get_zone_id() {
@@ -217,9 +217,9 @@ _get_zone_name() {
_zone_name="${_zone_name#name:}"
}
-#usaage _get_record_id $zone_id $record
-# where zone_id is thevalue returned by _get_zone_id
-# and record ist in the form _acme.www for an fqdn of _acme.www.example.com
+#usage _get_record_id $zone_id $record
+# where zone_id is the value returned by _get_zone_id
+# and record is in the form _acme.www for an fqdn of _acme.www.example.com
# returns _record_id
_get_record_id() {
_zone_id="$1"
From 880d93f7f7645995b716f39e9666cb76acc10351 Mon Sep 17 00:00:00 2001
From: Denis Kurz
Date: Sat, 10 Jan 2026 01:06:48 +0100
Subject: [PATCH 04/11] fix(dynv6): allow 'id' in dns challenge
If the random dns challenge string happens to contain 'id',
the parsing method passed a broken, mingled mix of the
record's data and id field, instead of just the id. As a result,
deleting the TXT record failed. We now specifically look for
'"id":', which cannot appear as part of the challenge string.
---
dnsapi/dns_dynv6.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh
index a68b5fb9..d5d49094 100644
--- a/dnsapi/dns_dynv6.sh
+++ b/dnsapi/dns_dynv6.sh
@@ -234,7 +234,7 @@ _get_record_id() {
_get_record_id_from_response() {
response="$1"
- _record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep id | tr -d '"' | tr -d 'id:')"
+ _record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep '"id":' | tr -d '"' | tr -d 'id:' | tr -d '{')"
#_record_id="${_record_id#id:}"
if [ -z "$_record_id" ]; then
_err "no such record: $record found in zone $_zone_id"
From b37867d027d6b54e3946193fa2d672de225b1c5f Mon Sep 17 00:00:00 2001
From: Denis Kurz
Date: Sat, 10 Jan 2026 01:26:06 +0100
Subject: [PATCH 05/11] remove unused code
---
dnsapi/dns_dynv6.sh | 2 --
1 file changed, 2 deletions(-)
diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh
index d5d49094..3e7ce8d6 100644
--- a/dnsapi/dns_dynv6.sh
+++ b/dnsapi/dns_dynv6.sh
@@ -189,7 +189,6 @@ _get_zone_id() {
_dynv6_rest GET zones
zones="$(echo "$response" | tr '}' '\n' | tr ',' '\n' | grep name | sed 's/\[//g' | tr -d '{' | tr -d '"')"
- #echo $zones
selected=""
for z in $zones; do
@@ -235,7 +234,6 @@ _get_record_id() {
_get_record_id_from_response() {
response="$1"
_record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep '"id":' | tr -d '"' | tr -d 'id:' | tr -d '{')"
- #_record_id="${_record_id#id:}"
if [ -z "$_record_id" ]; then
_err "no such record: $record found in zone $_zone_id"
return 1
From 5e670e0d93199c7a74146c9c93c4c1eed92e16fe Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:02:47 +0100
Subject: [PATCH 06/11] support haiku
---
.github/workflows/DNS.yml | 53 ++++++++++++++++++
.github/workflows/Haiku.yml | 79 +++++++++++++++++++++++++++
acme.sh | 104 +++++++++++++++++++++++++-----------
3 files changed, 205 insertions(+), 31 deletions(-)
create mode 100644 .github/workflows/Haiku.yml
diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml
index 4634ed96..957d0e97 100644
--- a/.github/workflows/DNS.yml
+++ b/.github/workflows/DNS.yml
@@ -597,4 +597,57 @@ jobs:
+ Haiku:
+ runs-on: ubuntu-latest
+ needs: OpenIndiana
+ env:
+ TEST_DNS : ${{ secrets.TEST_DNS }}
+ TestingDomain: ${{ secrets.TestingDomain }}
+ TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
+ TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
+ TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
+ CASE: le_test_dnsapi
+ TEST_LOCAL: 1
+ DEBUG: ${{ secrets.DEBUG }}
+ http_proxy: ${{ secrets.http_proxy }}
+ https_proxy: ${{ secrets.https_proxy }}
+ HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since OpenIndiana doesn't accept the expired ISRG X1 root
+ TokenName1: ${{ secrets.TokenName1}}
+ TokenName2: ${{ secrets.TokenName2}}
+ TokenName3: ${{ secrets.TokenName3}}
+ TokenName4: ${{ secrets.TokenName4}}
+ TokenName5: ${{ secrets.TokenName5}}
+ steps:
+ - uses: actions/checkout@v4
+ - name: Clone acmetest
+ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
+ - uses: vmactions/haiku-vm@v1
+ with:
+ envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
+ sync: rsync
+ run: |
+ if [ "${{ secrets.TokenName1}}" ] ; then
+ export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
+ fi
+ if [ "${{ secrets.TokenName2}}" ] ; then
+ export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
+ fi
+ if [ "${{ secrets.TokenName3}}" ] ; then
+ export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
+ fi
+ if [ "${{ secrets.TokenName4}}" ] ; then
+ export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
+ fi
+ if [ "${{ secrets.TokenName5}}" ] ; then
+ export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
+ fi
+ cd ../acmetest
+ ./letest.sh
+ - name: onError
+ if: ${{ failure() }}
+ run: |
+ echo "See how to debug in VM:"
+ echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM"
+
+
diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml
new file mode 100644
index 00000000..3ae50051
--- /dev/null
+++ b/.github/workflows/Haiku.yml
@@ -0,0 +1,79 @@
+name: Haiku
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - '*.sh'
+ - '.github/workflows/Haiku.yml'
+
+ pull_request:
+ branches:
+ - dev
+ paths:
+ - '*.sh'
+ - '.github/workflows/Haiku.yml'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+
+
+jobs:
+ Haiku:
+ strategy:
+ matrix:
+ include:
+ - TEST_ACME_Server: "LetsEncrypt.org_test"
+ CA_ECDSA: ""
+ CA: ""
+ CA_EMAIL: ""
+ TEST_PREFERRED_CHAIN: (STAGING)
+ - TEST_ACME_Server: "LetsEncrypt.org_test"
+ CA_ECDSA: ""
+ CA: ""
+ CA_EMAIL: ""
+ TEST_PREFERRED_CHAIN: (STAGING)
+ ACME_USE_WGET: 1
+ #- TEST_ACME_Server: "ZeroSSL.com"
+ # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
+ # CA: "ZeroSSL RSA Domain Secure Site CA"
+ # CA_EMAIL: "githubtest@acme.sh"
+ # TEST_PREFERRED_CHAIN: ""
+ runs-on: ubuntu-latest
+ env:
+ TEST_LOCAL: 1
+ TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
+ CA_ECDSA: ${{ matrix.CA_ECDSA }}
+ CA: ${{ matrix.CA }}
+ CA_EMAIL: ${{ matrix.CA_EMAIL }}
+ TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
+ ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: vmactions/cf-tunnel@v0
+ id: tunnel
+ with:
+ protocol: http
+ port: 8080
+ - name: Set envs
+ run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
+ - name: Clone acmetest
+ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
+ - uses: vmactions/haiku-vm@v1
+ with:
+ envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
+ nat: |
+ "8080": "80"
+ prepare: pkg install socat curl
+ sync: nfs
+ run: |
+ cd ../acmetest \
+ && ./letest.sh
+ - name: onError
+ if: ${{ failure() }}
+ run: |
+ echo "See how to debug in VM:"
+ echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM"
+
diff --git a/acme.sh b/acme.sh
index d2e3b766..1a3763c3 100755
--- a/acme.sh
+++ b/acme.sh
@@ -250,6 +250,13 @@ _dlg_versions() {
socat -V 2>&1
else
_debug "socat doesn't exist."
+ if _exists "python3"; then
+ python3 -V 2>&1
+ elif _exists "python2"; then
+ python2 -V 2>&1
+ elif _exists "python"; then
+ python -V 2>&1
+ fi
fi
}
@@ -2559,41 +2566,76 @@ _startserver() {
_debug Le_Listen_V4 "$Le_Listen_V4"
_debug Le_Listen_V6 "$Le_Listen_V6"
- _NC="socat"
- if [ "$Le_Listen_V6" ]; then
- _NC="$_NC -6"
- SOCAT_OPTIONS=TCP6-LISTEN
- elif [ "$Le_Listen_V4" ]; then
- _NC="$_NC -4"
- SOCAT_OPTIONS=TCP4-LISTEN
- else
- SOCAT_OPTIONS=TCP-LISTEN
- fi
+ if _exists "socat"; then
+ _NC="socat"
+ if [ "$Le_Listen_V6" ]; then
+ _NC="$_NC -6"
+ SOCAT_OPTIONS=TCP6-LISTEN
+ elif [ "$Le_Listen_V4" ]; then
+ _NC="$_NC -4"
+ SOCAT_OPTIONS=TCP4-LISTEN
+ else
+ SOCAT_OPTIONS=TCP-LISTEN
+ fi
- if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
- _NC="$_NC -d -d -v"
- fi
+ if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
+ _NC="$_NC -d -d -v"
+ fi
- SOCAT_OPTIONS=$SOCAT_OPTIONS:$Le_HTTPPort,crlf,reuseaddr,fork
+ SOCAT_OPTIONS=$SOCAT_OPTIONS:$Le_HTTPPort,crlf,reuseaddr,fork
- #Adding bind to local-address
- if [ "$ncaddr" ]; then
- SOCAT_OPTIONS="$SOCAT_OPTIONS,bind=${ncaddr}"
- fi
+ #Adding bind to local-address
+ if [ "$ncaddr" ]; then
+ SOCAT_OPTIONS="$SOCAT_OPTIONS,bind=${ncaddr}"
+ fi
- _content_len="$(printf "%s" "$content" | wc -c)"
- _debug _content_len "$_content_len"
- _debug "_NC" "$_NC $SOCAT_OPTIONS"
- export _SOCAT_ERR="$(_mktemp)"
- $_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \
+ _content_len="$(printf "%s" "$content" | wc -c)"
+ _debug _content_len "$_content_len"
+ _debug "_NC" "$_NC $SOCAT_OPTIONS"
+ export _SOCAT_ERR="$(_mktemp)"
+ $_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \
echo 'HTTP/1.0 200 OK'; \
echo 'Content-Length\: $_content_len'; \
echo ''; \
printf '%s' '$content';" 2>"$_SOCAT_ERR" &
- serverproc="$!"
+ serverproc="$!"
+ else
+ _PYTHON=""
+ if _exists "python3"; then
+ _PYTHON="python3"
+ elif _exists "python2"; then
+ _PYTHON="python2"
+ elif _exists "python"; then
+ _PYTHON="python"
+ fi
+ if [ "$_PYTHON" ]; then
+ _debug "Using python: $_PYTHON"
+ _AF="socket.AF_INET"
+ _BIND_ADDR="0.0.0.0"
+ if [ "$Le_Listen_V6" ]; then
+ _AF="socket.AF_INET6"
+ _BIND_ADDR="::"
+ fi
+ if [ "$ncaddr" ]; then
+ _BIND_ADDR="$ncaddr"
+ fi
+ export _SOCAT_ERR="$(_mktemp)"
+ $_PYTHON -c "import socket,sys;s=socket.socket($_AF,socket.SOCK_STREAM);s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1);s.bind((sys.argv[2],int(sys.argv[1])));s.listen(5);res='HTTP/1.0 200 OK\r\nContent-Length: '+str(len(sys.argv[3]))+'\r\n\r\n'+sys.argv[3];
+while True:
+ c,a=s.accept()
+ c.sendall(res.encode() if hasattr(res, 'encode') else res)
+ c.close()" "$Le_HTTPPort" "$_BIND_ADDR" "$content" 2>"$_SOCAT_ERR" &
+ serverproc="$!"
+ _NC="$_PYTHON"
+ else
+ _err "Please install socat or python first for standalone mode."
+ return 1
+ fi
+ fi
+
if [ -f "$_SOCAT_ERR" ]; then
if grep "Permission denied" "$_SOCAT_ERR" >/dev/null; then
- _err "socat: $(cat $_SOCAT_ERR)"
+ _err "$_NC: $(cat $_SOCAT_ERR)"
_err "Can not listen for user: $(whoami)"
_err "Maybe try with root again?"
rm -f "$_SOCAT_ERR"
@@ -3557,9 +3599,9 @@ _on_before_issue() {
fi
fi
- if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
- if ! _exists "socat"; then
- _err "Please install socat tools first."
+ if _hasfield "$_chk_web_roots" "$NO_VALUE" && [ "$_chk_web_roots" = "$NO_VALUE" ]; then
+ if ! _exists "socat" && ! _exists "python" && ! _exists "python2" && ! _exists "python3"; then
+ _err "Please install socat or python tools first."
return 1
fi
fi
@@ -6664,9 +6706,9 @@ _precheck() {
return 1
fi
- if ! _exists "socat"; then
- _err "It is recommended to install socat first."
- _err "We use socat for the standalone server, which is used for standalone mode."
+ if ! _exists "socat" && ! _exists "python" && ! _exists "python2" && ! _exists "python3"; then
+ _err "It is recommended to install socat or python first."
+ _err "We use socat or python for the standalone server, which is used for standalone mode."
_err "If you don't want to use standalone mode, you may ignore this warning."
fi
From 09009794e02b83606b025bbf72c83e1b1851bfe0 Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:10:37 +0100
Subject: [PATCH 07/11] fix
---
.github/workflows/Haiku.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml
index 3ae50051..3cf8d5db 100644
--- a/.github/workflows/Haiku.yml
+++ b/.github/workflows/Haiku.yml
@@ -66,8 +66,8 @@ jobs:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: |
"8080": "80"
- prepare: pkg install socat curl
- sync: nfs
+ sync: rsync
+ copyback: false
run: |
cd ../acmetest \
&& ./letest.sh
From 3e36b618237c19c7347bba3fcb718a36fea0eeab Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:14:29 +0100
Subject: [PATCH 08/11] fix haiku
---
.github/workflows/DNS.yml | 2 ++
.github/workflows/Haiku.yml | 1 +
2 files changed, 3 insertions(+)
diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml
index 957d0e97..73e19b89 100644
--- a/.github/workflows/DNS.yml
+++ b/.github/workflows/DNS.yml
@@ -625,6 +625,8 @@ jobs:
with:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
sync: rsync
+ copyback: false
+ prepare: pkgman install -y cronie
run: |
if [ "${{ secrets.TokenName1}}" ] ; then
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml
index 3cf8d5db..6034cc4f 100644
--- a/.github/workflows/Haiku.yml
+++ b/.github/workflows/Haiku.yml
@@ -66,6 +66,7 @@ jobs:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: |
"8080": "80"
+ prepare: pkgman install -y cronie
sync: rsync
copyback: false
run: |
From d8c062defb622ff08d3a333dd283cac300c385f6 Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:21:08 +0100
Subject: [PATCH 09/11] fix haiku
---
.github/workflows/Haiku.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml
index 6034cc4f..4b78f930 100644
--- a/.github/workflows/Haiku.yml
+++ b/.github/workflows/Haiku.yml
@@ -23,6 +23,7 @@ concurrency:
jobs:
Haiku:
strategy:
+ fail-fast: false
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
From d57ab0ab7dd29e844360c52baeefb0f8f51e85b1 Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:28:45 +0100
Subject: [PATCH 10/11] fix haiku
---
.github/workflows/DNS.yml | 5 ++++-
.github/workflows/Haiku.yml | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml
index 73e19b89..1a37b8a9 100644
--- a/.github/workflows/DNS.yml
+++ b/.github/workflows/DNS.yml
@@ -626,7 +626,10 @@ jobs:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
sync: rsync
copyback: false
- prepare: pkgman install -y cronie
+ prepare: |
+ mkdir -p /boot/home/.cache
+ pkgman install -y cronie
+
run: |
if [ "${{ secrets.TokenName1}}" ] ; then
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml
index 4b78f930..1dbfc2c4 100644
--- a/.github/workflows/Haiku.yml
+++ b/.github/workflows/Haiku.yml
@@ -67,7 +67,9 @@ jobs:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: |
"8080": "80"
- prepare: pkgman install -y cronie
+ prepare: |
+ mkdir -p /boot/home/.cache
+ pkgman install -y cronie
sync: rsync
copyback: false
run: |
From 40b29c1879193e7a8da824f1ffa8f195e573b276 Mon Sep 17 00:00:00 2001
From: neil
Date: Sun, 11 Jan 2026 21:37:02 +0100
Subject: [PATCH 11/11] support Haiku OS
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 41b6b272..740e5ef0 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@
+
@@ -108,6 +109,7 @@
|21|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|22|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|23|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
+|24|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml)|Haiku OS
> 🧪 Check our [testing project](https://github.com/acmesh-official/acmetest)