[QPKG] sherpa: a mini-package-manager (CLI)


sherpa: a mini-package-manager for QNAP NAS

The world’s first multi-action CLI package-manager!

Package management via sherpa provides features like easy application backup, upgrading, service and daemon management, multi-threaded operation, self-checking and repair, and all operations may be automated via cron.

Important: this is a command-line package and service manager, it’s in beta status, and packages have been known to break due to auto-upgrades going wrong. If you would like-to (and are able-to) help by diagnosing and providing logs, and don’t mind things breaking from time-to-time, please use this package. If you’re looking for complete stability and want a “set-and-forget” solution, it won’t be found here just yet. Do not use sherpa in production environments, unless you’re comfortable with the CLI and debugging bash and Python scripts, and/or can afford for applications to be out-of-order for extended periods of time.

That said: the majority of development is now complete, and I’m currently working-on increasing stability during auto-package upgrades. So, sherpa will work beautifully on a fresh (or new) system, but can experience issues when individual application updates are released.

Click here for installable packages

Installation

  • SSH into your NAS, and install the QPKG manually at the command-prompt:
    curl -skL https://tinyurl.com/get-sherpa > /share/Public/sherpa.qpkg; sudo sh /share/Public/sherpa.qpkg;

Usage

  • At the command-prompt, run:
    sudo sherpa
    … and follow the help from there.

    If ‘sudo’ is unavailable in your version of QTS, SSH into your NAS as the ‘admin’ user instead, and run:
    sherpa

If you have suggestions, advice, comments or concerns, please either create a new issue, or you are most welcome to start a new discussion topic.

This project is a community effort, and was built with combined feedback from many members of the QNAP community forum. Thank you to everyone who has contributed. :nerd_face:

Checkout the wiki for more information: https://github.com/OneCDOnly/sherpa/wiki

7 Likes

Some unfortunate news for Readarr users: the developers have ceased working on it and the current fork (used by sherpa) has been archived: https://www.reddit.com/r/Readarr/comments/1llqji9/announcement_retirement_of_readarr

If anyone knows of a maintained fork, please advise and I’ll switch the Readarr QPKG to use it. If-not, the Readarr QPKG will continue to be available, but won’t be upgraded any further.

1 Like

More bad news: the developers for TorrServer are now compiling their binaries to require libc 2.34 which isn’t available for QTS. :disappointed:

So, as-of right-now, the TorrServer package can’t be run. Existing TorrServer users will find their installation broken when TorrServer next updates, and TorrServer will be removed from sherpa support on the next stable QPKG release.

There’s an older version available in the myQNAP repository: https://www.myqnap.org/product/torrserver/ if you’d like to continue using this application.

You may be able to transfer your existing configs across to it. Don’t install the myQNAP version until you’ve manually backed-up your configs though.

Your sherpa TorrServer should be manually uninstalled via your QTS App Center.

1 Like

Hi OneCD, hope you are well?

After the latest Sherpa update I’m getting the following error for SickGear.

Error
OverflowError('date value out of range')

Traceback
Traceback (most recent call last):
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/web.py", line 1848, in _execute result = await result ^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 796, in run yielded = self.gen.throw(exc) ^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1044, in get yield self.route_method(route, use_404=True)
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 783, in run value = future.result() ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 796, in run yielded = self.gen.throw(exc) ^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 350, in route_method result = yield self.async_call(method, filter_kwargs) # method(**filter_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 783, in run value = future.result() ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/sg_futures/py3.py", line 40, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 359, in async_call raise e
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 357, in async_call return function(**kw) ^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1148, in view_shows return Home(self.application, self.request).view_shows() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1758, in view_shows return t.respond() ^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/config/cache/cheetah/_share_CACHEDEV1_DATA__qpkg_OSickGear_repo_cache_gui_slick_interfaces_default_home_tmpl.py", line 441, in respond data_lastdate = VFN(VFN(VFFSL(SL,"SGDatetime",True),"convert_to_setting",False)(VFN(VFFSL(SL,"network_timezones",True),"parse_date_time",False)(VFFSL(SL,"cur_airs_last",True), VFFSL(SL,"cur_show_obj.airs",True), VFFSL(SL,"cur_show_obj.network",True))),"strftime",False)('%Y%m%d%H%M') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 231, in dst if self._isdst(dt): ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 294, in _isdst if self.is_ambiguous(dt): ^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 256, in is_ambiguous (naive_dst != self._naive_is_dst(dt - self._dst_saved))) ~~~^~~~~~~~~~~~~~~~~
OverflowError: date value out of range

