Creating a Synology repository for Plex

Yes, It’s possible to create a repo. I’ve been trying to figure out HOW it works.

If anyone can point me in a direction to setup a repo, I will make it happen.

It’s on my To-Do list for a LONG time.

I reached out to SynoCommunity without success.
Other things I’ve seen did not work.

A nearly-empty repo, showing directory structure, 2 different architecture files, and required info (XML ?) files is all I need. I’ll reverse engineer it as required.

Once done, it will update when Plex.tv/downloads updates. one less dependency on external workarounds.

2 Likes

I just was about suggesting that :smiley:

After some research I could find (as an example) a repository by FileBot over here: https://get.filebot.net/syno/. When you take a look on their repo, you get a simple JSON output. Could that be all what’s needed for a own repo?

Besides the auto update possibility are there any other benefits to using it in Docker?

That JSON looks great!

Only thing I need to resolve is arch since I’ll be distributing binary executables.

I need x86_64, armv7, arm7hf, armv7_neon, and armv8.

You could also setup a webserver, enable logging and trying to add it into the Synology. That way you might be able to figure out how requests (retrieving packages, download, etc) might look like.

Otherwise SynoCommunity is also reachable via HTTP, so you could easily proxy/sniff in between:

$ tcpdump -i ovs_bond0 -vv ip6 host [SYNO_IP]
[...]
23:43:04.173992 IP6 (flowlabel 0x4139e, hlim 64, next-header TCP (6) payload length: 375) xx > xx.http: Flags [P.], cksum 0x69f4 (incorrect -> 0xf73d), seq 1:356, ack 1, win 225, length 355: HTTP, length: 355
        POST / HTTP/1.1
        Host: packages.synocommunity.com
        User-Agent: synology_apollolake_918+ DSM6.2-24922 Update 5 (package)
        Accept: */*
        Content-Length: 149
        Content-Type: application/x-www-form-urlencoded

        package_update_channel=beta&unique=synology_apollolake_918%2B&build=24922&language=enu&major=6&micro=2&arch=apollolake&minor=2&timezone=Dublin&nano=5[!http]

Using that kind of information you can actually build a curl command to bypass the “400 - Bad Request” and get the JSON output from SynoCommunity:

$ curl --user-agent "synology_apollolake_918+ DSM6.2-24922 Update 5 (package)" -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "package_update_channel=beta&unique=synology_apollolake_918%2B&build=24922&language=enu&major=6&micro=2&arch=apollolake&minor=2&timezone=Dublin&nano=5[!http]" http://packages.synocommunity.com/ | jq
{
  "keyrings": [
    "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\n..."
  ],
  "packages": [
    {
      "conflictpkgs": null,
      "deppkgs": null,
      "desc": "sslh accepts HTTPS, SSH, OpenVPN, tinc and XMPP connections on the same port. This makes it possible to connect to any of these servers on port 443 (e.g. from inside a corporate firewall, which almost never block port 443) while still serving HTTPS on that port.",
      "dname": "sslh",
      "download_count": 0,
      "link": "http://packages.synocommunity.com/sslh/3/sslh.v3.f4458%5Bapollolake-avoton-braswell-broadwell-broadwellnk-bromolow-cedarview-denverton-grantley-kvmx64-x86-x86_64%5D.spk?arch=apollolake&build=24922",
      "maintainer": "SynoCommunity",
      "package": "sslh",
      "qinst": true,
      "qstart": true,
      "qupgrade": true,
      "recent_download_count": 0,
      "thumbnail": [
        "http://packages.synocommunity.com/sslh/3/icon_72.png",
        "http://packages.synocommunity.com/sslh/3/icon_256.png"
      ],
      "version": "1.19c-3"
    },
    {

There you might see that they are apparently building the package lists on-demand based on the request sent to their server - to deliver the correct package for the requested arch: notice the ?arch=apollolake&build=24922 at the end of the link.

Edit:
Based on that information I guess they handle it that way:

http://packages.synocommunity.com/$PACKAGE_NAME/$UPDATE_ID/$PACKAGE_NAME.$UPDATE_ID.f4458%5B$SUPPORTED_ARCH_SPLITTED_BY_DASH%5D.spk?arch=$SYNOLOGY_ARCH&build=$SYNOLOGY_BUILD"

Im setting up locally now on the development syno to see what happens.

I am not a web guy so this is a huge step forward

My Linux background is pretty limited to wget / curl thinking at this point.

puts on dunce and learning caps

Please help me learn here?

I have a personal web server enabled for my Syno username.

Is this a situation where the master JSON is served up then Package Center does a curl/wget to pull the package? If so, what does that master JSON look like?

DSM seems to request the package lists when you add a new “Package Source” via UI, and most likely in an fixed interval for update purposes. It’s trying to get the lists by simply querying the address specified in the Location field (that should be the address where the JSON should be delivered)

The “master”-JSON is the JSON output you can see in the above posts - e.g. the excerpt from me or from the filebot link. That appears containing all needed information to let DSM build up the list you see - and also process updates, etc.

So when you take above JSON and re-write it to your needs (even when statically) it should basically do the job for testing purposes.

is there any special trick to having the .htm serve up the json?

My limited knowledge is that HTML is just the file served index.html to the browser (or other http client) to read. In that I place the raw JSON doc?

@Patschi95

Broke the thread out over here in consideration for the OP

I might have to test that myself, might work with using location = / {} and try_files at nginx webserver.

But a friend just pointed me towards a GitHub repo from SynoCommunity: GitHub - SynoCommunity/spkrepo: Synology Package Repository. Apparently they wrote a python project to manage a Synology repo… Would have been way easier than reverse engineering parts of the magic :smiley:

Also just found: https://archive.synology.com/download/Package/spk/Plex%20Media%20Server/1.18.5.2309-f5213a238/. (No idea if that public directory listening is intended from Synology)

Agreed… provided it doesn’t require spksrc compliance (which is a pita in my position)

See? Regarding how Synology groups the files is exactly how they are grouped on Plex.tv/downloads.

I just need the connectors / glue so Package Center (client) can find the media. I suspect they are

/spk/Plex Media Server/1.18.5.2309-f5213a238
/spk/Package Name/MasterVersion/Package-aarch-version.spk
	   PlexMediaServer-armada37xx-1.18.5.2309-f5213a238.spk	

That trivially becomes

PlexMediaserver-${arch}-${ReleaseVersion}.spk

I only need get our Continuing Integration team to change from

PlexMediaServer-1.18.7.2457-77cb9455c-aarch64.spk

to the new form and it’s universal.

Might I ask why spkrepo doesn’t work out? (it’s not spksrc!) I can’t find a requirement for using packages built using spksrc - seems to also handle different arch’s just fine: https://spkrepo.readthedocs.io/en/latest/api.html#endpoints

What I see looking at it is that it creates a DB & populates it.

Plex’s pages are pure web-served. There is a very flat redirector.

If you know the Plex version and file hash code, you can go back and grab some seriously old Plex versions.

The company has two major facets.

The downloads page is managed by the marketing team.
Engineering runs Operations and Continuing Integration.

We drop files into their directory which they run a ‘canned’ web page on.

Please do tell me if I’m all wrong about this but keeping it as no-code as possible is the best.

No, indeed, valid point!

I’ve got a other idea… This time taking a look on the Synology repo of Syncthing.

$ curl --silent --user-agent "synology_apollolake_918+ DSM6.2-24922 Update 5 (package)" -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "package_update_channel=beta&unique=synology_apollolake_918%2B&build=24922&language=enu&major=6&micro=2&arch=apollolake&minor=2&timezone=Dublin&nano=5[!http]" https://synology.kastelo.net/ | jq
{
  "keyrings": [
    "-----BEGIN PGP PUBLIC KEY BLOCK-----..."
  ],
  "packages": [
    {
      "package": "syncthing.net",
      "dname": "Syncthing",
      "version": "1.4.0",
      "desc": "...",
      "arch": "x86 bromolow cedarview avoton braswell broadwell dockerx64 kvmx64 grantley denverton apollolake broadwellnk",
      "maintainer": "Syncthing Community",
[...]
      "link": "https://synology.kastelo.net/download/syncthing.net-x86_64-1.4.0.spk",
[...]

Apparently it’s possible to provide a arch key in the JSON output so that DSM can pick up the correct release itself. That’s indeed great to make a static files deployment possible. Basically a separate item for each arch, pointing towards a different spk file.

This should work out, doesn’t it?

That’s precisely where my mind was headed.

A software-generated file which contains static paths to serve up.
Nice and simple.

Yes?

Look at a normal SPK file.
In it is the INFO file.
In there is an arch line.

Now look at what you just pulled.

SPK is a tar file. In it is a targz which is the binary for /var/packages/Package/target

Yes, I like that idea as well. Should work out! :slight_smile:

Ah, right! Yes, just opened the file now.

For generating the JSON the different Plex-builds have to match the arch used for the Synology systems - somehow. Maybe that helps in some way: What kind of CPU does my Synology NAS have? - Synology Knowledge Center

Each Syno knows its $arch.
When I created the master INFO file for each arch, I put in all the Synology codenames for that architecture (e.g. bromolo avoton x86_64 aarch64)

I know that Package center will search my arch= line for its name. If it finds it, it continues installation. if not, it errors with the incompatible message.

Here’s the map I use:


  # info on which synology package arch has NEON extenstions comes from the following websites;
  # http://domoticx.com/synology-nas-cpu-lijst/
  # https://www.synology.com/en-global/knowledgebase/DSM/tutorial/General/What_kind_of_CPU_does_my_NAS_have
  arch_map = {
    "aarch64": "rtd1296 armada37xx",
    "armv7hf_neon": "armada375 armada38x alpine alpine4k monaco comcerto2k",
    "armv7hf": "armada370 armadaxp",
    "x86_64": "x86_64",
    "x86": "x86 evansport",
  }

This is how each each syno can validate back to the file downloaded.

We generate those 5 files and boom-- done.

1 Like