EasyRunner Mid-June 2026 Update

Progress update since the May post: encrypted control-plane backup and restore, stronger Next.js self-hosting, smoother secret access, audit logs, app secret sync, and more.

This has been a very security-and-recovery focused stretch for EasyRunner. The May update made servers safer to operate with the WireGuard mesh, SSH lockdown and a much clearer doctor surface. This update keeps moving in that direction: EasyRunner can now back up and restore its own control-plane state, run self-hosted Next.js apps more confidently, read secrets with far fewer auth interruptions, show a tamper-evident audit trail, and push app secrets to the right places with one command.

The result is a CLI that feels much more ready for real use: you can recover from losing the machine that runs EasyRunner, handle secrets with fewer prompts, see what sensitive actions happened, and spend less time wiring together deployment-time and CI-time configuration by hand.

  • Encrypted control-plane backup and restore — EasyRunner can now back up and restore its own state to Cloudflare R2. The backup covers the SQLite store, config.json, license, SSH keys and secrets — everything needed to rebuild the control plane. This is not an app-data backup for your containers and databases; it is disaster recovery for EasyRunner itself, so a lost laptop or server-mode host does not mean rebuilding all of your app and server records from scratch.
  • Setup is guideder backup init reuses your linked Cloudflare account, auto-detects the account ID, and creates a per-install R2 bucket. It shows the full plan before it changes anything and asks for confirmation. Bucket names include the hostname plus a short unique suffix, making them easy to identify when you are choosing what to restore.
  • Restore onto a new machineer backup restore can recover onto a fresh host after you reinstall EasyRunner and re-link Cloudflare. It discovers candidate backup buckets, asks for the restic password, shows a restore plan, restores the store/config/license/SSH keys/secrets, and runs an integrity check. A --dry-run path lets you preview what would happen, and it refuses to overwrite an already configured host unless you explicitly force it.
  • Day-to-day commands includeder backup run, er backup status, er backup list, er backup doctor and er backup doctor --fix are all there. Status reports what is known without failing just because something needs attention, and doctor checks the Cloudflare token, R2 scope, restic, repository and integrity. Long operations show clear phase progress so you are never left wondering if anything is happening.

  • Smoother secret access with the same security posture — EasyRunner already had an encrypted vault for secrets; this work refactors how the CLI accesses it so macOS no longer asks you to approve every individual key read. Sensitive egress operations such as er app secret get, er app secret generate, er backup init, er backup run and er server run-sudo go through a presence gate with a configurable unlock window. The user-visible difference is simple: commands that need several secrets feel calmer, routine commands stay smooth, and commands that reveal or export sensitive material still get an intentional user-presence check. App secrets stored in the vault can also be pushed to your servers and GitHub Actions in one step with er app secret push — see below.

  • A tamper-evident audit trail — EasyRunner now records a hash-chained audit log for command actions, vault access and authentication challenges. The new top-level er audit command lets you view recent events, filter by event type with --event action, --event vault_access or --event auth_challenge, and verify the log chain with --verify. For operators, this is a big step toward being able to answer "what happened?" after a sensitive operation, not just whether the command succeeded.

  • Push app secrets to the server and GitHub Actionser app secret push <app_name> <server_name> gives app secrets a proper sync command. Plain app secrets are pushed to the server as Podman secrets. Secrets prefixed with GH_SECRET_ are pushed to GitHub Actions for the app's repository, with the prefix stripped, and EASYRUNNER_* internal secrets are skipped. That makes it much easier to keep runtime secrets and CI secrets in sync without copying values through terminals, repos or browser tabs.

  • Stronger Next.js self-hosting support — EasyRunner now lines up with the official Node.js server path for self-hosted Next.js apps: it keeps the simple long-running-container model with Caddy in front, uses clear Dockerfile and build/runtime environment patterns, and closes practical gaps around warm ISR cache, streaming, and graceful shutdown. Caddy is configured with framework-aware cache headers — immutable caching for /_next/static/*, no-store for API routes, and flush-based streaming for SSR and Suspense. EASYRUNNER_APP_DOMAIN and EASYRUNNER_APP_URL are also auto-injected as build args so Dockerfiles can wire them straight into NEXT_PUBLIC_* environment variables without hardcoding domains. EasyRunner also warns at deploy time if the app is marked as Next.js but has no volume mounted for .next/cache, since a missing cache mount silently disables ISR. In other words: Next.js on a small VPS now feels more like a first-class EasyRunner path without pulling in serverless machinery that does not fit how EasyRunner runs apps. See the Deploy a Next.js App recipe for a full walkthrough.

  • Security hardening around the edges — Several smaller changes close off places where sensitive material could linger or be shown too eagerly. WireGuard private keys are scrubbed from wg0.conf after the tunnel comes up, so the on-disk config never holds a live key. GHCR username and PAT are now vault-only — the old podman login -p argv path (which exposed credentials in process listings) has been removed and replaced with Podman's authfile mechanism. HTTP debug logging now redacts auth token fields (access_token, api_key, secret, password, and similar) rather than logging them verbatim. er link --status shows less token material. None of these are flashy features, but together they mean sensitive values are harder to leak from logs, disk, or process state.

  • Store migrations for smoother upgrades — EasyRunner now has a schema-migration runner and an indexed key-column convention for store tables, with backup_destinations moved onto that pattern. Most users will never think about this directly, which is the point: internal state changes can land with less upgrade drama, and restored databases can be migrated on load instead of leaving newer features to trip over older records.

  • License quota correctness — License enforcement now uses the server limit from the license itself instead of a hardcoded value. For alpha users this should mostly be invisible, but it means the CLI's behaviour is now aligned with the plan data it is checking.

The theme this time is resilience. EasyRunner is getting better at protecting the state it owns, recovering that state when something goes wrong, and making security-sensitive work visible without making everyday commands miserable. That is a good place for an alpha self-hosting tool to be heading.

We are still in alpha testing. If you'd like to get involved, drop me a line at janaka@easyrunner.xyz or a tweet @janaka_a.