Request Info
method: GET
uri: /view-shows/
version: HTTP/1.1
headers:
body: b''
remote_ip: xxxxxxxxxxxxxxx
protocol: http
host: xxxxxxxxxxxxxxxxxxx
host_name: xxxxxxxxxxxxxxxxxxx
files: {}
connection:
server_connection:
_start_time: 1758182428.793617
_finish_time: None
path: /view-shows/
query:
arguments: {}
query_arguments: {}
body_arguments: {}
_cookies:

I have tried restarting and reinstalling, but get the same error. Any ideas please?

Hi Shady, and welcome to the new forum. :slight_smile:

Can you please begin by running a check action?

sherpa check

sherpa check
sherpa v250822-stable
done: actions complete.

• Package actions started @ 10:20:15 AM, ended @ 10:20:41 AM, elapsed = 26 seconds

• These package actions completed OK:
install auxiliary PIP in 3 seconds
reactivate nzbToMedia QPKG in 1 second
reactivate OSickGear QPKG in 16 seconds
reactivate SABnzbd QPKG in 17 seconds

• These package actions were skipped (and why):
“sign” Entware QPKG in 1 second (already signed)
“sign” Par2 QPKG in 1 second (NAS arch incompatible)
“sign” Par2turbo QPKG in 1 second (already signed)
“sign” sherpa QPKG in 1 second (already signed)
“sign” SortMyQPKGs QPKG in 1 second (QTS version incompatible)
“sign” Unrar QPKG in 1 second (already signed)
“sign” nzbToMedia QPKG in 1 second (already signed)
“sign” SABnzbd QPKG in 1 second (already signed)
“sign” OSickGear QPKG in 1 second (already signed)
reactivate ClamAV QPKG in 1 second (not installed)

Looks good so-far. :+1:

Next thing: please run a clean action on SickGear:

/etc/init.d/sickgear.sh clean

… Then try starting it:

/etc/init.d/sickgear.sh start debug
[~] # /etc/init.d/sickgear.sh clean
> source: sickgear.sh, action: clean, time: Thu 18 Sep 2025 10:56:11 AM BST, load: 0.20 
- package: 250822, service: 250822, library: 250822
> QPKG enabled: true
> application auto-update: true
- active git branch: main
- daemon PID: 11350
> stop daemon PID 11350 with SIGTERM (no-more than 120 seconds): 1, 2, OK
- daemon PID: none
> clean local repository: OK
> clean virtual Python environment: OK
> clean PyPI cache: OK
> clean temp path: OK
- file exists: /opt/bin/git
> create 'OSickGear' from remote repository: OK
- active git branch: main
> create new virtual Python environment: OK
> create QPKG 'pip' config: OK
> add location '/share/CACHEDEV1_DATA/.qpkg/OSickGear/pip-cache' as 'pip' cache: OK
> add location '/share/CACHEDEV1_DATA/.qpkg/OSickGear/qpkg-wheels' to 'pip' search path: OK
> exclude problematic PyPI modules from pip-requirements.txt: OK
> exclude problematic PyPI modules from pip-recommended.txt: OK
> install PyPI modules from pip-requirements.txt: OK
> install PyPI modules from pip-recommended.txt: OK
> load ports from configuration file: OK
> start daemon: OK
> watch for daemon process name to appear (no-more than 120 seconds): 1, OK
> wait 10 seconds to confirm PID is still alive: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, done
- daemon PID: 8916
- daemon listening address: 0.0.0.0
> HTTPS port enabled: false
- HTTP port: 7181
> test for port 7181 response (no-more than 120 seconds): OK
> update QPKG icon with UI ports: OK
= source: sickgear.sh, action: clean, time: Thu 18 Sep 2025 10:56:36 AM BST, result: OK, elapsed: 0h:00m:26s, load: 0.45 
[~] # /etc/init.d/sickgear.sh start debug
> source: sickgear.sh, action: start, time: Thu 18 Sep 2025 10:56:56 AM BST, load: 0.32 
- package: 250822, service: 250822, library: 250822
> QPKG enabled: true
> application auto-update: true
- active git branch: main
- daemon PID: 8916
= source: sickgear.sh, action: start, time: Thu 18 Sep 2025 10:56:56 AM BST, result: OK, elapsed: 23ms, load: 0.32 

