- Created `TV_SHOWS_SQL_QUERY_PATTERNS.md` to document SQL query patterns for TV shows, including performance issues and missing indexes. - Added `README.md` for Linux package building, detailing steps for creating Debian and Red Hat packages. - Implemented build scripts for Debian and Red Hat, including service files and post-installation hooks. - Added necessary scripts for managing Jellyfin service lifecycle on both Debian and Red Hat systems. - Included package specifications and installation instructions for both distributions.
10 KiB
Building a Debian Package
This document describes how to build a Debian (.deb) package from the Jellyfin project using the current publishing parameters.
Overview
The Jellyfin project is configured to publish as a self-contained Linux application. These published files can be packaged into a Debian package for easy distribution and installation on Debian-based systems.
Current Publishing Parameters
The project is configured with the following publishing settings (from rebuild-solution.sh):
| Parameter | Value | Purpose |
|---|---|---|
| Runtime | linux-x64 |
Self-contained binary for 64-bit Linux |
| Configuration | Release |
Optimized production build |
| Self-contained | true |
Includes all .NET runtime dependencies |
| Output Directory | /opt/jellyfin |
Standard Linux application directory |
Prerequisites
Install the required tools on your system:
# Update package list
sudo apt-get update
# Install build tools
sudo apt-get install -y \
dotnet-sdk-11.0 \
ruby-dev \
build-essential
# Install FPM (Effing Package Manager) for easy package creation
sudo gem install fpm --no-document
Method 1: Using FPM (Recommended)
FPM automates the package creation process and handles dependencies, scripts, and metadata.
Step 1: Publish the Application
cd /home/wjones/projects/pgsql-jellyfin
# Restore dependencies
dotnet restore Jellyfin.sln -r linux-x64
# Build for Release
dotnet build Jellyfin.sln --configuration Release
# Publish as self-contained
dotnet publish Jellyfin.Server/Jellyfin.Server.csproj \
--configuration Release \
--self-contained true \
--runtime linux-x64 \
--output /tmp/jellyfin-build
Expected output location: /tmp/jellyfin-build/
Step 2: Extract Version
Get the version from the SharedVersion.cs file:
# Extract version number
VERSION=$(grep -oP 'Version\s*=\s*"\K[^"]+' SharedVersion.cs)
echo "Building Jellyfin version: $VERSION"
Step 3: Create the Debian Package
# Navigate to project root
cd /home/wjones/projects/pgsql-jellyfin
# Build the .deb package
fpm -s dir \
-t deb \
-n jellyfin \
-v "$VERSION" \
-C /tmp/jellyfin-build \
-p "jellyfin-${VERSION}_amd64.deb" \
--license "LICENSE" \
--vendor "Jellyfin Contributors" \
--maintainer "Your Name <your.email@example.com>" \
--description "Jellyfin Media Server - a free software media server" \
--url "https://jellyfin.org" \
--architecture x86_64 \
--depends "libssl3" \
--depends "libicu72" \
--depends "libfontconfig1" \
--depends "libc6 (>= 2.31)" \
opt/=opt/jellyfin \
etc/=etc/jellyfin
Output: jellyfin-{VERSION}_amd64.deb
Step 4 (Optional): Add Service Files
To include systemd integration, create service files:
# Create directories for package contents
mkdir -p fpm-package/etc/jellyfin
mkdir -p fpm-package/usr/lib/systemd/system
mkdir -p fpm-package/opt/jellyfin
# Copy published files
cp -r /tmp/jellyfin-build/* fpm-package/opt/jellyfin/
# Create systemd service file
cat > fpm-package/usr/lib/systemd/system/jellyfin.service << 'EOF'
[Unit]
Description=Jellyfin Media Server
After=network.target
[Service]
Type=simple
User=jellyfin
Group=jellyfin
WorkingDirectory=/opt/jellyfin
ExecStart=/opt/jellyfin/jellyfin
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
# Update FPM command to include systemd service
fpm -s dir \
-t deb \
-n jellyfin \
-v "$VERSION" \
-C fpm-package \
-p "jellyfin-${VERSION}_amd64.deb" \
--after-install ./scripts/debian/postinst \
--before-remove ./scripts/debian/prerm \
--license "LICENSE" \
--description "Jellyfin Media Server" \
--url "https://jellyfin.org" \
--architecture x86_64 \
--depends "libssl3" \
--depends "libicu72" \
opt/ \
usr/
Method 2: Using dpkg-deb (Manual)
For more control over the package structure, use dpkg-deb directly.
Step 1-2: Same as Method 1
Publish the application (Steps 1-2 above).
Step 3: Create Package Directory Structure
# Create control directory
mkdir -p jellyfin-pkg/DEBIAN
mkdir -p jellyfin-pkg/opt/jellyfin
mkdir -p jellyfin-pkg/etc/jellyfin
mkdir -p jellyfin-pkg/usr/lib/systemd/system
# Copy published application files
cp -r /tmp/jellyfin-build/* jellyfin-pkg/opt/jellyfin/
# Copy configuration template
cp jellyfin-setup.iss jellyfin-pkg/etc/jellyfin/jellyfin.conf.example
Step 4: Create DEBIAN Control Files
Create jellyfin-pkg/DEBIAN/control:
Package: jellyfin
Version: 10.x.x
Architecture: amd64
Maintainer: Jellyfin Contributors <https://jellyfin.org>
Depends: libssl3, libicu72, libfontconfig1, libc6 (>= 2.31)
Homepage: https://jellyfin.org
Description: Jellyfin Media Server
Jellyfin is a free software media server application
that allows you to collect, manage, and share your
digital media (video, music, photos) anywhere.
Create jellyfin-pkg/DEBIAN/postinst (post-install script):
#!/bin/bash
set -e
# Create jellyfin user if it doesn't exist
if ! getent passwd jellyfin > /dev/null; then
useradd --system --home /var/lib/jellyfin --shell /bin/false jellyfin
fi
# Create necessary directories
mkdir -p /var/lib/jellyfin /var/log/jellyfin /etc/jellyfin
chown -R jellyfin:jellyfin /var/lib/jellyfin /var/log/jellyfin /etc/jellyfin
# Reload systemd
systemctl daemon-reload
# Start the service
systemctl enable jellyfin.service
systemctl start jellyfin.service
exit 0
Create jellyfin-pkg/DEBIAN/prerm (pre-remove script):
#!/bin/bash
set -e
# Stop the service
systemctl stop jellyfin.service || true
systemctl disable jellyfin.service || true
exit 0
Create jellyfin-pkg/DEBIAN/postrm (post-remove script):
#!/bin/bash
set -e
# Clean up user and directories (optional)
# userdel jellyfin || true
# rm -rf /var/lib/jellyfin
exit 0
Make scripts executable:
chmod 0755 jellyfin-pkg/DEBIAN/postinst
chmod 0755 jellyfin-pkg/DEBIAN/prerm
chmod 0755 jellyfin-pkg/DEBIAN/postrm
Step 5: Build the Package
# Get version
VERSION=$(grep -oP 'Version\s*=\s*"\K[^"]+' SharedVersion.cs)
# Create the .deb package
dpkg-deb --build jellyfin-pkg "jellyfin-${VERSION}_amd64.deb"
# Verify the package
dpkg-deb --info "jellyfin-${VERSION}_amd64.deb"
Output: jellyfin-{VERSION}_amd64.deb
Installation
Once you have created the .deb package:
# Install the package
sudo dpkg -i jellyfin-10.x.x_amd64.deb
# If dependencies are missing, install them
sudo apt-get install -f
# Check service status
sudo systemctl status jellyfin
# View logs
sudo journalctl -u jellyfin -f
Verification
Check Package Contents
# List files in the package
dpkg-deb -c jellyfin-10.x.x_amd64.deb
# View package metadata
dpkg-deb -I jellyfin-10.x.x_amd64.deb
Test Installation
# Create a test environment
mkdir -p /tmp/jellyfin-test
cd /tmp/jellyfin-test
# Extract package contents
dpkg -x /path/to/jellyfin-10.x.x_amd64.deb .
dpkg -e /path/to/jellyfin-10.x.x_amd64.deb DEBIAN
# Review extracted files
ls -la
cat DEBIAN/control
Distribution
Options for Distribution
- Local Repository: Host
.debfiles on a private apt repository - GitHub Releases: Upload to GitHub releases for easy download
- Package Repository: Submit to Ubuntu/Debian repositories
- Direct Download: Provide
.debfile download link
Example: Create Local APT Repository
# Create repository directory
mkdir -p /var/www/jellyfin-repo/pool/main
# Copy package
cp jellyfin-10.x.x_amd64.deb /var/www/jellyfin-repo/pool/main/
# Generate package index (requires apt-utils)
cd /var/www/jellyfin-repo
dpkg-scanpackages pool/main /dev/null | gzip > Packages.gz
# Users can then add to their apt sources:
# echo "deb file:///var/www/jellyfin-repo /" | sudo tee /etc/apt/sources.list.d/jellyfin.list
Troubleshooting
Common Issues
Issue: dpkg-deb: error: unable to open jellyfin-pkg/DEBIAN/control (No such file or directory)
Solution: Ensure the DEBIAN directory exists and control file is properly created:
mkdir -p jellyfin-pkg/DEBIAN
# Recreate control file with proper permissions
Issue: Package installs but service won't start
Solution: Check if jellyfin user exists and has proper permissions:
sudo systemctl status jellyfin
sudo journalctl -u jellyfin -n 50
sudo ls -la /opt/jellyfin
sudo ls -la /var/lib/jellyfin
Issue: Missing dependencies warning
Solution: Ensure all required libraries are listed in the Depends: field:
ldd /opt/jellyfin/jellyfin | grep "not found"
Automation Script
Create scripts/linux/build-deb-package.sh:
#!/bin/bash
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
VERSION=$(grep -oP 'Version\s*=\s*"\K[^"]+' "$PROJECT_ROOT/SharedVersion.cs")
BUILD_DIR="/tmp/jellyfin-build-$$"
OUTPUT_DIR="$PROJECT_ROOT/dist"
echo "Building Jellyfin Debian package v$VERSION..."
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Build and publish
cd "$PROJECT_ROOT"
dotnet restore Jellyfin.sln -r linux-x64
dotnet build Jellyfin.sln --configuration Release
dotnet publish Jellyfin.Server/Jellyfin.Server.csproj \
--configuration Release \
--self-contained true \
--runtime linux-x64 \
--output "$BUILD_DIR"
# Create package
fpm -s dir \
-t deb \
-n jellyfin \
-v "$VERSION" \
-C "$BUILD_DIR" \
-p "$OUTPUT_DIR/jellyfin-${VERSION}_amd64.deb" \
--license "LICENSE" \
--description "Jellyfin Media Server" \
--url "https://jellyfin.org" \
--architecture x86_64 \
--depends "libssl3" \
--depends "libicu72" \
opt/=opt/jellyfin
# Cleanup
rm -rf "$BUILD_DIR"
echo "Package created: $OUTPUT_DIR/jellyfin-${VERSION}_amd64.deb"
dpkg-deb -I "$OUTPUT_DIR/jellyfin-${VERSION}_amd64.deb"
Make it executable:
chmod +x scripts/linux/build-deb-package.sh
Run it:
./scripts/linux/build-deb-package.sh