From 007c151a1cbbde64ada77da9724d3c3583ed76d1 Mon Sep 17 00:00:00 2001 From: Azat Date: Mon, 2 Feb 2026 23:44:22 +0100 Subject: [PATCH] Initial redis skill implementation --- SKILL.md | 119 +++++++++++++++++++++++++++++++++++++++++++++ scripts/autorun.sh | 76 +++++++++++++++++++++++++++++ scripts/run.sh | 64 ++++++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 SKILL.md create mode 100644 scripts/autorun.sh create mode 100644 scripts/run.sh diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..64cbcd4 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,119 @@ +--- +name: redis +description: Redis in-memory cache with persistence and pub/sub +metadata: + version: "1.0.0" + vibestack: + main: false + metrics-port: 9121 +--- + +# Redis Skill + +Installs and configures [Redis](https://redis.io/) in-memory data store for caching, pub/sub messaging, and session storage. + +## Features + +- In-memory key-value store +- RDB + AOF persistence +- Pub/sub messaging +- Optional authentication +- Memory limit with eviction policy +- Auto-registers with Caddy if domain set + +## Configuration + +### Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `REDIS_PORT` | `6379` | Redis port | +| `REDIS_PASSWORD` | (none) | Optional authentication password | +| `REDIS_MAXMEMORY` | `100mb` | Memory limit | +| `REDIS_MAXMEMORY_POLICY` | `allkeys-lru` | Eviction policy when memory limit reached | +| `REDIS_DATA_DIR` | `/data/redis` | Persistence directory | +| `REDIS_APPENDONLY` | `yes` | Enable AOF persistence | +| `REDIS_SAVE` | `900 1 300 10 60 10000` | RDB save intervals | +| `REDIS_DOMAIN` | (none) | Domain for Caddy auto-config | + +### Output Variables + +After starting, the skill exports: + +| Variable | Example | +|----------|---------| +| `REDIS_URL` | `redis://:password@localhost:6379` | + +## Usage + +### As a dependency + +```yaml +metadata: + vibestack: + requires: + - redis +``` + +### Connection + +```bash +# Connect with redis-cli +redis-cli -p 6379 + +# With authentication +redis-cli -p 6379 -a "$REDIS_PASSWORD" + +# From application +REDIS_URL=redis://localhost:6379 +# or with auth +REDIS_URL=redis://:password@localhost:6379 +``` + +### Common Operations + +```bash +# Set a key +redis-cli SET mykey "Hello" + +# Get a key +redis-cli GET mykey + +# Pub/sub +redis-cli SUBSCRIBE mychannel +redis-cli PUBLISH mychannel "Hello subscribers!" + +# Check memory usage +redis-cli INFO memory +``` + +## Persistence + +Redis is configured with both RDB snapshots and AOF (Append Only File): + +- **RDB**: Point-in-time snapshots at configured intervals +- **AOF**: Log of all write operations for durability + +Data is stored in `REDIS_DATA_DIR` (default: `/data/redis`). + +## Memory Management + +When `REDIS_MAXMEMORY` is reached, the `REDIS_MAXMEMORY_POLICY` determines behavior: + +| Policy | Description | +|--------|-------------| +| `allkeys-lru` | Evict least recently used keys (default) | +| `volatile-lru` | Evict LRU keys with TTL set | +| `allkeys-random` | Evict random keys | +| `noeviction` | Return errors on write | + +## Caddy Integration + +If the `caddy` skill is present and `REDIS_DOMAIN` is set, Redis will be accessible via HTTPS (useful for Redis Insight or other GUI tools). + +## Security + +For production use: +1. Always set `REDIS_PASSWORD` +2. Restrict network access +3. Use TLS for external connections diff --git a/scripts/autorun.sh b/scripts/autorun.sh new file mode 100644 index 0000000..8ab40ed --- /dev/null +++ b/scripts/autorun.sh @@ -0,0 +1,76 @@ +#!/bin/bash +set -e + +REDIS_DATA_DIR="${REDIS_DATA_DIR:-/data/redis}" +SKILLS_DIR="${SKILLS_DIR:-/skills}" + +# Idempotent Redis installation +install_redis() { + if command -v redis-server &>/dev/null; then + echo "Redis already installed: $(redis-server --version)" + return 0 + fi + + echo "Installing Redis..." + + # Install dependencies + apt-get update + apt-get install -y curl gpg lsb-release + + # Add Redis repository + curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg + echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" > /etc/apt/sources.list.d/redis.list + + # Install Redis + apt-get update + apt-get install -y redis + + echo "Redis installed: $(redis-server --version)" +} + +# Setup directories +setup_dirs() { + mkdir -p "$REDIS_DATA_DIR" + chown -R redis:redis "$REDIS_DATA_DIR" 2>/dev/null || true + chmod 755 "$REDIS_DATA_DIR" + + echo "Redis data directory: $REDIS_DATA_DIR" +} + +# Configure Caddy if present +configure_caddy() { + local caddy_dir="$SKILLS_DIR/caddy" + local redis_domain="${REDIS_DOMAIN:-}" + local redis_port="${REDIS_PORT:-6379}" + + if [ ! -d "$caddy_dir" ]; then + echo "Caddy not found - Redis will run standalone" + return 0 + fi + + if [ -z "$redis_domain" ]; then + echo "REDIS_DOMAIN not set - skipping Caddy config" + return 0 + fi + + echo "Caddy detected - configuring reverse proxy..." + + local snippets_dir="$caddy_dir/snippets.d" + mkdir -p "$snippets_dir" + + cat > "$snippets_dir/redis.caddy" << EOF +# Auto-generated by redis skill +# Note: Redis protocol is not HTTP - this is for Redis Insight or similar tools +# $redis_domain { +# reverse_proxy localhost:$redis_port +# } +EOF + + echo "Caddy snippet created (manual config needed for Redis)" +} + +install_redis +setup_dirs +configure_caddy + +echo "Redis setup complete" diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100644 index 0000000..d8bb03b --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,64 @@ +#!/bin/bash +set -e + +REDIS_PORT="${REDIS_PORT:-6379}" +REDIS_PASSWORD="${REDIS_PASSWORD:-}" +REDIS_MAXMEMORY="${REDIS_MAXMEMORY:-100mb}" +REDIS_MAXMEMORY_POLICY="${REDIS_MAXMEMORY_POLICY:-allkeys-lru}" +REDIS_DATA_DIR="${REDIS_DATA_DIR:-/data/redis}" +REDIS_APPENDONLY="${REDIS_APPENDONLY:-yes}" +REDIS_SAVE="${REDIS_SAVE:-900 1 300 10 60 10000}" + +# Build REDIS_URL +if [ -n "$REDIS_PASSWORD" ]; then + export REDIS_URL="redis://:${REDIS_PASSWORD}@localhost:${REDIS_PORT}" +else + export REDIS_URL="redis://localhost:${REDIS_PORT}" +fi +echo "REDIS_URL=$REDIS_URL" + +# Write to shared env file for other skills +mkdir -p /run/vibestack +echo "REDIS_URL=$REDIS_URL" > /run/vibestack/redis.env + +# Build command arguments +args=() +args+=("--port" "$REDIS_PORT") +args+=("--dir" "$REDIS_DATA_DIR") +args+=("--maxmemory" "$REDIS_MAXMEMORY") +args+=("--maxmemory-policy" "$REDIS_MAXMEMORY_POLICY") +args+=("--appendonly" "$REDIS_APPENDONLY") + +# Add authentication if set +if [ -n "$REDIS_PASSWORD" ]; then + args+=("--requirepass" "$REDIS_PASSWORD") +fi + +# Configure RDB persistence +# REDIS_SAVE format: "seconds changes [seconds changes ...]" +if [ -n "$REDIS_SAVE" ]; then + # Parse save intervals (e.g., "900 1 300 10 60 10000") + read -ra save_args <<< "$REDIS_SAVE" + for ((i=0; i<${#save_args[@]}; i+=2)); do + if [ $((i+1)) -lt ${#save_args[@]} ]; then + args+=("--save" "${save_args[i]} ${save_args[i+1]}") + fi + done +fi + +# Bind to all interfaces +args+=("--bind" "0.0.0.0") + +# Enable protected mode only if no password +if [ -z "$REDIS_PASSWORD" ]; then + args+=("--protected-mode" "yes") +else + args+=("--protected-mode" "no") +fi + +echo "Starting Redis on port $REDIS_PORT..." +echo "Max memory: $REDIS_MAXMEMORY" +echo "Eviction policy: $REDIS_MAXMEMORY_POLICY" +echo "Persistence: AOF=$REDIS_APPENDONLY" + +exec redis-server "${args[@]}"