### Install with Example Values Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Pulls the chart locally and installs it using the provided example values file. ```sh helm pull oci://ghcr.io/morgankryze/charts/cairn --untar helm install cairn oci://ghcr.io/morgankryze/charts/cairn -f cairn/values-example.yaml kubectl port-forward svc/cairn 8080:80 ``` -------------------------------- ### Install and enable systemd service Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/binary.md Commands to install the binary, initialize the configuration, and start the systemd service. ```sh install -m 755 cairn /usr/local/bin/cairn mkdir -p /etc/cairn/config cairn -init > /etc/cairn/config/services.yaml systemctl enable --now cairn ``` -------------------------------- ### Install Helm chart from registry Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Authenticate and install the chart from an internal OCI registry. ```sh helm registry login harbor.internal --ca-file /etc/pki/internal-ca.crt helm install cairn oci://harbor.internal/helm/cairn --version 1.17.1 \ --ca-file /etc/pki/internal-ca.crt -f values.yaml ``` -------------------------------- ### Launch the demo stack Source: https://github.com/morgankryze/cairn/blob/main/demo/README.md Starts the Docker containers for the demo environment. ```sh docker compose up -d --build # from this folder, or `just demo` from the repo root ``` -------------------------------- ### Install Helm chart from local tarball Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Install the chart directly from a local file when no registry is available. ```sh helm install cairn ./cairn-1.17.1.tgz -f values.yaml ``` -------------------------------- ### Start the Quadlet service Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/podman.md Reload the systemd daemon and start the container service. ```sh systemctl --user daemon-reload systemctl --user start cairn ``` -------------------------------- ### Install Cairn via Helm Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Installs the Cairn chart directly from the OCI registry without needing a repository. ```sh helm install cairn oci://ghcr.io/morgankryze/charts/cairn ``` -------------------------------- ### Define a service in services.yaml Source: https://github.com/morgankryze/cairn/blob/main/README.md Example configuration for a service entry in the services.yaml file. ```yaml # config/services.yaml - id: pdf url: https://pdf.example.org icon: stirling-pdf name: PDF toolbox desc: Merge, split, compress your PDFs. ``` -------------------------------- ### Start Cairn with Docker Compose Source: https://github.com/morgankryze/cairn/blob/main/README.md Command to start the services defined in the compose.yaml file. ```sh docker compose up -d ``` -------------------------------- ### Compare check output Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Example output showing the difference between mounting only config versus both config and assets. ```console $ docker run --rm -v ./config:/config:ro … -check warning: 2 icons load from a CDN in visitors' browsers (gatus, nginx); run cairn -emit-icons to self-host them ok: 2 services, 1 categories, 0 pages, locales [fr] $ docker run --rm -v ./config:/config:ro -v ./assets:/assets:ro … -check ok: 2 services, 1 categories, 0 pages, locales [fr] ``` -------------------------------- ### Configuration Directory Structure Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/multiple-files.md Example layout showing how multiple service files coexist with reserved configuration files. ```text config/ site.yaml categories.yaml documents.yaml media.yaml admin-tools.yaml ``` -------------------------------- ### Configure values.yaml for Cairn Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Example configuration for mounting assets and defining services in values.yaml. ```yaml # values.yaml image: repository: harbor.internal/cairn tag: "1.17.1" config: site.yaml: | title: Our tools locales: [fr, en] # The domain alone: cairn adds the sub-path from -base-path itself, and a # path written here would land twice in every canonical link. url: https://tools.internal # Raster, or link previews carry no image. svg is fine for the tab icon, # useless for a preview card. logo: /assets/logo.png status: gatus: http://gatus # the Service below, port 80, not 8080 linked: false # visitors have no route to Gatus services.yaml: | - id: pad url: https://pad.internal icon: hedgedoc name: { fr: Bloc-notes, en: Notepad } desc: { fr: Écrire à plusieurs., en: Write together. } extraVolumes: - name: logo configMap: name: cairn-logo - name: icons configMap: name: cairn-icons extraVolumeMounts: - name: logo mountPath: /assets # gives /assets/logo.png readOnly: true - name: icons mountPath: /assets/icons # gives /assets/icons/*.svg readOnly: true ingress: enabled: true className: nginx host: tools.internal ``` -------------------------------- ### Deploy the Cairn demo stack Source: https://github.com/morgankryze/cairn/blob/main/README.md Clones the repository and starts the demo stack using Docker Compose. ```sh git clone https://github.com/MorganKryze/cairn.git && cd cairn/demo docker compose up -d --build ``` -------------------------------- ### Full Site Configuration Example Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Defines the site title, tagline, locales, theme, and navigation structure using YAML. ```yaml title: Libre Internet tagline: fr: Des outils libres, simples, pour tout le monde. en: Free, simple tools for everyone. logo: /assets/logo.png locales: [fr, en] theme: accent: "#247b7b" about: fr: | Bienvenue ! Voici les services que j'héberge pour vous. en: | Welcome! These are the services I host for you. links: - label: Wiki url: https://wiki.example.org icon: book - label: GitHub url: https://github.com/you icon: github footer: - label: { fr: Statut des services, en: Service status } url: https://status.example.org - label: Contact url: mailto:admin@example.org pages: - id: legal title: { fr: Mentions légales, en: Legal notice } body: fr: | Éditeur : Prénom Nom, contact@exemple.org Hébergement : ce site est auto-hébergé par son éditeur. en: | Publisher: First Last, contact@example.org Hosting: this site is self-hosted by its publisher. ``` -------------------------------- ### Install or upgrade Cairn via Helm Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Deploy the chart using the OCI registry and the provided values file. ```sh helm upgrade --install cairn oci://ghcr.io/morgankryze/charts/cairn -f values.yaml ``` -------------------------------- ### Deploy with Docker Compose Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Configure and start the Cairn container using Docker Compose. ```yaml services: cairn: image: ghcr.io/morgankryze/cairn:latest ports: - 8080:8080 volumes: - ./config:/config:ro read_only: true cap_drop: - ALL security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "/cairn", "-healthcheck"] interval: 30s ``` ```sh docker compose up -d ``` -------------------------------- ### GET /readyz Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Readiness signal endpoint. Returns 200 OK if a valid configuration is loaded, otherwise returns 503. ```APIDOC ## GET /readyz ### Description Readiness signal endpoint. Returns 200 OK if a valid configuration is loaded, otherwise returns 503. ### Method GET ### Endpoint /readyz ``` -------------------------------- ### Install Gatus via Helm Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Deploy the Gatus chart using a private registry or a local chart archive. ```sh helm install gatus oci://harbor.internal/helm/gatus --version 1.5.0 \ -f gatus-values.yaml # or ./gatus-1.5.0.tgz without a registry ``` -------------------------------- ### Configure values.yaml for Gatus Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Example configuration for Gatus, including persistence settings and endpoint monitoring. ```yaml # gatus-values.yaml image: repository: harbor.internal/gatus # ghcr.io/twin/gatus with a route out tag: "5.36.0" # the chart's own default trails the app # memory is the default and loses everything on restart, which cairn shows: # with no stored results the API answers with endpoints and nothing in them, # so every pill reads Unknown until each endpoint has been checked again. # The chart mounts its claim at /data, and defaults to not making one. persistence: enabled: true size: 200Mi config: storage: type: sqlite path: /data/data.db # the endpoints cairn -emit-gatus wrote for you endpoints: - name: pad url: https://pad.internal interval: 5m conditions: ["[STATUS] == 200"] ``` -------------------------------- ### Run Cairn with Docker Source: https://github.com/morgankryze/cairn/blob/main/README.md Starts a temporary Cairn container on port 8080. ```sh docker run --rm -p 8080:8080 ghcr.io/morgankryze/cairn:stable ``` -------------------------------- ### Automate Configuration Checks in CI Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Example GitHub Actions workflow to validate configuration files on push. ```yaml # .github/workflows/check.yml name: check on: [push, pull_request] jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - run: docker run --rm -v ./config:/config ghcr.io/morgankryze/cairn:stable -check ``` -------------------------------- ### Configure Docker Compose for Cairn Source: https://github.com/morgankryze/cairn/blob/main/README.md Example compose.yaml file to run Cairn with a mounted configuration directory. ```yaml # compose.yaml services: cairn: image: ghcr.io/morgankryze/cairn:latest ports: - 8080:8080 volumes: - ./config:/config:ro ``` -------------------------------- ### Project directory structure for fonts Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/theming.md Example of the expected directory layout for custom font files within the configuration folder. ```text /config/site.yaml /config/services.yaml /config/fonts/custom-font.woff2 ``` -------------------------------- ### Service Definition in Separate Files Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/multiple-files.md Example of defining services within a specific YAML file like documents.yaml. ```yaml # documents.yaml - id: pdf url: https://pdf.example.org category: documents name: { fr: Boîte à outils PDF, en: PDF toolbox } - id: pad url: https://pad.example.org category: documents name: { fr: Bloc-notes partagé, en: Shared notepad } ``` -------------------------------- ### Port-forward to Cairn Service Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Exposes the Cairn service locally to verify the installation. ```sh kubectl port-forward svc/cairn 8080:80 ``` -------------------------------- ### GET / Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Redirects the user to the negotiated locale based on cookies, Accept-Language headers, or the default setting. ```APIDOC ## GET / ### Description Redirects the user to the negotiated locale based on cookies, Accept-Language headers, or the default setting. ### Method GET ### Endpoint / ``` -------------------------------- ### Define a category entry in categories.yaml Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Example of a category entry with localized names and an explicit sort order. ```yaml - id: documents name: { fr: Documents, en: Documents } order: 1 ``` -------------------------------- ### Site URL configuration error Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Example of the error message generated when a path is included in the site URL. ```console config: site.yaml: url "https://example.org/cairn" must be the domain alone, with no path (serving under example.org/cairn is what -base-path is for, and cairn adds that prefix itself) ``` -------------------------------- ### Enable lingering for rootless services Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/podman.md Ensure the rootless container starts automatically without requiring a user login. ```sh loginctl enable-linger $USER ``` -------------------------------- ### Verify TLS negative control Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Example output showing expected success and failure states for certificate bundle validation. ```plain alpha success=true in the bundle beta success=true in the bundle, and CA:FALSE gamma success=false absent: x509: certificate signed by unknown authority ``` -------------------------------- ### GET /{locale}/ Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Serves the home page for a specific locale. Responses are server-rendered and include ETag and Cache-Control headers. ```APIDOC ## GET /{locale}/ ### Description Serves the home page for a specific locale. Responses are server-rendered and include ETag and Cache-Control headers. ### Method GET ### Endpoint /{locale}/ ### Parameters #### Path Parameters - **locale** (string) - Required - The target language locale. ``` -------------------------------- ### Cairn heading demotion warning Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/text.md Example of the console warning issued by cairn -check when a single # is used at the start of a page body. ```console warning: page "legal" body opens a heading with a single #: cairn renders it as ## because the page already has its own top heading, so # and ## come out the same (write ## and the output is unchanged) ``` -------------------------------- ### Uninstall the chart Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Remove the installed Cairn release from the cluster. ```sh helm uninstall cairn ``` -------------------------------- ### Build Cairn from source Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/binary.md Clone the repository and compile the binary using the Go toolchain. ```sh git clone https://github.com/MorganKryze/cairn.git && cd cairn go build -o cairn ./src/cmd/cairn ``` -------------------------------- ### Define Services Configuration Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Create a services.yaml file to define the services displayed on the site. ```yaml - id: pdf url: https://pdf.example.org category: documents icon: stirling-pdf name: PDF toolbox desc: Merge, split, compress your PDFs. ``` -------------------------------- ### GET /healthz Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Liveness signal endpoint that returns 200 OK while the process is running. ```APIDOC ## GET /healthz ### Description Liveness signal endpoint that returns 200 OK while the process is running. ### Method GET ### Endpoint /healthz ``` -------------------------------- ### Create Configuration Directory Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Initialize the directory structure for Cairn configuration files. ```sh mkdir -p cairn/config && cd cairn ``` -------------------------------- ### Generated security.txt output Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Example of the automatically generated security.txt file content served by Cairn. ```text Contact: mailto:security@example.org Expires: 2027-07-30T17:45:16Z Preferred-Languages: fr, en Canonical: https://tools.example.org/.well-known/security.txt ``` -------------------------------- ### Run Cairn binary Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/binary.md Execute the binary by specifying the configuration directory, assets path, and network address. ```sh ./cairn -config ./config -assets ./assets -addr :8080 ``` -------------------------------- ### Validate Configuration Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Run the configuration check tool to identify errors before deployment. ```sh docker run --rm -v ./config:/config ghcr.io/morgankryze/cairn:stable -check ``` -------------------------------- ### Build from Source Configuration Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/docker-compose.md Alternative build configuration to replace the image directive in Docker Compose. ```yaml build: context: https://github.com/MorganKryze/cairn.git dockerfile: docker/Dockerfile ``` -------------------------------- ### Configure icon using a URL Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/icons.md Reference an icon directly via a full image URL. ```yaml icon: https://cdn.jsdelivr.net/gh/selfhst/icons/svg/vaultwarden.svg ``` -------------------------------- ### Create and Deploy a Custom CA Bundle Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Commands to concatenate multiple certificates into a single bundle and create a Kubernetes ConfigMap for deployment. ```sh cat pad.crt photos.crt wiki.crt > ca-bundle.crt kubectl create configmap ca-bundle --from-file=ca-certificates.crt=ca-bundle.crt ``` ```sh cat /etc/ssl/certs/ca-certificates.crt mine.crt > ca-bundle.crt ``` -------------------------------- ### Apply manifest error Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/kubernetes.md Error message encountered when attempting to apply a manifest over an existing Helm chart installation. ```console $ kubectl apply -f cairn.yaml The Deployment "cairn" is invalid: spec.selector: Invalid value: …: field is immutable ``` -------------------------------- ### Run Development Commands Source: https://github.com/morgankryze/cairn/blob/main/CONTRIBUTING.md Common shell commands for running the application, executing tests, and building the Docker container. ```sh go run ./src/cmd/cairn -config example # http://localhost:8080, live-reloads example/ go test ./... docker compose -f docker/compose.yaml up --build # what CI and users get ``` -------------------------------- ### Define a Quadlet container unit Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/podman.md Create this file in ~/.config/containers/systemd/cairn.container for rootless execution or /etc/containers/systemd/cairn.container for root-level execution. ```ini [Unit] Description=cairn directory page [Container] Image=ghcr.io/morgankryze/cairn:stable PublishPort=8080:8080 Volume=%h/cairn/config:/config:ro,Z ReadOnly=true DropCapability=all NoNewPrivileges=true HealthCmd=/cairn -healthcheck HealthInterval=30s HealthStartPeriod=5s AutoUpdate=registry [Service] Restart=on-failure [Install] WantedBy=default.target ``` -------------------------------- ### Create ConfigMaps for Assets Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Commands to create Kubernetes ConfigMaps from local asset directories and files for mounting into the container. ```sh kubectl create configmap cairn-icons --from-file=assets/icons/ kubectl create configmap cairn-logo --from-file=logo.png=assets/logo.png ``` -------------------------------- ### Kubernetes Probe Configuration Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/docker-compose.md Liveness and readiness probe definitions for Kubernetes deployments. ```yaml # Kubernetes, if that is where you run it livenessProbe: httpGet: { path: /healthz, port: 8080 } readinessProbe: httpGet: { path: /readyz, port: 8080 } ``` -------------------------------- ### Define preview images in YAML Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/services.md Reference images by filename or as an object with a source path and localized captions. ```yaml - id: photos # … images: - screen.png - src: albums.png caption: { fr: La vue albums., en: The albums view. } ``` -------------------------------- ### Invalid URL scheme error Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Example of the error message generated when using an unsupported URL scheme like tel: in site configuration. ```console config: site.yaml: footer url "tel:+33123456789" uses the tel: scheme, which cairn does not emit: the link would render dead and nothing would say why (expected https://…, mailto:… or an absolute path) ``` -------------------------------- ### Verify release binary attestation Source: https://github.com/morgankryze/cairn/blob/main/SECURITY.md Use the GitHub CLI to verify the attestation of a specific release binary. ```sh gh attestation verify cairn_1.8.0_linux_amd64.tar.gz --repo MorganKryze/cairn ``` -------------------------------- ### Rebuild the Fraunces font asset Source: https://github.com/morgankryze/cairn/blob/main/docs/reference.md Installs necessary dependencies and runs a Python script to subset and instantiate the Fraunces variable font for web use. ```sh pip install fonttools brotli python - <<'EOF' from fontTools.ttLib import TTFont from fontTools.varLib import instancer from fontTools import subset f = TTFont("Fraunces[SOFT,WONK,opsz,wght].ttf") instancer.instantiateVariableFont(f, {"WONK": 0, "SOFT": 50}, inplace=True) o = subset.Options() o.layout_features = ["kern", "liga", "calt", "ccmp", "locl"] o.name_IDs = ["*"] s = subset.Subsetter(options=o) s.populate(unicodes=subset.parse_unicodes( "U+0000-00FF,U+0100-017F,U+0180-024F,U+2000-206F,U+20A0-20BF,U+2122")) s.subset(f) f.flavor = "woff2" f.save("src/internal/render/assets/fonts/fraunces.woff2") EOF ``` -------------------------------- ### Configure Caddy as a reverse proxy Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/reverse-proxies.md Use the handle directive instead of handle_path to ensure the prefix is preserved for the backend. ```caddy example.org { handle /cairn/* { reverse_proxy cairn:8080 # handle, not handle_path: keep the prefix } } ``` -------------------------------- ### Verify registry catalog Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Use curl to verify that the repositories are present in the registry. ```console $ curl -s https://harbor.internal/v2/_catalog {"repositories":["helm/cairn","helm/gatus"]} ``` -------------------------------- ### Generate manifests from chart Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Render the Helm chart templates to a local file for review or customization. ```sh helm template cairn oci://ghcr.io/morgankryze/charts/cairn -f values.yaml > cairn.yaml ``` -------------------------------- ### Restart pods to apply certificate changes Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Command to restart deployments to force a reload of the trust store. ```sh kubectl rollout restart deploy/gatus deploy/cairn ``` -------------------------------- ### Import container images into local runtime Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Use these commands to import images from a tarball into the local container runtime. Ensure the namespace is set to k8s.io for visibility by the kubelet. ```sh sudo ctr -n k8s.io images import images.tar # containerd sudo k3s ctr images import images.tar # k3s sudo nerdctl --namespace k8s.io load -i images.tar # nerdctl ``` -------------------------------- ### Check site configuration for logo compatibility Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Run the check command to identify if the configured logo is a raster image suitable for social media link previews. ```console $ cairn -check -config ./config warning: site.yaml logo "/assets/logo.svg" is not a raster image: links to the site preview with no image (og:image wants a png, jpg, webp or gif) ``` -------------------------------- ### Create ConfigMaps for assets Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Create ConfigMaps from local directories or files. Note that ConfigMap keys cannot contain slashes, requiring separate objects for different directory levels. ```sh kubectl create configmap cairn-icons --from-file=assets/icons/ kubectl create configmap cairn-logo --from-file=logo.png=assets/logo.png ``` -------------------------------- ### Update and Verify Deployment Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/docker-compose.md Commands to update the container image and verify configuration files. ```sh docker compose pull && docker compose up -d ``` ```sh docker run --rm -v ./config:/config ghcr.io/morgankryze/cairn:stable -check ``` -------------------------------- ### Configure hosting flag links Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/services.md Set targets for self-hosted and external flags in site.yaml to provide context to visitors. ```yaml # site.yaml hosting_flag: self: hosting # a page cairn serves, by its id external: https://example.org/why # or any URL ``` -------------------------------- ### Mount local assets for icons Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/icons.md Mount a local directory to /assets to serve custom icon files. ```yaml # compose.yaml volumes: - ./config:/config:ro - ./assets:/assets:ro ``` ```yaml # services.yaml icon: /assets/icons/intranet.svg ``` -------------------------------- ### Download icons for self-hosting Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/icons.md Use the emit-icons command to generate a script that downloads all referenced slug icons to your local assets directory. ```sh docker run --rm -v ./config:/config ghcr.io/morgankryze/cairn:stable -emit-icons > get-icons.sh cd assets && sh ../get-icons.sh ``` -------------------------------- ### Validate configuration with Docker Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Run the Cairn check command to verify configuration and asset availability. ```sh docker run --rm -v ./config:/config:ro -v ./assets:/assets:ro \ ghcr.io/morgankryze/cairn:1.17.1 -check ``` -------------------------------- ### Inspect SLSA build provenance Source: https://github.com/morgankryze/cairn/blob/main/SECURITY.md Use this command to inspect the SLSA build provenance of the container image. ```sh docker buildx imagetools inspect ghcr.io/morgankryze/cairn:stable \ --format '{{ json .Provenance }}' ``` -------------------------------- ### Configure CA bundle via site.yaml Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Defines the status endpoint and the local path to the CA certificate bundle. ```yaml # site.yaml status: gatus: https://status.internal ca: /assets/ca.crt ``` -------------------------------- ### Configure site URL Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Define the base domain for the site. Do not include sub-paths in the URL field. ```yaml url: https://tools.example.org # yes url: https://example.org/cairn # no, even if that is where visitors land ``` -------------------------------- ### Validate icon configuration Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/site.md Run the -check command to verify that your icon declarations match the actual file dimensions. ```console $ cairn -check -config ./config -assets ./assets warning: site.yaml icons entry 2 declares sizes "512x512" but /assets/brand-512.png measures 256x256: the manifest states the declared size as fact, so a phone picks this file for a slot it does not fill (correct sizes, or supply a file that size) ``` -------------------------------- ### Configure theme-specific logos and favicons Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/theming.md Provide separate image paths for light and dark themes to ensure visibility across different backgrounds. ```yaml # site.yaml logo: light: /assets/logo.svg # shown in the light theme dark: /assets/logo-white.svg # shown in the dark theme favicon: light: /assets/fav.svg dark: /assets/fav-white.svg ``` -------------------------------- ### Configure systemd service Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/binary.md Define a systemd unit file to manage the Cairn process with security hardening enabled. ```ini # /etc/systemd/system/cairn.service [Unit] Description=cairn, the directory page for the people you host for After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/local/bin/cairn -config /etc/cairn/config -assets /etc/cairn/assets DynamicUser=yes NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes PrivateTmp=yes Restart=on-failure [Install] WantedBy=multi-user.target ``` -------------------------------- ### Project Directory Layout Source: https://github.com/morgankryze/cairn/blob/main/CONTRIBUTING.md Overview of the source code structure and responsibilities of each directory. ```text src/cmd/cairn/ wiring only: flags, startup, hand off to the server src/internal/ config/ read and validate the YAML; depends on nothing render/ config to bytes; templates/ and assets/ embed here status/ the Gatus client server/ routes, handlers, probes, the two background loops check/ backs -check: validates like a boot would testutil/ the one helper shared by every package's tests docker/ Dockerfile (FROM scratch) and the hardened compose charts/cairn/ the Helm chart, same objects as docs/deployment/kubernetes.md example/ the config served by the dev loop and the docs scripts/ the browser tests and their fixtures, icons, screenshots docs/ GitHub-native Markdown, no generator ``` -------------------------------- ### Configure a single logo Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/theming.md Set a global logo path in the site configuration. ```yaml # site.yaml logo: /assets/logo.png ``` -------------------------------- ### Configure Status Provider with Token File Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/status.md Use a file path for the token to ensure security. The token is read on every poll, allowing for rotation without service restarts. ```yaml status: provider: json url: https://uptime.betterstack.com/api/v2/monitors token_file: /run/secrets/status-token # a mounted file, not a value token_scheme: Bearer # the default; OAuth for Statuspage, Basic for HTTP Basic map: { list: data, key: attributes.pronounceable_name, state: attributes.status, up: [up] } ``` -------------------------------- ### Configure Argo CD Application Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Application manifest for deploying Cairn with inline configuration values. ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: cairn namespace: argocd spec: project: default source: repoURL: harbor.internal/helm chart: cairn targetRevision: 1.17.1 helm: valuesObject: ingress: enabled: true className: nginx host: tools.internal config: site.yaml: | title: Our tools locales: [fr, en] destination: server: https://kubernetes.default.svc namespace: cairn ``` -------------------------------- ### Configure typography Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/theming.md Define a custom font stack and optionally provide a local font file for the project. ```yaml # site.yaml theme: font: family: "Inter, system-ui, sans-serif" file: "fonts/custom-font.woff2" ``` -------------------------------- ### Verify image presence via kubectl events Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Check if images are already present on the machine to confirm successful import. ```console $ kubectl get events --field-selector reason=Pulled Container image "harbor.internal/cairn:1.17.1" already present on machine Container image "harbor.internal/gatus:5.36.0" already present on machine ``` -------------------------------- ### Configure Site Metadata Source: https://github.com/morgankryze/cairn/blob/main/docs/getting-started.md Define site-wide settings such as title, tagline, and supported locales in site.yaml. ```yaml title: Libre Internet tagline: fr: Des outils libres, simples, pour tout le monde. en: Free, simple tools for everyone. locales: [fr, en] ``` -------------------------------- ### Configure site locales Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/i18n.md Define the supported locales in the site.yaml configuration file. ```yaml # site.yaml locales: [ar, en] ``` -------------------------------- ### Define configuration in values.yaml Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Use the config key to define files that will be mounted as a ConfigMap at /config. The pipe operator ensures the content is treated as an opaque string to preserve formatting. ```yaml # values.yaml config: site.yaml: | title: Our tools locales: [fr, en] about: fr: Bienvenue. Voici les services que nous hébergeons. en: Welcome. Here are the services we host. services.yaml: | - id: pad url: https://pad.example.org icon: hedgedoc name: { fr: Bloc-notes, en: Notepad } desc: { fr: Écrire à plusieurs., en: Write together. } ``` -------------------------------- ### Configure Extra Volumes and Mounts Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/helm.md Helm configuration to mount the previously created ConfigMaps into the container filesystem. ```yaml extraVolumes: - name: logo configMap: name: cairn-logo - name: icons configMap: name: cairn-icons extraVolumeMounts: - name: logo mountPath: /assets # gives /assets/logo.png readOnly: true - name: icons mountPath: /assets/icons # gives /assets/icons/*.svg readOnly: true ``` -------------------------------- ### Push Helm charts to OCI registry Source: https://github.com/morgankryze/cairn/blob/main/docs/deployment/airgap.md Commands to push Helm charts as OCI artifacts to the internal registry. ```sh helm push cairn-1.17.1.tgz oci://harbor.internal/helm helm push gatus-1.5.0.tgz oci://harbor.internal/helm ``` -------------------------------- ### Configure themed icons Source: https://github.com/morgankryze/cairn/blob/main/docs/recipes/icons.md Provide separate icon slugs for light and dark themes to ensure proper contrast. ```yaml icon: light: github dark: github-light ``` -------------------------------- ### Alternative top heading syntax Source: https://github.com/morgankryze/cairn/blob/main/docs/configuration/text.md Using an underline of equals signs to define a top-level heading in YAML configuration. ```yaml body: | A perfectly ordinary line. === ```