How to set up a Ubuntu Media server with Jellyfin, Samba, Qbittorrent and video conversion scripts
| 16 min read
As I have written over the past few months. I've been working on building an Ubuntu Media Server. This machine runs Samba Filesharing, sFTP, Jellyfin server, Qbittorent, and a basic Apache webserver. It also handles video and audio conversion to a uniform super compatible format. Should you want to import all your DVDs and CDs into your Jellyfin Library.
I've been using this setup for a while now, and this is the, for me, fine tuned version of how to install Ubuntu server from a blank OS to a fully working Media Server.
For these steps to work we assume that you have a freshly installed Ubuntu Server 24 LTS (or newer) on a Intel PC of some sort. I use a refurbished HP Elitedesk computer, but any kind of PC will (should) work.
Hardware used
- HP EliteDesk 800 G4 SFF
- Intel Core i5-8500
- Intel HD630 integrated video
- 32 GB DDR4 memory
- 256GB NVMe m.2 SSD
- 6TB 3.5" Western Digital Red NAS disk
- Gigabit onboard lan
Basic Ubuntu setup
I've used the standard installation for everything and mounted the 6TB Nas drive on /data. This is relevant for the installation below. If you mount your storage disk elsewhere, change the commands below accordingly.
Once the installation of Ubuntu completes and you're at the login prompt you can continue with the steps below.
The server can use DHCP, but I always prefer a static IP. Set that up according to your network.
For networking, we use .home.lan as a network domain. You can use your own domain if you prefer. Or if you do not have a local domain or DNS server, you can use .local or rely on IP Addresses. In this setup, the Media server will be at media.local.lan or media.local.
I always prefer to use DNS names for convenience.
A few ground rules
- We don't use a firewall (LAN only!)
- Everything is HTTP, not HTTPS
- Keep it simple, even if it takes longer to set up
- Rely as much as possible on local solutions
- Avoid dependencies as much as possible
For the commands below, most of them can be copy/pasted. But take note of what you're doing! A few require you to make some changes. Such as enter a hostname, your username(s), time zone and things like that. Never blindly copy anything! Always, always interpret and try to understand what you're doing!
Commands that need your input are easily identified by all capital words.
YOURUSERNAME always refers to your own user other than root! The other 'usernames' are other users of your choosing.
I've ignored the UFW firewall entirely, this computer only works on my LAN network and sits behind a pfSense firewall. The UFW firewall is installed on Ubuntu Server by default, rules can easily be added to it. Make sure you let Samba, Apache, sFTP and Jellyfin through it if you decide to use it. Also a few ports for Qbittorrent are probably useful to have.
You can set up and use the firewall, but setting it up is beyond the scope of this article.
After installing Ubuntu
Here we set the servers hostname, I use 'media' for mine. Set your timezone too.
sudo hostnamectl set-hostname media
sudo timedatectl set-timezone UTC
Next run all updates.
sudo apt update
sudo apt upgrade
Scripts and extra files
This zip-file contains scripts and configuration files referenced throughout this guide.
Download: arnan.me_ubuntu-server-files.zip
File: zip file / Size: 1.3 MB / Uploaded: September 08 2026
Install software and users
This command will install almost all required software which we will set up in this guide.
sudo apt install acl avahi-daemon avahi-utils samba intel-media-va-driver-non-free intel-opencl-icd vainfo qbittorrent-nox apache2 libapache2-mod-cgi vsftpd -y
Set up your users. If you're also installing qbittorrent, you'll need the qbtuser. The rest is optional. Switch out USERNAME with the desired username. Add as many as you need.
sudo adduser qbtuser
sudo adduser USERNAME
Set up folders
Here we set up all the required folders. User groups, user permissions and ownership. As you'll note we don't really touch the base Ubuntu file system. Everything of note goes on the /data mount.
The second line adds folders for video files; movies, tv-shows and animation. Add different ones as needed. If you don't care for an Animated library you can leave that out. Or if you want a different storage routine - Sort by genre for example - add different folders. These are what the various Jellyfin libraries will look for once you create them.
sudo mkdir -p /data/{jellyfin-data,downloads,incomplete,converted,www,scripts}
sudo mkdir -p /data/jellyfin-data/{movies,tv-shows,animation}
sudo mkdir -p /data/jellyfin-data/{cache,meta}
sudo mkdir -p /data/scripts/log
sudo mkdir -p /data/www/cgi-bin
sudo groupadd media-server
sudo usermod -aG media-server YOURUSERNAME
sudo usermod -aG media-server www-data
sudo usermod -aG media-server qbtuser
sudo usermod -aG media-server ftp
sudo usermod -aG users YOURUSERNAME
sudo usermod -aG users YOUROTHERUSERS
sudo chown root:media-server /data
sudo chown -R YOURUSERNAME:media-server /data/jellyfin-data /data/downloads /data/incomplete /data/converted /data/scripts
sudo chown -R www-data:media-server /data/www
sudo setfacl -R -m g:media-server:rwx /data/jellyfin-data /data/downloads /data/incomplete /data/converted
sudo setfacl -R -d -m g:media-server:rwx /data/jellyfin-data /data/downloads /data/incomplete /data/converted
I found that the best way to give multiple users and groups access to folders was to use ACLs. Basic chown/chmod didn't quite cut it and I got hopelessly stuck with it after several days of messing with it.
With that out of the way we continue to configure the various services the server is going to offer. Each is optional, especially the Torrent client. But I find all of them useful.
Set up the sFTP server
sFTP can be used for reliable remote file management. You'll need a sFTP client like Cyberduck or Transmit to access it. Sometimes sending/downloading larger files will go more consistent compared to Samba shares.
Configure the sFTP server
See config file in zip-file -> /configurations/vsftpd/
Copy the file to /etc/vsftpd.conf (or write a new one based on it).
You can tune this file to your needs of-course. I just use this (mostly default) version which lets me browse and handle folders and files as needed. Which is all I want from sFTP.
Make vsftpd start on boot
sudo systemctl enable vsftpd
sudo systemctl start vsftpd
Avahi (mDNS/Zeroconf/Bonjour)
Avahi handles auto-discovery for mDNS. Mac users will know this service as Bonjour. Windows and Linux users may know this as Zeroconf or simply mDNS. This takes away the direct need for a local DNS resolver and allows you to use basic domain names on your network. The primary use-case here is to make Samba visible on the network.
Add services
See services file in zip-file ->/configurations/avahi/
Move all .service files to /etc/avahi/services with sFTP, or a generic location and move them with ssh/terminal later.
These enable auto-discovery services for Samba, the Webserver (Apache) and JellyFin.
The Samba service is the most important one. We rely on Avahi to promote Samba since Samba's own method (netbios/multicast) kinda sucks.
Make avahi start on boot
sudo systemctl enable avahi-daemon
sudo systemctl start avahi-daemon
Check it out
If you're curious what Avahi outputs to the network you can check what it does with this command.
avahi-browse -at
It should list all services, so you should see terms like; jellyfin and smb.
Samba
Samba handles filesharing between computers. Most notably, this mounts folders of the server as external drives on a MacOS, Linux and Windows computer. The purpose of Samba in this set up is to give access to the Downloads, Converted and Jellyfin folders. But you're of-course free to add more (or less) shares in smb.conf.
Add users
Add as many users as you need. These users need to exist as Ubuntu users also. So create those first.
sudo smbpasswd -a USERNAME
Configuring Samba
See configuration file in zip-file ->/configurations/samba/
Move the file to /etc/samba/smb.conf with sFTP, or a generic location and move it with ssh/terminal later.
This configuration is highly optimized for fast and reliable file transfers. It demands modern(ish) Operating Systems using the latest SMB3 protocol. Any computer of the last 10 years should be able to connect.
Test the configuration
Test the configuration. This'll warn about the socket options, since we override their defaults and auto-tuning.
testparm
sudo smbstatus
Make samba start on boot
sudo systemctl enable smbd
sudo systemctl start smbd
JellyFin
The actual media server. JellyFin comes from it's own repository. So to install it we need to get it from a different server then everything else.
Installing Jellyfin
From ~ (home) run the following.
curl -s https://repo.jellyfin.org/install-debuntu.sh -O
Then to install the package.
sudo bash install-debuntu.sh
Add the JellyFin user to groups
Jellyfin requires its own user, and that user needs access to certain folders and services. We gave the media-server group access already at the start, so adding Jellyfin to that is the easiest without breaking other users access. The render group is for video conversion and hardware acceleration.
sudo usermod -aG render jellyfin
sudo usermod -aG media-server jellyfin
Make jellyfin start on boot
sudo systemctl enable jellyfin
sudo systemctl start jellyfin
Continue in your web browser
That's the basic installation done. Now you can configure the server through the browser.
Visit: http://media.home.lan:8096 in a web browser and do the basic setup from there.
Set the main folder to /data/jellyfin-data.
JellyFin Configuration
We set up folders for certain things at the start. You can configure those in Jellyfin.
- In General, set cache path to
/data/jellyfin-data/cache - In General, Set metadata path to
/data/jellyfin-data/metadata - Set each Library path to be inside
/data/jellyfin-data(for example:/data/jellyfin-data/moviesand/data/jellyfin-data/tv-shows, we already created a few folders for this at the start.)
Check Intel hardware encoding
If you're using an Intel CPU/GPU you can probably use hardware encoding. This works very efficient versus CPU encoding.
ls -l /dev/dri
Look for 'renderD128'. If it's there, all good. Skip the next header.
If renderD128 is not there
If it's not enabled, set up the users and permissions first.
sudo groupadd render
sudo usermod -aG render,video jellyfin
sudo usermod -aG render,video YOURUSERNAME
sudo usermod -aG render,video www-data
Then continue with the setup
Now we look for the Hardware Video Acceleration.
sudo -u jellyfin vainfo
If there are no errors, skip the next header.
If it says "error: failed to initialize"
If vainfo gave you an error. Install the drivers so Hardware encoding will work.
echo "LIBVA_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri" | sudo tee -a /etc/environment
source /etc/environment
Enable hardware acceleration in Jellyfin
In Jellyfin (either via the Web GUI or the Jellyfin App), go to the admin dashboard. In the dashboard settings navigate to: Playback > Transcoding and select Intel Quicksync (QSV)
This depends a bit on the CPU, for my CPU I can use all codecs except:
- AV1
- HEVC RExt 8/10bit
- HEVC RExt 12bit
Newer CPUs might support more or other codecs. You can check this in the Intel documentation, or ask Google Gemini / Duck AI for what your CPU supports.
Add Jellyfin users
If you won't be the only JellyFin user, add the ones you need. Family, friends, neighbors. Whoever you trust with it.
For the few people that have access to my server I've disabled: Live TV, Downloads, Transcoding and set a limit on remote streaming (via internet).
But do whatever makes sense for you.
I've disabled transcoding because we'll set up conversion scripts to convert every video to a compatible format so that your server will never have to transcode anything. I believe that transcoding files over and over is a waste of energy and CPU cycles. Better to do it right the first time. If you throw your files in without conversion you may need to enable transcoding for your users though.
QBittorrent
You can source your video and audio files from the internet if you so desire. Qbittorrent is a decent, and very popular, client to do that. Torrenting is not always legal, keep that in mind.
Setup
Do the basic setup as qbtuser, and exit when done.
sudo su qbtuser
qbittorrent-nox
exit
The actual configuration is done through a web interface.
Make qbittorrent start on boot
sudo systemctl enable qbittorrent
sudo systemctl start qbittorrent
Continue in your web browser
With the basic setup done. You can configure qbittorrent through the browser.
Visit: http://media.home.lan:8080 in a browser and do the basic setup from there.
Qbittorrent Configuration
Don't forget, we set up folders for certain things at the start. You'll use those in Qbittorrent.
- Set download folder to
/data/downloads - Set incomplete folder to
/data/incomplete - Set log folder to
/data/scripts/log
Own the log
chown qbtuser:media-server /data/scripts/log/qbittorrent.log
chmod 664 /data/scripts/log/qbittorrent.log
This has Qbittorrent own the file, but the 'media-server' group can also see the file. Your user is in this group, letting you review the file if you need it.
Apache
And lastly we're setting up a simple webserver. This is so you'll have some basic monitoring scripts and a webpage to start file conversions from. This makes things more convenient and easy.
See configuration file in zip-file ->/configurations/apache/
Move the config file to /etc/apache2/sites-available/000-default.conf with sFTP, or a generic location and move it with ssh/terminal later.
This configuration file adds a vhost to apache (for your webpage) and looks for those files in /data/www/. It also sets the hostname to media.home.lan.
Add Apache modules
We'll need mod_rewrite and mod_cgi. These are like plugins (modules) for Apache. Everything else can be default.
sudo a2enmod rewrite cgi
Set up the website
See website files in zip-file ->/www/
Move the website files to /data/www/ with sFTP.
Once in place give the files the right permissions.
sudo chown YOURUSERNAME:www-data /data/www/*.*
sudo chown YOURUSERNAME:www-data /data/www/cgi-bin/*.sh
sudo chmod 0755 /data/www/cgi-bin/*.sh
Set up scripts
There are a couple of scripts that the webpages control, these convert audio and video files with ffmpeg to compatible formats.
See scripts in zip-file ->/scripts/
Copy all scripts to /data/scripts/ with sFTP.
Make them executable for the owner and group.
sudo chmod 0775 /data/scripts/*.sh
Make apache start on boot
sudo systemctl enable apache2
sudo systemctl start apache2
Done!
Reboot the system and it should all work once the system comes back online!
sudo reboot now
Usage
Jellyfin
Access Jellyfin through the webbrowser at http://media.home.lan:8096.
Or, of-course, through any of the JellyFin apps - I kinda like Swiftfin or just the default app. But any of them will do.
Samba
In MacOS the Samba server should be visible through auto-discovery in Finder, just look for the Network section in the sidebar. The server should be called Media Server.
To connect, click it and log in with any of the samba users you've created.
From Windows and Linux, the server should be easily found in its file manager. Or if not, add a network share and use smb://media.home.lan to connect to it. If you don't use a domain, smb://media.local or the IP Address should work. Log in as directed and mount shares as needed.
SSH & sFTP Server
Point your terminal to ssh USERNAME@media.home.lan. Follow the prompts and log in.
For file sharing, connect your sFTP client to media.home.lan:22 and follow the login prompts.
I mainly use sFTP to move files around with a GUI instead of ssh, so that new content can easily be added to JellyFin.
Webserver
In your webbrowser visit http://media.home.lan or http://media.local. This'll show a blue page with a few buttons on it. Each circular button acts as a shortcut to a function. From here you can connect to the Jellyfin web client and Qbittorrent, but also the converstion scripts. These pages embed shell scripts. The embedded script on the video and audio conversion page monitor the conversion script that will run in the background as needed.
If nothing is being converted but new files are detected in the /data/downloads/ folder it'll offer to convert them. Click the button and it starts doing so.
While converting files, the button is hidden and a elapsed time and remaining files counter is shown. This status updates every few seconds until the process is complete. Depending on what you're doing this can take minutes, or several hours.
The actual conversion scripts will look for compatible video files of any kind and try to convert them into standardized MKV files. For audio, it takes any compatible file and converts them to M4A files.
Simply throw any (common) type of video or audio file in the /data/downloads folder and the script will detect it.
I've created these shell/bash scripts myself and made the more complex parts work with suggestions from Google Gemini and Duck AI. This was a lot of trial and error, but I think they work pretty good now.
What the video conversion script does
- Detects source video and converts to h265 at a standardized bitrate if needed.
- Detects source audio and converts to 2 or 6 channel AAC audio if needed.
- Detects subtitles in english/undefined and embeds those in the files.
- Detects external subtitles in english/undefined and embeds those in files as well.
- Creates relevant metadata for video players to see/detect the various streams.
- Assumes hardware acceleration is available and tries to use it, the same renderD128 driver JellyFin uses.
- Converted files are logged in a 10000 file cycle (so repeat conversions are avoided).
- Converted files are stored in /data/converted
- Logs for each run are stored in /data/scripts/log as human readable files
What the audio conversion script does
- Detects source audio and converts to 2 or 6 channel AAC audio.
- Converted files are logged in a 10000 file cycle (so repeat conversions are avoided)
- Converted files are stored in /data/converted
- Logs for each run are stored in /data/scripts/log as human readable files
QBittorrent
You can access the torrent client through http://media.home.lan:8080. This UI lets you manage your torrent/magnet downloads.
Conclusion
And there you have it. A self serving handy machine you can hook up to your network and let any kind of device connect to it. Stream audio and video all over your house. Of-course you'll only stream your own home-videos - Right?
Have fun!