Files
homelab/docs/services.md
Arpad Krejczinger e97a0f641e Update services documentation with Jellyfin and improvements
- Add comprehensive Jellyfin media server documentation
- Document successful folder structure compatibility testing
- Update Copyparty URLs from /cloud to /files
- Add metadata management instructions for Jellyfin
- Include music collection management strategies
- Document SSL certificate setup completion

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-17 20:58:20 +02:00

19 KiB

Services & Applications

Planning and configuration for self-hosted services and applications.

Git Repository Hosting

Service Options

  • Gitea: Lightweight, Go-based, minimal resource usage Recommended
  • Forgejo: Gitea fork, community-driven development
  • GitLab CE: Feature-rich but more resource intensive
  • Gogs: Simple, lightweight alternative

Status: Container Running ⚠️ Configuration Issues - UI accessible, config needs debugging

Prerequisites:

# Install Docker and Docker Compose
sudo pacman -S docker docker-compose
sudo systemctl enable docker
sudo systemctl start docker

# Add user to docker group (logout/login required)
sudo usermod -aG docker hoborg

Gitea Docker Setup:

# Create directories for persistent data
mkdir -p ~/docker/gitea/{data,config}

# Run Gitea container
docker run -d \
  --name gitea \
  -p 3000:3000 \
  -p 2222:22 \
  -v ~/docker/gitea/data:/data \
  -v ~/docker/gitea/config:/etc/gitea \
  -e USER_UID=1000 \
  -e USER_GID=1000 \
  gitea/gitea:latest

# Alternative: Docker Compose (preferred)
# See docker-compose.yml below

Docker Compose Configuration: Create ~/docker/gitea/docker-compose.yml:

version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - gitea
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2223:22"  # Gitea SSH (avoid conflict with system SSH on 2222)

Start with Docker Compose:

cd ~/docker/gitea
docker-compose up -d

Current Configuration

Container Status: Running at /opt/docker/gitea Access URLs:

Port Assignments:

  • System SSH: 2222 (for server administration)
  • Gitea SSH: 2223 (for Git operations)
  • Gitea Web: 3000 (web interface)

Database: SQLite (default, stored in container volume) Data Location: /opt/docker/gitea/data (persistent volume)

Router Port Forwarding Required:

  • 3000 → 192.168.0.100:3000 (web interface)
  • 2223 → 192.168.0.100:2223 (Git SSH operations)

Container Management:

cd /opt/docker/gitea
docker-compose logs gitea        # View logs
docker-compose down             # Stop container
docker-compose up -d            # Start container
docker-compose pull && docker-compose up -d  # Update

Gitea Configuration Recommendations

Database Selection:

  • SQLite (Recommended for homelab)
    • Zero configuration, single file
    • Perfect for personal/small team use
    • Easy backups and migration
  • PostgreSQL (Production alternative)
    • Better performance for heavy usage
    • Requires additional container setup

Domain & URL Configuration:

  • Server Domain: ak-homelab.duckdns.org
  • Gitea Base URL: http://ak-homelab.duckdns.org/gitea/
  • SSH Domain: ak-homelab.duckdns.org
  • SSH Port: 2223

Password Hash Algorithm:

  • Argon2 (Recommended)
    • Most secure modern algorithm
    • Resistant to GPU/ASIC attacks
    • Higher CPU usage but excellent security
  • bcrypt (Alternative)
    • Well-tested, lower resource usage
    • Good balance of security and performance

Setup Progress:

  1. Gitea container running
  2. Nginx reverse proxy setup complete
  3. Router port forwarding (80, 443) - COMPLETE - External access working
  4. Gitea web configuration - COMPLETE
    • Initial setup wizard completed
    • Admin user account created
    • SSH access configured
    • Repository migration completed
  5. SSL certificate setup - COMPLETE - Let's Encrypt with auto-renewal

Current Access:

Completed Configuration:

  • Router forwards: 80→80, 443→443, 2223→2223
  • Removed direct port 3000 forwarding
  • Homelab repository successfully migrated to Gitea
  • External access confirmed working from Windows PC
  • SSL certificates installed with Let's Encrypt
  • Automatic HTTP→HTTPS redirect enabled
  • Certificate auto-renewal configured

Cloud Storage Solutions

Service Options

  • Copyparty: Lightweight file server with resumable uploads, dedup, WebDAV DEPLOYED
  • Nextcloud: Full-featured, extensive app ecosystem
  • ownCloud: Original project, stable and mature
  • Seafile: Performance-focused file sync
  • Syncthing: Decentralized sync (no server needed) INSTALLED

Copyparty Installation and Configuration

