feat: initial ThinkCentre setup repo — Android, Ollama, Otto migration docs + scripts
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
# ZeitAnker ThinkCentre Setup
|
||||||
|
|
||||||
|
Infrastructure docs, scripts, and runbooks for ThinkCentre 1 and 2.
|
||||||
|
|
||||||
|
> ⚠️ No credentials in this repo. Secrets live in `/home/secondclaw/.openclaw/secrets/` and are managed manually.
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
| | ThinkCentre 1 | ThinkCentre 2 |
|
||||||
|
|---|---|---|
|
||||||
|
| **IP** | 192.168.0.91 | TBD |
|
||||||
|
| **User** | secondclaw | TBD |
|
||||||
|
| **CPU** | i5-13400T (10C/16T) | i5-13400T (10C/16T, baugleich) |
|
||||||
|
| **RAM** | 16 GB | 16 GB |
|
||||||
|
| **Disk** | 233 GB NVMe | 233 GB NVMe |
|
||||||
|
| **GPU** | Intel UHD 730 | Intel UHD 730 |
|
||||||
|
| **OS** | Ubuntu 24.04 LTS | Ubuntu 24.04 LTS |
|
||||||
|
| **Role** | Build Server + LLM | Otto (OpenClaw) |
|
||||||
|
|
||||||
|
## ThinkCentre 1 — Roles
|
||||||
|
|
||||||
|
### 1. Android APK Build Server
|
||||||
|
Local Gradle builds for StaySober, BlockBlitz, Ticked — replaces GitHub Actions.
|
||||||
|
- See `android/` for setup scripts and build wrapper
|
||||||
|
- Builds served via `lighttpd` on port 8080 (same as Pi currently)
|
||||||
|
- Trigger: SSH from Pi or manual
|
||||||
|
|
||||||
|
### 2. Local LLM (Ollama)
|
||||||
|
- Model: `qwen2.5:7b` (default), swappable
|
||||||
|
- API: `http://192.168.0.91:11434`
|
||||||
|
- Use: Otto fallback inference, code review, summarization
|
||||||
|
- See `ollama/` for model management and prompt scripts
|
||||||
|
|
||||||
|
### 3. Potential: Otto performance offload
|
||||||
|
- Heavy subagent tasks can be delegated here via API
|
||||||
|
- TBD once ThinkCentre 2 (Otto's new home) is set up
|
||||||
|
|
||||||
|
## ThinkCentre 2 — Roles
|
||||||
|
|
||||||
|
### Otto Migration
|
||||||
|
- OpenClaw fresh install (not in-place migration from Pi)
|
||||||
|
- Pi remains active until migration is validated
|
||||||
|
- See `docs/otto-migration.md` for migration plan
|
||||||
|
|
||||||
|
## SSH Access (from Pi)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh secondclaw@192.168.0.91 # ThinkCentre 1
|
||||||
|
# Key already deployed: ~/.ssh/id_ed25519
|
||||||
|
```
|
||||||
|
|
||||||
|
## Repo Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
thinkcentre-setup/
|
||||||
|
├── android/
|
||||||
|
│ ├── setup.sh # One-shot Android SDK install
|
||||||
|
│ ├── build.sh # Build wrapper (takes app name + optional branch)
|
||||||
|
│ └── README.md
|
||||||
|
├── ollama/
|
||||||
|
│ ├── setup.sh # Ollama install + default model pull
|
||||||
|
│ ├── models.md # Model comparison and RAM requirements
|
||||||
|
│ └── README.md
|
||||||
|
├── scripts/
|
||||||
|
│ ├── provision.sh # Base Ubuntu provisioning (apt, docker, node, etc.)
|
||||||
|
│ └── ssh-keygen.sh # Deploy Pi SSH key to ThinkCentre
|
||||||
|
└── docs/
|
||||||
|
├── otto-migration.md # ThinkCentre 2 migration plan
|
||||||
|
└── management.md # Who manages what, runbooks
|
||||||
|
```
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Android APK Build Wrapper — ThinkCentre 1
|
||||||
|
# Usage: bash build.sh <app> [branch]
|
||||||
|
# app: staysober | blockblitz | ticked
|
||||||
|
# branch: main (default)
|
||||||
|
#
|
||||||
|
# Output: /var/www/downloads/<app>/<app>-latest.apk
|
||||||
|
# Served: http://192.168.0.91:8080/<app>/
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP="${1:-}"
|
||||||
|
BRANCH="${2:-main}"
|
||||||
|
BUILD_DIR="/tmp/builds"
|
||||||
|
SERVE_DIR="/var/www/downloads"
|
||||||
|
GIT_BASE="git@192.168.0.34" # Pi git server
|
||||||
|
|
||||||
|
# App → repo mapping
|
||||||
|
declare -A REPOS=(
|
||||||
|
[staysober]="ottobringts/staysober"
|
||||||
|
[blockblitz]="ottobringts/blockblitz"
|
||||||
|
[ticked]="ottobringts/obsidian-tasks-app"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -z "$APP" || -z "${REPOS[$APP]}" ]]; then
|
||||||
|
echo "Usage: $0 <app> [branch]"
|
||||||
|
echo "Apps: ${!REPOS[@]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO="${REPOS[$APP]}"
|
||||||
|
WORK_DIR="$BUILD_DIR/$APP"
|
||||||
|
APK_OUT="$SERVE_DIR/$APP"
|
||||||
|
|
||||||
|
echo "=== Building $APP ($BRANCH) ==="
|
||||||
|
echo "Repo: $REPO"
|
||||||
|
|
||||||
|
# Clone / pull
|
||||||
|
if [ -d "$WORK_DIR/.git" ]; then
|
||||||
|
echo "Pulling latest..."
|
||||||
|
cd "$WORK_DIR"
|
||||||
|
git fetch origin
|
||||||
|
git checkout "$BRANCH"
|
||||||
|
git pull origin "$BRANCH"
|
||||||
|
else
|
||||||
|
echo "Cloning..."
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
git clone --branch "$BRANCH" "https://github.com/$REPO.git" "$WORK_DIR"
|
||||||
|
cd "$WORK_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set ANDROID_HOME
|
||||||
|
export ANDROID_HOME="$HOME/android-sdk"
|
||||||
|
export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/34.0.0"
|
||||||
|
|
||||||
|
# Expo prebuild if needed
|
||||||
|
if [ -f "app.json" ] && grep -q '"expo"' app.json; then
|
||||||
|
echo "Expo project detected — running prebuild..."
|
||||||
|
npx expo prebuild --platform android --no-install 2>&1 | tail -5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Gradle build
|
||||||
|
echo "Running Gradle assembleRelease..."
|
||||||
|
cd android 2>/dev/null || cd .
|
||||||
|
chmod +x gradlew
|
||||||
|
./gradlew assembleRelease --no-daemon --quiet 2>&1 | tail -20
|
||||||
|
|
||||||
|
# Find and copy APK
|
||||||
|
APK=$(find . -name "*.apk" -path "*/release/*" | head -1)
|
||||||
|
if [ -z "$APK" ]; then
|
||||||
|
echo "ERROR: No APK found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$APK_OUT"
|
||||||
|
cp "$APK" "$APK_OUT/$APP-latest.apk"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Build complete ==="
|
||||||
|
echo "APK: $APK_OUT/$APP-latest.apk"
|
||||||
|
echo "URL: http://192.168.0.91:8080/$APP/$APP-latest.apk"
|
||||||
|
ls -lh "$APK_OUT/$APP-latest.apk"
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Android SDK Setup for ThinkCentre 1
|
||||||
|
# Run as secondclaw — installs Java 17 + Android SDK + NDK
|
||||||
|
# Usage: bash setup.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ANDROID_HOME="$HOME/android-sdk"
|
||||||
|
SDK_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
|
||||||
|
|
||||||
|
echo "=== Android Build Environment Setup ==="
|
||||||
|
|
||||||
|
# Java 17
|
||||||
|
echo "[1/5] Java 17..."
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y -qq openjdk-17-jdk-headless wget unzip curl
|
||||||
|
java --version
|
||||||
|
|
||||||
|
# Android CLI Tools
|
||||||
|
echo "[2/5] Android Command Line Tools..."
|
||||||
|
mkdir -p "$ANDROID_HOME/cmdline-tools"
|
||||||
|
cd /tmp
|
||||||
|
wget -q "$SDK_TOOLS_URL" -O cmdline-tools.zip
|
||||||
|
unzip -q cmdline-tools.zip -d "$ANDROID_HOME/cmdline-tools"
|
||||||
|
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest"
|
||||||
|
rm cmdline-tools.zip
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
echo "[3/5] Environment variables..."
|
||||||
|
if ! grep -q ANDROID_HOME ~/.bashrc; then
|
||||||
|
cat >> ~/.bashrc << EOF
|
||||||
|
|
||||||
|
# Android SDK
|
||||||
|
export ANDROID_HOME=\$HOME/android-sdk
|
||||||
|
export PATH=\$PATH:\$ANDROID_HOME/cmdline-tools/latest/bin:\$ANDROID_HOME/platform-tools:\$ANDROID_HOME/build-tools/34.0.0
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
export ANDROID_HOME
|
||||||
|
export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools"
|
||||||
|
|
||||||
|
# SDK Components
|
||||||
|
echo "[4/5] SDK components (platform-tools, android-34, build-tools, NDK r26b)..."
|
||||||
|
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
|
||||||
|
--sdk_root="$ANDROID_HOME" \
|
||||||
|
"platform-tools" \
|
||||||
|
"platforms;android-34" \
|
||||||
|
"build-tools;34.0.0" \
|
||||||
|
"ndk;26.1.10909125"
|
||||||
|
|
||||||
|
# Accept licenses
|
||||||
|
echo "[5/5] Accepting licenses..."
|
||||||
|
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" --licenses > /dev/null 2>&1 || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done ==="
|
||||||
|
java --version
|
||||||
|
"$ANDROID_HOME/platform-tools/adb" version
|
||||||
|
echo "ANDROID_HOME=$ANDROID_HOME"
|
||||||
|
echo ""
|
||||||
|
echo "Reload shell: source ~/.bashrc"
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# ThinkCentre Management
|
||||||
|
|
||||||
|
## Wer managed was
|
||||||
|
|
||||||
|
| Aufgabe | Zuständig | Wie |
|
||||||
|
|---------|-----------|-----|
|
||||||
|
| Hardware (Ein/Aus, LAN) | Chris | physisch |
|
||||||
|
| OS Updates | Otto | `sudo apt upgrade` via SSH, monatlich |
|
||||||
|
| Android SDK Updates | Otto | `sdkmanager --update` bei Bedarf |
|
||||||
|
| Ollama Modelle | Otto | `ollama pull/rm` nach Absprache |
|
||||||
|
| OpenClaw Config | Otto + Chris | gemeinsam |
|
||||||
|
| Secrets | Chris | manuell, nie per Git |
|
||||||
|
| Backups | Otto | Cron-Job (täglich, nach Pi-Backup-Muster) |
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
- **Uptime Kuma** (`uptime.zeitanker.digital`) — Push-Heartbeat von ThinkCentre 2 (Otto)
|
||||||
|
- **ThinkCentre 1** — kein Push-Monitor nötig (Build-Server, on-demand)
|
||||||
|
|
||||||
|
## SSH Zugang
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Von Pi aus:
|
||||||
|
ssh secondclaw@192.168.0.91 # ThinkCentre 1
|
||||||
|
# Key: ~/.ssh/id_ed25519 (bereits deployed)
|
||||||
|
|
||||||
|
# Von extern: via Pi als Jumphost
|
||||||
|
ssh -J claw@192.168.0.84 secondclaw@192.168.0.91
|
||||||
|
```
|
||||||
|
|
||||||
|
## Runbooks
|
||||||
|
|
||||||
|
### Neustart ThinkCentre 1
|
||||||
|
```bash
|
||||||
|
ssh secondclaw@192.168.0.91 "sudo reboot"
|
||||||
|
# Nach ~60s wieder erreichbar
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android Build auslösen (manuell)
|
||||||
|
```bash
|
||||||
|
ssh secondclaw@192.168.0.91 "bash ~/scripts/build.sh staysober main"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ollama Modell wechseln
|
||||||
|
```bash
|
||||||
|
ssh secondclaw@192.168.0.91 "ollama pull mistral:7b && ollama rm qwen2.5:7b"
|
||||||
|
```
|
||||||
|
|
||||||
|
### OS Update
|
||||||
|
```bash
|
||||||
|
ssh secondclaw@192.168.0.91 "sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Netzwerk
|
||||||
|
|
||||||
|
| Host | IP | Port | Dienst |
|
||||||
|
|------|----|----- |--------|
|
||||||
|
| ThinkCentre 1 | 192.168.0.91 | 22 | SSH |
|
||||||
|
| ThinkCentre 1 | 192.168.0.91 | 8080 | APK Download Server |
|
||||||
|
| ThinkCentre 1 | 192.168.0.91 | 11434 | Ollama API |
|
||||||
|
| ThinkCentre 2 | TBD | 22 | SSH |
|
||||||
|
| ThinkCentre 2 | TBD | 18789 | OpenClaw Gateway |
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
# Otto Migration — Pi → ThinkCentre 2
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
OpenClaw (Otto) von `192.168.0.84` (Pi, ARM64) auf ThinkCentre 2 (x86, i5-13400T, 16 GB) migrieren.
|
||||||
|
|
||||||
|
## Vorteile
|
||||||
|
|
||||||
|
| | Pi (aktuell) | ThinkCentre 2 |
|
||||||
|
|---|---|---|
|
||||||
|
| CPU | Cortex-A76 (4C) | i5-13400T (10C/16T) |
|
||||||
|
| RAM | 8 GB | 16 GB |
|
||||||
|
| Arch | ARM64 | x86_64 |
|
||||||
|
| Node builds | langsam | schnell |
|
||||||
|
| Expo/Gradle | hakelig | nativ |
|
||||||
|
|
||||||
|
## Migrationsstrategie
|
||||||
|
|
||||||
|
**Fresh Install** (nicht in-place) — sauberer Start, keine ARM-Reste.
|
||||||
|
|
||||||
|
Pi bleibt aktiv bis ThinkCentre 2 vollständig validiert ist.
|
||||||
|
|
||||||
|
## Schritt für Schritt
|
||||||
|
|
||||||
|
### Phase 1 — ThinkCentre 2 vorbereiten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Base provisioning
|
||||||
|
bash scripts/provision.sh
|
||||||
|
|
||||||
|
# OpenClaw fresh install
|
||||||
|
npm install -g openclaw
|
||||||
|
openclaw setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2 — Daten übertragen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Workspace (ohne secrets, ohne node_modules)
|
||||||
|
rsync -av --exclude='node_modules' --exclude='.git' \
|
||||||
|
pi@192.168.0.84:~/.openclaw/workspace/ \
|
||||||
|
~/.openclaw/workspace/
|
||||||
|
|
||||||
|
# Secrets manuell übertragen (nie per Git!)
|
||||||
|
# - ~/.openclaw/secrets/
|
||||||
|
# - ~/.openclaw/openclaw.json (enthält API Keys)
|
||||||
|
|
||||||
|
# QMD collections neu indexieren (ARM → x86, Embeddings neu)
|
||||||
|
qmd embed -c vault
|
||||||
|
qmd embed -c workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3 — Services migrieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# APK Server (lighttpd)
|
||||||
|
sudo apt install lighttpd
|
||||||
|
# Config: /etc/lighttpd/lighttpd.conf → serve /var/www/downloads auf :8080
|
||||||
|
|
||||||
|
# PM2 Services
|
||||||
|
pm2 start ecosystem.config.cjs # zeitanker-tasks
|
||||||
|
pm2 save
|
||||||
|
pm2 startup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 4 — Cutover
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# DNS/IP in relevanten Configs aktualisieren:
|
||||||
|
# - TOOLS.md: APK Server URL
|
||||||
|
# - MEMORY.md: Otto Pi IP
|
||||||
|
# - Uptime Kuma: Monitor auf neue IP
|
||||||
|
# - Discord Webhooks falls nötig
|
||||||
|
|
||||||
|
# Pi-Heartbeat-Cron auf ThinkCentre 2 umziehen
|
||||||
|
# Uptime Kuma Push-URL aktualisieren
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 5 — Validierung
|
||||||
|
|
||||||
|
- [ ] OpenClaw antwortet auf Discord
|
||||||
|
- [ ] Heartbeat läuft (Uptime Kuma grün)
|
||||||
|
- [ ] QMD search funktioniert
|
||||||
|
- [ ] PM2 Services alle online
|
||||||
|
- [ ] APK Server erreichbar
|
||||||
|
|
||||||
|
### Phase 6 — Pi dekommissionieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pi-Services stoppen
|
||||||
|
pm2 stop all
|
||||||
|
|
||||||
|
# Pi als Fallback/Backup behalten oder neu nutzen für:
|
||||||
|
# - Home Assistant (wenn .59 stirbt)
|
||||||
|
# - Reserve
|
||||||
|
```
|
||||||
|
|
||||||
|
## Offene Fragen
|
||||||
|
|
||||||
|
- [ ] ThinkCentre 2 IP bestimmen (nach Netzwerk-Einbindung)
|
||||||
|
- [ ] Neuer Hostname: `otto-tc` oder `otto-2`?
|
||||||
|
- [ ] Pi-Rolle nach Migration klären
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Ollama Models — ThinkCentre 1
|
||||||
|
|
||||||
|
CPU-only inference (Intel UHD 730, no dedicated GPU). 16 GB RAM.
|
||||||
|
|
||||||
|
## Installed
|
||||||
|
|
||||||
|
| Model | Size | RAM | Speed (tok/s) | Best for |
|
||||||
|
|-------|------|-----|---------------|----------|
|
||||||
|
| `qwen2.5:7b` | ~4.7 GB | ~6 GB | ~15-25 | Default — code, German, reasoning |
|
||||||
|
|
||||||
|
## Recommended Candidates
|
||||||
|
|
||||||
|
| Model | Size | RAM needed | Notes |
|
||||||
|
|-------|------|-----------|-------|
|
||||||
|
| `qwen2.5:7b` ✅ | 4.7 GB | 6 GB | Best quality/speed ratio on CPU |
|
||||||
|
| `mistral:7b` | 4.1 GB | 5 GB | Strong English reasoning |
|
||||||
|
| `llama3.2:3b` | 2.0 GB | 3 GB | Fastest, lower quality |
|
||||||
|
| `qwen2.5:14b` | 9.0 GB | 11 GB | Better quality, slower (~8 tok/s) |
|
||||||
|
| `deepseek-r1:7b` | 4.7 GB | 6 GB | Strong at reasoning/math |
|
||||||
|
| `nomic-embed-text` | 0.3 GB | 1 GB | Embeddings (QMD alternative) |
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Chat
|
||||||
|
curl http://192.168.0.91:11434/api/generate -d '{
|
||||||
|
"model": "qwen2.5:7b",
|
||||||
|
"prompt": "Your prompt here",
|
||||||
|
"stream": false
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Via OpenAI-compatible endpoint
|
||||||
|
curl http://192.168.0.91:11434/v1/chat/completions \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"model":"qwen2.5:7b","messages":[{"role":"user","content":"Hello"}]}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama list # Installed models
|
||||||
|
ollama pull <model> # Download model
|
||||||
|
ollama rm <model> # Remove model
|
||||||
|
ollama run <model> # Interactive chat
|
||||||
|
sudo systemctl status ollama
|
||||||
|
sudo systemctl restart ollama
|
||||||
|
```
|
||||||
|
|
||||||
|
## OpenClaw Integration (future)
|
||||||
|
|
||||||
|
Add to `openclaw.json` as fallback:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"agents": {
|
||||||
|
"defaults": {
|
||||||
|
"model": {
|
||||||
|
"fallbacks": [
|
||||||
|
"openrouter/anthropic/claude-sonnet-4-6",
|
||||||
|
"ollama/qwen2.5:7b@http://192.168.0.91:11434",
|
||||||
|
"google/gemini-2.5-flash"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Ollama Setup — ThinkCentre 1
|
||||||
|
# Usage: bash setup.sh [model]
|
||||||
|
# Default model: qwen2.5:7b
|
||||||
|
|
||||||
|
set -e
|
||||||
|
MODEL="${1:-qwen2.5:7b}"
|
||||||
|
|
||||||
|
echo "=== Ollama Setup ==="
|
||||||
|
|
||||||
|
echo "[1/3] Installing Ollama..."
|
||||||
|
curl -fsSL https://ollama.ai/install.sh | sh
|
||||||
|
|
||||||
|
echo "[2/3] Enabling service..."
|
||||||
|
sudo systemctl enable ollama
|
||||||
|
sudo systemctl start ollama
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
echo "[3/3] Pulling default model: $MODEL (~5 GB, dauert je nach Netz 5-15 min)..."
|
||||||
|
ollama pull "$MODEL"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Done ==="
|
||||||
|
ollama list
|
||||||
|
echo ""
|
||||||
|
echo "Test: curl http://localhost:11434/api/generate -d '{\"model\":\"$MODEL\",\"prompt\":\"Hello\",\"stream\":false}'"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Base Provisioning — ThinkCentre 1 + 2
|
||||||
|
# Run as target user (secondclaw) with NOPASSWD sudo
|
||||||
|
# Usage: bash provision.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== ZeitAnker ThinkCentre Base Provisioning ==="
|
||||||
|
|
||||||
|
echo "[1/6] System update..."
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get upgrade -y -qq
|
||||||
|
sudo apt-get install -y -qq \
|
||||||
|
curl wget git unzip build-essential \
|
||||||
|
htop tmux vim jq \
|
||||||
|
lighttpd \
|
||||||
|
ca-certificates gnupg lsb-release
|
||||||
|
|
||||||
|
echo "[2/6] Node.js 22 (LTS)..."
|
||||||
|
if ! command -v node &>/dev/null; then
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
||||||
|
sudo apt-get install -y nodejs
|
||||||
|
fi
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
|
||||||
|
echo "[3/6] Docker (if not installed)..."
|
||||||
|
if ! command -v docker &>/dev/null; then
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
sudo usermod -aG docker "$USER"
|
||||||
|
fi
|
||||||
|
docker --version
|
||||||
|
|
||||||
|
echo "[4/6] PM2..."
|
||||||
|
npm install -g pm2 2>/dev/null || true
|
||||||
|
pm2 --version
|
||||||
|
|
||||||
|
echo "[5/6] lighttpd APK Server..."
|
||||||
|
sudo mkdir -p /var/www/downloads
|
||||||
|
sudo chown "$USER:$USER" /var/www/downloads
|
||||||
|
sudo tee /etc/lighttpd/lighttpd.conf > /dev/null << 'EOF'
|
||||||
|
server.modules = ( "mod_dirlisting" )
|
||||||
|
server.document-root = "/var/www/downloads"
|
||||||
|
server.port = 8080
|
||||||
|
dir-listing.activate = "enable"
|
||||||
|
mimetype.assign = (
|
||||||
|
".apk" => "application/vnd.android.package-archive",
|
||||||
|
".html" => "text/html",
|
||||||
|
)
|
||||||
|
EOF
|
||||||
|
sudo systemctl enable lighttpd
|
||||||
|
sudo systemctl restart lighttpd
|
||||||
|
|
||||||
|
echo "[6/6] SSH key (from Pi)..."
|
||||||
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||||
|
# Pi's public key — allows Otto to SSH in without password
|
||||||
|
PI_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP0AOGdfsP2pewLTZ5yq9podhDaPinPqLeI148tecY5o ottobringts@gmail.com"
|
||||||
|
grep -qF "$PI_KEY" ~/.ssh/authorized_keys 2>/dev/null || echo "$PI_KEY" >> ~/.ssh/authorized_keys
|
||||||
|
chmod 600 ~/.ssh/authorized_keys
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Provisioning complete ==="
|
||||||
|
echo "Node: $(node --version)"
|
||||||
|
echo "Docker: $(docker --version)"
|
||||||
|
echo "PM2: $(pm2 --version)"
|
||||||
|
echo "lighttpd: http://$(hostname -I | awk '{print $1}'):8080"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " Android: bash android/setup.sh"
|
||||||
|
echo " Ollama: bash ollama/setup.sh"
|
||||||
|
echo " OpenClaw (TC2 only): npm install -g openclaw && openclaw setup"
|
||||||
Reference in New Issue
Block a user