Files
pgsql-jellyfin/docs/BUILD_DEBIAN_PACKAGE.md
T
wjones 8914f4dce9 Add SQL query patterns documentation and Linux package build scripts
- 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.
2026-07-14 10:32:56 -04:00

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

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

  1. Local Repository: Host .deb files on a private apt repository
  2. GitHub Releases: Upload to GitHub releases for easy download
  3. Package Repository: Submit to Ubuntu/Debian repositories
  4. Direct Download: Provide .deb file 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

References