diff --git a/dockerfiles/Dockerfile.monero-p2pool b/dockerfiles/Dockerfile.monero-p2pool index a7c1cb5..08faea3 100644 --- a/dockerfiles/Dockerfile.monero-p2pool +++ b/dockerfiles/Dockerfile.monero-p2pool @@ -5,43 +5,33 @@ ARG P2POOL_VERSION=v4.9 FROM ${DEBIAN_IMAGE} AS fetch ARG TARGETARCH ARG P2POOL_VERSION - RUN set -eux; \ apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl jq xz-utils tar unzip; \ - update-ca-certificates; \ - rm -rf /var/lib/apt/lists/* - -# Pick the correct asset URL for our arch from the release metadata + apt-get install -y --no-install-recommends ca-certificates curl jq xz-utils tar; \ + update-ca-certificates; rm -rf /var/lib/apt/lists/* RUN set -eux; \ case "${TARGETARCH:-arm64}" in \ - amd64) ARCH_RE='(x86_64|amd64)';; \ - arm64) ARCH_RE='(arm64|aarch64|armv8)';; \ - arm) ARCH_RE='(arm|armv7|armhf)';; \ + amd64) ARCH_RE='(x86_64|amd64)';; \ + arm64) ARCH_RE='(arm64|aarch64|armv8)';; \ + arm) ARCH_RE='(arm|armv7|armhf)';; \ *) echo "Unsupported TARGETARCH=${TARGETARCH}"; exit 1;; \ esac; \ API="https://api.github.com/repos/SChernykh/p2pool/releases/tags/${P2POOL_VERSION}"; \ - URL="$(curl -fsSL "$API" | jq -r --arg re "$ARCH_RE" \ - '.assets[] | select((.name|test("linux")) and (.name|test($re))) | .browser_download_url' | head -n1)"; \ - test -n "$URL"; \ - echo "Downloading $URL"; \ - mkdir -p /tmp/p2pool; \ - curl -fsSL "$URL" -o /tmp/p2pool/p2pool.tar; \ - # try both common formats - ( tar -xOf /tmp/p2pool/p2pool.tar >/dev/null 2>&1 && tar -xf /tmp/p2pool/p2pool.tar -C /tmp/p2pool ) \ - || ( tar -xzf /tmp/p2pool/p2pool.tar -C /tmp/p2pool || tar -xJf /tmp/p2pool/p2pool.tar -C /tmp/p2pool ); \ - # find the p2pool binary and install as a stable name - P="$(find /tmp/p2pool -maxdepth 2 -type f -name 'p2pool' | head -n1)"; \ - test -n "$P"; \ - install -m 0755 "$P" /usr/local/bin/p2pool + URL="$(curl -fsSL "${API}" | jq -r --arg re "${ARCH_RE}" '.assets[].browser_download_url | select(test("linux") and test($re))' | head -n1)"; \ + test -n "${URL}"; echo "Downloading ${URL}"; \ + curl -fsSL "${URL}" -o /tmp/p2pool.tgz; \ + mkdir -p /out; tar -xzf /tmp/p2pool.tgz -C /out; \ + BIN="$(find /out -maxdepth 1 -type f -name 'p2pool*' | head -n1)"; \ + test -n "${BIN}"; install -m0755 "${BIN}" /out/p2pool FROM ${DEBIAN_IMAGE} RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends ca-certificates; \ - update-ca-certificates; \ - rm -rf /var/lib/apt/lists/* -COPY --from=fetch /usr/local/bin/p2pool /usr/local/bin/p2pool + update-ca-certificates; rm -rf /var/lib/apt/lists/* +COPY --from=fetch /out/p2pool /usr/local/bin/p2pool +RUN /usr/local/bin/p2pool --version || true EXPOSE 3333 -ENTRYPOINT ["p2pool"] +ENTRYPOINT ["/usr/local/bin/p2pool"] + diff --git a/dockerfiles/Dockerfile.monero-wallet-rpc b/dockerfiles/Dockerfile.monero-wallet-rpc index 85db546..7f65d71 100644 --- a/dockerfiles/Dockerfile.monero-wallet-rpc +++ b/dockerfiles/Dockerfile.monero-wallet-rpc @@ -20,17 +20,14 @@ RUN set -eux; \ *) echo "Unsupported TARGETARCH=${TARGETARCH}"; exit 1 ;; \ esac; \ URL="https://downloads.getmonero.org/cli/${F}-${MONERO_VERSION}.tar.bz2"; \ - echo "Downloading $URL"; \ + echo "Fetching $URL"; \ mkdir -p /opt/monero; \ curl -fsSL "$URL" -o /opt/monero/monero.tar.bz2; \ tar -xjf /opt/monero/monero.tar.bz2 -C /opt/monero --strip-components=1; \ - rm -f /opt/monero/monero.tar.bz2; \ - install -m 0755 /opt/monero/monero-* /usr/local/bin/ || true; \ - install -m 0755 /opt/monero/monerod /usr/local/bin/ || true; \ - install -m 0755 /opt/monero/monero-wallet-rpc /usr/local/bin/ + install -m 0755 /opt/monero/monero-wallet-rpc /usr/local/bin/monero-wallet-rpc; \ + rm -f /opt/monero/monero.tar.bz2 +ENV PATH="/usr/local/bin:/usr/bin:/bin" RUN /usr/local/bin/monero-wallet-rpc --version || true EXPOSE 18083 -ENTRYPOINT ["monero-wallet-rpc"] - diff --git a/scripts/monero_wallet_setup.fish b/scripts/wallet_monero_setup.fish similarity index 99% rename from scripts/monero_wallet_setup.fish rename to scripts/wallet_monero_setup.fish index 3033044..27fac29 100644 --- a/scripts/monero_wallet_setup.fish +++ b/scripts/wallet_monero_setup.fish @@ -518,7 +518,7 @@ function walletsvc_bootstrap --description "Interactive setup of monero-wallet-r echo " - |" echo " RPCU=\$(cat /run/monero-secrets/rpc-user);" echo " RPCP=\$(cat /run/monero-secrets/rpc-pass);" - echo " exec monero-wallet-rpc \\" + echo " exec /usr/local/bin/monero-wallet-rpc \\" echo " --wallet-dir /data \\" echo " --daemon-address $daemon_addr \\" echo " --rpc-bind-ip 0.0.0.0 --rpc-bind-port 18083 \\" diff --git a/scripts/wallet_sui_setup.fish b/scripts/wallet_sui_setup.fish new file mode 100644 index 0000000..db6eb95 --- /dev/null +++ b/scripts/wallet_sui_setup.fish @@ -0,0 +1,275 @@ +### --------- helpers ---------- +function _need + for c in $argv + if not type -q $c + echo (set_color red)"Error:"(set_color normal)" missing command: $c" >&2 + return 1 + end + end +end + +function _banner -a MSG + set_color cyan; echo; echo "==> $MSG"; set_color normal +end + +function _k8s_name -a S + set s (string lower -- $S) + set s (string replace -ar -- '[^a-z0-9-]' '-' $s) + set s (string replace -r -- '^-+|(-)+$' '$1' $s) + echo $s +end + +function _require -a WHAT VAL + if test -z "$VAL" + echo (set_color red)"Error:"(set_color normal)" $WHAT cannot be empty." >&2 + return 1 + end +end + +function _sc_list + kubectl get storageclass -o json 2>/dev/null | jq -r ' + .items[] | [ + .metadata.name, + .provisioner, + (.reclaimPolicy // "Delete"), + ( .metadata.annotations["storageclass.kubernetes.io/is-default-class"] == "true" + or .metadata.annotations["storageclass.beta.kubernetes.io/is-default-class"] == "true") + ] | @tsv' +end + +function _choose_sc + set lines (_sc_list) + if test (count $lines) -eq 0 + echo (set_color red)"Error:"(set_color normal)" No StorageClasses found." >&2 + return 1 + end + echo "" >&2 + echo "==> Available StorageClasses" >&2 + echo " # | name | provisioner | reclaim | default" >&2 + echo "----+----------------------+------------------------+---------+--------" >&2 + set i 1 + for l in $lines + set name (echo $l | awk -F'\t' '{print $1}') + set prov (echo $l | awk -F'\t' '{print $2}') + set rec (echo $l | awk -F'\t' '{print $3}') + set def (echo $l | awk -F'\t' '{print $4}') + printf " %2d | %-20s | %-22s | %-7s | %s\n" $i $name $prov $rec $def >&2 + set i (math $i + 1) + end + set prefer (printf "%s\n" $lines | awk -F'\t' '$4=="true"{print $1}' | head -n1) + if test -z "$prefer" + set prefer (printf "%s\n" $lines | awk -F'\t' '{print $1}' | head -n1) + end + read -P "Pick StorageClass by number or name (blank = $prefer): " choice + if test -z "$choice" + echo $prefer + return 0 + end + if string match -qr '^[0-9]+$' -- $choice + set idx (math $choice) + if test $idx -lt 1 -o $idx -gt (count $lines) + echo (set_color red)"Error:"(set_color normal)" Choice out of range." >&2 + return 1 + end + printf "%s\n" $lines[$idx] | awk -F'\t' '{print $1}' + else + printf "%s\n" $lines | awk -F'\t' -v want="$choice" '$1==want{print $1}' + end +end + +### --------- main workflow ---------- +function suiwallet_bootstrap --description "Create a Sui wallet (PVC+Deployment) and generate a new address" + _need kubectl jq awk; or return 1 + + _banner "Sui wallet bootstrap" + + read -P "Namespace [crypto]: " ns + if test -z "$ns"; set ns crypto; end + set ns (_k8s_name $ns) + + echo "Ensuring namespace '$ns' exists…" + if not kubectl get ns $ns >/dev/null 2>&1 + kubectl create ns $ns; or return 1 + end + + kubectl get storageclass 2>/dev/null + echo "TIP: Prefer a Retain StorageClass so deleting the pod won't delete keys." + set sc (_choose_sc); or return 1 + + read -P "Wallet name (e.g. 'brad' → wallet-sui-brad): " wallet_raw + _require "Wallet name" $wallet_raw; or return 1 + set base (_k8s_name $wallet_raw) + set app "wallet-sui-$base" + set pvc $app + + read -P "Network [mainnet|testnet|devnet] [mainnet]: " net + if test -z "$net"; set net mainnet; end + switch $net + case mainnet + set rpc_url https://fullnode.mainnet.sui.io:443 + case testnet + set rpc_url https://fullnode.testnet.sui.io:443 + case devnet + set rpc_url https://fullnode.devnet.sui.io:443 + case '*' + echo (set_color red)"Error:"(set_color normal)" network must be mainnet|testnet|devnet"; return 1 + end + + read -P "Container image [mysten/sui-tools:latest]: " image + if test -z "$image"; set image mysten/sui-tools:latest; end + + read -P "Address alias to create [main]: " alias + if test -z "$alias"; set alias main; end + + read -P "Mnemonic word length [24]: " wl + if test -z "$wl"; set wl 24; end + + read -P "Store mnemonic as a Kubernetes Secret? (NOT recommended) (y/N): " store_mn + set store_mn (string lower -- $store_mn) + + _banner "Summary" + echo " Namespace: $ns" + echo " App name: $app" + echo " StorageClass: $sc" + echo " PVC: $pvc" + echo " Image: $image" + echo " Network: $net" + echo " RPC URL: $rpc_url" + echo " New alias: $alias (word length: $wl)" + read -P "Proceed? [y/N]: " ok + if not string match -qi 'y*' -- $ok + echo "Aborted."; return 1 + end + + _banner "Applying PVC" + kubectl -n $ns get pvc $pvc >/dev/null 2>&1; or begin + printf "%s\n" \ +"apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: $pvc + namespace: $ns +spec: + accessModes: [\"ReadWriteOnce\"] + storageClassName: $sc + resources: + requests: + storage: 1Gi" | kubectl apply -f -; or return 1 + end + + _banner "Applying Deployment" + printf "%s\n" \ +"apiVersion: apps/v1 +kind: Deployment +metadata: + name: $app + namespace: $ns + labels: { app: $app } +spec: + replicas: 1 + selector: { matchLabels: { app: $app } } + template: + metadata: + labels: { app: $app } + spec: + containers: + - name: sui-tools + image: $image + imagePullPolicy: IfNotPresent + command: [\"bash\",\"-lc\",\"sleep infinity\"] + volumeMounts: + - name: data + mountPath: /root/.sui + resources: + requests: { cpu: 50m, memory: 128Mi } + limits: { cpu: 1, memory: 512Mi } + volumes: + - name: data + persistentVolumeClaim: { claimName: $pvc }" | kubectl apply -f -; or return 1 + + _banner "Waiting for rollout" + kubectl -n $ns rollout status deploy/$app --timeout=120s; or return 1 + + _banner "Initializing Sui client env ($net) and creating a new address" + # new-env: writes client.yaml; new-address: writes to sui.keystore and prints the phrase + set OUT (mktemp) + kubectl -n $ns exec deploy/$app -- bash -lc \ + (printf 'mkdir -p /root/.sui/sui_config ; + sui client new-env --alias %s --rpc %s >/dev/null 2>&1 || true ; + sui client new-address ed25519 --word-length %s --alias %s' \ + $net $rpc_url $wl $alias) | tee $OUT + + set ADDR (kubectl -n $ns exec deploy/$app -- bash -lc \ + (printf 'sui client addresses | awk "/%s/{print \$NF}" | tail -n1' $alias)) + + echo + echo (set_color yellow)"IMPORTANT — Secret Recovery Phrase (write down & store offline):"(set_color normal) + grep -E 'Secret Recovery Phrase|Mnemon' $OUT -A2 | sed -e 's/^\s\+//' + echo + echo "Address alias '$alias' appears to be: $ADDR" + rm -f $OUT + + if test "$store_mn" = "y" -o "$store_mn" = "yes" + set MN (kubectl -n $ns exec deploy/$app -- bash -lc \ + (printf 'sui client addresses >/dev/null 2>&1 ; sui client new-address ed25519 --word-length %s --alias %s --json 2>/dev/null | jq -r .secretRecoveryPhrase || true' $wl "${alias}-dup")) + if test -n "$MN" -a "$MN" != "null" + kubectl -n $ns create secret generic {$app}-mnemonic \ + --from-literal=mnemonic="$MN" --dry-run=client -o yaml | kubectl -n $ns apply -f - + echo (set_color yellow)"Stored mnemonic in Secret $ns/{$app}-mnemonic. Treat your cluster as sensitive."(set_color normal) + # clean the duplicate alias we created to harvest JSON + kubectl -n $ns exec deploy/$app -- bash -lc "sui client remove-address --alias ${alias}-dup >/dev/null 2>&1 || true" >/dev/null 2>&1 + else + echo (set_color red)"Warning:"(set_color normal)" could not capture mnemonic via --json, not storing." + end + end + + echo + echo "Done. Files inside the pod:" + kubectl -n $ns exec deploy/$app -- bash -lc 'ls -l /root/.sui/sui_config || true' + echo + echo "Useful commands:" + echo " suiwallet_addresses $ns $app" + echo " suiwallet_export_keystore $ns $app ./sui.keystore.$base" + echo " kubectl -n $ns exec -it deploy/$app -- bash # interactive CLI" +end + +### --------- utilities ---------- +function suiwallet_addresses -a NS APP + if test -z "$NS"; set NS crypto; end + if test -z "$APP"; set APP wallet-sui-main; end + kubectl -n $NS exec deploy/$APP -- bash -lc 'sui client addresses || true' +end + +function suiwallet_export_keystore -a NS APP DEST + if test -z "$NS"; set NS crypto; end + if test -z "$APP"; set APP wallet-sui-main; end + if test -z "$DEST"; set DEST ./sui.keystore; end + echo "Copying keystore to $DEST (keep it safe!)" + kubectl -n $NS cp deploy/$APP:/root/.sui/sui_config/sui.keystore $DEST +end + +function suiwallet_status -a NS APP + if test -z "$NS"; set NS crypto; end + if test -z "$APP"; set APP wallet-sui-main; end + kubectl -n $NS get deploy,po,pvc -l app=$APP -o wide +end + +function suiwallet_stop -a NS APP + if test -z "$NS"; set NS crypto; end + if test -z "$APP"; set APP wallet-sui-main; end + kubectl -n $NS delete deploy $APP --ignore-not-found + echo "Stopped $NS/$APP (PVC kept)." +end + +function suiwallet_purge -a NS APP PVC + if test -z "$NS"; set NS crypto; end + if test -z "$APP"; set APP wallet-sui-main; end + if test -z "$PVC"; set PVC $APP; end + echo "Type to confirm: PURGE $NS $PVC" + read CONFIRM + if test "$CONFIRM" != "PURGE $NS $PVC" + echo "Aborted."; return 1 + end + kubectl -n $NS delete deploy $APP --ignore-not-found + kubectl -n $NS delete pvc $PVC --ignore-not-found --wait=true +end diff --git a/services/crypto/xmr-miner/xmrig-daemonset.yaml b/services/crypto/xmr-miner/xmrig-daemonset.yaml index 7c3d324..5abea02 100644 --- a/services/crypto/xmr-miner/xmrig-daemonset.yaml +++ b/services/crypto/xmr-miner/xmrig-daemonset.yaml @@ -39,7 +39,7 @@ spec: -o p2pool.crypto.svc.cluster.local:3333 \ -u x \ -k \ - --donate-level 0 \ + --donate-level N \ --cpu-priority 1 \ --threads "${THR}" ${EXTRA} volumeMounts: diff --git a/services/zot/deployment.yaml b/services/zot/deployment.yaml index ad4fa30..856880b 100644 --- a/services/zot/deployment.yaml +++ b/services/zot/deployment.yaml @@ -14,7 +14,7 @@ spec: labels: { app: zot } spec: nodeSelector: - kubernetes.io/arch: arm64 + node-role.kubernetes.io/worker: "true" containers: - name: zot image: ghcr.io/project-zot/zot-linux-arm64:latest