Deploying Weaviate on Raspberry Pi: A Production-Grade 2026 Guide for Self-Hosted Vector Search
Step-by-step production deployment of Weaviate vector database on Raspberry Pi (ARM64). Covers Docker Compose, reverse proxy, Tailscale, automated backups, and troubleshooting.
Deploying Weaviate on Raspberry Pi: A Production-Grade 2026 Guide for Self-Hosted Vector Search
1. Executive Summary & Architecture Overview
Weaviate is an open-source vector database that enables semantic search, similarity matching, and AI-powered applications through vector embeddings. Self-hosting Weaviate on a Raspberry Pi offers complete data ownership, privacy, and cost savings compared to commercial SaaS vector databases like Pinecone or Weaviate Cloud. Your data never leaves your infrastructure, and you retain full control over schema, indexing, and access policies.
This guide walks you through a production-ready deployment on a Raspberry Pi 4 or 5 (ARM64) using Docker Compose. We cover bare-metal preparation, container orchestration, reverse proxy with SSL, zero-trust remote access via Tailscale, automated backups, and a deep troubleshooting matrix.
Architecture Overview:
- Host: Raspberry Pi 4/5 running Raspberry Pi OS (64-bit) or Ubuntu Server 24.04 LTS.
- Containerization: Docker Engine + Docker Compose V2.
- Weaviate: Single-node deployment with persistent volume for data.
- Reverse Proxy: Nginx Proxy Manager or Caddy for domain-based access with Let's Encrypt SSL.
- Remote Access: Tailscale VPN for private, encrypted access without opening router ports.
- Backup: Cron-driven script that stops the container, snapshots the data volume, and compresses to an external drive.
2. Hardware, OS & Network Requirements
| Component | Minimum | Recommended |
|---|---|---|
| CPU | ARM Cortex-A72 (RPi 4) | ARM Cortex-A76 (RPi 5) |
| RAM | 4 GB | 8 GB (for larger datasets) |
| Storage | 32 GB SD card (slow) | 256 GB NVMe SSD via USB 3.0 |
| Network | 100 Mbps Ethernet | 1 Gbps Ethernet |
| OS | Raspberry Pi OS Lite (64-bit) | Ubuntu Server 24.04 LTS (ARM64) |
| Docker | Docker Engine 24+ | Docker Engine 26+ |
Ports Used:
| Port | Protocol | Purpose |
|---|---|---|
| 8080 | TCP | Weaviate HTTP REST API |
| 6060 | TCP | Weaviate gRPC (optional) |
| 80/443 | TCP | Reverse proxy (public) |
| 22 | TCP | SSH (admin) |
| 41641 | UDP | Tailscale (outbound) |
3. Step 1: Host Preparation & Directory Layout
Update System and Install Docker
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git vim htop
Install Docker via convenience script (verify after):
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
Add your user to docker group (logout/login after):
sudo usermod -aG docker $USER
Verify Docker Compose V2:
docker compose version
# Should output: Docker Compose version v2.x.x
Create Directory Layout
We'll use /opt/weaviate as our base. Create the structure:
sudo mkdir -p /opt/weaviate/data
sudo mkdir -p /opt/weaviate/backups
sudo chown -R $USER:$USER /opt/weaviate
Set proper permissions for the data directory (we'll run container as non-root):
sudo chmod -R 755 /opt/weaviate
Create .env File
Navigate to the directory:
cd /opt/weaviate
Generate secure credentials:
openssl rand -hex 32 # Use output for WEAVIATE_APIKEY
openssl rand -hex 16 # Use output for WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS
Create .env with your values:
cat > .env <<EOF
# Weaviate Configuration
WEAVIATE_APIKEY=your_generated_hex_key_here
WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=your_generated_hex_key_here
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=false
WEAVIATE_PERSISTENCE_DATA_PATH=/var/lib/weaviate
WEAVIATE_QUERY_DEFAULTS_LIMIT=25
WEAVIATE_DEFAULT_VECTORIZER_MODULE=none
WEAVIATE_ENABLE_MODULES=text2vec-transformers,generative-openai
WEAVIATE_CLUSTER_HOSTNAME=weaviate-cluster
WEAVIATE_GRPC_PORT=6060
# Timezone
TZ=UTC
EOF
Important: Replace the placeholder keys with actual generated values. Never commit .env to version control.
4. Step 2: Production-Grade docker compose.yaml
Create docker-compose.yml (note: no version key, modern Compose spec):
services:
weaviate:
container_name: weaviate
image: semitechnologies/weaviate:1.28.6
restart: unless-stopped
security_opt:
- no-new-privileges:true
environment:
- WEAVIATE_APIKEY=${WEAVIATE_APIKEY}
- WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS}
- WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED}
- WEAVIATE_PERSISTENCE_DATA_PATH=${WEAVIATE_PERSISTENCE_DATA_PATH}
- WEAVIATE_QUERY_DEFAULTS_LIMIT=${WEAVIATE_QUERY_DEFAULTS_LIMIT}
- WEAVIATE_DEFAULT_VECTORIZER_MODULE=${WEAVIATE_DEFAULT_VECTORIZER_MODULE}
- WEAVIATE_ENABLE_MODULES=${WEAVIATE_ENABLE_MODULES}
- WEAVIATE_CLUSTER_HOSTNAME=${WEAVIATE_CLUSTER_HOSTNAME}
- WEAVIATE_GRPC_PORT=${WEAVIATE_GRPC_PORT}
- TZ=${TZ}
volumes:
- ./data:/var/lib/weaviate
ports:
- "8080:8080"
- "6060:6060"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/v1/.well-known/ready"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
networks:
- weaviate_net
networks:
weaviate_net:
driver: bridge
Explanation:
security_opt: no-new-privilegesreduces risk of privilege escalation.- Healthcheck uses Weaviate's built-in readiness endpoint.
- Named volume
./datamaps to/var/lib/weaviateinside container. - Custom bridge network isolates Weaviate from other containers.
5. Step 3: Deployment & Health Verification
Pull and start the container:
docker compose up -d
Check logs:
docker compose logs -f weaviate
Wait until you see "Weaviate is ready" or similar. Verify container status:
docker compose ps
Test the API with curl (using your API key):
curl -H "Authorization: Bearer ${WEAVIATE_APIKEY}" http://localhost:8080/v1/meta
You should receive JSON with version info. Also test readiness endpoint:
curl -f http://localhost:8080/v1/.well-known/ready
Initial Onboarding: Weaviate has no GUI by default. Use the Python client or REST API to create schemas and objects. For a quick test, create a class:
curl -X POST http://localhost:8080/v1/schema \
-H "Authorization: Bearer ${WEAVIATE_APIKEY}" \
-H "Content-Type: application/json" \
-d '{"class": "Document", "properties": [{"name": "content", "dataType": ["text"]}]}'
6. Step 4: Reverse Proxy, Domain & SSL Hardening
Expose Weaviate via a subdomain like weaviate.example.com. Use Nginx Proxy Manager (NPM) or Caddy.
Nginx Proxy Manager Setup
- Deploy NPM (see official docs) and add a proxy host.
- Domain:
weaviate.example.com - Forward host:
weaviate(container name) or127.0.0.1if using host network. - Port:
8080 - Enable WebSockets (if needed).
- Add custom Nginx configuration:
location / {
proxy_pass http://weaviate:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
}
- Request Let's Encrypt SSL certificate via NPM UI.
- Enable HSTS in NPM advanced tab:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Caddy (Alternative)
Caddyfile:
weaviate.example.com {
reverse_proxy weaviate:8080
header Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
Caddy auto-configures SSL and HTTP/2.
7. Step 5: Zero-Trust Remote Access with Tailscale
Install Tailscale on the Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --ssh
Authenticate via browser URL. Once connected, the Pi gets a 100.x.y.z IP. To access Weaviate from any device on your tailnet:
curl -H "Authorization: Bearer ${WEAVIATE_APIKEY}" http://100.x.y.z:8080/v1/meta
No public ports opened, traffic is encrypted via WireGuard. For centralized access, use Tailscale Serve to expose Weaviate on the tailnet with HTTPS:
sudo tailscale serve --bg --https=443 http://127.0.0.1:8080
Now you can access https://weaviate.tailnet-name.ts.net.
8. Step 6: Automated Backup & Disaster Recovery
Create a backup script /opt/weaviate/backup.sh:
#!/bin/bash
# Configuration
BACKUP_DIR="/opt/weaviate/backups"
DATA_DIR="/opt/weaviate/data"
RETENTION_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="weaviate_backup_${TIMESTAMP}.tar.gz"
# Stop Weaviate gracefully to ensure consistent state
echo "Stopping Weaviate container..."
docker compose -f /opt/weaviate/docker-compose.yml down
# Create backup
echo "Creating backup..."
tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" -C "${DATA_DIR}" .
# Restart Weaviate
echo "Starting Weaviate container..."
docker compose -f /opt/weaviate/docker-compose.yml up -d
# Cleanup old backups
echo "Cleaning up old backups..."
find "${BACKUP_DIR}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete
echo "Backup completed: ${BACKUP_FILE}"
Make executable:
chmod +x /opt/weaviate/backup.sh
Add to crontab (run daily at 2 AM):
crontab -e
Add line:
0 2 * * * /opt/weaviate/backup.sh >> /var/log/weaviate-backup.log 2>&1
Disaster Recovery: To restore, stop Weaviate, extract backup into data dir, restart:
docker compose down
tar -xzf backups/weaviate_backup_YYYYMMDD_HHMMSS.tar.gz -C data/
docker compose up -d
9. Step 7: Deep Troubleshooting Matrix
| Error / Symptom | Root Cause | Verified Resolution |
|---|---|---|
EACCES: permission denied when writing to /var/lib/weaviate |
Host directory permissions not correct | Ensure /opt/weaviate/data is owned by $USER and chmod 755. Run sudo chown -R $USER:$USER /opt/weaviate/data. |
Container exits with Error: listen tcp :8080: bind: address already in use |
Port 8080 occupied by another service | Run sudo lsof -i :8080 and stop conflicting process, or change host port mapping to e.g. 18080:8080. |
connection refused from Python client |
Weaviate not fully started or wrong port | Check docker compose ps and logs. Wait for healthcheck to pass. Test with curl http://localhost:8080/v1/.well-known/ready. |
| Reverse proxy returns 502 Bad Gateway | Proxy cannot reach Weaviate container | Ensure proxy uses correct container name and network. Verify with docker exec weaviate curl http://localhost:8080. Check proxy headers. |
unauthorized when calling API |
Missing or invalid API key | Confirm WEAVIATE_APIKEY in .env matches the Authorization: Bearer header. Restart container after changing .env. |
| High memory usage on Pi 4 | Weaviate default caching uses too much RAM | Set WEAVIATE_QUERY_DEFAULTS_LIMIT lower, or adjust JVM heap if using modules. Consider limiting via Docker mem_limit: 2g. |
10. Step 8: Frequently Asked Questions (FAQ)
Q1: Can I run Weaviate on a Raspberry Pi 4 with 4GB RAM?
Yes, for small datasets (up to ~100k vectors). Limit memory by setting mem_limit in Docker Compose and reduce WEAVIATE_QUERY_DEFAULTS_LIMIT. Use NVMe storage for better performance. For production with large datasets, use Pi 5 or a cluster.
Q2: Should I use Watchtower for automatic updates?
I recommend manual pinning over Watchtower. Weaviate upgrades can change schema or API behavior. Pin the image tag (e.g., 1.28.6) and test updates in a staging environment. If you must automate, use Watchtower with --revive-stopped and schedule during low traffic, but always backup first.
Q3: How do I migrate from an existing vector database to Weaviate?
Export vectors and metadata in JSON format, then import via Weaviate's REST API using batch endpoints. Use the Python client for efficient ingestion. Ensure vector dimensions match the target class configuration.
Q4: What modules should I enable for production?
Start with none for vectorizer if you're using external embeddings (e.g., from OpenAI). Enable modules like text2vec-transformers only if you need on-device embedding, but be aware of high CPU/RAM usage on Pi. For generative search, use generative-openai but keep API keys secure.
Q5: How can I monitor Weaviate performance?
Use Prometheus metrics endpoint at /v1/metrics (if enabled). Integrate with Grafana. Also monitor system resources with htop, docker stats, and enable Weaviate's built-in metrics via environment variable WEAVIATE_METRICS_ENABLED=true.
Q6: Can I run Weaviate in a Kubernetes cluster on Pi?
Yes, for high availability, but it's overkill for most homelabs. Use k3s on multiple Pi nodes. Follow Weaviate's Helm chart for deployment. Be prepared for complexity in persistent storage and networking.
Q7: How do I secure Weaviate further?
- Use API key authentication (as shown).
- Disable anonymous access.
- Place behind reverse proxy with SSL.
- Use Tailscale for remote access.
- Regularly update Docker and Weaviate images.
- Backup data regularly.
This guide was last updated in 2026 based on Weaviate 1.28.6 stable release.
Community Technical Desk & Troubleshooting
0 Homelab Technical DeskEncountering an error, permission issue, or port conflict with this stack? Submit your setup question below — our engineering team reviews and replies with tested solutions.
No technical questions yet for this guide.
Have a question or running into an error? Ask above and our technical support team will reply in ~2 minutes!