{"id":30546420,"url":"https://github.com/hassan-ach/homelab","last_synced_at":"2026-04-07T09:31:08.650Z","repository":{"id":311536274,"uuid":"1042312042","full_name":"Hassan-ach/homelab","owner":"Hassan-ach","description":"Self-hosted homelab with Nextcloud, Jellyfin, MariaDB, Redis, and SWAG reverse proxy using Docker Compose","archived":false,"fork":false,"pushed_at":"2025-08-25T04:04:07.000Z","size":286,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-25T05:54:54.911Z","etag":null,"topics":["docker","docker-compose","jellyfin","mariadb","nextcloud","nginx-docker","nginx-reverse-proxy"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hassan-ach.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-21T20:15:33.000Z","updated_at":"2025-08-25T04:04:10.000Z","dependencies_parsed_at":"2025-08-25T05:55:12.752Z","dependency_job_id":null,"html_url":"https://github.com/Hassan-ach/homelab","commit_stats":null,"previous_names":["hassan-ach/homelab"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Hassan-ach/homelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hassan-ach%2Fhomelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hassan-ach%2Fhomelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hassan-ach%2Fhomelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hassan-ach%2Fhomelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hassan-ach","download_url":"https://codeload.github.com/Hassan-ach/homelab/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hassan-ach%2Fhomelab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272417972,"owners_count":24931557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","jellyfin","mariadb","nextcloud","nginx-docker","nginx-reverse-proxy"],"created_at":"2025-08-28T02:00:41.630Z","updated_at":"2025-12-30T21:35:25.644Z","avatar_url":"https://github.com/Hassan-ach.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Self-Hosted Cloud Services with Docker Compose\n\nA complete homelab setup for self-hosting Nextcloud and Jellyfin with automated SSL certificates, reverse proxy, and database management.\n\n## Motivation\n\n- Ran out of free Google Drive storage\n- Didn't want to pay for more cloud storage\n- Learning experience about home-labbing and self-hosting\n- Curiosity about containerized applications\n- Privacy and control over personal data\n\n## Hardware Specifications\n\n- **Device**: HP Mini PC\n- **CPU**: Intel i5 6th Gen\n- **RAM**: 8GB\n- **Storage**: 256GB SSD + 256GB HDD\n- **GPU**: Intel HD 530 iGPU\n\n## Prerequisites\n\n- Ubuntu Server or Desktop (20.04+ recommended)\n- Docker \u0026 Docker Compose\n- Domain name (free option: [DuckDNS](https://www.duckdns.org))\n- Router with port forwarding capability (for WAN access)\n\n## Tech Stack Overview\n\n### [SWAG](https://docs.linuxserver.io/images/docker-swag/) (Secure Web Application Gateway)\n\n- **Purpose**: Reverse proxy with automated SSL certificates\n- **Features**:\n    - Nginx web server and reverse proxy\n    - Automated Let's Encrypt SSL certificate generation and renewal\n    - Fail2ban for additional security\n    - DNS validation support for various providers\n\n### [ Nextcloud ](https://jellyfin.org/docs/)\n\n- **Purpose**: Self-hosted cloud storage and collaboration platform\n- **Key Features**:\n    - File storage \u0026 synchronization across devices\n    - Sharing \u0026 collaboration tools\n    - Rich app ecosystem (calendars, contacts, notes, office suite)\n    - Security features (end-to-end encryption, 2FA)\n    - Mobile and desktop clients\n\n### [ Jellyfin ](https://jellyfin.org/docs/)\n\n- **Purpose**: Media server for personal content streaming\n- **Features**:\n    - Stream movies, TV shows, music, and photos\n    - Hardware transcoding support\n    - Mobile apps and web interface\n    - No licensing fees or restrictions\n\n### MariaDB\n\n- **Purpose**: Database backend for Nextcloud\n- **Benefits**: MySQL-compatible, reliable, optimized for containerized environments\n\n### Redis\n\n- **Purpose**: Caching layer for improved Nextcloud performance\n- **Benefits**: Session storage, file locking, distributed caching\n\n## Directory Layout\n\nWhen you run `install.sh`, the following structure is created under `${COMMUNE_DIR}`:\n\n```bash\ncommune/\n├─ nextcloud/\n│ ├─ config/\n│ ├─ data/\n│ └─ logs/\n├─ jellyfin/\n│ ├─ config/\n│ ├─ cache/\n│ └─ logs/\n├─ mysql/\n│ ├─ data/\n│ ├─ config/\n│ └─ logs/\n├─ redis/\n│ ├─ data/\n│ └─ logs/\n└─ swag/\n  ├─ config/\n  └─ logs/\n\n```\n\n## Architecture\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/Docker_Arch.png\" alt=\"Docker Architecture\" width=\"95%\"/\u003e\n\u003c/div\u003e\n\n## Installation\n\n### 1. Clone the Repository\n\n```bash\ngit clone https://github.com/Hassan-ach/homelab\ncd homelab\n```\n\n### 2. Get a Domain Name\n\nIf you don't have a domain, get one for free at [DuckDNS](https://www.duckdns.org):\n\n1. Sign in with your preferred account\n2. Create a subdomain (e.g., `yourhomelab.duckdns.org`)\n3. Note your token for later configuration\n\n### 3. Configure Environment Variables\n\n```bash\ncp .env.example .env\nnano .env\n```\n\nFill in all required values (see configuration section below).\n\n### 4. Run the Installation Script\n\n```bash\nsudo chmod +x install.sh\nsudo ./install.sh\n```\n\n## Configuration\n\n### Environment Variables (.env file)\n\n**Critical settings to configure:**\n\n1. **Domain Settings**:\n\n    ```bash\n    URL=yourdomain.duckdns.org\n    DUCKDNSTOKEN=your-duckdns-token\n    EMAIL=your.email@example.com\n    ```\n\n2. **Security Credentials** (generate strong passwords):\n\n    ```bash\n    ADMIN_PASSWORD=your-strong-admin-password\n    DB_ROOT_PASSWORD=your-strong-mysql-root-password\n    DB_NC_PASSWORD=your-strong-mysql-nc-password\n    REDIS_PASSWORD=your-strong-redis-password\n    ```\n\n3. **System Settings**:\n    ```bash\n    PUID=1000  # Run 'id' to get your user ID\n    PGID=1000  # Run 'id' to get your group ID\n    TZ=Africa/Casablanca  # Your timezone\n    ```\n\n### Post-Installation Configuration\n\n**Important: Stop Docker containers before manual configuration:**\n\n```bash\ndocker compose down\n```\n\n#### SWAG Configuration\n\n1. **DNS Configuration** (for DuckDNS):\n\n    ```bash\n    # Edit: /opt/commune/swag/config/dns-conf/duckdns.ini\n    dns_duckdns_token=your-duckdns-token\n    ```\n\n2. **Nginx Reverse Proxy**:\n    ```bash\n    cd /opt/commune/swag/config/nginx/proxy-confs\n    cp nextcloud.subfolder.conf.sample nextcloud.subfolder.conf\n    cp jellyfin.subfolder.conf.sample jellyfin.subfolder.conf\n    ```\n\n#### Nextcloud Configuration\n\nEdit `/opt/commune/nextcloud/config/www/nextcloud/config/config.php`:\n\n```php\n'trusted_domains' =\u003e array(\n    0 =\u003e 'yourdomain.duckdns.org',\n    1 =\u003e '192.168.x.x',  # Your local IP\n),\n'trusted_proxies' =\u003e array(\n    0 =\u003e 'swag',\n),\n'overwritewebroot' =\u003e '/nextcloud',\n'overwriteprotocol' =\u003e 'https',\n'memcache.local' =\u003e '\\\\OC\\\\Memcache\\\\APCu',\n'memcache.distributed' =\u003e '\\\\OC\\\\Memcache\\\\Redis',\n'memcache.locking' =\u003e '\\\\OC\\\\Memcache\\\\Redis',\n'redis' =\u003e array(\n    'host' =\u003e 'redis',\n    'port' =\u003e 6379,\n    'timeout' =\u003e 0.0,\n    'read_timeout' =\u003e 1.0,\n    'password' =\u003e 'your-redis-password',\n),\n```\n\n**PHP Configuration** - Edit `/opt/commune/nextcloud/config/php/php-local.ini`:\n\n```ini\nupload_max_filesize = 10G\npost_max_size = 10G\nmax_execution_time = 3600\nmemory_limit = 1G\n```\n\n#### Jellyfin Configuration\n\n- Access the web interface during first startup\n- Complete the Setup Wizard\n- Configure media libraries pointing to `/data` (mapped to Nextcloud Media folder)\n- Enable hardware transcoding if supported by your hardware\n\n## External Storage Setup\n\n### Mounting USB/External Drives\n\n1. **Manual Mount**:\n\n    ```bash\n    sudo mount -o uid=1000,gid=1000 /dev/sdX1 /opt/commune/nextcloud/data/admin/files/External\n    ```\n\n2. **Scan Files in Nextcloud**:\n\n    ```bash\n    docker exec nextcloud occ files:scan --path=\"/admin/files/External\"\n    # Or scan all files:\n    docker exec nextcloud occ files:scan --all\n    ```\n\n3. **Automatic Mount Service** - Create `/etc/systemd/system/mount-usb.service`:\n\n    ```ini\n    [Unit]\n    Description=Mount USB drive for Nextcloud\n    DefaultDependencies=no\n    Before=docker.service\n    After=local-fs.target\n\n    [Service]\n    Type=oneshot\n    ExecStart=/usr/bin/mount -o uid=1000,gid=1000 /dev/sdX1 /opt/commune/nextcloud/data/admin/files/External\n    ExecStartPost=/bin/echo \"USB mounted successfully\"\n    RemainAfterExit=yes\n\n    [Install]\n    WantedBy=multi-user.target\n    ```\n\n    Enable the service:\n\n    ```bash\n    sudo systemctl enable mount-usb.service\n    sudo systemctl start mount-usb.service\n    ```\n\n### Restart Services\n\n```bash\ndocker compose up -d\n```\n\n## Network Access\n\n### Local Access\n\n- **Nextcloud**: `https://yourdomain.duckdns.org/nextcloud`\n- **Jellyfin**: `https://yourdomain.duckdns.org/jellyfin`\n- **Direct Jellyfin** (if proxy issues): `http://your-local-ip:8099`\n\n### WAN Access Setup\n\n1. **Router Configuration**:\n\n    - Forward port 80 → your server's local IP:80\n    - Forward port 443 → your server's local IP:443\n\n2. **Domain DNS**:\n\n    - Configure your domain to point to your public IP\n    - For DuckDNS, this updates automatically\n\n3. **Firewall Configuration**:\n    ```bash\n    sudo ufw allow 80/tcp\n    sudo ufw allow 443/tcp\n    sudo ufw allow 22/tcp  # Keep SSH access\n    sudo ufw enable\n    ```\n\n## Maintenance\n\n### Regular Tasks\n\n```bash\n# Update containers\ndocker compose pull\ndocker compose up -d\n\n# View logs\ndocker compose logs -f [service-name]\n\n# Backup configuration\nsudo tar -czf homelab-backup-$(date +%Y%m%d).tar.gz /opt/commune/\n\n# Nextcloud maintenance\ndocker exec nextcloud occ maintenance:mode --on\ndocker exec nextcloud occ upgrade\ndocker exec nextcloud occ maintenance:mode --off\n```\n\n### Monitoring\n\n```bash\n# Check service status\ndocker compose ps\n\n# Check resource usage\ndocker stats\n\n# Check disk usage\ndf -h /opt/commune/\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Jellyfin mobile app connection issues**:\n\n    - Use direct port access: `http://your-ip:8099`\n    - Check firewall settings\n\n2. **Nextcloud file scan not working**:\n\n    - Verify mount permissions\n    - Run manual scan: `docker exec nextcloud occ files:scan --all`\n\n3. **SSL certificate issues**:\n\n    - Check SWAG logs: `docker logs swag`\n    - Verify domain DNS resolution\n    - Check DuckDNS token validity\n\n4. **Database connection errors**:\n    - Check MariaDB logs: `docker logs mariadb`\n    - Verify database credentials in `.env`\n\n## Security Considerations\n\n1. **Strong Passwords**: Use unique, complex passwords for all services\n2. **Regular Updates**: Keep containers and host system updated\n3. **Firewall**: Only open necessary ports\n4. **SSL Certificates**: Ensure HTTPS is working properly\n5. **Backup Strategy**: Regular backups of configuration and data\n6. **Network Isolation**: Consider VPN access for enhanced security\n\n## What I Learned\n\n### Technical Skills\n\n- **Docker \u0026 Docker Compose**: Container orchestration and networking\n- **Reverse Proxy**: Nginx configuration and SSL termination\n- **SSL/TLS**: Let's Encrypt certificate automation\n- **Linux System Administration**: Service management and security\n- **Networking**: Port forwarding, DNS configuration, firewall setup\n\n### Key Concepts\n\n- **Infrastructure as Code**: Reproducible deployments with Docker Compose\n- **Security Best Practices**: Defense in depth, principle of least privilege\n- **Self-hosting Benefits**: Data privacy, cost savings, learning opportunities\n- **System Integration**: How different services work together in a homelab environment\n\n## License\n\nThis project is open source and available under the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhassan-ach%2Fhomelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhassan-ach%2Fhomelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhassan-ach%2Fhomelab/lists"}