Cairn

CI/CD application for creating custom images with frappe-docker

Install Cairn

bench get-app https://github.com/Datahenge/cairn

Tags

  • deployment
  • deployment-automation
  • devops
  • docker-registry
  • erpnext
  • frappe
  • frappe-erpnext
  • frappe-framework

Add the Frappe Gems badge to your README

Maintain Cairn? Paste this into your README:

[![Listed on Frappe Gems](https://frappegems.com/api/method/frappe_gems.seo.badge?app=Datahenge%2Fcairn)](https://frappegems.com/gems/apps/Datahenge/cairn)

About Cairn

cairn

A thin, opinionated wrapper around frappe/frappe_docker that makes running a custom ERPNext deployment (Frappe + ERPNext + custom apps) on a single VPS reproducible, immutable, and low-thought — without ever modifying upstream.

Distributed as datahenge-cairn on PyPI — installs the cairn-build, cairn-adopt, and cairn-registry commands.

Two pillars: reproducible custom image builds and a pull-based deploy lifecycle (git ref → image tag → running stack, with image-only rollback). A strict data-plane boundary keeps cairn out of your databases and volumes entirely — it ships code, not data.

> Cairn: a trail marker of stacked stones. Each deploy drops a durable marker > (ref → resolved commits → image tag → digest) you can navigate back to.

📖 Documentation

Three roles, one install

cairn is three commands, one package, told apart by what's configured on a machine rather than by what's installed:

Buildercairn-build Targetcairn-adopt Registrycairn-registry
Does Builds images, pushes them, moves environment pointers Polls for its pointer, pulls the image, converges the running stack Provisions and operates a local OCI registry: lifecycle, retention, garbage collection
Reads cairn.toml (the manifest) /etc/cairn/adopt.toml (a descriptor, generated by cairn-adopt examine) /etc/cairn/registry.toml (optional — built-in defaults otherwise)
Needs Docker Engine v23+ or podman v4+, git Docker Engine + docker compose Docker Engine + docker compose, openssl
Credential push access to the registry pull-only none — reads no manifest, no [cairn] environment

One pip install datahenge-cairn installs all three — see Get Started for installing it, and note that a target simply never has a reason to run cairn-build's commands, and its pull-only registry credential means it couldn't push or retag even if it did. cairn-registry is only needed at all if you choose the self-hosted local-registry option (see Where your images live) — it is independent of the other two roles and is sometimes colocated with a builder or target, sometimes not.

Configuration

One manifest declares the image (cairn.toml, committed with the deployment); machine-local build settings, if you need any, live separately and are never shared. See the Builder walkthrough for provisioning one from scratch (cairn-build setup --client), and the published reference for the full manifest schema (cairn.toml), the machine-local /etc/cairn/builder.toml layer and its CAIRN_* environment-variable overrides (builder.toml), and a target's /etc/cairn/adopt.toml descriptor (target descriptor).

Where images are pushed

Which registry you use, and who owns the credential, is worth thinking about deliberately — especially when you're building images for a client. See Where your images live below. cairn itself is registry-agnostic and stores no credentials — authenticate with docker login or podman login before pushing.

How to use

On a builder — build, push, and manage environment pointers: see the Builder walkthrough and Build Automation.

On a target — adopt an existing deployment and converge it going forward: see the Target walkthrough and Reconcile Automation.

On a registry host (only if you self-host — see Where your images live): see the Registry guide.

Where your images live

cairn builds an image and puts it in a container registry; your deployment targets pull from there. cairn is registry-agnostic and assumes nothing — but which registry is not a neutral choice when you build software for clients:

📦 Choosing a container registry — start here. The image belongs in the account that owns the source; your credential should reach the engagement's images and nothing else; and what each option costs at ERPNext image sizes. Includes what to ask a client for.

🐙 GitHub Container Registry — GHCR in detail: tokens, scopes, how narrow access can be, visibility, and the deletion rule that is genuinely surprising. One option among several, not the default.

If you choose to self-host — cost dominates and off-host rollback history is genuinely not needed — cairn-registry provisions and operates that registry: lifecycle, retention, and garbage collection, so disk use stays bounded. See the Self-Hosted Registry guide or cairn-registry --help.

> You should never be the sole owner of a client's image. If the relationship ends, they must > still be able to deploy and roll back software they own. cairn is built so the registry can be > an account you do not control, and so your push credential can be scoped to one repository.

Related Developer Tools apps for Frappe & ERPNext

  • Frappe — Low code web framework for real world applications, in Python and Javascript
  • Frappe Docker — Docker environment for developing, deploying, and running Frappe applications (ERPNext and custom apps) in production and development
  • Builder — Craft beautiful websites effortlessly with an intuitive visual builder and publish them instantly
  • Bench — CLI to manage Multi-tenant deployments for Frappe apps
  • Frappe Ui — A set of components and utilities for rapid UI development
  • Press — Full service cloud hosting for the Frappe stack - powers Frappe Cloud
  • Gameplan — Open Source Discussions Platform for Remote Teams
  • Doppio — A Frappe app (CLI) to magically setup single page applications and Vue/React powered desk pages on your custom Frappe apps.