Updated for new version

This commit is contained in:
2026-10-29 11:44:17 -04:00
parent d038fe3bab
commit 885f4160a7
11 changed files with 199 additions and 56 deletions
+60 -42
View File
@@ -5,13 +5,16 @@ Deploy the Wikideck production container to an existing Kubernetes cluster using
volume claim, a dedicated ServiceAccount, a ClusterIP Service, and a NetworkPolicy.
An HTTPS Ingress is optional and disabled by default.
**Wikideck is an experimental RandomX testnet, not a production-ready public
mainnet.** The updated application has independent validating nodes, fork choice,
native NFTs, and encrypted wallet backup/recovery. It supplies no public bootnodes
or deployed public network. Use test wallets and no valuable assets. This role
**Wikideck is mainnet-first in code but remains an experimental, launch-gated
candidate; the current production decision is NO-GO.** No public network,
bootnodes, independent audit, or production readiness is established. The
application includes validating nodes, fork choice, native NFTs, and encrypted
local-wallet backup/recovery. Use test wallets and no valuable assets. This role
deploys a **validator**, never a miner: mining is an explicitly started native CLI
process outside the browser. Private keys, backups and passwords must stay off
validator pods and out of Ansible variables.
validator pods and out of Ansible variables. See the upstream
[mainnet launch gates](https://github.com/ericomeehan/wikideck/blob/main/docs/mainnet-launch.md)
and [operations/recovery guidance](https://github.com/ericomeehan/wikideck/blob/main/docs/operations-recovery.md).
## Requirements
@@ -24,13 +27,16 @@ validator pods and out of Ansible variables.
- Kubeconfig access to create/update/read the resources in the target namespace,
delete the role's Ingress/NetworkPolicy when disabled, and optionally create a
Namespace. No cluster-admin access or in-cluster workload RBAC is needed.
- **A published image built from Wikideck's production Dockerfile.** There is no
- **A published, immutable image built from Wikideck's production Dockerfile.** There is no
assumed official registry image. Set `wikideck_image` to your actual tagged or
digest-pinned image. The role does not build/push images or install a cluster.
preferably digest-pinned image. The role does not build/push images or install a cluster.
Rebuild from the current source: the image must include Node 24, libstdc++, and
the native RandomX executable, with `RANDOMX_BINARY` set by the image. An old
browser-mining image is incompatible. Build and verify for your worker node
architecture; do not assume a locally built image is multi-architecture.
architecture; do not assume a locally built image is multi-architecture. The
production Dockerfile defaults to mainnet and pins its profile/genesis into the
image manifest; runtime settings cannot change that identity. Testnet is an
explicit development fixture, not a public deployment profile.
- For ingress: an ingress controller, DNS, and a trusted TLS Secret in the app
namespace. Alternatively, configure cert-manager annotations and an existing
issuer. The role does not install cert-manager or create an issuer.
@@ -43,30 +49,23 @@ environment. Windows controllers must run Ansible through WSL or Linux container
Install this checkout into your playbook's role search path as `roles/wikideck`,
or install it using an Ansible Galaxy Git role requirement named `wikideck`.
[examples/playbook.yml](examples/playbook.yml) shows an HTTPS deployment with
ingress-nginx and cert-manager. Replace the image, hostname, peer URLs, class,
issuer, and controller namespace with real values before running it.
```yaml
- name: Deploy a cluster-internal Wikideck instance
hosts: localhost
connection: local
gather_facts: false
roles:
- role: wikideck
vars:
wikideck_image: registry.example.com/games/wikideck:1.0.0
```
[examples/playbook.yml](examples/playbook.yml) is the gated HTTPS deployment
example with ingress-nginx and cert-manager. It requires an approved image
digest, the image's verified manifest/genesis, launch gates, and real peers before
it will change the cluster. There is intentionally no ungated, copy-and-run
mainnet snippet: use a pre-task gate like the example. Empty gates cause the
application to exit before listening, but do not by themselves prevent Kubernetes
resources from being created.
Run the playbook on the controller, using its normal kubeconfig discovery or
`wikideck_kubeconfig` / `wikideck_kube_context` overrides. Do not target every
Kubernetes node: the role operates on the Kubernetes API, not over node SSH.
For a private local preview, forward the Service with
For an explicitly built testnet development image, forward the Service with
`kubectl -n wikideck port-forward service/wikideck 3001:80` and open
<http://127.0.0.1:3001>. Keep the forwarding bind address at its loopback default.
Wikideck already allows this local origin. Different hosts, ports, schemes, and
browser profiles use different browser wallets.
The app allows this local origin. Different hosts, ports, schemes, and browser
profiles use different browser wallets. This does not bypass mainnet startup gates.
For remote browsers, enable ingress and set `wikideck_public_origin` to exactly
`https://` followed by `wikideck_ingress_host` (no slash or path). HTTPS is needed
@@ -81,6 +80,11 @@ Set `wikideck_peers` to a list of up to 16 compatible peer HTTPS origins, such a
An empty list deliberately starts an **isolated validator**. There is no automatic
discovery, bootnode list, or automatic reciprocal configuration: configure the
other operators' nodes too. All nodes must run the same network/genesis/consensus.
For mainnet, application startup additionally requires at least two distinct
public HTTPS peer origins, an arrived image-pinned genesis time, the exact chain-ID
approval, and explicit unaudited-risk acceptance. These switches are not launch
approval from this role; the project currently records a NO-GO decision. The role
does not discover or verify peer independence.
Peer RPC uses `/p2p/*` on the **same port 3001** as the UI/API; no separate TCP/UDP
P2P Service or host networking is required. The existing `/` ingress path forwards
@@ -149,6 +153,8 @@ All defaults are in [defaults/main.yml](defaults/main.yml).
| `wikideck_image_pull_secrets` | `[]` | Names of existing registry Secrets in this namespace. |
| `wikideck_peers` | `[]` | Up to 16 static peer origins; empty means isolated. |
| `wikideck_allow_private_peers` | `false` | Explicit test-only private/HTTP peer permission. |
| `wikideck_mainnet_launch` | empty | Exact 64-character chain-ID startup approval; leave empty unless a launch is formally approved. |
| `wikideck_mainnet_risk_ack` | empty | Must equal `operator-accepts-unaudited-risk` to acknowledge residual risk; not a certification. |
| `wikideck_public_origin` | empty | Additional allowed HTTPS browser origin; required with ingress. |
| `wikideck_ingress_enabled` | `false` | Create TLS ingress; disabling removes the role's named ingress. |
| `wikideck_ingress_host` | empty | DNS hostname, without scheme, port, or path. |
@@ -161,6 +167,8 @@ All defaults are in [defaults/main.yml](defaults/main.yml).
| `wikideck_storage_access_modes` | `[ReadWriteOnce]` | `ReadWriteOnce` or `ReadWriteOncePod`; never `ReadWriteMany`. |
| `wikideck_resources` | see defaults | CPU/memory requests `250m`/`512Mi`, limits `1`/`1Gi`; small-validator starting point, not a capacity guarantee. |
| `wikideck_node_selector` / `wikideck_tolerations` / `wikideck_affinity` | `{}` / `[]` / `{}` | Pod placement settings. |
| `wikideck_trusted_proxies` | `[]` | Up to 16 literal proxy IPs/CIDRs; only trust actual edge source addresses after the edge overwrites forwarded headers. |
| `wikideck_ops_port` | empty | Optional port for a diagnostics listener bound only to container loopback; never add it to the Service, Ingress, or NetworkPolicy. |
| `wikideck_network_policy_enabled` | `true` | Manage network isolation; disabling deletes this role's policy. |
| `wikideck_network_policy_ingress_from` | same-namespace pods | List of NetworkPolicy peers allowed to reach TCP 3001; empty list denies all ingress. |
| `wikideck_network_policy_dns_to` | `kube-system` namespace | DNS peers allowed on UDP/TCP 53; adapt for custom/NodeLocal DNS. |
@@ -182,10 +190,14 @@ entrypoint are deliberately preserved; no production fake-PoW fallback is added.
`ReadWriteOncePod` if supported by your CSI driver. Do not force-delete an old
pod on a partitioned node until it has been fenced; Recreate is not a
distributed storage lock.
- `/app/data/testnet/ledger.json` stores the block DAG and pending transfers;
`/app/data/testnet-node.lock` exclusively locks the entire data directory.
The old demo chain is separate, not imported, and has **no migration** to the
new testnet. Back it up first; preferably use a fresh claim for the new network.
- The active ledger is SQLite at `/app/data/<profile>/ledger.sqlite` (with WAL
sidecars); `/app/data/<profile>-node.lock` exclusively locks that profile's data.
A matching legacy `ledger.json` may be imported once and is retained as a
recovery copy. The import path accepts at most 128 MiB and 10,000 blocks; these
are legacy-import limits, not live SQLite disk bounds. Different profiles and
chain identities must not share a writable claim. Preserve and back up existing
data before changing image profile or genesis; incompatible chain data fails
closed rather than resetting automatically.
The process runs
as UID/GID 1000 with `fsGroup: 1000`. Your storage driver must honor ownership
settings, or the existing volume must already be writable by this identity.
@@ -199,15 +211,18 @@ entrypoint are deliberately preserved; no production fake-PoW fallback is added.
backup or use your CSI provider's documented snapshot procedure. Encrypt disks
and backups, define retention, and test restores. Deleting a namespace or PVC
can still destroy data depending on the underlying reclaim policy.
- The current `node:backup` utility creates/verifies/restores ledger-only packages
while the node is stopped. It does not contain browser wallets, secrets, or
configuration, and it does not encrypt the package; store it in restricted,
encrypted off-host storage and verify a restore before relying on it.
- Full native RandomX revalidation runs before the server listens. Increase
`wikideck_startup_probe_failure_threshold` and `wikideck_wait_timeout` together
for your measured replay time, leaving scheduling/image-pull margin. A healthy
empty node does not exercise the native cache or prove peer synchronization.
- The app bounds the ledger to 128 MiB and 10,000 total DAG blocks, with 256
pending transfers. Complete NFT states are retained per DAG node, so RAM may
grow quadratically despite disk bounds. Whole-ledger rewrites and full replay
are **not suitable for a long-lived public chain**; a larger PVC does not fix
those application limits.
- SQLite avoids whole-ledger JSON rewrites, but the node retains DAG records in
memory, rebuilds state roots over the full NFT set, and revalidates proofs at
startup. Long-chain capacity and archival-scale operation remain unresolved;
a larger PVC does not fix memory, replay, or consensus-capacity limits.
### Crash recovery and resource sizing
@@ -268,12 +283,15 @@ your worker architecture and runtime security profile; HTTP health alone cannot
detect every native engine failure. Do not grant privileged mode or disable
seccomp as an untested performance workaround.
Wikideck does not currently configure Express `trust proxy`. Clients behind one
proxy can therefore share an IP-based application rate limit. Review the
application before public exposure; do not try to fix this by blindly trusting
forwarded headers. The current app limits `/api` and `/p2p` together; default
forwarded-header behavior can also produce express-rate-limit validation errors
in logs. The role adds no authentication, WAF, or abuse protection. Eclipse,
`WIKIDECK_TRUSTED_PROXIES` is empty/untrusted by default. Populate
`wikideck_trusted_proxies` only with the literal source addresses/CIDRs actually
used by the trusted edge; the app validates them at startup. The edge must
overwrite forwarded headers, and network controls must prevent direct backend
access. Do not copy a generic proxy range without verifying the cluster path.
The optional `WIKIDECK_OPS_PORT` listener is loopback-only inside the pod and is
not exposed by role resources. It is intended for local/container-exec checks,
not an ingress endpoint. The role adds no authentication, WAF, or abuse
protection. Eclipse,
majority-hashpower, spam/DoS and reorganization risks remain application/protocol
issues; deployment hardening does not make a public mainnet safe.
@@ -282,8 +300,8 @@ issues; deployment hardening does not make a public mainnet safe.
[tests/render.yml](tests/render.yml) runs entirely offline: it validates inputs,
renders/parses every template across default, ingress, existing-claim, storage
class, isolated/public/private peers, custom HTTPS ports, deny-all, longer startup,
and digest-image variants, and checks wiring/security
invariants. It also checks that unsafe/invalid settings are rejected. Run it with
digest-image, launch-gate, proxy-trust and diagnostics variants, and checks
wiring/security invariants. It also checks that unsafe/invalid settings are rejected. Run it with
`ansible-playbook -i tests/inventory tests/render.yml`.
[tests/test.yml](tests/test.yml) is a real-cluster smoke test using the local