Skip to content

Commit 24f772a

Browse files
authored
Interactive installer (#15)
1 parent ddf45ac commit 24f772a

5 files changed

Lines changed: 505 additions & 17 deletions

File tree

AGENTS.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ Agent runtime layout:
7676
## Development Workflow
7777

7878
```bash
79+
# First-time install (interactive — handles everything)
80+
sudo ~/hornet/install.sh
81+
7982
# Edit source files directly in ~/hornet/
8083

8184
# Deploy to agent runtime
@@ -116,6 +119,38 @@ Add new test files to `bin/test.sh` — don't scatter test invocations across CI
116119
- **When changing behavior, update all docs.** Check and update: `README.md`, `CONFIGURATION.md`, skill files (`pi/skills/*/SKILL.md`), and `AGENTS.md`. Inline code examples in docs must match the actual implementation.
117120
- **No distro-specific commands.** Scripts must work on both Arch and Ubuntu (and any standard Linux). Use `grep -E` (not `grep -P`), POSIX-compatible tools, and avoid package manager calls (`pacman`, `apt`, etc.). If a package is needed, document it as a prerequisite rather than auto-installing it.
118121

122+
## Testing on Droplets
123+
124+
Use `bin/ci/droplet.sh` to spin up ephemeral DigitalOcean droplets for testing setup, install, or shell changes on real Linux. Requires `DO_API_TOKEN` env var.
125+
126+
```bash
127+
# Generate a throwaway SSH key
128+
ssh-keygen -t ed25519 -f /tmp/ci_key -N "" -q
129+
130+
# Create a droplet (Ubuntu or Arch)
131+
eval "$(bin/ci/droplet.sh create my-test ubuntu-24-04-x64 /tmp/ci_key.pub)"
132+
# → sets DROPLET_ID, DROPLET_IP, SSH_KEY_ID
133+
134+
# Or Arch (custom image):
135+
eval "$(bin/ci/droplet.sh create my-test 217410218 /tmp/ci_key.pub)"
136+
137+
# Wait for SSH, upload source, run a CI script
138+
bin/ci/droplet.sh wait-ssh "$DROPLET_IP" /tmp/ci_key
139+
tar czf /tmp/hornet-src.tar.gz --exclude=node_modules --exclude=.git .
140+
scp -i /tmp/ci_key /tmp/hornet-src.tar.gz "root@$DROPLET_IP:/tmp/"
141+
bin/ci/droplet.sh run "$DROPLET_IP" /tmp/ci_key bin/ci/setup-ubuntu.sh
142+
143+
# Or SSH in for manual poking
144+
ssh -i /tmp/ci_key "root@$DROPLET_IP"
145+
146+
# Clean up when done (~$0.003/run)
147+
bin/ci/droplet.sh destroy "$DROPLET_ID" "$SSH_KEY_ID"
148+
```
149+
150+
Droplets take ~15s to create, ~10s for SSH, ~90s for full setup+tests. Always destroy after — they cost ~$0.003 per run but add up if forgotten.
151+
152+
The CI scripts (`bin/ci/setup-ubuntu.sh`, `bin/ci/setup-arch.sh`) run `install.sh` with simulated input, verify the result, then run the full test suite. Use them as-is or SSH in and test manually.
153+
119154
## Security Notes
120155

121156
- `tool-guard.ts` blocks: writes outside `/home/hornet_agent/`, writes to source repo, writes to protected runtime files, dangerous bash patterns (reverse shells, fork bombs, rm -rf /, etc.), credential exfiltration.

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,21 @@ Agents work on real files in real repos — no sandbox friction. They make real
3333
## Quick Start
3434

3535
```bash
36-
# Clone (as admin — source lives in admin's home, not agent's)
37-
git clone <your-hornet-repo-url> ~/hornet
36+
git clone https://github.com/modem-dev/hornet.git ~/hornet
37+
sudo ~/hornet/install.sh
38+
```
39+
40+
The installer detects your distro, installs dependencies, creates the agent user, sets up the firewall, and walks you through API keys interactively. Takes ~2 minutes.
41+
42+
<details>
43+
<summary>Manual setup (without installer)</summary>
3844

45+
```bash
3946
# Setup (creates user, firewall, permissions — run as root)
4047
sudo bash ~/hornet/setup.sh <admin_username>
4148

4249
# Add secrets
43-
sudo su - hornet_agent -c 'vim ~/.config/.env'
50+
sudo -u hornet_agent vim ~/.config/.env
4451

4552
# Deploy source → agent runtime
4653
~/hornet/bin/deploy.sh
@@ -49,6 +56,9 @@ sudo su - hornet_agent -c 'vim ~/.config/.env'
4956
sudo -u hornet_agent ~/runtime/start.sh
5057
```
5158

59+
See [CONFIGURATION.md](CONFIGURATION.md) for the full list of secrets and how to obtain them.
60+
</details>
61+
5262
## Configuration
5363

5464
Secrets and configuration live in `~hornet_agent/.config/.env` (not in repo, 600 perms).

bin/ci/setup-arch.sh

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#!/bin/bash
22
# CI setup script for Arch Linux droplets.
3-
# Runs as root on a fresh droplet. Installs prereqs, uploads source,
4-
# runs setup.sh, and executes the test suite.
3+
# Runs as root on a fresh droplet. Tests the interactive installer,
4+
# then runs the test suite.
55
#
66
# Expects: /tmp/hornet-src.tar.gz already uploaded via scp.
77

88
set -euo pipefail
99

10-
echo "=== [Arch] Installing prerequisites ==="
11-
pacman -Syu --noconfirm --needed git curl tmux iptables docker sudo 2>&1 | tail -10
10+
echo "=== [Arch] Installing git (needed to init test repo) ==="
11+
pacman -Sy --noconfirm --needed git sudo 2>&1 | tail -3
1212

1313
echo "=== Preparing source ==="
1414
useradd -m -s /bin/bash hornet_admin
@@ -18,9 +18,24 @@ tar xzf /tmp/hornet-src.tar.gz
1818
chown -R hornet_admin:hornet_admin /home/hornet_admin/
1919
sudo -u hornet_admin bash -c 'cd ~/hornet && git init -q && git config user.email "ci@test" && git config user.name "CI" && git add -A && git commit -q -m "init"'
2020

21-
echo "=== Running setup.sh ==="
22-
cd /
23-
bash /home/hornet_admin/hornet/setup.sh hornet_admin
21+
echo "=== Running install.sh ==="
22+
# Simulate interactive input: admin user, required secrets, skip optionals, decline launch
23+
printf 'hornet_admin\nsk-test-key\nghp_testtoken\nxoxb-test\nxapp-test\nU01TEST\n\n\n\n\n\nn\n' \
24+
| bash /home/hornet_admin/hornet/install.sh
25+
26+
echo "=== Verifying install ==="
27+
# .env exists with correct permissions
28+
test -f /home/hornet_agent/.config/.env
29+
test "$(stat -c '%a' /home/hornet_agent/.config/.env)" = "600"
30+
test "$(stat -c '%U' /home/hornet_agent/.config/.env)" = "hornet_agent"
31+
# Runtime deployed
32+
test -f /home/hornet_agent/runtime/start.sh
33+
test -d /home/hornet_agent/.pi/agent/extensions
34+
# Required secrets written
35+
grep -q "OPENCODE_ZEN_API_KEY=sk-test-key" /home/hornet_agent/.config/.env
36+
grep -q "SLACK_BOT_TOKEN=xoxb-test" /home/hornet_agent/.config/.env
37+
grep -q "HORNET_SOURCE_DIR=" /home/hornet_agent/.config/.env
38+
echo " ✓ install.sh verification passed"
2439

2540
echo "=== Installing test dependencies ==="
2641
export PATH="/home/hornet_agent/opt/node-v22.14.0-linux-x64/bin:$PATH"

bin/ci/setup-ubuntu.sh

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22
# CI setup script for Ubuntu droplets.
3-
# Runs as root on a fresh droplet. Installs prereqs, uploads source,
4-
# runs setup.sh, and executes the test suite.
3+
# Runs as root on a fresh droplet. Tests the interactive installer,
4+
# then runs the test suite.
55
#
66
# Expects: /tmp/hornet-src.tar.gz already uploaded via scp.
77

@@ -17,9 +17,9 @@ for _ in $(seq 1 60); do
1717
sleep 2
1818
done
1919

20-
echo "=== [Ubuntu] Installing prerequisites ==="
20+
echo "=== [Ubuntu] Installing git (needed to init test repo) ==="
2121
apt-get update -qq
22-
apt-get install -y -qq git curl tmux iptables docker.io 2>&1 | tail -3
22+
apt-get install -y -qq git 2>&1 | tail -1
2323

2424
echo "=== Preparing source ==="
2525
useradd -m -s /bin/bash hornet_admin
@@ -29,9 +29,24 @@ tar xzf /tmp/hornet-src.tar.gz
2929
chown -R hornet_admin:hornet_admin /home/hornet_admin/
3030
sudo -u hornet_admin bash -c 'cd ~/hornet && git init -q && git config user.email "ci@test" && git config user.name "CI" && git add -A && git commit -q -m "init"'
3131

32-
echo "=== Running setup.sh ==="
33-
cd /
34-
bash /home/hornet_admin/hornet/setup.sh hornet_admin
32+
echo "=== Running install.sh ==="
33+
# Simulate interactive input: admin user, required secrets, skip optionals, decline launch
34+
printf 'hornet_admin\nsk-test-key\nghp_testtoken\nxoxb-test\nxapp-test\nU01TEST\n\n\n\n\n\nn\n' \
35+
| bash /home/hornet_admin/hornet/install.sh
36+
37+
echo "=== Verifying install ==="
38+
# .env exists with correct permissions
39+
test -f /home/hornet_agent/.config/.env
40+
test "$(stat -c '%a' /home/hornet_agent/.config/.env)" = "600"
41+
test "$(stat -c '%U' /home/hornet_agent/.config/.env)" = "hornet_agent"
42+
# Runtime deployed
43+
test -f /home/hornet_agent/runtime/start.sh
44+
test -d /home/hornet_agent/.pi/agent/extensions
45+
# Required secrets written
46+
grep -q "OPENCODE_ZEN_API_KEY=sk-test-key" /home/hornet_agent/.config/.env
47+
grep -q "SLACK_BOT_TOKEN=xoxb-test" /home/hornet_agent/.config/.env
48+
grep -q "HORNET_SOURCE_DIR=" /home/hornet_agent/.config/.env
49+
echo " ✓ install.sh verification passed"
3550

3651
echo "=== Installing test dependencies ==="
3752
export PATH="/home/hornet_agent/opt/node-v22.14.0-linux-x64/bin:$PATH"

0 commit comments

Comments
 (0)