| 99f1a2e | | | 1 | #!/bin/bash |
| 99f1a2e | | | 2 | # Sets up EdenFS on the hub server. |
| 99f1a2e | | | 3 | # EdenFS runs on the HOST (not in Docker) because it needs FUSE access. |
| 99f1a2e | | | 4 | # |
| 99f1a2e | | | 5 | # Prerequisites: |
| 99f1a2e | | | 6 | # - grove/edenfs:latest Docker image must be built |
| 99f1a2e | | | 7 | # - Mononoke SLAPI must be running (grove.host:8443) |
| 99f1a2e | | | 8 | # - TLS client certs at /data/grove/tls/ |
| 99f1a2e | | | 9 | # |
| 99f1a2e | | | 10 | # What this does: |
| 99f1a2e | | | 11 | # 1. Extracts edenfs + edenfs_privhelper binaries from Docker image |
| 99f1a2e | | | 12 | # 2. Creates EdenFS config pointing at Mononoke SLAPI |
| 99f1a2e | | | 13 | # 3. Creates a backing repo (metadata-only sl clone) |
| 99f1a2e | | | 14 | # 4. Installs a systemd service for the edenfs daemon |
| 99f1a2e | | | 15 | # 5. Creates an EdenFS mount at /mnt/sapling |
| 99f1a2e | | | 16 | # |
| 99f1a2e | | | 17 | # Usage: sudo bash setup-edenfs.sh |
| 99f1a2e | | | 18 | |
| 99f1a2e | | | 19 | set -euo pipefail |
| 99f1a2e | | | 20 | |
| 99f1a2e | | | 21 | EDEN_DIR="/data/eden" |
| 99f1a2e | | | 22 | EDEN_CONFIG_DIR="/etc/eden" |
| 99f1a2e | | | 23 | EDEN_BIN_DIR="/usr/local/bin" |
| 99f1a2e | | | 24 | MOUNT_POINT="/mnt/sapling" |
| 99f1a2e | | | 25 | BACKING_REPO="/data/eden/backing/sapling" |
| 99f1a2e | | | 26 | TLS_DIR="/data/grove/tls" |
| 99f1a2e | | | 27 | SLAPI_URL="https://localhost:8443" |
| 99f1a2e | | | 28 | REPO_NAME="sapling" |
| 99f1a2e | | | 29 | |
| 99f1a2e | | | 30 | # ── Extract binaries from Docker image ──────────────────────────── |
| 99f1a2e | | | 31 | |
| 99f1a2e | | | 32 | echo "Extracting EdenFS binaries from Docker image..." |
| 99f1a2e | | | 33 | CONTAINER_ID=$(docker create grove/edenfs:latest) |
| 99f1a2e | | | 34 | docker cp "$CONTAINER_ID:/usr/local/bin/edenfs" "$EDEN_BIN_DIR/edenfs" || true |
| 99f1a2e | | | 35 | docker cp "$CONTAINER_ID:/usr/local/bin/edenfs_privhelper" "$EDEN_BIN_DIR/edenfs_privhelper" || true |
| 99f1a2e | | | 36 | docker cp "$CONTAINER_ID:/usr/local/bin/edenfsctl" "$EDEN_BIN_DIR/edenfsctl" || true |
| 99f1a2e | | | 37 | docker rm "$CONTAINER_ID" |
| 99f1a2e | | | 38 | |
| 99f1a2e | | | 39 | chmod +x "$EDEN_BIN_DIR/edenfs" "$EDEN_BIN_DIR/edenfs_privhelper" "$EDEN_BIN_DIR/edenfsctl" 2>/dev/null || true |
| 99f1a2e | | | 40 | |
| 99f1a2e | | | 41 | echo "Extracted binaries:" |
| 99f1a2e | | | 42 | ls -la "$EDEN_BIN_DIR/edenfs" "$EDEN_BIN_DIR/edenfs_privhelper" "$EDEN_BIN_DIR/edenfsctl" 2>/dev/null || echo "(some binaries not found — build may have produced different names)" |
| 99f1a2e | | | 43 | |
| 99f1a2e | | | 44 | # ── Create directories ──────────────────────────────────────────── |
| 99f1a2e | | | 45 | |
| 99f1a2e | | | 46 | mkdir -p "$EDEN_DIR" |
| 99f1a2e | | | 47 | mkdir -p "$EDEN_CONFIG_DIR" |
| 99f1a2e | | | 48 | mkdir -p "$MOUNT_POINT" |
| 99f1a2e | | | 49 | mkdir -p "$BACKING_REPO" |
| 99f1a2e | | | 50 | |
| 99f1a2e | | | 51 | # ── Create EdenFS system config ─────────────────────────────────── |
| 99f1a2e | | | 52 | |
| 99f1a2e | | | 53 | cat > "$EDEN_CONFIG_DIR/edenfs.toml" <<TOML |
| 99f1a2e | | | 54 | [core] |
| 99f1a2e | | | 55 | edenDirectory = "$EDEN_DIR" |
| 99f1a2e | | | 56 | |
| 99f1a2e | | | 57 | [clone] |
| 99f1a2e | | | 58 | default-revision = "main" |
| 99f1a2e | | | 59 | TOML |
| 99f1a2e | | | 60 | |
| 99f1a2e | | | 61 | # ── Create backing repo config ──────────────────────────────────── |
| 99f1a2e | | | 62 | # EdenFS needs a Sapling backing repo with edenapi config pointing |
| 99f1a2e | | | 63 | # at Mononoke. This is like a metadata-only clone — EdenFS fetches |
| 99f1a2e | | | 64 | # actual file contents lazily via SLAPI. |
| 99f1a2e | | | 65 | |
| 99f1a2e | | | 66 | mkdir -p "$BACKING_REPO/.sl" |
| 99f1a2e | | | 67 | |
| 99f1a2e | | | 68 | cat > "$BACKING_REPO/.sl/config" <<TOML |
| 99f1a2e | | | 69 | [remotefilelog] |
| 99f1a2e | | | 70 | reponame = $REPO_NAME |
| 99f1a2e | | | 71 | |
| 99f1a2e | | | 72 | [edenapi] |
| 99f1a2e | | | 73 | url = $SLAPI_URL |
| 99f1a2e | | | 74 | |
| 99f1a2e | | | 75 | [auth] |
| 99f1a2e | | | 76 | grove.cert = $TLS_DIR/client.crt |
| 99f1a2e | | | 77 | grove.key = $TLS_DIR/client.key |
| 99f1a2e | | | 78 | grove.cacerts = $TLS_DIR/ca.crt |
| 99f1a2e | | | 79 | grove.prefix = * |
| 99f1a2e | | | 80 | |
| 99f1a2e | | | 81 | [remotenames] |
| 99f1a2e | | | 82 | selectivepulldefault = main |
| 99f1a2e | | | 83 | |
| 99f1a2e | | | 84 | [push] |
| 99f1a2e | | | 85 | edenapi = true |
| 99f1a2e | | | 86 | TOML |
| 99f1a2e | | | 87 | |
| 99f1a2e | | | 88 | # ── Install systemd service ─────────────────────────────────────── |
| 99f1a2e | | | 89 | |
| 99f1a2e | | | 90 | cat > /etc/systemd/system/edenfs.service <<SERVICE |
| 99f1a2e | | | 91 | [Unit] |
| 99f1a2e | | | 92 | Description=EdenFS Virtual Filesystem Daemon |
| 99f1a2e | | | 93 | After=network.target docker.service |
| 99f1a2e | | | 94 | Wants=network.target |
| 99f1a2e | | | 95 | |
| 99f1a2e | | | 96 | [Service] |
| 99f1a2e | | | 97 | Type=simple |
| 99f1a2e | | | 98 | ExecStart=$EDEN_BIN_DIR/edenfs \ |
| 99f1a2e | | | 99 | --edenDir $EDEN_DIR \ |
| 99f1a2e | | | 100 | --etcEdenDir $EDEN_CONFIG_DIR \ |
| 99f1a2e | | | 101 | --configPath $EDEN_CONFIG_DIR/edenfs.toml \ |
| 99f1a2e | | | 102 | --foreground |
| 99f1a2e | | | 103 | Restart=on-failure |
| 99f1a2e | | | 104 | RestartSec=5 |
| 99f1a2e | | | 105 | |
| 99f1a2e | | | 106 | # FUSE requires these capabilities |
| 99f1a2e | | | 107 | AmbientCapabilities=CAP_SYS_ADMIN |
| 99f1a2e | | | 108 | NoNewPrivileges=false |
| 99f1a2e | | | 109 | |
| 99f1a2e | | | 110 | [Install] |
| 99f1a2e | | | 111 | WantedBy=multi-user.target |
| 99f1a2e | | | 112 | SERVICE |
| 99f1a2e | | | 113 | |
| 99f1a2e | | | 114 | systemctl daemon-reload |
| 99f1a2e | | | 115 | |
| 99f1a2e | | | 116 | echo "" |
| 99f1a2e | | | 117 | echo "=== EdenFS Setup Complete ===" |
| 99f1a2e | | | 118 | echo "" |
| 99f1a2e | | | 119 | echo "Next steps:" |
| 99f1a2e | | | 120 | echo " 1. Start the daemon: systemctl start edenfs" |
| 99f1a2e | | | 121 | echo " 2. Check status: systemctl status edenfs" |
| 99f1a2e | | | 122 | echo " 3. Mount the sapling repo:" |
| 99f1a2e | | | 123 | echo " edenfsctl clone $BACKING_REPO $MOUNT_POINT" |
| 99f1a2e | | | 124 | echo " 4. Verify the mount: ls $MOUNT_POINT" |
| 99f1a2e | | | 125 | echo " 5. Enable on boot: systemctl enable edenfs" |
| 99f1a2e | | | 126 | echo "" |
| 99f1a2e | | | 127 | echo "The sapling repo will be lazily mounted at $MOUNT_POINT" |
| 99f1a2e | | | 128 | echo "Files are fetched on-demand from Mononoke SLAPI ($SLAPI_URL)" |