Files
homelab-configs/docs/testing/opencode-testing-guide.md
T
jgitta 821f954200 Add Caddy reverse proxy configuration and Kopia backup documentation
- Create INFRASTRUCTURE-COMPLETE.md: Comprehensive infrastructure overview
  * Network architecture and DNS configuration
  * Storage architecture for Nextcloud (1.4TB warm storage via LVM)
  * Kopia backup setup with Backblaze B2 integration
  * Caddy reverse proxy configuration (CT 202)
  * Security configuration and capacity planning

- Add Caddy reverse proxy configurations:
  * caddy-kopia-integration.md: Integration steps for CT 202
  * caddy-kopia-reverse-proxy.md: Complete configuration reference
  * caddy/Caddyfile: Production-ready configuration
  * caddy/docker-compose.yml: Docker deployment spec

- Add Kopia backup documentation:
  * kopia-nextcloud-backblaze-setup.md: Complete Kopia setup guide
  * Backup strategy, retention policies, and restore procedures

- Update related documentation with consolidated references

Status: Infrastructure documented and ready for deployment
2026-04-27 11:46:47 -05:00

7.6 KiB

OpenCode + LiteLLM Testing Guide (Nextcloud VM)

VM: next (Nextcloud) @ 192.168.88.62
OpenCode: Running in Docker
API Gateway: LiteLLM @ 192.168.88.27:4000
Config Source: Gitea @ 192.168.88.27:3002


🧪 Test 1: Verify Configuration Loaded

1.1 Check Config File on VM

ssh jgitta@192.168.88.62

# Check if config exists
cat ~/.opencode/config.json | jq '.'

# Expected output:
{
  "apiProvider": "openai",
  "apiBase": "http://192.168.88.27:4000",
  "apiKey": "litellm-local-key-change-in-production",
  "model": "gpt-4o",
  "timeout": 600,
  "maxTokens": 4096,
  "verbose": true
}

If you see this config: The setup is working! Config was pulled from Gitea.
If file doesn't exist: Check docker logs (see troubleshooting below)

1.2 Check Docker Container Logs

ssh jgitta@192.168.88.62
cd /path/to/docker-compose

# View startup logs
docker-compose logs opencode | tail -30

# Look for these messages:
# ✅ 🔄 Fetching configuration from Gitea...
# ✅ ✅ Configuration fetched successfully
# ✅ ✅ OpenCode config loaded from Gitea
# ✅ 🚀 Starting OpenCode...

🌐 Test 2: Verify Network Access

2.1 Can OpenCode Reach LiteLLM?

ssh jgitta@192.168.88.62

# Test from inside the container
docker exec opencode curl -s http://192.168.88.27:4000/models \
  -H "Authorization: Bearer litellm-local-key-change-in-production" | jq '.data | length'

# Expected output: 16

If you see 16: OpenCode can reach the LiteLLM gateway!
If connection refused: Check network/firewall

2.2 Can OpenCode Reach Gitea?

docker exec opencode curl -s http://192.168.88.27:3002/api/v1/version | jq '.version'

# Expected output: "1.21.4"

If version shown: Gitea is reachable
If connection refused: Check Gitea status


💻 Test 3: Test OpenCode API Calls

3.1 Direct API Test (Using gpt-4o)

ssh jgitta@192.168.88.62

# Make a test API call through the LiteLLM gateway
curl -X POST http://192.168.88.27:4000/chat/completions \
  -H "Authorization: Bearer litellm-local-key-change-in-production" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "What is 2+2?"}]
  }' 2>/dev/null | jq '.choices[0].message.content'

⚠️ With placeholder keys (current setup):

OpenAIException - Error code: 401 - Incorrect API key

This is EXPECTED - proves the system is routing correctly!

Once you add real API keys, you'll get actual responses.


🎯 Test 4: OpenCode Usage

4.1 Access OpenCode Web Interface

If OpenCode has a web UI, access it:

http://192.168.88.62:8000

(Port may differ - check your docker-compose)

4.2 Use OpenCode Command Line

ssh jgitta@192.168.88.62

# OpenCode will use the config from ~/.opencode/config.json
# pointing to LiteLLM at 192.168.88.27:4000

# Go to a project directory
cd ~/my-project

# Run OpenCode (it will use LiteLLM automatically)
opencode

# Or in background
opencode &

4.3 Test OpenCode with Code Files

ssh jgitta@192.168.88.62

# Create a test project
mkdir -p ~/opencode-test
cd ~/opencode-test