Status: DEPLOYED AND WORKING - File server with upload/download capabilities

Installation:

# Installed via Arch package
sudo pacman -S copyparty

# Configuration file location
/home/hoborg/.config/copyparty/copyparty.conf

# Systemd service location
/etc/systemd/system/copyparty.service

Current Setup:

User Accounts:

  • guest: Standard user with read/write access to shared areas
  • hoborg: Admin user with access to all areas including private folder

Volume Structure:

/shared     → /home/hoborg/shared       (guest, hoborg: rw)
/documents  → /home/hoborg/Documents    (guest, hoborg: rw)
/music      → /home/hoborg/Music        (guest, hoborg: rw)
/videos     → /home/hoborg/Videos       (guest, hoborg: rw)
/private    → /home/hoborg/private      (hoborg only: rw)

Features Enabled:

  • User-changeable passwords (stored securely in encrypted database)
  • Upload deduplication (saves storage space)
  • File indexing and search (e2dsa)
  • Resumable uploads with up2k
  • File integrity verification
  • Thumbnail generation for images and videos

Security:

  • Authentication required for all access
  • Passwords stored in encrypted format: /home/hoborg/.config/copyparty/passwords.json
  • Admin-only private folder isolated from shared areas
  • Reverse proxy headers for proper client IP logging

Service Management:

# Check status
sudo systemctl status copyparty

# View logs
journalctl -fu copyparty

# Restart service
sudo systemctl restart copyparty

# Enable/disable autostart
sudo systemctl enable copyparty
sudo systemctl disable copyparty

Configuration Files:

  • Main config: /home/hoborg/.config/copyparty/copyparty.conf
  • Systemd service: /home/hoborg/homelab/config/systemd/copyparty.service
  • Nginx integration: Path /files/ in homelab.conf

Testing Confirmed:

  • File uploads working (including video files)
  • User authentication and authorization
  • Private folder access restricted to admin
  • External access through reverse proxy
  • Service auto-starts on boot

Nextcloud Installation

# Via snap (recommended)
sudo snap install nextcloud

# Or via Docker
docker run -d \
  --name nextcloud \
  -p 8080:80 \
  -v nextcloud_data:/var/www/html \
  nextcloud

Personal notes: Not a fan of snap, isn't there an AUR package? Go with docker otherwise

Features

  • File synchronization across devices
  • Video files, game installers -> high prio
  • Self-hosted git mirrors of favorite FOSS projects -> medium prio
  • Calendar and contacts (CalDAV/CardDAV) -> low prio
  • Document editing (OnlyOffice/Collabora) -> low prio
  • Photo management and sharing -> low prio
  • Mobile apps available?

Media Management

Jellyfin Media Server

Status: DEPLOYED AND WORKING - Docker-based media server with hardware acceleration

Installation:

# Deploy configuration files
sudo mkdir -p /opt/docker/jellyfin/{config,cache}
sudo cp config/docker/jellyfin/docker-compose.yml /opt/docker/jellyfin/

# Start container
cd /opt/docker/jellyfin
sudo docker-compose up -d

Current Setup:

Media Library Structure:

/media/music    → /home/hoborg/Music        (shared with Copyparty)
/media/videos   → /home/hoborg/Videos       (shared with Copyparty)
/media/shared   → /home/hoborg/shared       (shared with Copyparty)

Features Enabled:

  • Hardware transcoding (Intel/AMD GPU via /dev/dri)
  • Multiple codec support (H.264, H.265, AV1, etc.)
  • Hardware acceleration filters and encoders
  • Reverse proxy integration with optimized streaming settings
  • Resource limits: 2GB max memory, 512MB reserved

Configuration Management:

# Check container status
cd /opt/docker/jellyfin && sudo docker-compose logs jellyfin

# Container management
sudo docker-compose down             # Stop
sudo docker-compose up -d            # Start
sudo docker-compose pull && sudo docker-compose up -d  # Update

# View detailed logs
sudo docker-compose logs -f jellyfin

Integration with Other Services:

  • Copyparty: Shares same media folders without duplication
  • Nginx: Reverse proxy with streaming-optimized configuration
  • SSL: Secured with Let's Encrypt certificates and auto-renewal

Initial Setup:

  1. Visit http://localhost:8096 for setup wizard
  2. Create admin account and configure server
  3. Add media libraries pointing to /media/music, /media/videos, /media/shared
  4. Configure hardware acceleration in Dashboard > Playback settings

Folder Structure Compatibility: CONFIRMED WORKING

  • Music Library: Successfully works with existing Artist/Album structure
  • Copyparty Interoperability: Both services share same folders without conflicts
  • Metadata Support: Downloads album artwork, descriptions, and artist information from online sources
  • Electronic Music: Works well with existing organized structure (e.g., "The Hu - Discography/Albums/...")

