A collection of Docker containers for self-hosted services on Raspberry Pi systems
This repository contains Docker Compose configurations for running various self-hosted services on Raspberry Pi devices. Each service is organized in its own directory with persistent data volumes and consistent configuration patterns.
- Overview
- Port Allocation
- Container Services
- Getting Started
- Managing Containers
- Adding New Containers
- Raspberry Pi Considerations
- Troubleshooting
This setup provides a complete homelab environment with:
- Media Server: Jellyfin for streaming
- Network Management: Pi-hole for DNS-based ad blocking
- Reverse Proxy: Nginx Proxy Manager for HTTPS and domain routing
- Automation: n8n for workflow automation
- Monitoring: LGTM stack (Loki, Grafana, Tempo, Mimir) for observability
- Container Management: CasaOS for easy Docker management
- Dashboards: Grafana standalone for custom visualizations
- Backend: PocketBase for lightweight backend/database
- Project Management: OpenProject for team collaboration
- Backend-as-a-Service: Appwrite for full-stack development
- Downloads: qBittorrent for torrent management
- Music Server: Mopidy for YouTube Music streaming with remote control
All services are configured to run on Raspberry Pi with appropriate resource considerations and hardware acceleration where applicable.
IMPORTANT: Use unique ports to avoid conflicts. This table shows all allocated ports.
| Port | Service | Description |
|---|---|---|
| 80 | Nginx Proxy Manager | Public HTTP |
| 81 | Nginx Proxy Manager | Admin UI |
| 443 | Nginx Proxy Manager | Public HTTPS |
| 3000 | LGTM Stack | Grafana (built-in) |
| 3050 | Grafana | Standalone Grafana |
| 3100 | LGTM Stack | Loki |
| 4317 | LGTM Stack | OTLP gRPC |
| 4318 | LGTM Stack | OTLP HTTP |
| 5678 | n8n | Workflow automation |
| 8055 | PocketBase | Backend/Admin UI |
| 8060 | OpenProject | Project management |
| 8070 | Appwrite | Console/API |
| 8071 | Appwrite | Realtime |
| 8075 | qBittorrent | Web UI |
| 8096 | Jellyfin | Media server |
| 8443 | Pi-hole | Admin UI |
| 9090 | CasaOS | Container management |
| 9092 | LGTM Stack | Prometheus |
| 6881 | qBittorrent | BitTorrent (TCP/UDP) |
| 6680 | Mopidy | Web interface (Iris) |
| 6600 | Mopidy | MPD protocol |
| 8085 | ZeroClaw | Gateway / Webhook API |
When adding new services, choose ports not listed above to avoid conflicts.
Purpose: Web-based Docker container management interface
Location: /casa and /casaos
Docker Image: dockurr/casa
Access: http://<raspberry-pi-ip>:9090
Configuration:
ports:
- 9090:8080
volumes:
- ./casa:/DATA
- /var/run/docker.sock:/var/run/docker.sock # Docker socket accessDescription: CasaOS provides a user-friendly web interface for managing Docker containers. It has access to the Docker socket, allowing it to start, stop, and monitor other containers on your system.
Purpose: Media server for streaming movies, TV shows, and music
Location: /jellyfin
Docker Image: jellyfin/jellyfin:latest
Access: http://<raspberry-pi-ip>:8096
Configuration:
network_mode: host
user: 1000:1000 # Replace with your user ID
volumes:
- ./config:/config
- ./cache:/cache
- ~/media:/media:ro
- /home/stoxmod/media/movies:/Movies:ro
- /mnt/passport:/Passport:ro
devices:
- /dev/dri:/dev/dri # Hardware acceleration for Pi 5Features:
- Hardware-accelerated video transcoding (Raspberry Pi 5 VideoCore VII)
- Network mode:
hostfor optimal performance - Read-only media mounts for data protection
- Customizable media library paths
Setup Notes:
- Update
userwith your user ID (runid -uandid -g) - Update
JELLYFIN_PublishedServerUrlwith your Pi's IP address - Customize media volume paths to match your setup
Purpose: Network-wide ad blocking and DNS server
Location: /pihole
Docker Image: pihole/pihole:latest
Access: http://<raspberry-pi-ip>:8443/admin
Configuration:
network_mode: host
environment:
TZ: "Asia/Colombo"
WEBPASSWORD: "<your-password>"
FTLCONF_LOCAL_IPV4: "192.168.1.174"
PIHOLE_DNS_: "1.1.1.1;1.0.0.1" # Cloudflare DNS
WEB_PORT: 8443
volumes:
- ./etc-pihole:/etc/pihole
- ./etc-dnsmasq.d:/etc/dnsmasq.dFeatures:
- Network-wide ad blocking
- Custom DNS server
- Web interface on port 8443
- Persistent configuration and block lists
Setup Notes:
- Change
WEBPASSWORDto your desired admin password - Update
FTLCONF_LOCAL_IPV4with your Pi's static IP address - Configure your router to use Pi-hole as the DNS server
Purpose: Reverse proxy with SSL certificate management
Location: /npm
Docker Image: jc21/nginx-proxy-manager:latest
Access:
- Admin UI:
http://<raspberry-pi-ip>:81 - HTTP: Port 80
- HTTPS: Port 443
Configuration:
ports:
- "80:80" # Public HTTP
- "443:443" # Public HTTPS
- "81:81" # Admin interface
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencryptFeatures:
- Easy SSL certificate management with Let's Encrypt
- Reverse proxy for all your services
- Web-based configuration interface
- Access lists for security
Default Credentials:
- Email:
admin@example.com - Password:
changeme - Change these immediately after first login!
Purpose: Workflow automation platform
Location: /n8n
Docker Image: docker.n8n.io/n8nio/n8n
Access: http://<raspberry-pi-ip>:5678
Configuration:
ports:
- "5678:5678"
environment:
- GENERIC_TIMEZONE=Asia/Colombo
- TZ=Asia/Colombo
volumes:
- n8n_data:/home/node/.n8nFeatures:
- Visual workflow builder
- Hundreds of integrations
- Persistent workflow storage
- Timezone configuration
Optional Settings: Uncomment in the docker-compose.yml to enable:
- Basic authentication
- Custom webhook URL for domain access
Purpose: Complete observability stack (Loki, Grafana, Tempo, Mimir, Prometheus)
Location: /lgtm
Docker Images:
grafana/otel-lgtm(main stack)prom/node-exporter(system metrics)
Access:
- Grafana:
http://<raspberry-pi-ip>:3000 - Prometheus:
http://<raspberry-pi-ip>:9092
Configuration:
ports:
- "3000:3000" # Grafana UI
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "9092:9090" # Prometheus
- "3100:3100" # Loki
volumes:
- otel-lgtm-data:/data
- ./lgtm-config.yaml:/otel-lgtm/prometheus.yaml:ro
- /sys:/host/sys:ro
- /proc:/host/proc:roFeatures:
- Grafana: Visualization and dashboards
- Prometheus: Metrics collection
- Loki: Log aggregation
- Tempo: Distributed tracing
- Node Exporter: System metrics (CPU, memory, disk, temperature)
- Anonymous viewer access enabled
Monitored Metrics:
- System resources (CPU, memory, disk)
- Hardware temperatures and thermal zones
- Container performance
- Custom application metrics
Purpose: Standalone visualization and dashboards platform
Location: /grafana
Docker Image: grafana/grafana:latest
Access: http://<raspberry-pi-ip>:3050
Configuration:
ports:
- "3050:3000" # Unique port to avoid conflict with LGTM
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafanaDefault Credentials:
- Username:
admin - Password:
admin(change on first login)
Features:
- Custom dashboards separate from LGTM stack
- Plugin ecosystem for extended functionality
- Connect to external data sources
Purpose: Lightweight backend with built-in database and admin UI
Location: /pocketbase
Docker Image: ghcr.io/muchobien/pocketbase:latest
Access:
- Admin UI:
http://<raspberry-pi-ip>:8055/_/ - API:
http://<raspberry-pi-ip>:8055/api/
Configuration:
ports:
- "8055:8090" # Unique port
volumes:
- ./pb_data:/pb_dataFeatures:
- SQLite database with REST API
- Real-time subscriptions
- Built-in authentication
- File storage
- Admin dashboard
Setup Notes:
- Visit the admin UI on first run to create admin account
- Data persists in
./pb_datadirectory
Purpose: Open-source project management and collaboration platform
Location: /openproject
Docker Image: openproject/openproject:16
Access: http://<raspberry-pi-ip>:8060
Configuration:
ports:
- "8060:80" # Unique port
environment:
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
- OPENPROJECT_HOST__NAME=localhost:8060
volumes:
- ./pgdata:/var/openproject/pgdata
- ./assets:/var/openproject/assetsDefault Credentials:
- Username:
admin - Password:
admin(change on first login)
Setup Notes:
- Copy
.env.exampleto.env - Generate secret:
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 - Set
SECRET_KEY_BASEin.env
Features:
- Gantt charts and timelines
- Agile boards (Scrum/Kanban)
- Time tracking
- Team collaboration
- Document management
Purpose: Open-source Backend-as-a-Service (BaaS) platform for web and mobile apps
Location: /appwrite
Docker Images:
appwrite/appwrite:1.6(main + workers)mariadb:10.11(database)redis:7.2-alpine(cache)
Access:
- Console:
http://<raspberry-pi-ip>:8070 - Realtime:
http://<raspberry-pi-ip>:8071
Configuration:
ports:
- "8070:80" # Console/API
- "8071:80" # Realtime
environment:
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
- _APP_DB_PASS=${_APP_DB_PASS}
- _APP_REDIS_PASS=${_APP_REDIS_PASS}Setup Notes:
- Copy
.env.exampleto.env - Generate secrets:
# OpenSSL key openssl rand -hex 32 # Passwords openssl rand -base64 24
- Fill in all values in
.env - Start:
docker compose up -d
Features:
- Authentication (OAuth, Email, Phone)
- Database with real-time subscriptions
- File storage
- Serverless functions
- Messaging (Push, SMS, Email)
- Full REST and GraphQL API
Resource Requirements:
- Minimum 2GB RAM for basic operation
- Consider adding resource limits on Raspberry Pi
Purpose: Feature-rich BitTorrent client with web interface
Location: /qbittorrent
Docker Image: lscr.io/linuxserver/qbittorrent:latest
Access: http://<raspberry-pi-ip>:8075
Configuration:
ports:
- "8075:8080" # Web UI
- "6881:6881" # BitTorrent TCP
- "6881:6881/udp" # BitTorrent UDP
environment:
- TZ=Asia/Colombo
- PUID=1000
- PGID=1000
volumes:
- ./config:/config
- ./downloads:/downloadsDefault Credentials:
- Username:
admin - Password: Check container logs on first run (
docker logs qbittorrent)
Setup Notes:
- Update
PUIDandPGIDwith your user ID (id -uandid -g) - Adjust
./downloadspath to your preferred download location - Forward port 6881 on your router for optimal speeds
Features:
- Web-based remote access
- RSS feed support
- Search plugins
- Sequential downloading
- Bandwidth scheduling
Purpose: Music server with YouTube Music integration and remote control
Location: /mopidy
Docker Image: Custom build based on ghcr.io/mopidy/mopidy:latest
Access:
- Web Interface:
http://<raspberry-pi-ip>:6680 - Iris UI (recommended):
http://<raspberry-pi-ip>:6680/iris - Mobile UI:
http://<raspberry-pi-ip>:6680/mobile
Configuration:
build: .
ports:
- "6680:6680" # Web interface
- "6600:6600" # MPD protocol
volumes:
- ./mopidy.conf:/config/mopidy.conf
- ./ytmusic_auth.json:/config/ytmusic_auth.json
- ./local:/var/lib/mopidy/local
- ./media:/var/lib/mopidy/media
devices:
- /dev/snd:/dev/snd # Audio device accessSetup Notes:
-
Generate YouTube Music auth file (on your PC with a browser):
pip install mopidy-ytmusic mopidy-ytmusic setup # Follow prompts to authenticate with Google account -
Transfer auth file to Pi:
scp ytmusic_auth.json pi@<raspberry-pi-ip>:~/homelab-configs/mopidy/
-
Build and start:
cd mopidy docker compose up -d --build
Audio Configuration:
If audio doesn't work initially:
# Check ALSA devices on Pi
aplay -l
# Test audio output
speaker-test -t wav -c 2
# Adjust volume
alsamixerYou may need to adjust the audio device in mopidy.conf:
[audio]
output = alsasink device=hw:X,Y # Replace X,Y with your device numbersFeatures:
- Web-based control from any device on your network
- YouTube Music library search and playback
- Queue management and playlists
- Multiple clients can control simultaneously
- Persistent state - resumes where you left off
- MPD protocol support for alternative clients
Purpose: Lightweight AI assistant agent with webhook gateway
Location: /zeroclaw
Docker Image: Custom build (pre-compiled binary)
Access: http://<raspberry-pi-ip>:8085
Configuration:
build: .
ports:
- "8085:8080" # Gateway / Webhook API
volumes:
- ./data:/root/.zeroclaw/workspace # Agent workspace & memory
- ./config.toml:/root/.zeroclaw/config.toml # Config file
environment:
- RUST_LOG=infoFeatures:
- Extremely lightweight (<5MB RAM)
- SQLite vector database for memory
- Supervised autonomy mode
- Pairing-based security
- OpenRouter / Claude Haiku integration
Setup Notes:
- Download the ARM64 binary from ZeroClaw releases
- Edit
config.tomlwith your API key - Build and start:
docker compose up -d --build - Check logs for pairing code:
docker compose logs -f zeroclaw - See zeroclaw/SETUP.md for full deployment instructions
- Raspberry Pi (tested on Pi 5)
- Docker and Docker Compose installed
- Static IP address configured for your Pi
- Sufficient storage for media and data
-
Clone this repository:
git clone <repository-url> cd homelab-configs
-
Configure environment-specific settings:
- Update IP addresses in configurations
- Set passwords and credentials
- Adjust volume paths for your system
-
Start all services:
# Start all services for dir in */; do (cd "$dir" && docker compose up -d) done
Or start individual services:
cd jellyfin docker compose up -d
cd <service-directory>
docker compose up -dcd <service-directory>
docker compose downcd <service-directory>
docker compose logs -fcd <service-directory>
docker compose restartcd <service-directory>
docker compose pull
docker compose up -ddocker psFollow this standardized structure when adding new services:
mkdir new-service
cd new-serviceUse this template:
version: "3.8"
services:
service-name:
image: <docker-image>:latest
container_name: service-name
restart: unless-stopped
# Ports (if needed)
ports:
- "host-port:container-port"
# Environment variables
environment:
- TZ=Asia/Colombo
# Add service-specific variables
# Volumes for persistent data
volumes:
- ./data:/data
# Add service-specific volumes
# Network (optional)
# networks:
# - service-network
# Define volumes (if using named volumes)
volumes:
service-data:
driver: local
# Define networks (if needed)
# networks:
# service-network:
# driver: bridgeOrganize your service following this pattern:
new-service/
├── docker-compose.yml
├── data/ # Application data
├── config/ # Configuration files
└── logs/ # Log files (if needed)
- Restart Policy: Use
unless-stoppedfor most services - Timezone: Set
TZenvironment variable - Volumes: Use relative paths (
./) for easy portability - Ports: Document all exposed ports in comments
- Security: Never commit passwords; use environment files
- User Permissions: Set appropriate user IDs for file access
# Validate configuration
docker compose config
# Start in foreground to check for errors
docker compose up
# If successful, run in background
docker compose up -d
# Check logs
docker compose logs -fAdd a section to this README documenting:
- Service purpose
- Access URLs and ports
- Important configuration options
- Any special setup requirements
- Minimum: Raspberry Pi 4 with 4GB RAM
- Recommended: Raspberry Pi 5 with 8GB RAM
- Storage: SSD recommended for better performance (vs SD card)
- Cooling: Heatsink or fan recommended under load
-
Use Hardware Acceleration:
- Jellyfin uses
/dev/drifor video transcoding - Check available devices:
ls -la /dev/dri
- Jellyfin uses
-
Network Mode:
- Some services use
hostnetwork mode for better performance - Trade-off: Port conflicts are possible
- Some services use
-
Resource Limits: Add to docker-compose.yml if needed:
deploy: resources: limits: cpus: "2" memory: 1G
-
Storage Optimization:
- Mount external drives for media storage
- Use SSD for Docker volumes
- Regular cleanup:
docker system prune
All images in this setup support ARM architecture (arm64). When adding new services, verify ARM support:
docker manifest inspect <image-name>:latest | grep architectureServices are configured with restart: unless-stopped to survive reboots. To disable auto-start:
restart: "no"-
Check logs:
docker compose logs
-
Verify port availability:
sudo netstat -tlnp | grep <port>
-
Check file permissions:
ls -la sudo chown -R 1000:1000 ./data
-
Monitor resources:
docker stats
-
Check Pi temperature:
vcgencmd measure_temp
-
Monitor disk I/O:
iostat -x 1
-
Check container networking:
docker network ls docker network inspect <network-name>
-
Verify DNS resolution:
docker exec <container> ping google.com
-
Find your user/group ID:
id -u # User ID id -g # Group ID
-
Update ownership:
sudo chown -R $(id -u):$(id -g) ./directory
View detailed logs with timestamps:
docker compose logs -f --timestamps --tail=100# Backup all configurations and data
tar -czf homelab-backup-$(date +%Y%m%d).tar.gz \
--exclude='*/cache/*' \
--exclude='*/logs/*' \
homelab-configs/# Update all services
for dir in */; do
echo "Updating $dir..."
(cd "$dir" && docker compose pull && docker compose up -d)
done# Remove unused images and volumes
docker system prune -a --volumes- Change default passwords immediately
- Use Nginx Proxy Manager to add HTTPS
- Consider setting up Tailscale or WireGuard for remote access
- Enable UFW firewall for additional security
- Keep Docker and images updated regularly
When adding new services:
- Follow the directory structure
- Document in this README
- Test thoroughly on Raspberry Pi
- Include resource requirements
Personal homelab configuration - use at your own discretion.
For issues with specific services, consult their official documentation: