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

440 lines
10 KiB
Markdown

# 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](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:
```bash
# 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
```bash
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:
```bash
# Extract version number
VERSION=$(grep -oP 'Version\s*=\s*"\K[^"]+' SharedVersion.cs)
echo "Building Jellyfin version: $VERSION"
```
### Step 3: Create the Debian Package
```bash
# 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:
```bash
# 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
```bash
# 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`:
```ini
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):
```bash
#!/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):
```bash
#!/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):
```bash
#!/bin/bash
set -e
# Clean up user and directories (optional)
# userdel jellyfin || true
# rm -rf /var/lib/jellyfin
exit 0
```
Make scripts executable:
```bash
chmod 0755 jellyfin-pkg/DEBIAN/postinst
chmod 0755 jellyfin-pkg/DEBIAN/prerm
chmod 0755 jellyfin-pkg/DEBIAN/postrm
```
### Step 5: Build the Package
```bash
# 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:
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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:
```bash
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:
```bash
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:
```bash
ldd /opt/jellyfin/jellyfin | grep "not found"
```
## Automation Script
Create `scripts/linux/build-deb-package.sh`:
```bash
#!/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:
```bash
chmod +x scripts/linux/build-deb-package.sh
```
Run it:
```bash
./scripts/linux/build-deb-package.sh
```
## References
- [Debian New Maintainers' Guide](https://www.debian.org/doc/manuals/maint-guide/)
- [Packaging with fpm](https://github.com/jordansissel/fpm)
- [dpkg-deb Manual](https://manpages.debian.org/dpkg-deb)
- [systemd Unit Files](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)