Metadata Management:

  • Auto-Download: Enable MusicBrainz, TheAudioDB, Last.fm in Dashboard > Metadata > Music
  • Manual Refresh: Library scan via Dashboard > Libraries > Music > Scan Library
  • Force Refresh: Use "Replace All Metadata" for complete metadata re-download
  • Individual Items: Right-click albums/artists for targeted metadata refresh

Music Collection Management

Playlist Extraction:

  • YouTube Music: Use ytmusicapi Python library or Google Takeout
  • SoundCloud: Use scdl tool or SoundCloud API
  • Output Formats: CSV (artist, title, playlist), JSON metadata, M3U playlists, plain text lists

Legal Music Sources:

  • High Quality: Bandcamp (FLAC), Beatport, 7digital, HDtracks
  • Mainstream: Amazon Music, iTunes Store, artist websites
  • Subscription Downloads: Tidal, Qobuz premium tiers
  • Physical Media: CD ripping, vinyl digitization, cassette conversion

Organization Tools:

  • MusicBrainz Picard: Automatic metadata tagging and correction
  • beets: Advanced music library management and organization
  • Bulk Scripts: Custom automation for file organization and import

Photo Management

  • PhotoPrism: AI-powered photo management
  • Immich: Modern photo backup solution
  • LibrePhotos: Privacy-focused alternative

Monitoring & Logging

System Monitoring

# Prometheus + Grafana stack
docker-compose up -d prometheus grafana node-exporter

Log Management

  • Centralized logging: rsyslog or journald
  • Log rotation: logrotate configuration
  • Analysis: grep, awk, or ELK stack for advanced needs

Health Checks

  • Uptime monitoring: Simple HTTP checks
  • Service status: systemd service monitoring
  • Disk space: Automated alerts for low space

Containerization Strategy

Docker Setup

# Install Docker
pacman -S docker docker-compose
sudo systemctl enable docker

# Add user to docker group
sudo usermod -aG docker hoborg

Container Management

  • Orchestration: Docker Compose for multi-service apps
  • Storage: Named volumes for persistent data
  • Networking: Custom networks for service isolation
  • Updates: Watchtower for automated updates

Reverse Proxy Configuration

Decision Matrix: Nginx vs Traefik

Problem: Multiple services need to be accessible under single domain with path-based routing. Solution: Reverse proxy to route requests based on URL paths.

Nginx

Pros:

  • Mature & battle-tested (decades of production use)
  • High performance for static files and caching
  • Flexible configuration - handles any routing scenario
  • Extensive ecosystem and documentation
  • Can handle non-Docker services easily

Cons:

  • Manual configuration required
  • No auto-discovery of services
  • Requires config reload for changes

Traefik

Pros:

  • Docker-native auto-discovery via labels
  • Automatic HTTPS with Let's Encrypt
  • Dynamic configuration (no restarts)
  • Modern design for containerized environments

Cons:

  • Less mature, smaller ecosystem
  • Docker-dependent (less flexible)
  • Steeper learning curve for complex scenarios

Decision: Nginx - Better for homelab due to reliability, documentation, and flexibility for mixed Docker/non-Docker services.

URL Architecture Decision

Options Considered:

  1. Separate subdomains: gitea.ak-homelab.duckdns.org DuckDNS doesn't support nested subdomains
  2. Multiple DuckDNS domains: ak-homelab-git.duckdns.org Management overhead
  3. Path-based routing: ak-homelab.duckdns.org/gitea/ Selected

Chosen Architecture:

https://ak-homelab.duckdns.org/          → Landing page/dashboard
https://ak-homelab.duckdns.org/gitea/    → Gitea Git server ✅ DEPLOYED
https://ak-homelab.duckdns.org/files/    → Copyparty file server ✅ DEPLOYED
https://ak-homelab.duckdns.org/media/    → Jellyfin media server (planned)
https://ak-homelab.duckdns.org/monitor/  → System monitoring (planned)

SSL/TLS Configuration

Status: COMPLETE - Let's Encrypt SSL with automatic renewal

SSL Certificate Setup:

# Certificate installation (completed)
sudo certbot --nginx -d ak-homelab.duckdns.org

# Auto-renewal service (enabled)
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timer

Certificate Details:

  • CA: Let's Encrypt (trusted by all major browsers)
  • Certificate: /etc/letsencrypt/live/ak-homelab.duckdns.org/fullchain.pem
  • Private Key: /etc/letsencrypt/live/ak-homelab.duckdns.org/privkey.pem
  • Renewal: Automatic every 90 days via systemd timer
  • Security: Strong TLS configuration with DH parameters

