A modular Docker-based homelab setup with organized service stacks for infrastructure, media, AI, and container management.
- Pi-hole: Network-wide ad blocking and DNS
- Traefik: Reverse proxy with automatic SSL certificates
- Jellyfin: Media streaming server for movies, TV shows, and music
- Nextcloud: Personal cloud storage and collaboration platform
- Open WebUI: Interface for local AI/LLM models
- Portainer: Docker container management interface
- Beszel: Infrastructure health monitoring and rollout service
| Service | Stack | URL | Purpose |
|---|---|---|---|
| Pi-hole | infra | https://pihole.home |
DNS & Ad blocking |
| Traefik | infra | https://traefik.home |
Reverse proxy dashboard |
| Jellyfin | media | https://jellyfin.home |
Media streaming |
| Nextcloud | nextcloud | https://nextcloud.home |
Personal cloud |
| Open WebUI | llm | https://chat.home |
AI interface |
| Portainer | portainer | https://portainer.home |
Container management |
| Beszel | monitoring | https://health.koye.casa |
Health monitoring |
- Docker and Docker Compose installed
- Shared storage mounted at
/mnt/shared - Domain resolution for
*.homedomains (Pi-hole or hosts file)
-
Clone the repository
git clone <repository-url> cd homelab
-
Start infrastructure first
cd infra docker-compose up -d cd ..
-
Deploy other stacks
# Media stack cd media docker-compose up -d cd .. # Personal cloud cd nextcloud docker-compose up -d cd .. # AI services cd llm docker-compose up -d cd .. # Container management cd portainer docker-compose up -d # Monitoring services cd monitoring docker-compose up -d
-
Create required directories
sudo mkdir -p /mnt/shared/portainer/nextcloud/{db,html,data} sudo mkdir -p /mnt/shared/nextcloud-files -
Set proper permissions
# Nextcloud directories need www-data ownership sudo chown -R www-data:www-data /mnt/shared/portainer/nextcloud/html sudo chown -R www-data:www-data /mnt/shared/portainer/nextcloud/data sudo chown -R www-data:www-data /mnt/shared/nextcloud-files sudo chmod -R 755 /mnt/shared/portainer/nextcloud/{html,data} sudo chmod -R 755 /mnt/shared/nextcloud-files -
Configure environment variables (
β οΈ Important)Set these environment variables in Portainer or create a
.envfile:NEXTCLOUD_DB_ROOT_PASSWORD=your_secure_root_password NEXTCLOUD_DB_PASSWORD=your_secure_db_password NEXTCLOUD_ADMIN_PASSWORD=your_secure_admin_password
-
Complete setup via web interface
After starting the containers, access
https://nextcloud.hometo complete installation:- Create admin account (use your
NEXTCLOUD_ADMIN_PASSWORDvalue) - Important: Choose MySQL/MariaDB as database (not SQLite)
- Database settings:
- Database user:
nextcloud - Database password: Your
NEXTCLOUD_DB_PASSWORDvalue - Database name:
nextcloud - Database host:
nextcloud-db:3306
- Database user:
- Create admin account (use your
- homelab-network: External Docker network created by infrastructure stack
- All services connect to this shared network for inter-service communication
- Traefik handles SSL termination and routing for all
*.homedomains
- infra must be deployed first (creates network and handles routing)
- media, nextcloud, llm, and portainer can be deployed in any order after infra
All services are configured for Europe/Warsaw timezone. Update the TZ environment variable in each stack if needed.
- Media files:
/mnt/shared/mediaβ Jellyfin media library (read-only) - Cloud storage:
/mnt/shared/nextcloud-filesβ Nextcloud user files - Config persistence:
/mnt/shared/portainer/β Service configurations
- Hardware acceleration enabled (
/dev/dridevice mapping) - Auto-discovery and DLNA support
- Published server URL configured for external access
- MariaDB 10.11 database backend
- HTTPS protocol override for proper reverse proxy handling
- Trusted domain configured for
nextcloud.home - Admin user:
admin(change the password!)
- Network-wide DNS and ad blocking
- Web interface for managing blocklists and queries
- Custom DNS entries for local services
- Automatic SSL certificate management
- Dynamic service discovery via Docker labels
- Dashboard for monitoring routes and services
# Start a specific stack
cd [stack-name]
docker-compose up -d
# View stack logs
cd [stack-name]
docker-compose logs -f
# Update stack services
cd [stack-name]
docker-compose pull
docker-compose up -d
# Stop a stack
cd [stack-name]
docker-compose down# Start all stacks (in correct order)
./deploy.sh
# Check status across all stacks
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"Important directories to backup by stack:
- infra:
/mnt/shared/portainer/traefik/,/mnt/shared/portainer/pihole/ - media:
/mnt/shared/portainer/jellyfin/,/mnt/shared/media/ - nextcloud:
/mnt/shared/portainer/nextcloud/,/mnt/shared/nextcloud-files/ - llm:
/mnt/shared/portainer/openwebui/ - portainer:
/mnt/shared/portainer/portainer/ - monitoring:
/mnt/shared/portainer/beszel/
- Verify infra stack is running:
cd infra && docker-compose ps - Check
homelab-networkexists:docker network ls - Confirm DNS resolution for
*.homedomains (Pi-hole admin interface) - Check Traefik dashboard for service registration
- If services can't communicate, ensure infra stack created
homelab-network - Restart dependent stacks if network was recreated
# Check file ownership
ls -la /mnt/shared/portainer/nextcloud/
# Fix Nextcloud permissions
sudo chown -R 33:33 /mnt/shared/portainer/nextcloud/{html,data}
sudo chown -R 33:33 /mnt/shared/nextcloud-files/- Check MariaDB container logs:
docker-compose logs nextcloud-db - Verify database credentials in environment variables
- Ensure database container started before Nextcloud
- Change all default passwords before deployment
- Consider using Docker secrets for sensitive data
- Implement regular backups of configuration and data
- Keep services updated with latest security patches
- Fork the repository
- Create a feature branch
- Make your changes
- Test the configuration
- Submit a pull request
This homelab configuration is provided as-is for educational and personal use.