Update docs: new README, IIS guide, and production web.config

- Replaced README.md with a modern, production-focused version featuring quick start, architecture, workflow, troubleshooting, and security sections
- Added DEPLOYMENT_GUIDE_IIS_Windows11.md with step-by-step IIS deployment instructions, including SSL, CORS, and permissions
- Added version-controlled web.config files for API and Blazor app with HTTPS redirection, security headers, and SPA/static file support
- Moved detailed yt-dlp integration notes to README_UPDATED.md for technical reference
- Improves clarity, maintainability, and production readiness of documentation and deployment
This commit is contained in:
Michal Vrba
2025-12-12 15:31:03 +01:00
parent 3ecff7ca73
commit 54fb8c2c5e
6 changed files with 1096 additions and 380 deletions
+723
View File
@@ -0,0 +1,723 @@
# TuneRipper Deployment Guide - IIS on Windows 11
This guide provides step-by-step instructions for manually deploying the TuneRipper Blazor WebAssembly application and API to Internet Information Services (IIS) on Windows 11.
## Deployment Scenarios
### Scenario A: Production Server (Recommended)
Deploy pre-built applications to a clean production server.
**Requirements**: Only .NET 10 Hosting Bundle + IIS
### Scenario B: Build + Deploy on Same Machine
Build and deploy applications on the same machine.
**Requirements**: .NET 10 SDK + .NET 10 Hosting Bundle + IIS
---
## Prerequisites
### System Requirements
- Windows 11 (Pro, Enterprise, or Education edition recommended)
- **IIS (Internet Information Services)** already installed and configured
- Administrative privileges
- Internet connection for downloading dependencies
- **Domain names configured** (for production HTTPS setup)
### Software Dependencies
- **.NET 10 Hosting Bundle** (production) OR **.NET 10 SDK** (development)
- **yt-dlp.exe** (for video processing)
- **ffmpeg** (required by yt-dlp for audio conversion)
- **Let's Encrypt ACME tool** (for SSL certificates in production)
---
## Step 1: Install .NET 10 Hosting Bundle for IIS
> **Critical**: This step is required for ALL deployment scenarios
### 1.1 Download .NET 10 Hosting Bundle
The Hosting Bundle contains the ASP.NET Core runtime and IIS integration components needed to run .NET 10 applications on IIS.
1. Go to [Microsoft .NET Downloads](https://dotnet.microsoft.com/download/dotnet/10.0)
2. Scroll to **"ASP.NET Core Runtime"** section
3. Under **"Run server apps"**, find **"Hosting Bundle"**
4. Download **"Hosting Bundle"** for Windows (e.g., `dotnet-hosting-10.0.x-win.exe`)
5. **Important**: This is different from the SDK - it's specifically for IIS hosting
### 1.2 Install the Hosting Bundle
1. Close all IIS Manager windows and web browsers
2. Run the downloaded hosting bundle installer as **Administrator**
3. Follow the installation wizard:
- Accept license terms
- Complete the installation
4. **Critical**: Restart IIS services by running this command in **Command Prompt as Administrator**:
```cmd
iisreset /restart
```
5. Alternatively, restart the entire computer to ensure all services are updated
### 1.3 Verify Hosting Bundle Installation
1. Open **Command Prompt as Administrator**
2. Run: `dotnet --info`
3. Look for the ASP.NET Core Module in IIS:
```cmd
%windir%\system32\inetsrv\appcmd.exe list modules
```
4. You should see `AspNetCoreModuleV2` in the output
5. Check the registry for the module (PowerShell as Administrator):
```powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\IIS Extensions\IIS AspNetCore Module V2"
```
### 1.4 Verify ASP.NET Core Module Installation
1. Open **IIS Manager** (`Win + R` ? `inetmgr`)
2. Select your server name in the left panel
3. Double-click **"Modules"** in the main panel
4. Look for **"AspNetCoreModuleV2"** - it should be present and enabled
5. If not visible, you may need to restart IIS again:
```cmd
iisreset
```
---
## Step 2: Install Required Tools
### 2.1 Download yt-dlp
1. Go to [yt-dlp releases](https://github.com/yt-dlp/yt-dlp/releases)
2. Download the latest `yt-dlp.exe` (Windows executable)
3. **Important**: Keep this file ready for later deployment
### 2.2 Install FFmpeg
1. Go to [FFmpeg downloads](https://ffmpeg.org/download.html#build-windows)
2. Choose **"Windows"** ? **"Windows builds by BtbN"**
3. Download the latest **"ffmpeg-master-latest-win64-gpl.zip"**
4. Extract to `C:\ffmpeg\`
5. Add `C:\ffmpeg\bin` to your System PATH:
- Press `Win + X`, select **"System"**
- Click **"Advanced system settings"**
- Click **"Environment Variables"**
- Under **"System Variables"**, find and edit **"Path"**
- Click **"New"** and add: `C:\ffmpeg\bin`
- Click **OK** to save all dialogs
6. Restart Command Prompt and verify: `ffmpeg -version`
### 2.3 Install Let's Encrypt ACME Tool (Production HTTPS)
For production deployment with custom domains, install an ACME client:
1. **Install win-acme (Recommended for Windows/IIS)**:
- Go to [win-acme releases](https://github.com/win-acme/win-acme/releases)
- Download the latest `win-acme.v2.x.x.x.pluggable.zip`
- Extract to `C:\win-acme\`
---
## Step 3: Get Application Files
### Option A: Use Pre-Built Files (Production Deployment)
If you have pre-built application files from another machine:
1. Copy the published API files to: `C:\Publish\TuneRipper.Api\`
2. Copy the published Blazor WebAssembly files to: `C:\Publish\TuneRipper\`
3. **Skip to Step 4** (Prepare Deployment Files)
### Option B: Build Applications (Build + Deploy Scenario)
If you need to build the applications on this machine, continue below:
#### 3B.1 Install .NET 10 SDK (If Building Locally)
1. Go to [Microsoft .NET Downloads](https://dotnet.microsoft.com/download/dotnet/10.0)
2. Download and install the .NET 10 SDK
3. Restart your computer after installation
#### 3B.2 Verify Build Environment
Before publishing, ensure your development environment is ready:
1. Open **Command Prompt** in your project directory: `C:\DevHome\TuneRipper`
2. Run: `dotnet --version` (should show 10.0.x)
3. Run: `dotnet restore` (restore NuGet packages)
4. Run: `dotnet build` (verify everything compiles)
#### 3B.3 Publish the API (TuneRipper.Api)
**Using Visual Studio:**
1. Open the TuneRipper solution in **Visual Studio 2022**
2. Ensure you have **.NET 10 workload** installed in Visual Studio:
- Go to **Tools** ? **Get Tools and Features**
- Under **Workloads**, ensure **"ASP.NET and web development"** is checked
- Under **Individual Components**, ensure **.NET 10 Runtime** is selected
3. Right-click on **TuneRipper.Api** project
4. Select **"Publish..."**
5. Choose **"Folder"** as the publish target
6. Set publish folder to: `C:\Publish\TuneRipper.Api`
7. Click **"Show all settings"** and configure:
- **Configuration**: `Release`
- **Target Framework**: `net10.0`
- **Deployment Mode**: `Framework-dependent`
- **Target Runtime**: `Portable`
8. Click **"Save"** and then **"Publish"**
**Using Command Line:**
```cmd
cd C:\DevHome\TuneRipper
dotnet publish TuneRipper.Api\TuneRipper.Api.csproj -c Release -f net10.0 -o C:\Publish\TuneRipper.Api --verbosity normal
```
#### 3B.4 Publish the Blazor WebAssembly App (TuneRipper)
**Using Visual Studio:**
1. Right-click on **TuneRipper** project
2. Select **"Publish..."**
3. Choose **"Folder"** as the publish target
4. Set publish folder to: `C:\Publish\TuneRipper`
5. Configure settings:
- **Configuration**: `Release`
- **Target Framework**: `net10.0`
6. Click **"Save"** and then **"Publish"**
**Using Command Line:**
```cmd
cd C:\DevHome\TuneRipper
dotnet publish TuneRipper\TuneRipper.csproj -c Release -f net10.0 -o C:\Publish\TuneRipper --verbosity normal
```
#### 3B.5 Verify Published Output
After publishing, check the output directories:
**API Output** (`C:\Publish\TuneRipper.Api\`):
- `TuneRipper.Api.dll`
- `TuneRipper.Api.exe`
- `web.config` (should be auto-generated)
- `appsettings.json`
- Various .NET 10 runtime files
**Blazor Output** (`C:\Publish\TuneRipper\`):
- `wwwroot\` folder containing:
- `index.html`
- `_framework\` folder
- Static assets (CSS, JS, etc.)
---
## Step 4: Prepare Deployment Files
### 4.1 Create Deployment Directories
```cmd
mkdir C:\inetpub\wwwroot\TuneRipper
mkdir C:\inetpub\wwwroot\TuneRipperApi
mkdir C:\inetpub\wwwroot\TuneRipperApi\wwwroot
mkdir C:\inetpub\wwwroot\TuneRipperApi\wwwroot\downloads
```
### 4.2 Copy API Files
1. Copy all contents from `C:\Publish\TuneRipper.Api\` to `C:\inetpub\wwwroot\TuneRipperApi\`
2. Copy `yt-dlp.exe` to `C:\inetpub\wwwroot\TuneRipperApi\wwwroot\yt-dlp.exe`
3. Verify the API structure:
```
C:\inetpub\wwwroot\TuneRipperApi\
??? TuneRipper.Api.dll
??? TuneRipper.Api.exe
??? appsettings.json
??? web.config
??? wwwroot\
? ??? yt-dlp.exe
? ??? downloads\
??? [other .NET 10 runtime files]
```
### 4.3 Copy Blazor WebAssembly Files
1. Copy all contents from `C:\Publish\TuneRipper\wwwroot\` to `C:\inetpub\wwwroot\TuneRipper\`
2. Verify the Blazor structure:
```
C:\inetpub\wwwroot\TuneRipper\
??? index.html
??? _framework\
? ??? blazor.webassembly.js
? ??? dotnet.10.x.x.js
? ??? [.NET 10 WebAssembly files]
??? css\
??? images\
??? [other static files]
```
---
## Step 5: Configure IIS Sites
### 5.1 Open IIS Manager
1. Press `Win + R`, type `inetmgr`, press Enter
2. IIS Manager should open
### 5.2 Create API Application
1. In IIS Manager, expand the server node
2. Right-click **"Sites"** ? **"Add Website..."**
3. Configure the API site:
- **Site name**: `TuneRipper API`
- **Physical path**: `C:\inetpub\wwwroot\TuneRipperApi`
- **Port**: `80` (HTTP) and `443` (HTTPS)
- **Host name**: `tuneripper-api.vrba.one`
4. Click **"OK"**
### 5.3 Create Blazor WebAssembly Application
1. Right-click **"Sites"** ? **"Add Website..."**
2. Configure the Blazor site:
- **Site name**: `TuneRipper App`
- **Physical path**: `C:\inetpub\wwwroot\TuneRipper`
- **Port**: `80` (HTTP) and `443` (HTTPS)
- **Host name**: `tuneripper.vrba.one`
3. Click **"OK"**
### 5.4 Configure Application Pool for API (.NET 10 Specific)
1. Click **"Application Pools"** in the left panel
2. Find the application pool for **TuneRipper API** (usually has the same name)
3. Right-click ? **"Advanced Settings..."**
4. Set the following **.NET 10 specific settings**:
- **.NET CLR Version**: `No Managed Code` (This is correct for .NET 10!)
- **Managed Pipeline Mode**: `Integrated`
- **Start Mode**: `OnDemand`
- **Process Identity**: `ApplicationPoolIdentity`
- **Load User Profile**: `True` (important for .NET 10)
- **Idle Time-out (minutes)**: `20` or `0` (no timeout for testing)
5. Click **"OK"**
### 5.5 Verify ASP.NET Core Module for API Site
1. Select your **TuneRipper API** site in IIS Manager
2. Double-click **"Modules"**
3. Ensure **AspNetCoreModuleV2** is present and enabled
4. If not present, the Hosting Bundle installation may have failed
---
## Step 6: Configure SSL Certificates with Let's Encrypt
### 6.1 Using win-acme (Recommended)
1. Open **Command Prompt as Administrator**
2. Navigate to win-acme directory:
```cmd
cd C:\win-acme\
```
3. Run win-acme and create certificates for both domains:
```cmd
wacs.exe --target iis --siteid 1 --commonname tuneripper.vrba.one
wacs.exe --target iis --siteid 2 --commonname tuneripper-api.vrba.one
```
4. Follow the prompts to:
- Select the IIS sites
- Validate domain ownership
- Install certificates
- Set up automatic renewal
### 6.2 Configure HTTPS Bindings in IIS
1. In IIS Manager, select **TuneRipper App** site
2. Click **"Bindings..."** in the Actions panel
3. Click **"Add..."**
4. Configure HTTPS binding:
- **Type**: `https`
- **Port**: `443`
- **Host name**: `tuneripper.vrba.one`
- **SSL certificate**: Select the Let's Encrypt certificate
5. Repeat for **TuneRipper API** site with `tuneripper-api.vrba.one`
---
## Step 7: Configure Production Settings
### 7.1 Update API Configuration for Production
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
2. Edit `appsettings.json`:
```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"TuneRipper.Api.Services.VideoService": "Information"
}
},
"AllowedHosts": "tuneripper-api.vrba.one",
"ApiSettings": {
"BaseUrl": "https://tuneripper-api.vrba.one",
"HttpBaseUrl": "https://tuneripper-api.vrba.one",
"TimeoutSeconds": 300,
"EnableLogging": true,
"RetryAttempts": 3,
"RetryDelaySeconds": 2
}
}
```
### 7.2 Update CORS for Production Domains
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
2. If you need to restrict CORS (optional), modify the API's `Program.cs`:
```csharp
// Update CORS policy for production
builder.Services.AddCors(options =>
{
options.AddPolicy("ProductionPolicy", policy =>
{
policy.WithOrigins(
"https://tuneripper.vrba.one",
"https://tuneripper-api.vrba.one"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
// Use the production policy
app.UseCors("ProductionPolicy");
```
**Note**: The current CORS configuration uses `AllowAnyOrigin()` which will work fine with your subdomains without changes. The above restriction is optional for enhanced security.
### 7.3 Update Blazor App Configuration
1. Navigate to `C:\inetpub\wwwroot\TuneRipper\`
2. Update `appsettings.json`:
```json
{
"ApiSettings": {
"BaseUrl": "https://tuneripper-api.vrba.one",
"HttpBaseUrl": "https://tuneripper-api.vrba.one",
"TimeoutSeconds": 300,
"EnableLogging": false,
"RetryAttempts": 3,
"RetryDelaySeconds": 2
},
"AppSettings": {
"AppName": "TuneRipper",
"Version": "1.0.0",
"Environment": "Production",
"EnableDetailedErrors": false
}
}
```
### 7.4 Update API Root Endpoint URLs
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
2. If needed, update the root endpoint in `Program.cs` to show production URLs:
```csharp
urls = new
{
https = "https://tuneripper-api.vrba.one",
app = "https://tuneripper.vrba.one"
}
```
---
## Step 8: Verify Web Configuration Files
> **? Good News**: The `web.config` files are now included in both projects and will be automatically deployed during publish!
### 8.1 API web.config (Auto-deployed)
The API project now includes a `web.config` file that will be automatically copied during publish. It includes:
- **HTTPS redirection** for production security
- **ASP.NET Core hosting** configuration for IIS
- **Security headers** for production
- **Environment variables** set to Production
**Location after publish**: `C:\inetpub\wwwroot\TuneRipperApi\web.config`
### 8.2 Blazor WebAssembly web.config (Auto-deployed)
The Blazor project now includes a `web.config` file that will be automatically copied during publish. It includes:
- **HTTPS redirection** for production security
- **SPA routing support** for client-side navigation
- **MIME type mappings** for .wasm and .dll files
- **Security headers** for production
**Location after publish**: `C:\inetpub\wwwroot\TuneRipper\web.config`
### 8.3 Manual Verification (Optional)
After deployment, you can verify the files are present:
1. Check API web.config: `C:\inetpub\wwwroot\TuneRipperApi\web.config`
2. Check Blazor web.config: `C:\inetpub\wwwroot\TuneRipper\web.config`
> **Note**: These files are now version-controlled and automatically deployed. No manual configuration needed!
---
## Step 9: Set Permissions
### 9.1 Configure Folder Permissions
1. Right-click `C:\inetpub\wwwroot\TuneRipperApi\wwwroot\downloads`
2. Select **"Properties"** ? **"Security"** tab
3. Click **"Edit..."** ? **"Add..."**
4. Type: `IIS_IUSRS` and click **"Check Names"** ? **"OK"**
5. Select **IIS_IUSRS** and check:
- ? **Full Control**
- ? **Modify**
- ? **Read & Execute**
- ? **Write**
6. Click **"OK"** to save
### 9.2 Set Application Pool Identity Permissions
1. Right-click `C:\inetpub\wwwroot\TuneRipperApi`
2. **Properties** ? **Security** ? **Edit** ? **Add**
3. Type: `IIS AppPool\TuneRipper API` ? **Check Names** ? **OK**
4. Grant **Read & Execute** permissions
5. Click **OK**
---
## Step 10: Test Deployment
### 10.1 Test .NET 10 Runtime in IIS
1. Start both websites in IIS Manager
2. Check Application Pool status - should be **"Started"**
3. If Application Pool keeps stopping, check Event Viewer for errors
### 10.2 Test Production URLs
1. Open a web browser
2. Navigate to: `https://tuneripper-api.vrba.one/api/health`
3. You should see a JSON health check response
4. Test the root endpoint: `https://tuneripper-api.vrba.one/`
5. Verify the API information is displayed
### 10.3 Test Blazor WebAssembly App
1. Navigate to: `https://tuneripper.vrba.one`
2. The TuneRipper application should load
3. Check browser developer tools (F12) for any loading errors
4. Test the YouTube URL input functionality
### 10.4 Test End-to-End Functionality
1. In the Blazor app, enter a YouTube URL
2. Click **"Download MP3"**
3. Monitor the processing progress
4. Verify the file download works
### 10.5 Test SSL Certificates
1. Check certificate validity in browser
2. Verify automatic HTTP to HTTPS redirection
3. Test certificate auto-renewal (win-acme sets up scheduled tasks)
---
## Step 11: Troubleshooting
### 11.1 Common .NET 10 Issues
#### Application Pool Keeps Stopping
**Problem**: Application pool stops immediately after starting
**Solutions**:
1. Check Event Viewer: `Windows Logs` ? `Application` and `System`
2. Look for ASP.NET Core errors or .NET runtime issues
3. Verify .NET 10 Hosting Bundle is properly installed:
```cmd
dotnet --list-runtimes
```
4. Ensure `web.config` has correct `processPath` and `arguments`
5. Check Application Pool settings:
- .NET CLR Version = "No Managed Code"
- Managed Pipeline Mode = "Integrated"
#### SSL Certificate Issues
**Problem**: SSL certificate not working or expired
**Solutions**:
1. Check certificate binding in IIS Manager
2. Verify Let's Encrypt certificate renewal:
```cmd
# For win-acme
wacs.exe --list
# For certbot
certbot certificates
```
3. Check Windows Task Scheduler for renewal tasks
4. Manually renew if needed:
```cmd
# For win-acme
wacs.exe --renew
# For certbot
certbot renew
```
#### CORS Errors
**Problem**: Cross-origin requests blocked
**Solutions**:
1. Verify CORS configuration in `Program.cs`
2. Current configuration uses `AllowAnyOrigin()` which should work
3. If you implemented production CORS restrictions, ensure domains are correctly specified
4. Check browser console for specific CORS error messages
#### 500 Internal Server Error
**Problem**: HTTP 500 error when accessing API
**Solutions**:
1. Enable detailed errors in `web.config`:
```xml
<aspNetCore processPath="dotnet" arguments=".\TuneRipper.Api.dll"
stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout"
hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
```
2. Create `logs` folder in API directory
3. Check stdout logs for detailed error information
4. Verify all .NET 10 dependencies are published
#### Blazor WebAssembly Loading Issues
**Problem**: Blazor app shows loading indefinitely
**Solutions**:
1. Check browser console (F12) for JavaScript errors
2. Verify all `.wasm` and `.dll` files are present in `_framework` folder
3. Check that `dotnet.js` and `blazor.webassembly.js` are loading
4. Ensure proper MIME types in `web.config`
5. Verify API base URL is correctly configured in `appsettings.json`
### 11.2 Verification Commands
```cmd
# Check .NET installation (Hosting Bundle should show runtimes, SDK not required)
dotnet --list-runtimes
# Check IIS status
iisreset /status
# List IIS sites
%windir%\system32\inetsrv\appcmd.exe list sites
# Check Application Pools
%windir%\system32\inetsrv\appcmd.exe list appPools
# Verify ASP.NET Core Module (Critical for .NET 10)
%windir%\system32\inetsrv\appcmd.exe list modules | findstr AspNet
# Check SSL certificates
certlm.msc
# Test HTTPS connectivity
curl -I https://tuneripper-api.vrba.one/api/health
curl -I https://tuneripper.vrba.one
```
### 11.3 Log Locations
- **IIS Logs**: `C:\inetpub\logs\LogFiles\W3SVC1\` (and W3SVC2, etc.)
- **Windows Event Log**: Event Viewer ? Application and System logs
- **ASP.NET Core stdout logs**: `C:\inetpub\wwwroot\TuneRipperApi\logs\` (if enabled)
- **Application-specific logs**: Configure in `appsettings.json`
- **Let's Encrypt Logs**:
- win-acme: `C:\win-acme\logs\`
- certbot: `C:\Certbot\log\`
---
## Step 12: Security Considerations
### 12.1 Production Security
1. **SSL/TLS**: Certificates automatically managed by Let's Encrypt
2. **HTTPS Enforcement**: Configured in `web.config` for automatic redirection
3. **CORS**: Current configuration uses `AllowAnyOrigin()` (works with subdomains)
4. **Security Headers**: Added to `web.config` (X-Frame-Options, etc.)
5. **File Upload Limits**: Configure maximum file sizes if needed
6. **Rate Limiting**: Consider implementing rate limiting for API endpoints
7. **Update .NET Regularly**: Keep .NET 10 runtime updated via Hosting Bundle
### 12.2 Firewall Configuration
1. Open Windows Defender Firewall
2. Create inbound rules for HTTP (80) and HTTPS (443) ports
3. Block development ports (7160, 8080) from external access
4. Configure network access as needed
### 12.3 CORS Security Analysis
The current CORS configuration in your API uses:
```csharp
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
```
**? This will work perfectly with your subdomain setup** because:
- `AllowAnyOrigin()` permits requests from any domain
- Your Blazor app at `https://tuneripper.vrba.one` can call API at `https://tuneripper-api.vrba.one`
- No CORS configuration changes are required
**For enhanced security (optional)**, you could restrict to specific domains as shown in Step 7.2.
---
## Step 13: Maintenance
### 13.1 Regular Tasks
- Monitor disk space in downloads folder
- Update yt-dlp.exe regularly for YouTube compatibility
- Check for .NET 10 updates and security patches
- Review and rotate log files
- Monitor application pool health
- **Monitor SSL certificate renewals** (should be automatic)
### 13.2 SSL Certificate Maintenance
- **win-acme**: Automatic renewal via Windows Task Scheduler
- **certbot**: Set up automatic renewal:
```cmd
# Add to Task Scheduler to run twice daily
certbot renew --quiet
```
### 13.3 Updating .NET 10
When new .NET 10 updates are released:
1. Download and install **new .NET 10 Hosting Bundle** (SDK not required)
2. Restart IIS: `iisreset`
3. Test application functionality
4. Update applications if needed (rebuild only if breaking changes)
---
## Conclusion
Your TuneRipper application should now be successfully deployed on IIS with Windows 11 using .NET 10, complete with production HTTPS via Let's Encrypt.
**Production URLs:**
- **API**: `https://tuneripper-api.vrba.one`
- **Blazor App**: `https://tuneripper.vrba.one`
**Key Production Features:**
- ? **Automatic HTTPS** with Let's Encrypt certificates
- ? **Automatic HTTP?HTTPS redirection**
- ? **CORS compatibility** with subdomain setup
- ? **Security headers** configured
- ? **Automatic certificate renewal** set up
## CORS Compatibility Summary
### ? **Current CORS Configuration Works Perfect**
Your existing API CORS setup using `AllowAnyOrigin()` will work seamlessly with:
- `https://tuneripper.vrba.one` ? `https://tuneripper-api.vrba.one`
- No code changes required
- Cross-subdomain requests allowed
### ?? **Optional Security Enhancement**
For production, you can optionally restrict CORS to specific domains (see Step 7.2), but it's not required for functionality.
## Quick Reference Commands
```cmd
# Check .NET 10 runtime installation (production)
dotnet --list-runtimes
# Restart IIS
iisreset
# Verify FFmpeg
ffmpeg -version
# Test production endpoints
curl https://tuneripper-api.vrba.one/api/health
curl -I https://tuneripper.vrba.one
# Check SSL certificates
certlm.msc
# View IIS processes
tasklist | findstr w3wp
# Check Application Pool status
%windir%\system32\inetsrv\appcmd.exe list appPools /text:name,state
# Renew SSL certificates manually
wacs.exe --renew
# or
certbot renew
```
---
*This guide includes production-ready HTTPS setup with Let's Encrypt for the subdomain configuration: `https://tuneripper.vrba.one` and `https://tuneripper-api.vrba.one`. The existing CORS configuration will work without modifications.*
+298
View File
@@ -0,0 +1,298 @@
# TuneRipper - YouTube to MP3 Converter
A modern Blazor WebAssembly application with ASP.NET Core API for converting YouTube videos to MP3 files using yt-dlp.
## ?? Overview
TuneRipper is a full-stack web application that allows users to convert YouTube videos to MP3 format. It features a responsive Blazor WebAssembly frontend and a robust ASP.NET Core API backend with real-time progress monitoring.
## ??? Architecture
### Projects Structure
```
TuneRipper/
??? TuneRipper/ # Blazor WebAssembly Client
??? TuneRipper.Api/ # ASP.NET Core API
??? TuneRipper.Shared/ # Shared Models & Configuration
??? DEPLOYMENT_GUIDE_IIS_Windows11.md
```
### Technology Stack
- **.NET 10** - Latest .NET framework
- **Blazor WebAssembly** - Modern SPA framework
- **ASP.NET Core API** - RESTful backend services
- **yt-dlp** - YouTube video processing
- **FFmpeg** - Audio conversion
- **IIS** - Production deployment platform
## ?? Quick Start
### Prerequisites
1. **.NET 10 SDK** installed
2. **yt-dlp.exe** (automatically placed in API wwwroot)
3. **FFmpeg** available in system PATH
### Development Setup
#### 1. Clone the Repository
```bash
git clone https://git.vrba.one/TuneRipper.git
cd TuneRipper
```
#### 2. Start the API
```bash
cd TuneRipper.Api
dotnet run
```
API will be available at:
- **HTTPS**: https://localhost:7160
- **HTTP**: http://localhost:5112
#### 3. Start the Blazor WebAssembly App
```bash
cd TuneRipper
dotnet run
```
App will be available at: https://localhost:7070
### Quick Testing
1. Navigate to the Blazor app
2. Enter a YouTube URL
3. Click "Download MP3"
4. Monitor real-time progress
5. Download the converted file
## ?? File Management System
### GUID-Based Naming
Downloaded files use the format: **`{jobId}_{title}.mp3`**
**Examples:**
- `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3`
- `6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3`
**Benefits:**
- ? **Unique Identification**: No filename conflicts
- ? **Direct Job Mapping**: Easy file lookup using GUID
- ? **User-Friendly Downloads**: Converted to readable names
- ? **Secure Access**: Job ID acts as access token
### File Storage
- **Location**: `TuneRipper.Api/wwwroot/downloads/`
- **Access**: Via API endpoints or direct static file serving
- **Cleanup**: Automated cleanup by job ID pattern
## ?? API Workflow
### 1. Start Processing
```http
POST /api/video/process
Content-Type: application/json
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"format": "mp3",
"quality": "128"
}
```
### 2. Monitor Progress
```http
GET /api/video/status/{jobId}
```
Returns real-time progress with video details.
### 3. Download Result
```http
GET /api/download/{jobId}
```
Returns MP3 file with user-friendly filename.
## ?? Progress Monitoring
Real-time progress updates from yt-dlp processing:
- **5-15%**: Fetching video details
- **15-70%**: Downloading audio stream
- **70-85%**: Converting to MP3 format
- **85-95%**: Finalizing and cleanup
- **100%**: Ready for download
## ??? Development
### API Endpoints
- **Health Check**: `GET /api/health`
- **Process Video**: `POST /api/video/process`
- **Check Status**: `GET /api/video/status/{jobId}`
- **Get Result**: `GET /api/video/result/{jobId}`
- **Download File**: `GET /api/download/{jobId}`
- **List Jobs**: `GET /api/video/jobs`
### Configuration
Update `appsettings.json` for environment-specific settings:
```json
{
"ApiSettings": {
"BaseUrl": "https://localhost:7160",
"TimeoutSeconds": 300,
"EnableLogging": true
}
}
```
### Testing
Use the provided HTTP test file:
```bash
# Open TuneRipper.Api/api-tests.http in VS Code or Visual Studio
```
## ?? Deployment
### IIS on Windows 11 (Recommended)
Follow the comprehensive deployment guide:
```bash
# See DEPLOYMENT_GUIDE_IIS_Windows11.md for detailed instructions
```
**Key Deployment Steps:**
1. Install .NET 10 Hosting Bundle for IIS
2. Enable IIS with ASP.NET Core support
3. Publish applications using Release configuration
4. Configure IIS sites and application pools
5. Set proper file permissions
6. Test end-to-end functionality
### Docker (Alternative)
```dockerfile
# Dockerfile examples available for containerized deployment
```
## ?? Configuration Details
### Required Tools
- **yt-dlp.exe**: Place in `TuneRipper.Api/wwwroot/`
- **FFmpeg**: Add to system PATH for audio conversion
### Environment Variables
- `ASPNETCORE_ENVIRONMENT`: Development/Production
- `ASPNETCORE_URLS`: Custom binding URLs
### CORS Configuration
API is configured to allow Blazor WebAssembly client access:
```csharp
builder.Services.AddCors(options =>
{
options.AddPolicy("BlazorPolicy", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
```
## ?? Troubleshooting
### Common Issues
#### API Not Starting
```bash
# Check .NET installation
dotnet --version
# Trust development certificates
dotnet dev-certs https --trust
```
#### yt-dlp Not Found
- Verify `yt-dlp.exe` is in `TuneRipper.Api/wwwroot/`
- Check file permissions
- Ensure downloads directory exists
#### FFmpeg Issues
```bash
# Verify FFmpeg installation
ffmpeg -version
# Add to PATH if needed
```
#### CORS Errors
- Verify API base URL configuration in Blazor app
- Check CORS policy settings
- Ensure API is running on expected port
### Debug Logging
Enable detailed logging in `appsettings.json`:
```json
{
"Logging": {
"LogLevel": {
"TuneRipper.Api.Services.VideoService": "Debug"
}
}
}
```
## ?? Security Considerations
### Production Deployment
- **HTTPS Only**: Configure SSL certificates
- **CORS Restrictions**: Limit allowed origins
- **Rate Limiting**: Implement API rate limiting
- **File Cleanup**: Set up automated cleanup jobs
- **Access Control**: Consider authentication for production
### File Security
- Job IDs provide secure file access
- No directory traversal vulnerabilities
- Automatic cleanup prevents disk space issues
## ?? Performance Optimization
### Recommended Settings
- **Application Pool**: Configure for .NET 10
- **File Storage**: Consider cloud storage for scale
- **Caching**: Implement response caching where appropriate
- **Monitoring**: Set up application insights
### Scaling Considerations
- GUID-based naming supports distributed environments
- Stateless API design enables horizontal scaling
- Consider queue-based processing for high load
## ?? Maintenance
### Regular Tasks
- Update yt-dlp.exe for YouTube compatibility
- Monitor disk space in downloads directory
- Check for .NET 10 security updates
- Review and rotate log files
### Monitoring
- Application pool health
- File system usage
- API response times
- Error rates and patterns
## ?? Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Test thoroughly
5. Submit a pull request
## ?? License
This project is licensed under the MIT License - see the LICENSE file for details.
## ?? Related Files
- **Deployment Guide**: `DEPLOYMENT_GUIDE_IIS_Windows11.md`
- **API Tests**: `TuneRipper.Api/api-tests.http`
- **Project Files**: `*.csproj` in each project directory
---
**Built with ?? using .NET 10, Blazor WebAssembly, and modern web technologies.**
-84
View File
@@ -1,84 +0,0 @@
# TuneRipper API
## Quick Start
### Starting the API
**Option 1: Using the start script (Windows)**
```cmd
cd TuneRipper.Api
start-api.bat
```
**Option 2: Using the start script (Linux/Mac)**
```bash
cd TuneRipper.Api
chmod +x start-api.sh
./start-api.sh
```
**Option 3: Manual start**
```cmd
cd TuneRipper.Api
dotnet run
```
### API Endpoints
Once running, the API will be available at:
- **HTTPS**: https://localhost:7160
- **HTTP**: http://localhost:5112
### Testing the API
1. **Start the API** using one of the methods above
2. **Open the HTTP test file**: `TuneRipper.Api/api-tests.http`
3. **Run the connectivity tests first** to verify the API is responding
4. **Use the main API tests** once connectivity is confirmed
### Troubleshooting
#### "This localhost page can't be found" errors:
1. **Check if API is running**:
- Look for console output showing "Now listening on: https://localhost:7160"
- If not running, start it using the methods above
2. **Try HTTP instead of HTTPS**:
- Use `http://localhost:5112` instead of `https://localhost:7160`
- Some development environments have HTTPS certificate issues
3. **Trust development certificates** (for HTTPS):
```cmd
dotnet dev-certs https --trust
```
4. **Check port availability**:
- Make sure ports 7160 and 5112 aren't used by other applications
- You can change ports in `Properties/launchSettings.json`
#### HTTP test file variables not working:
1. **Copy job IDs manually**:
- Run a POST request to start processing
- Copy the `fileName` value from the response
- Use it in the manual test sections
2. **Use the troubleshooting section**:
- Start with connectivity tests
- Use manual GUID replacements if variables fail
### API Documentation
When the API is running, you can access:
- **Root endpoint**: https://localhost:7160/ (lists available endpoints)
- **OpenAPI spec**: https://localhost:7160/openapi/v1.json
- **Health check**: https://localhost:7160/api/health
### Development
The API includes:
- Automatic reload on code changes (when using `dotnet run`)
- Detailed logging in the console
- CORS enabled for Blazor WebAssembly client
- OpenAPI/Swagger support for API documentation
-296
View File
@@ -1,296 +0,0 @@
# TuneRipper API - yt-dlp Integration
## Overview
The TuneRipper API has been updated to use `yt-dlp.exe` for real YouTube video processing with progress monitoring. Videos are downloaded and converted to MP3 files, stored in the `wwwroot/downloads` directory with a GUID-based filename format, and served directly through the API.
## Setup
### Prerequisites
1. **.NET 10** installed
2. **yt-dlp.exe** placed in `TuneRipper.Api/wwwroot/yt-dlp.exe`
3. **ffmpeg** available in PATH (required by yt-dlp for audio conversion)
### File Structure
```
TuneRipper.Api/
??? wwwroot/
? ??? yt-dlp.exe # YouTube downloader executable
? ??? downloads/ # Downloaded MP3 files (auto-created)
??? Controllers/
??? Services/
??? Program.cs
```
## Filename Format
Downloaded files use the structured format: **`{jobId}_{title}.mp3`**
### Format Breakdown:
- **`{jobId}`**: GUID identifier for the processing job (e.g., `550e8400-e29b-41d4-a716-446655440000`)
- **`_{title}`**: Sanitized video title with spaces replaced by underscores
- **`.mp3`**: Audio format extension
### Examples:
- `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3`
- `6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3`
- `6ba7b811-9dad-11d1-80b4-00c04fd430c8_Amazing_Guitar_Solo_Performance.mp3`
### Benefits:
- **Unique Identification**: GUID ensures no filename conflicts
- **Direct Job Mapping**: Easy file lookup using job ID
- **Human Readable**: Title part provides context
- **System Friendly**: Sanitized for filesystem compatibility
### Title Sanitization:
- Invalid filename characters are replaced with safe alternatives
- Spaces become underscores (`_`)
- Special characters: `< > | : * ? " /` are replaced with safe chars
- Maximum title length: 50 characters
- Fallback to "video" if title cannot be determined
## Key Changes
### 1. Program.cs Updates
- Added `UseStaticFiles()` middleware for serving downloaded files
- Added `AddHttpClient()` for VideoService HTTP requests
- Updated logging and endpoint information
### 2. VideoService Updates
- **GUID-Based Filenames**: Uses job ID as primary identifier in filename
- **Title Sanitization**: Converts video titles to safe filenames
- **Direct Job Mapping**: Files can be found using `{jobId}_*.*` pattern
- **Real yt-dlp Integration**: Uses actual yt-dlp.exe with progress monitoring
- **Progress Parsing**: Real-time progress from yt-dlp output streams
- **Error Handling**: Comprehensive error handling with 5-minute timeout
### 3. VideoController Updates
- Passes job ID to VideoService for filename generation
- Uses actual yt-dlp processing instead of simulation
- Stores downloaded file information with GUID-based naming
- Returns real download URLs for completed files
### 4. DownloadController Updates
- **Precise Job Lookup**: Uses `{jobId}_*.*` pattern for exact file matching
- **User-Friendly Downloads**: Converts filenames back to readable format
- **Example**: `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3` ? `Rick Astley Never Gonna Give You Up.mp3`
- **Reliable File Operations**: No ambiguity in file identification
- Serves actual MP3 files from `wwwroot/downloads/`
- Proper MIME type detection for audio files
## API Workflow
### 1. Start Processing
```http
POST /api/video/process
Content-Type: application/json
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"format": "mp3",
"quality": "128"
}
```
**Response:**
```json
{
"success": true,
"message": "Processing started",
"fileName": "550e8400-e29b-41d4-a716-446655440000",
"downloadUrl": null,
"videoDetails": null
}
```
### 2. Monitor Progress
```http
GET /api/video/status/550e8400-e29b-41d4-a716-446655440000
```
**Response (Processing):**
```json
{
"percentageComplete": 45,
"status": "Processing",
"message": "Downloading audio...",
"videoDetails": {
"id": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up",
"thumbnailUrl": "https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg"
}
}
```
### 3. Get Final Result
```http
GET /api/video/result/550e8400-e29b-41d4-a716-446655440000
```
**Response:**
```json
{
"success": true,
"message": "Video processed successfully",
"fileName": "550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3",
"downloadUrl": "/downloads/550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3",
"videoDetails": { ... }
}
```
### 4. Download File
```http
GET /api/download/550e8400-e29b-41d4-a716-446655440000
```
**Response:** Binary MP3 file download with user-friendly filename
**Download Name:** `Rick Astley Never Gonna Give You Up.mp3`
**Alternative Static File Access:**
```http
GET /downloads/550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3
```
## File Management
### Download Directory
- **Location**: `wwwroot/downloads/`
- **Naming Pattern**: `{jobId}_{title}.ext`
- **Job Lookup**: Files found using `Directory.GetFiles(dir, "{jobId}_*.*")`
- **User Download**: Converted back to readable names
- **Cleanup**: Files can be deleted by job ID
### File Serving Options
1. **API Download**: Controlled access via `/api/download/{jobId}` (recommended)
- Uses job ID for secure file lookup
- Returns user-friendly filename
- Proper error handling
2. **Static Files**: Direct access via `/downloads/{actual_filename}`
- Requires knowing the full filename
- Less secure but faster
3. **Content-Type**: Automatic detection based on file extension
### File Operations by Job ID
- **Find**: `GET /api/download/info/{jobId}` - Get file metadata
- **Download**: `GET /api/download/{jobId}` - Download the file
- **Delete**: `DELETE /api/download/{jobId}` - Remove the file
## Progress Monitoring
The VideoService monitors yt-dlp output and translates it to progress updates:
- **5-15%**: Fetching video details
- **15-70%**: Downloading audio (yt-dlp download progress × 0.7)
- **70-85%**: Converting to MP3 (ffmpeg processing)
- **85-95%**: Finalizing (cleanup)
- **100%**: Complete
## Error Handling
### Common Errors:
1. **yt-dlp.exe not found**: Ensure yt-dlp.exe is in wwwroot directory
2. **ffmpeg not available**: Install ffmpeg and add to PATH
3. **Invalid YouTube URL**: URL format validation
4. **Download timeout**: 5-minute timeout for processing
5. **File not found**: File may have been cleaned up or job ID invalid
### Error Response Format:
```json
{
"success": false,
"message": "Error description",
"fileName": null,
"downloadUrl": null,
"videoDetails": null
}
```
## Configuration
### appsettings.json
```json
{
"Logging": {
"LogLevel": {
"TuneRipper.Api.Services.VideoService": "Debug"
}
}
}
```
### yt-dlp Arguments Used:
- `--extract-audio`: Extract audio only
- `--audio-format mp3`: Convert to MP3
- `--audio-quality 0`: Best quality
- `--no-playlist`: Single video only
- `--no-warnings`: Clean output
- `--newline`: Line-by-line progress
- `--output "{jobId}_{title}.%(ext)s"`: Uses job ID-based filename
## Testing
### Manual Testing:
1. Start the API: `dotnet run --project TuneRipper.Api`
2. Use API testing tools or the Blazor client
3. Check logs for yt-dlp progress
4. Verify files in `wwwroot/downloads/` with GUID-based naming
### Example Test Files:
```
wwwroot/downloads/
??? 550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3
??? 6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3
??? 6ba7b811-9dad-11d1-80b4-00c04fd430c8_Amazing_Guitar_Solo_Performance.mp3
```
### Health Check:
```http
GET /api/health
```
### Job Listing:
```http
GET /api/video/jobs
```
## Production Considerations
1. **File Storage**: Consider cloud storage for production
2. **Cleanup Strategy**: Implement automatic file cleanup/retention using job completion timestamps
3. **Security**: Job IDs provide secure file access (no directory traversal)
4. **Performance**: Consider queue-based processing for high load
5. **Monitoring**: Add detailed logging and metrics
6. **Updates**: Keep yt-dlp.exe updated for compatibility
7. **Scalability**: GUID-based naming prevents conflicts in distributed systems
## Troubleshooting
### Common Issues:
1. **Permissions**: Ensure API can write to wwwroot/downloads
2. **Antivirus**: yt-dlp.exe may be flagged by antivirus
3. **Network**: YouTube may block requests from some IPs
4. **Format Support**: Some videos may not support audio extraction
5. **Long Titles**: Titles are truncated to 50 characters for filesystem compatibility
### Debug Logging:
Enable debug logging for VideoService to see detailed yt-dlp output:
```json
{
"Logging": {
"LogLevel": {
"TuneRipper.Api.Services.VideoService": "Debug"
}
}
```
### File Lookup Issues:
- Verify job ID matches the GUID format
- Check that files exist with the `{jobId}_` prefix
- Look at directory contents if files are not found
- Ensure proper case sensitivity on Linux systems
### Advantages of GUID-Based Naming:
1. **Unique**: No filename conflicts possible
2. **Secure**: Job ID acts as access token
3. **Traceable**: Direct mapping from API calls to files
4. **Scalable**: Works in distributed environments
5. **Clean**: Easy cleanup by job ID pattern
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\TuneRipper.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
</environmentVariables>
</aspNetCore>
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
<!-- Security headers -->
<httpProtocol>
<customHeaders>
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="DENY" />
<add name="X-XSS-Protection" value="1; mode=block" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration>
+41
View File
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- Force HTTPS -->
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
</rule>
<rule name="Serve subdir">
<match url=".*" />
<action type="Rewrite" url="wwwroot\{R:0}" />
</rule>
<rule name="SPA fallback routing" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="wwwroot\" />
</rule>
</rules>
</rewrite>
<staticContent>
<mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
<mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
</staticContent>
<!-- Security headers -->
<httpProtocol>
<customHeaders>
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="DENY" />
<add name="X-XSS-Protection" value="1; mode=block" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>