mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-08 20:59:47 +10:00
Update config
This commit is contained in:
-602
@@ -1,602 +0,0 @@
|
||||
# YouMusic Deployment Guide
|
||||
|
||||
Complete guide for deploying YouMusic to production using Docker and Kubernetes.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Docker Deployment](#docker-deployment)
|
||||
2. [Kubernetes Deployment](#kubernetes-deployment)
|
||||
3. [Data Persistence](#data-persistence)
|
||||
4. [Environment Configuration](#environment-configuration)
|
||||
5. [Backup and Restore](#backup-and-restore)
|
||||
|
||||
---
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
### Using Docker Compose (Recommended for Single Server)
|
||||
|
||||
The simplest way to deploy YouMusic is using Docker Compose:
|
||||
|
||||
```bash
|
||||
# Start the service
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Stop the service
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Your music player will be available at `http://localhost:8000`
|
||||
|
||||
### Using Docker Run
|
||||
|
||||
```bash
|
||||
# Create data directory
|
||||
mkdir -p ./data
|
||||
|
||||
# Run container
|
||||
docker run -d \
|
||||
--name youmusic \
|
||||
-p 8000:8000 \
|
||||
-v $(pwd)/data:/app/data \
|
||||
-e DATABASE_URL=sqlite+aiosqlite:///./data/youmusic.db \
|
||||
ghcr.io/wahyd4/youmusic:latest
|
||||
|
||||
# View logs
|
||||
docker logs -f youmusic
|
||||
```
|
||||
|
||||
### Building Custom Image
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://github.com/wahyd4/you-music.git
|
||||
cd you-music
|
||||
|
||||
# Build image
|
||||
docker build -t youmusic:custom .
|
||||
|
||||
# Run with custom image
|
||||
docker run -d \
|
||||
--name youmusic \
|
||||
-p 8000:8000 \
|
||||
-v $(pwd)/data:/app/data \
|
||||
youmusic:custom
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- k3s/k8s cluster
|
||||
- kubectl configured
|
||||
- cert-manager (for TLS)
|
||||
- nginx-ingress controller
|
||||
|
||||
### Step-by-Step Deployment
|
||||
|
||||
#### 1. Build and Push Image
|
||||
|
||||
```bash
|
||||
# Build the image
|
||||
docker build -t youmusic:latest .
|
||||
|
||||
# Tag for registry
|
||||
docker tag youmusic:latest ghcr.io/wahyd4/youmusic:latest
|
||||
|
||||
# Login to GitHub Container Registry
|
||||
echo $GITHUB_TOKEN | docker login ghcr.io -u wahyd4 --password-stdin
|
||||
|
||||
# Push to registry
|
||||
docker push ghcr.io/wahyd4/youmusic:latest
|
||||
```
|
||||
|
||||
Or use GitHub Actions (automatic on push to main):
|
||||
```bash
|
||||
git push origin main
|
||||
# Image will be built and pushed automatically
|
||||
```
|
||||
|
||||
#### 2. Configure Manifest
|
||||
|
||||
Edit `k8s/manifest.yaml`:
|
||||
|
||||
```yaml
|
||||
# Update image name (line 47)
|
||||
image: "ghcr.io/wahyd4/youmusic:latest"
|
||||
|
||||
# Update domain (line 125-126)
|
||||
- host: music.yourdomain.com
|
||||
secretName: youmusic-tls
|
||||
```
|
||||
|
||||
#### 3. Deploy to Cluster
|
||||
|
||||
```bash
|
||||
# Apply manifest
|
||||
kubectl apply -f k8s/manifest.yaml
|
||||
|
||||
# Check status
|
||||
kubectl get pods -l app=youmusic
|
||||
kubectl get svc youmusic
|
||||
kubectl get ingress youmusic-ingress
|
||||
```
|
||||
|
||||
#### 4. Verify Deployment
|
||||
|
||||
```bash
|
||||
# Watch pod startup
|
||||
kubectl get pods -l app=youmusic -w
|
||||
|
||||
# Check logs
|
||||
kubectl logs -f deployment/youmusic
|
||||
|
||||
# Check ingress
|
||||
kubectl describe ingress youmusic-ingress
|
||||
```
|
||||
|
||||
#### 5. Access Application
|
||||
|
||||
```bash
|
||||
# Get ingress IP/hostname
|
||||
kubectl get ingress youmusic-ingress
|
||||
|
||||
# Wait for TLS certificate
|
||||
kubectl get certificate youmusic-tls
|
||||
|
||||
# Access via domain
|
||||
https://music.yourdomain.com
|
||||
```
|
||||
|
||||
### Common Deployment Scenarios
|
||||
|
||||
#### Scenario 1: Private Registry
|
||||
|
||||
```bash
|
||||
# Create secret
|
||||
kubectl create secret docker-registry github-image-pull-secret \
|
||||
--docker-server=ghcr.io \
|
||||
--docker-username=wahyd4 \
|
||||
--docker-password=$GITHUB_TOKEN
|
||||
|
||||
# Uncomment in manifest
|
||||
# imagePullSecrets:
|
||||
# - name: github-image-pull-secret
|
||||
```
|
||||
|
||||
#### Scenario 2: Custom Storage
|
||||
|
||||
Update PVC in manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: youmusic-data-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: your-storage-class # Update this
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi # Adjust size
|
||||
```
|
||||
|
||||
#### Scenario 3: Enable Authentication
|
||||
|
||||
Add to ingress annotations:
|
||||
|
||||
```yaml
|
||||
nginx.ingress.kubernetes.io/auth-url: "https://auth.yourdomain.com/verify"
|
||||
nginx.ingress.kubernetes.io/auth-signin: "https://auth.yourdomain.com/login"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Persistence
|
||||
|
||||
### Directory Structure
|
||||
|
||||
All persistent data is stored in `/app/data`:
|
||||
|
||||
```
|
||||
/app/data/
|
||||
├── youmusic.db # SQLite database
|
||||
├── youmusic.db-shm # SQLite shared memory
|
||||
├── youmusic.db-wal # SQLite write-ahead log
|
||||
├── music/ # Music files
|
||||
│ ├── song1.mp3
|
||||
│ ├── song2.mp3
|
||||
│ └── thumbnails/ # Song thumbnails
|
||||
│ ├── song1.jpg
|
||||
│ └── song2.jpg
|
||||
├── uploads/ # User uploads
|
||||
├── temp/ # Temporary downloads
|
||||
└── cache/ # Cache directory
|
||||
├── artists/ # Artist metadata
|
||||
│ ├── Westlife.json
|
||||
│ └── Taylor_Swift.json
|
||||
└── artist_images/ # Artist avatars
|
||||
├── Westlife.jpg
|
||||
└── Taylor_Swift.jpg
|
||||
```
|
||||
|
||||
### Volume Mounting
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
-v /path/on/host:/app/data
|
||||
```
|
||||
|
||||
**Kubernetes:**
|
||||
```yaml
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /app/data
|
||||
```
|
||||
|
||||
### Storage Requirements
|
||||
|
||||
| Component | Size per Item | Example (100 items) |
|
||||
|-----------|---------------|---------------------|
|
||||
| Database | ~1KB per song | 100KB |
|
||||
| Music Files | 3-10MB per song | 500MB |
|
||||
| Thumbnails | 50-200KB per song | 10MB |
|
||||
| Artist Info | 2KB per artist | 200KB |
|
||||
| Artist Images | 100-200KB per artist | 15MB |
|
||||
| **Total** | - | **~525MB** |
|
||||
|
||||
**Recommended PVC Size:**
|
||||
- Small (100 songs): 10Gi
|
||||
- Medium (500 songs): 25Gi
|
||||
- Large (1000+ songs): 50Gi+
|
||||
|
||||
---
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
### Required Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `DATABASE_URL` | SQLite connection string | `sqlite+aiosqlite:///./data/youmusic.db` |
|
||||
| `MUSIC_DIR` | Music files directory | `/app/data/music` |
|
||||
| `UPLOAD_DIR` | Upload directory | `/app/data/uploads` |
|
||||
| `TEMP_DIR` | Temporary files | `/app/data/temp` |
|
||||
| `BASE_DIR` | Application base path | `/app` |
|
||||
|
||||
### Optional Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `FFMPEG_LOCATION` | FFmpeg binary path | `ffmpeg` |
|
||||
| `PROXY` | HTTP proxy for downloads | - |
|
||||
|
||||
### Setting Variables
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
docker run -e DATABASE_URL="..." -e MUSIC_DIR="..." youmusic
|
||||
```
|
||||
|
||||
**Docker Compose:**
|
||||
```yaml
|
||||
environment:
|
||||
- DATABASE_URL=sqlite+aiosqlite:///./data/youmusic.db
|
||||
- MUSIC_DIR=/app/data/music
|
||||
```
|
||||
|
||||
**Kubernetes:**
|
||||
```yaml
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: "sqlite+aiosqlite:///./data/youmusic.db"
|
||||
- name: MUSIC_DIR
|
||||
value: "/app/data/music"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Docker Backup
|
||||
|
||||
```bash
|
||||
# Stop container
|
||||
docker stop youmusic
|
||||
|
||||
# Backup data directory
|
||||
tar czf youmusic-backup-$(date +%Y%m%d).tar.gz ./data
|
||||
|
||||
# Restart container
|
||||
docker start youmusic
|
||||
```
|
||||
|
||||
### Docker Restore
|
||||
|
||||
```bash
|
||||
# Stop container
|
||||
docker stop youmusic
|
||||
|
||||
# Restore data
|
||||
tar xzf youmusic-backup-20241030.tar.gz
|
||||
|
||||
# Start container
|
||||
docker start youmusic
|
||||
```
|
||||
|
||||
### Kubernetes Backup
|
||||
|
||||
```bash
|
||||
# Get pod name
|
||||
POD=$(kubectl get pod -l app=youmusic -o jsonpath='{.items[0].metadata.name}')
|
||||
|
||||
# Backup entire data directory
|
||||
kubectl exec $POD -- tar czf - /app/data > youmusic-backup-$(date +%Y%m%d).tar.gz
|
||||
|
||||
# Or copy files directly
|
||||
kubectl cp $POD:/app/data ./youmusic-backup
|
||||
```
|
||||
|
||||
### Kubernetes Restore
|
||||
|
||||
```bash
|
||||
# Get pod name
|
||||
POD=$(kubectl get pod -l app=youmusic -o jsonpath='{.items[0].metadata.name}')
|
||||
|
||||
# Restore from tar
|
||||
kubectl exec -i $POD -- tar xzf - -C /app < youmusic-backup-20241030.tar.gz
|
||||
|
||||
# Or copy files
|
||||
kubectl cp ./youmusic-backup $POD:/app/data-restore
|
||||
|
||||
# Move files (exec into pod)
|
||||
kubectl exec -it $POD -- bash
|
||||
mv /app/data-restore/* /app/data/
|
||||
```
|
||||
|
||||
### Database-Only Backup
|
||||
|
||||
```bash
|
||||
# Docker
|
||||
docker exec youmusic sqlite3 /app/data/youmusic.db ".backup /app/data/backup.db"
|
||||
docker cp youmusic:/app/data/backup.db ./youmusic-db-backup.db
|
||||
|
||||
# Kubernetes
|
||||
kubectl exec deployment/youmusic -- sqlite3 /app/data/youmusic.db ".backup /app/data/backup.db"
|
||||
kubectl cp deployment/youmusic:/app/data/backup.db ./youmusic-db-backup.db
|
||||
```
|
||||
|
||||
### Automated Backups
|
||||
|
||||
Create a CronJob for automated backups:
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: youmusic-backup
|
||||
spec:
|
||||
schedule: "0 2 * * *" # Daily at 2 AM
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: backup
|
||||
image: alpine:latest
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
apk add --no-cache sqlite
|
||||
cd /data
|
||||
sqlite3 youmusic.db ".backup backup-$(date +%Y%m%d).db"
|
||||
find /data -name "backup-*.db" -mtime +7 -delete
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: youmusic-data-pvc
|
||||
restartPolicy: OnFailure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring and Maintenance
|
||||
|
||||
### Health Checks
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
# Check container health
|
||||
docker inspect youmusic | grep Health -A 10
|
||||
|
||||
# Manual health check
|
||||
curl http://localhost:8000/
|
||||
```
|
||||
|
||||
**Kubernetes:**
|
||||
```bash
|
||||
# Check pod health
|
||||
kubectl describe pod -l app=youmusic | grep -A 5 Conditions
|
||||
|
||||
# Check endpoints
|
||||
kubectl get endpoints youmusic
|
||||
```
|
||||
|
||||
### Log Management
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
# View logs
|
||||
docker logs youmusic
|
||||
|
||||
# Follow logs
|
||||
docker logs -f youmusic
|
||||
|
||||
# Last 100 lines
|
||||
docker logs --tail=100 youmusic
|
||||
```
|
||||
|
||||
**Kubernetes:**
|
||||
```bash
|
||||
# View logs
|
||||
kubectl logs deployment/youmusic
|
||||
|
||||
# Follow logs
|
||||
kubectl logs -f deployment/youmusic
|
||||
|
||||
# Last 100 lines
|
||||
kubectl logs --tail=100 deployment/youmusic
|
||||
```
|
||||
|
||||
### Resource Monitoring
|
||||
|
||||
**Kubernetes:**
|
||||
```bash
|
||||
# Resource usage
|
||||
kubectl top pod -l app=youmusic
|
||||
|
||||
# Detailed metrics
|
||||
kubectl describe pod -l app=youmusic
|
||||
```
|
||||
|
||||
### Updates
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ghcr.io/wahyd4/youmusic:latest
|
||||
|
||||
# Stop and remove old container
|
||||
docker stop youmusic
|
||||
docker rm youmusic
|
||||
|
||||
# Start new container
|
||||
docker run -d --name youmusic ...
|
||||
```
|
||||
|
||||
**Kubernetes:**
|
||||
```bash
|
||||
# Update image
|
||||
kubectl set image deployment/youmusic \
|
||||
youmusic=ghcr.io/wahyd4/youmusic:v2
|
||||
|
||||
# Or reapply manifest
|
||||
kubectl apply -f k8s/manifest.yaml
|
||||
|
||||
# Check rollout
|
||||
kubectl rollout status deployment/youmusic
|
||||
|
||||
# Rollback if needed
|
||||
kubectl rollout undo deployment/youmusic
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. Database Locked
|
||||
|
||||
**Cause:** Multiple instances trying to write to SQLite
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Kubernetes: Ensure single replica
|
||||
kubectl scale deployment/youmusic --replicas=1
|
||||
|
||||
# Check for hung processes
|
||||
kubectl exec deployment/youmusic -- ps aux | grep python
|
||||
```
|
||||
|
||||
#### 2. Permission Denied
|
||||
|
||||
**Cause:** Volume mount permission issues
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check permissions
|
||||
kubectl exec deployment/youmusic -- ls -la /app/data
|
||||
|
||||
# Fix permissions
|
||||
kubectl exec deployment/youmusic -- chmod -R 755 /app/data
|
||||
```
|
||||
|
||||
#### 3. FFmpeg Not Found
|
||||
|
||||
**Cause:** FFmpeg not installed in container
|
||||
|
||||
**Check:**
|
||||
```bash
|
||||
kubectl exec deployment/youmusic -- which ffmpeg
|
||||
```
|
||||
|
||||
**Solution:** Image already includes ffmpeg, ensure using correct image.
|
||||
|
||||
#### 4. Storage Full
|
||||
|
||||
**Check:**
|
||||
```bash
|
||||
kubectl exec deployment/youmusic -- df -h /app/data
|
||||
```
|
||||
|
||||
**Solution:** Increase PVC size or clean up old files.
|
||||
|
||||
---
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Use Authentication**
|
||||
- Enable nginx auth
|
||||
- Use OAuth2 proxy
|
||||
- Restrict network access
|
||||
|
||||
2. **Regular Updates**
|
||||
- Keep image updated
|
||||
- Monitor security advisories
|
||||
- Update dependencies
|
||||
|
||||
3. **Backup Regularly**
|
||||
- Automated daily backups
|
||||
- Test restore procedures
|
||||
- Store backups securely
|
||||
|
||||
4. **Resource Limits**
|
||||
- Set CPU/memory limits
|
||||
- Monitor resource usage
|
||||
- Scale appropriately
|
||||
|
||||
5. **Network Policies**
|
||||
- Restrict ingress/egress
|
||||
- Use TLS everywhere
|
||||
- Limit exposed services
|
||||
|
||||
---
|
||||
|
||||
## Production Checklist
|
||||
|
||||
- [ ] Domain configured
|
||||
- [ ] TLS certificate issued
|
||||
- [ ] Storage provisioned
|
||||
- [ ] Backups configured
|
||||
- [ ] Authentication enabled
|
||||
- [ ] Resource limits set
|
||||
- [ ] Monitoring enabled
|
||||
- [ ] Logs aggregated
|
||||
- [ ] Health checks working
|
||||
- [ ] Update strategy defined
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2024-10-30
|
||||
**Version:** 1.0.0
|
||||
+10
-10
@@ -7,7 +7,7 @@ class Settings(BaseSettings):
|
||||
# API Settings
|
||||
API_V1_STR: str = "/api/v1"
|
||||
PROJECT_NAME: str = "YouMusic"
|
||||
|
||||
|
||||
# Directories
|
||||
BASE_DIR: str = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
MUSIC_DIR: str = os.path.join(BASE_DIR, "data", "music")
|
||||
@@ -15,30 +15,30 @@ class Settings(BaseSettings):
|
||||
UPLOAD_DIR: str = os.path.join(BASE_DIR, "data", "uploads")
|
||||
TEMP_DIR: str = os.path.join(BASE_DIR, "data", "temp")
|
||||
CACHE_DIR: str = os.path.join(BASE_DIR, "data", "cache")
|
||||
|
||||
|
||||
# Database
|
||||
DATABASE_URL: str = "sqlite+aiosqlite:///./data/youmusic.db"
|
||||
|
||||
DATABASE_URL: str = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./data/youmusic.db")
|
||||
|
||||
# CORS
|
||||
BACKEND_CORS_ORIGINS: list = ["*"]
|
||||
|
||||
|
||||
# Download Settings
|
||||
PROXY: Optional[str] = None
|
||||
FFMPEG_LOCATION: str = "/usr/local/bin/ffmpeg"
|
||||
|
||||
FFMPEG_LOCATION: str = os.getenv("FFMPEG_LOCATION", "/usr/local/bin/ffmpeg")
|
||||
|
||||
# YT-DLP Settings
|
||||
YT_DLP_FORMAT: str = "bestaudio/best"
|
||||
YT_DLP_AUDIO_FORMAT: str = "mp3"
|
||||
YT_DLP_AUDIO_QUALITY: str = "0"
|
||||
|
||||
|
||||
# Scanner Settings
|
||||
SCAN_INTERVAL: int = 3600 # Default 1 hour (in seconds)
|
||||
DELETE_MISSING_FILES: bool = False # Don't delete missing files by default
|
||||
AUTO_SCAN_ENABLED: bool = True # Enable automatic scanning
|
||||
|
||||
|
||||
# Share Link Settings
|
||||
SHARE_LINK_EXPIRATION_DAYS: int = 14 # Default expiration for share links
|
||||
|
||||
|
||||
class Config:
|
||||
case_sensitive = True
|
||||
env_file = ".env"
|
||||
|
||||
Reference in New Issue
Block a user