Security Features:

  • HTTP→HTTPS Redirect: All HTTP traffic automatically redirected to HTTPS
  • HSTS Headers: Included via Let's Encrypt nginx configuration
  • Strong Ciphers: Modern TLS 1.2/1.3 cipher suites
  • Perfect Forward Secrecy: Enabled via Diffie-Hellman parameters

Renewal Management:

# Check renewal status
sudo systemctl status certbot-renew.timer

# Manual renewal test (dry run)
sudo certbot renew --dry-run

# View renewal logs
journalctl -u certbot-renew.service

Certificate Verification:

  • Browser shows green padlock for all services
  • SSL Labs rating: A+ (expected)
  • All services accessible via HTTPS only

Advanced Nginx Options

Nginx Plus (Commercial): $2500+/year

  • Advanced load balancing, health checks
  • API management, JWT validation
  • Real-time monitoring dashboard
  • Verdict: Overkill for homelab

Nginx + Lua (OpenResty):

  • Embed Lua scripts for dynamic processing
  • Complex routing logic, authentication
  • API gateway functionality
  • Verdict: Powerful but complex, not needed initially

Nginx Setup

Status: Complete - Reverse proxy configured and running

# Install nginx and SSL tools
sudo pacman -S nginx certbot certbot-nginx

# Create configuration
sudo nano /etc/nginx/sites-available/homelab

# Enable site
sudo ln -s /etc/nginx/sites-available/homelab /etc/nginx/sites-enabled/

# Test and reload
sudo nginx -t
sudo systemctl reload nginx

Configuration Template:

server {
    listen 80;
    server_name ak-homelab.duckdns.org;

    # Main landing page
    location / {
        root /var/www/homelab;
        index index.html;
    }

    # Gitea reverse proxy
    location /gitea/ {
        proxy_pass http://127.0.0.1:3000/;
        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;
    }

    # Future services
    # location /cloud/ {
    #     proxy_pass http://127.0.0.1:8080/;
    #     proxy_set_header Host $host;
    # }
}

Router Port Forwarding Requirements

  • HTTP: Port 80 → 192.168.0.100:80
  • HTTPS: Port 443 → 192.168.0.100:443
  • Remove: Direct port 3000 forwarding (will go through nginx)

SSL Certificates

# Let's Encrypt via certbot (after nginx setup)
sudo certbot --nginx -d ak-homelab.duckdns.org

# Auto-renewal
sudo systemctl enable certbot.timer

Backup Strategy

Configuration Backups

  • Service configs: Docker volumes, /etc configs
  • Database dumps: Regular automated backups
  • Storage: External drive or cloud backup

Automated Backups

#!/bin/bash
# backup-services.sh
DATE=$(date +%Y%m%d)

# Backup Gitea
tar -czf /backup/gitea-$DATE.tar.gz /var/lib/gitea/

# Backup Nextcloud data
rsync -av /var/snap/nextcloud/common/nextcloud/data/ /backup/nextcloud-$DATE/

# Database backup
sudo -u postgres pg_dump gitea > /backup/gitea-db-$DATE.sql

Resource Planning

Hardware Requirements

  • RAM: 4GB minimum, 8GB recommended
  • Storage:
    • System: 50GB SSD
    • Data: 1TB+ HDD for media/files
  • Network: Gigabit Ethernet preferred

Service Resource Usage

Service RAM CPU Storage Port
Gitea 200MB Low 5GB+ 3000
Nextcloud 512MB Medium 10GB+ 8080
Jellyfin 1GB High* Media 8096
Monitoring 500MB Low 2GB 3000/9090

*High during transcoding

Security Considerations

Service Hardening

  • Regular updates: Automated security patches
  • Access control: VPN-only access when possible
  • Authentication: Strong passwords, 2FA where available
  • Network isolation: Separate VLANs or containers

Data Protection

  • Encryption: Full disk encryption (LUKS)
  • Backups: Encrypted offsite backups
  • Access logs: Monitor service access patterns
  • Fail2ban: Automatic IP blocking for repeated failures

Future Expansion

Additional Services to Consider

  • Home Assistant: ABSOLUTELY NOT
  • Bitwarden/Vaultwarden: Password management
    • How is this better than keepassxc + filesync?
  • Pi-hole: Network-wide ad blocking
  • Wireguard UI: Web interface for VPN management
  • Bookstack: Documentation wiki
    • What is this for? How does it compare to Logseq?
  • FreshRSS: RSS feed aggregator