Done that. Still shows the error

Clean looks good, and start too (in fact, looks like the SickGear daemon was already running). :+1:

Where do you see that error?

http://xxxxxxxxxxxxx:7181/view-shows

I login in ok, then it errors when facing the show page.

Have you force-refreshed your web browser page? CTRL-F5.

Yep, still no joy

Hmm, I’m wondering if an invalid value has been written into the SickGear database?

For testing purposes, let’s try starting SickGear with a fresh database. We’ll backup your existing database first, and restore it afterward. This isn’t a fix - just a test.

To backup your current database files:

/etc/init.d/sickgear.sh backup

… then reset the SickGear config to its defaults:

/etc/init.d/sickgear.sh reset-config

Now, try accessing your SickGear webpage again. Your TV shows list will be empty. Are there any errors shown?

After you’ve tried this, restore your SickGear database files with:

/etc/init.d/sickgear.sh restore

SickGear will be stopped and started as-required automatically. No-need to post any output this time.

An important notice for all Medusa users.

Tried those mate and no joy. Still the same error msg

To confirm: you tried accessing the SickGear webpage after resetting your config and before restoring it? And saw the same error?

This problem may need the assistance of the SickGear developers: [How to] Report Issues · SickGear/SickGear Wiki · GitHub

There’s also an “official” SickGear package available, might be worth trying? Install SickGear 05 QNAP · SickGear/SickGear Wiki · GitHub

Ok I cheated. I used Claude to decode the error :slight_smile:

SickGear Date Overflow Error - Issue Summary & Fix

The Problem:

SickGear was throwing an OverflowError('date value out of range') when trying to load the view-shows page. The error occurred during timezone calculations when processing show air dates.

Root Cause:

The SickGear database contained timestamps from 1970 (around January 9, 1970) instead of proper recent dates:

  • Shows: last_update_indexer values around 739435 (translating to 1970-01-09)
  • Episodes: airdate values around 738153-738181 (also from 1970)

These extremely old dates caused Python’s dateutil timezone calculation functions to fail when trying to process daylight saving time transitions and timezone conversions.

The Fix:

Two SQL UPDATE commands to correct the problematic timestamps:

sql

-- Fix show update timestamps (set to current time)
UPDATE tv_shows SET last_update_indexer = strftime('%s', 'now') WHERE last_update_indexer < 946684800;

-- Fix episode air dates (set to NULL/unknown)
UPDATE tv_episodes SET airdate = NULL WHERE airdate > 0 AND airdate < 946684800;

Resolution Steps:

  1. Stopped the SickGear service (PID 31531)
  2. Backed up the database (sickbeard.db)
  3. Applied the SQL fixes to update problematic dates
  4. Restarted SickGear using /share/CACHEDEV1_DATA/.qpkg/OSickGear/sickgear.sh start

This fix resolves the overflow error by ensuring all dates in the database are within the valid range for modern timezone calculations, allowing SickGear’s web interface to function properly again.

Oh nice! :+1:

And did this actually fix the issue?

Yes, works great. As a non-coder, being able to get Claude to find the issue, write the code and tell me how to fix it, really is very clever.

Amazing!

Still, would be worth letting the developers know of this issue, and the fix. It might help prevent this happening again.