Blockyard is a self-hosted platform for running
blockr applications in production.
blockr apps evaluate user-supplied R expressions inside every session,
which is a security model no general-purpose
Shiny host was designed for. Blockyard
provides hardened per-session worker isolation (as a Docker container
or a bubblewrap-sandboxed process), per-user credential management
via a Vault-compatible secrets manager, server-side dependency resolution,
and built-in board storage — the full blockr stack as a single binary.
How it works#
- You deploy a bundle — run
by deploy ./my-boardor upload a.tar.gzarchive via the REST API. Bundles can include dependency metadata (renv.lock,DESCRIPTION, ormanifest.json), or none at all — the server discovers what’s needed. - Blockyard resolves dependencies server-side — it spins up a build container and uses pak to install packages. Unpinned bundles can be refreshed in place later without a redeploy.
- Users visit the app — when a request hits
/app/<name>/, Blockyard spawns a worker on demand and reverse-proxies HTTP and WebSocket traffic to it. Each session gets its own isolated worker.
Workers run in one of two backends:
- Docker backend (default). Each worker is a container with a
private bridge network, read-only filesystem, all Linux capabilities
dropped,
no-new-privilegesset, and cloud metadata endpoint access blocked. High-security deployments can run workers under the Kata runtime for per-session VMs. - Process backend. Each worker is a
bubblewrap-sandboxed child process with PID/mount/user namespaces, capability dropping, and seccomp filtering. No container runtime required. Suitable for hosts where the Docker socket is unacceptable or where cold-start latency matters.
See Backend Security for the full comparison and Docker worker hardening for the Docker backend’s baseline settings.
Authentication & Authorization#
Blockyard supports OIDC-based authentication. When configured, users must
log in before accessing apps. System roles (admin, publisher, viewer) are
assigned directly by blockyard admins — not derived from IdP groups. Per-app
access control lists (ACLs) provide fine-grained authorization, and each app
has a visibility setting (acl, logged_in, or public).
Optionally, Blockyard integrates with a Vault-compatible secrets manager (tested against OpenBao; HashiCorp Vault also works) for per-user credential management, allowing Shiny apps to securely access external services like AI providers, databases, and object storage.
Key concepts#
- App
- A named Shiny application registered in Blockyard. Each app has a unique
URL-safe slug (e.g.
my-dashboard) and can have multiple bundles, with one marked as active. - Bundle
- A versioned deployment artifact — the
.tar.gzyou upload. Bundles go through a build step (dependency restore) before becoming ready to serve. - Worker
- A running process serving a Shiny app. Implemented as a Docker container or a bubblewrap-sandboxed child process depending on the configured backend. Workers are spawned on-demand and pinned to user sessions via cookies.
- Session
- A user’s connection to a running worker. Sessions are tracked automatically — they start when the proxy assigns a user to a worker and end when the worker is stopped or the session is idle for too long.
- Task
- A background operation with streamable logs. Currently used for dependency restoration builds.