Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
da1e05b
feat: add edgenode-harvester container variant
evangineer Mar 19, 2026
de03936
test: add Tier 1 integration tests for edgenode-harvester
evangineer Mar 19, 2026
a41db8b
test: add e2e pipeline test for log-sender → log-collector → harvester
evangineer Mar 19, 2026
b5ad7e1
docs: document harvester test suite in TESTING.md and quickstart
evangineer Mar 19, 2026
aebcf55
fix: move config to /data, fix s6 shebangs, add GHA build caching
evangineer Mar 19, 2026
82c6b6d
ci: clone unytco/log-collector in CI before building
evangineer Mar 19, 2026
5957d6f
ci: authenticate log-collector checkout with HARVESTER_REPO_TOKEN
evangineer Mar 19, 2026
791dd38
ci: add Dockerfile.log-collector to repo, reference from compose and CI
evangineer Mar 19, 2026
a7b5e8f
ci: fix harvester build secret — use secrets: not secret-envs:
evangineer Mar 19, 2026
87e6adb
ci: use run: step for harvester build to fix secret passing
evangineer Mar 19, 2026
1027b59
fix: pre-clone log-harvester source instead of using Docker build sec…
evangineer Mar 19, 2026
b12d5a6
fix: start only edgenode+log-collector in run_tests_multi.sh
evangineer Mar 19, 2026
e760781
fix: apply D1 schema on log-collector startup
evangineer Mar 19, 2026
edf3e97
fix: pass ADMIN_SECRET to wrangler dev via --var
evangineer Mar 19, 2026
00fc842
fix: exclude harvester tests from run_tests_multi.sh; add setup guards
evangineer Mar 19, 2026
864a3c3
fix: prevent wrangler crash cascade in edgenode test suite
evangineer Mar 19, 2026
94cc3d7
docs: update CHANGELOG, TESTING, and quickstart for harvester additions
evangineer Mar 19, 2026
6317964
docs: fix stale Dockerfile.unyt and latest-unyt references
evangineer Mar 19, 2026
2ad7065
docs: propose cloud deployment IaC design (OpenTofu + Ansible + Hetzner)
evangineer Apr 2, 2026
ec81f1e
docs: update deployment design — linker + caddy in edgenode container
evangineer Apr 3, 2026
9baf1be
docs: prefer Hetzner Object Storage as OpenTofu state backend
evangineer Apr 3, 2026
3ece4fb
spike: test cloudflare_worker_script feasibility for both Workers
evangineer Apr 7, 2026
04d2e1e
spike: fix build script — NODE_PATH, externals, multi-repo paths
evangineer Apr 7, 2026
3989771
chore: exclude .agents/.
evangineer Apr 7, 2026
3d0a33e
spike: update main.tf to current Cloudflare provider resource model
evangineer Apr 7, 2026
da70dc2
spike: record findings, fix build and tofu for full deployment
evangineer Apr 7, 2026
174f834
Major revision WIP!
evangineer Apr 7, 2026
c106904
docs: update deployment design with architecture clarifications and DR
evangineer Apr 9, 2026
5fec19c
docs: add Appendix B — platform-track self-registering harvester
evangineer Apr 9, 2026
96a235d
chore: update .env.example — remove stale Ansible refs, add missing vars
evangineer Apr 9, 2026
7aaa829
chore: drop spike-era docker regressions, restore main versions
evangineer Apr 17, 2026
9f404e3
feat: add h2hc-linker and Caddy services to edgenode container
evangineer Apr 17, 2026
f645fcf
test: add linker_caddy.bats for h2hc-linker and Caddy service coverage
evangineer Apr 17, 2026
8f48f1a
fix(linker): update to h2hc-linker v0.1.1 env-var API and fix asset n…
evangineer Apr 21, 2026
177459b
docs(readme): document optional linker and caddy services and toggles
evangineer Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 75 additions & 5 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,83 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Checkout log-collector
uses: actions/checkout@v4
with:
repository: unytco/log-collector
path: docker/log-collector
token: ${{ secrets.HARVESTER_REPO_TOKEN }}

- name: Build log-collector (cached)
uses: docker/build-push-action@v5
with:
context: docker/log-collector
file: docker/Dockerfile.log-collector
load: true
tags: edgenode-log-collector:latest
cache-from: type=gha,scope=log-collector
cache-to: type=gha,mode=max,scope=log-collector