# Create a simple Python file
cat > hello.py << 'EOF'
def greet(name):
    """Greet someone by name"""
    # TODO: Add more greeting logic
    return f"Hello, {name}!"

# Usage
result = greet("World")
print(result)
EOF

# Run OpenCode on this directory
# It will use the LiteLLM gateway for any AI features
opencode

🔍 Test 5: Verify Config Updates Work

5.1 Change Model in Gitea

On your workstation:

# Clone the homelab-configs repo
git clone http://192.168.88.27:3002/jgitta/homelab-configs.git
cd homelab-configs

# Edit the config to use Claude instead
nano opencode/config.json

# Change line:
# FROM: "model": "gpt-4o",
# TO:   "model": "claude-3.5-sonnet",

git add opencode/config.json
git commit -m "Test: Switch to claude-3.5-sonnet"
git push origin main

5.2 Verify VM Pulls New Config

ssh jgitta@192.168.88.62

# Restart OpenCode to pull latest
cd /path/to/docker-compose
docker-compose restart opencode

# Wait 10 seconds
sleep 10

# Check the config was updated
cat ~/.opencode/config.json | jq '.model'

# Should now show: "claude-3.5-sonnet"

If model changed: Config updates are working!


📊 Complete Testing Checklist

# Run all tests in sequence
ssh jgitta@192.168.88.62

echo "Test 1: Config File"
cat ~/.opencode/config.json | jq '.apiBase'
# Expected: "http://192.168.88.27:4000"

echo ""
echo "Test 2: Docker Logs"
docker-compose logs opencode | grep "✅"
# Expected: Multiple ✅ messages

echo ""
echo "Test 3: LiteLLM Reachability"
docker exec opencode curl -s http://192.168.88.27:4000/models \
  -H "Authorization: Bearer litellm-local-key-change-in-production" | jq '.data | length'
# Expected: 16

echo ""
echo "Test 4: Gitea Reachability"
docker exec opencode curl -s http://192.168.88.27:3002/api/v1/version | jq '.version'
# Expected: "1.21.4"

echo ""
echo "Test 5: API Call (will fail with placeholder keys)"
curl -X POST http://192.168.88.27:4000/chat/completions \
  -H "Authorization: Bearer litellm-local-key-change-in-production" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "test"}]}' 2>/dev/null | jq '.detail | contains("401")'
# Expected: true (authorization error with placeholder keys is OK)

echo ""
echo "✅ All tests completed!"

🚨 Troubleshooting

Problem: "Config file not found"

# The docker-compose might not have pulled from Gitea
docker-compose logs opencode | grep -i "fetch\|clone"

# Check if Gitea is accessible
curl http://192.168.88.27:3002/
# If fails, Gitea might be down

# Manually update the config
docker exec opencode mkdir -p /root/.opencode
docker exec opencode cat > /root/.opencode/config.json << 'EOF'
{
  "apiProvider": "openai",
  "apiBase": "http://192.168.88.27:4000",
  "apiKey": "litellm-local-key-change-in-production",
  "model": "gpt-4o"
}
EOF

Problem: "Connection refused" to LiteLLM

# Check if LiteLLM is running on docker-server
curl http://192.168.88.27:4000/models

# Check docker-server networking
ssh root@192.168.88.27
docker ps | grep litellm
docker logs litellm | tail -20

# Restart if needed
cd /opt/litellm
docker-compose restart

Problem: "Config not updating after git push"

# Containers only pull on startup
# Restart OpenCode to fetch latest
docker-compose restart opencode

# Or fully recreate
docker-compose down
docker-compose up -d opencode

Problem: "OpenCode not starting"

# Check full error logs
docker-compose logs opencode

# Check if git/curl are available in container
docker exec opencode which git
docker exec opencode which curl

# If missing, update the docker image or Dockerfile

🎓 Next Steps

  1. Verify all 5 tests pass
  2. Add real API keys to /opt/litellm/.env on docker-server
  3. Test actual API calls without 401 errors
  4. Use OpenCode normally - it will route through LiteLLM automatically
  5. Manage configs centrally via Gitea - no per-VM setup needed

📝 Key Points

  • OpenCode pulls config from Gitea at startup
  • Config points to LiteLLM gateway at 192.168.88.27:4000
  • All 16 models available through LiteLLM
  • Change model for all VMs by editing one file in Gitea
  • No per-VM configuration needed
  • Network is internal only (no internet exposure)

  • LiteLLM Setup: litellm-complete-setup.md
  • Models Available: litellm-models-update.md
  • Implementation Guide: gitea-centralized-implementation.md