Files
ansible-role-wikideck/README.md
T
2026-10-19 12:51:18 -04:00

12 KiB
Raw Blame History

Ansible role: Wikideck

Deploy the Wikideck production container to an existing Kubernetes cluster using kubernetes.core.k8s. The role creates a single-replica Deployment, a persistent volume claim, a dedicated ServiceAccount, a ClusterIP Service, and a NetworkPolicy. An HTTPS Ingress is optional and disabled by default.

Wikideck is a prototype, not a hardened public service. This role does not add application authentication, distributed consensus, a database, or wallet recovery. Use test wallets and restrict access. Mining happens in the browser; the server coordinates the chain and verifies proofs.

Requirements

  • A Linux/macOS/WSL controller with Python 3.10+ and Ansible Core 2.16–2.19 (the selected Ansible release may require a newer Python).
  • Install controller packages from requirements.txt and the collection from requirements.yml.
  • A supported Kubernetes cluster with apps/v1 and networking.k8s.io/v1 APIs, a storage provisioner or an existing PVC, and a NetworkPolicy-capable CNI.
  • 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 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.
  • 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.

Install dependencies on the controller with pip install -r requirements.txt and ansible-galaxy collection install -r requirements.yml. Use an isolated Python environment. Windows controllers must run Ansible through WSL or Linux containers.

Usage

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 shows an HTTPS deployment with ingress-nginx and cert-manager. Replace the image, hostname, class, issuer, and controller namespace with real values before running it.

- 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

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 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.

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 for browser wallet cryptography. Configure HTTP-to-HTTPS redirect at your ingress controller; the example includes the ingress-nginx annotation. Ingress creation does not wait for DNS, certificate issuance, or an externally reachable endpoint.

Variables

All defaults are in defaults/main.yml.

Variable Default Description
wikideck_image empty, required Published image with explicit tag or SHA-256 digest; prefer a verified digest.
wikideck_name wikideck Resource name and instance label; at most 50 characters.
wikideck_namespace wikideck Namespace for all namespaced resources.
wikideck_create_namespace true Create the namespace; disable for a pre-provisioned namespace.
wikideck_kubeconfig / wikideck_kube_context null Override controller authentication/context. API TLS verification remains enabled.
wikideck_wait / wikideck_wait_timeout true / 300 Wait for Deployment readiness, timeout in seconds.
wikideck_image_pull_policy IfNotPresent Always, IfNotPresent, or Never.
wikideck_image_pull_secrets [] Names of existing registry Secrets in this namespace.
wikideck_offline false Starter articles without live Wikipedia requests.
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.
wikideck_ingress_class_name empty Omit to use the cluster default IngressClass.
wikideck_ingress_annotations {} Controller/cert-manager-specific configuration.
wikideck_tls_secret_name {{ wikideck_name }}-tls Existing or externally provisioned TLS Secret.
wikideck_existing_claim empty Use an existing PVC instead of creating one.
wikideck_storage_size 1Gi Requested PVC capacity; resizing requires StorageClass support.
wikideck_storage_class null null: cluster default; empty string: no class; otherwise a class name.
wikideck_storage_access_modes [ReadWriteOnce] ReadWriteOnce or ReadWriteOncePod; never ReadWriteMany.
wikideck_resources see defaults CPU/memory requests 100m/128Mi, limits 1/512Mi.
wikideck_node_selector / wikideck_tolerations / wikideck_affinity {} / [] / {} Pod placement settings.
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.
wikideck_network_policy_https_to public IPv4/IPv6 ranges, private/link-local excluded TCP 443 egress peers; omitted in offline mode.

Storage and safe updates

  • Exactly one replica and Recreate updates are deliberate and cannot be changed through role variables. Updates briefly interrupt service. Do not add an HPA, manually scale, or attach the same chain PVC to another writer.
  • ReadWriteOnce alone does not enforce a single pod on the same node. Prefer 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 contains the chain and signed transfer journal. 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. No privileged/root ownership-fixing init container is used.
  • The PVC is created before the Deployment without waiting, supporting WaitForFirstConsumer storage classes. Existing claims are not modified.
  • The role never deletes PVCs or Namespaces, and does not assign ownerReferences that would garbage-collect storage with the Deployment. Renaming resources or switching claims does not migrate data or remove previous resources.
  • Back up the chain before upgrades. Stop the Deployment for a consistent file 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.
  • Chain verification runs at startup. For large chains, review resources, startup probe budget (300 seconds), and readiness wait timeout. JSON storage is unbounded; this role cannot solve Wikideck's persistence scalability limits.

Security and networking

The workload uses a read-only root filesystem, drops all Linux capabilities, disallows privilege escalation, uses runtime-default seccomp, and has no mounted service account token or RBAC grants. Only persistent data and a 32 MiB memory temporary directory are writable. All three HTTP probes target /healthz on port 3001; Kubernetes does not use the image's Docker HEALTHCHECK. A 30-second grace period accommodates the application's 25-second shutdown deadline.

NetworkPolicy defaults allow same-namespace clients, cluster DNS in kube-system, and public HTTPS for Wikipedia. With ingress, explicitly allow the ingress controller's namespace/pods as shown in the example. Peer entries are additive OR alternatives: put a namespaceSelector and podSelector in the same entry to restrict pods within that namespace. Empty peer lists deny that traffic; empty peer objects are rejected to avoid accidentally allowing every source/destination.

Standard NetworkPolicy cannot allow Wikipedia by hostname; the default public TCP 443 egress is broader than a domain allowlist. Use CNI FQDN policies or an egress gateway if required. Policies are additive with any other policies in the namespace and have no effect without an enforcing CNI. NodeLocal DNS, host-network ingress controllers, service meshes, and private proxies may need peer changes.

TLS terminates at ingress; backend HTTP is private but not encrypted by this role. Use a properly configured service mesh if in-cluster encryption is required. TLS keys and registry credentials must be provisioned separately, not committed to playbooks. Use trusted, rotated certificates and retain Kubernetes API certificate verification. The role does not embed secrets or implement its own cryptography; image signature verification and encrypted storage are cluster operator responsibilities. Scan and rebuild the application image regularly.

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 role adds no authentication, WAF, or abuse protection.

Validation

tests/render.yml runs entirely offline: it validates inputs, renders/parses every template across default, ingress, existing-claim, storage class, offline, deny-all, and digest-image 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 is a real-cluster smoke test using the local checkout. Syntax-check it with ansible-playbook -i tests/inventory tests/test.yml --syntax-check. To deploy to a disposable test namespace, run it with ansible-playbook -i tests/inventory tests/test.yml -e wikideck_image=YOUR_IMAGE -e wikideck_namespace=wikideck-test. Run it a second time to verify idempotence. Check Pod readiness, /healthz, PVC retention across updates, DNS/HTTPS egress, TLS, and browser mining/transfer flows on your chosen cluster. Offline tests do not prove CSI/CNI/controller behavior.

Ansible check mode (--check --diff) is supported by the Kubernetes module, but still needs API access; creating a new namespace in check mode may require a separate namespace provisioning pass. No uninstall or automatic data deletion is provided.

License

MIT-0. See LICENSE. The application and Wikipedia/Wikimedia content retain their own upstream licenses and attribution requirements.