- name: Build image for testing
run: |
docker buildx build docker/ --file docker/Dockerfile \
--platform linux/amd64 \
--load \
--tag local-edgenode
uses: docker/build-push-action@v5
with:
context: docker/
file: docker/Dockerfile
load: true
tags: local-edgenode
cache-from: type=gha,scope=edgenode
cache-to: type=gha,mode=max,scope=edgenode

- name: Run tests
run: |
CI_RELEASE_TEST=true ./docker/run_tests_multi.sh local-edgenode

test-harvester-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Checkout log-collector
uses: actions/checkout@v4
with:
repository: unytco/log-collector
path: docker/log-collector
token: ${{ secrets.HARVESTER_REPO_TOKEN }}

- name: Build log-collector (cached)
uses: docker/build-push-action@v5
with:
context: docker/log-collector
file: docker/Dockerfile.log-collector
load: true
tags: edgenode-log-collector:latest
cache-from: type=gha,scope=log-collector
cache-to: type=gha,mode=max,scope=log-collector

- name: Checkout log-harvester
uses: actions/checkout@v4
with:
repository: unytco/log-harvester
path: docker/log-harvester-src
token: ${{ secrets.HARVESTER_REPO_TOKEN }}

- name: Build harvester image for testing
uses: docker/build-push-action@v5
with:
context: docker/
file: docker/Dockerfile.harvester
load: true
tags: local-edgenode-harvester
cache-from: type=gha,scope=edgenode-harvester
cache-to: type=gha,mode=max,scope=edgenode-harvester

- name: Run harvester tests
run: |
CI_RELEASE_TEST=true ./docker/run_harvester_tests.sh local-edgenode-harvester
40 changes: 40 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,43 @@ jobs:
--push \
--tag "${VERSION_TAG}" \
--tag "${LATEST_TAG}"

build-and-push-harvester-image:
runs-on: ubuntu-latest
needs: create-release
if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ needs.create-release.outputs.tag }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push harvester image
run: |
VERSION_TAG="ghcr.io/holo-host/edgenode-harvester:${{ needs.create-release.outputs.tag }}"
LATEST_TAG="ghcr.io/holo-host/edgenode-harvester:latest"

docker buildx build docker/ --file docker/Dockerfile.harvester \
--platform linux/amd64,linux/arm64 \
--push \
--tag "${VERSION_TAG}" \
--tag "${LATEST_TAG}" \
--secret id=github_token,env=GITHUB_TOKEN
env:
GITHUB_TOKEN: ${{ secrets.HARVESTER_REPO_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ test-data/
holo-data-test/
.roo/
.gemini/
.agents/
docker/happ_config_file
docker/log-collector/
docker/log-harvester-src/
AGENTS.md
log_fix.md
UNYT_TEST_ANALYSIS.md
Expand Down
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This repo contains the tooling needed to deploy and operate always-on nodes for

The tooling consists of:

1. Edge Node - A Docker container specification for running Holochain with hApps in an OCI-compliant containerized environment.
1. Edge Node - Docker container specifications for running Holochain with hApps in an OCI-compliant containerized environment. Two variants: `edgenode` (standard, with log-sender) and `edgenode-harvester` (with log-harvester for Unyt invoice aggregation).
2. HolOS - A streamlined Linux ISO that enables the deployment of this container on physical or virtual hardware (especially HoloPorts).

For a detailed overview and usage instructions [see here](/USAGE.md).
Expand All @@ -23,8 +23,9 @@ For a detailed overview and usage instructions [see here](/USAGE.md).

A [Docker-based container](docker/README.md) that delivers Edge Node, ready to run hApps:

- Holochain conductor configured to automatically run via `tini`.
- Holochain conductor managed by s6-overlay, starting automatically on container launch.
- Tools for installing and managing hApps from configuration files.
- Two variants: standard (`edgenode`) and harvester (`edgenode-harvester`).

### HolOS Build System

Expand All @@ -43,9 +44,9 @@ A [specialized OS builder](holos/README.md) for creating custom ISO images using

## Quick Start

### To test the Edge Node container:
### Standard Edge Node

1. Pull the Docker image:
1. Pull the image:

```sh
docker pull ghcr.io/holo-host/edgenode
Expand All @@ -64,6 +65,29 @@ docker exec -it edgenode su - nonroot
ps -ef
```

### Harvester Edge Node

1. Pull the image:

```sh
docker pull ghcr.io/holo-host/edgenode-harvester
```

2. Launch with your log-collector credentials:

```sh
docker run --name harvester -dit \
-v $(pwd)/holo-data:/data \
-p 4444:4444 \
-p 4445:4445 \
-e COLLECTOR_URL=https://your-log-collector.unyt.dev \
-e ADMIN_SECRET=your-admin-secret \
-e LAIR_PASSWORD=your-lair-password \
ghcr.io/holo-host/edgenode-harvester
```

See [docker/LOG_HARVESTER_QUICKSTART.md](docker/LOG_HARVESTER_QUICKSTART.md) for full setup instructions.

### For HolOS Users

1. Download a release of the iso from our [releases page](https://github.com/Holo-Host/edgenode/releases)
Expand All @@ -74,5 +98,7 @@ ps -ef

- [Detailed overview and usage instructions](/USAGE.md)
- [Edge Node Container Instructions](docker/README.md)
- [Log-Sender Quickstart (Unyt resource accounting)](docker/LOG_SENDER_QUICKSTART.md)
- [Log-Harvester Quickstart (Unyt invoice aggregation)](docker/LOG_HARVESTER_QUICKSTART.md)
- [HolOS Build System Guide](holos/README.md)
- [Tools for working with Edge Nodes](tools/README.md)
61 changes: 61 additions & 0 deletions deploy/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Edge Node Cloud Deployment — Environment Variables
#
# Copy this file to .env.staging or .env.production and fill in your values.
# Source it before running any deploy scripts:
#
# cp deploy/.env.example deploy/.env.staging
# $EDITOR deploy/.env.staging
# source deploy/.env.staging
#
# Never commit .env.staging or .env.production — they are gitignored.

# --- Hetzner Cloud ---
HCLOUD_TOKEN=""

# --- Cloudflare ---
CLOUDFLARE_ACCOUNT_ID=""
CLOUDFLARE_API_TOKEN=""
# Workers subdomain (found in Workers & Pages → Overview → Your subdomain)
CLOUDFLARE_WORKERS_SUBDOMAIN=""
# Zone ID for the domain used by this deployment (found in the Cloudflare dashboard Overview tab)
CLOUDFLARE_ZONE_ID=""

# --- SSH ---
# Contents of the SSH public key to install on Hetzner VMs (e.g. ~/.ssh/id_ed25519.pub)
SSH_PUBLIC_KEY=""

# --- Joining Service ---
# Shared secret between h2hc-linker and the joining service Worker.
LINKER_ADMIN_SECRET=""
# Comma-separated invite codes for HWC browser nodes.
INVITE_CODES="test-invite-123"

# --- Unyt / Log-Sender (edgenode) ---
# URL of the Cloudflare log-collector Worker.
LOG_SENDER_ENDPOINT=""
# Unyt agent public key (uhCAk...) of the party paying for resources.
LOG_SENDER_UNYT_PUB_KEY=""

# --- Harvester ---
# URL of the Cloudflare log-collector Worker (same as LOG_SENDER_ENDPOINT).
COLLECTOR_URL=""
# Admin secret for the log-collector.
ADMIN_SECRET=""
# Lair keystore password for the harvester Holochain conductor.
HARVESTER_LAIR_PASSWORD=""

# --- edgenode container ---
# Lair keystore password for the Holochain conductor.
LAIR_PASSWORD=""

# --- OpenTofu variable passthrough ---
# These map env vars to TF_VAR_* so tofu picks them up automatically.
export TF_VAR_hcloud_token="$HCLOUD_TOKEN"
export TF_VAR_cloudflare_account_id="$CLOUDFLARE_ACCOUNT_ID"
export TF_VAR_cloudflare_api_token="$CLOUDFLARE_API_TOKEN"
export TF_VAR_cloudflare_workers_subdomain="$CLOUDFLARE_WORKERS_SUBDOMAIN"
export TF_VAR_cloudflare_zone_id="$CLOUDFLARE_ZONE_ID"
export TF_VAR_ssh_public_key="$SSH_PUBLIC_KEY"
export TF_VAR_linker_admin_secret="$LINKER_ADMIN_SECRET"
export TF_VAR_invite_codes="$INVITE_CODES"
export TF_VAR_harvester_lair_password="$HARVESTER_LAIR_PASSWORD"
Loading
Loading