Unofficial
On this page
  1. 01What the film shows, what you need
  2. 02First-run setup
  3. 03Modules, builder, Go, Python and QDK
  4. 04New project
  5. 05The recipes
  6. 06Build and make qpkg
  7. 07The signature
  8. 08Test deploy and the first sign-in
  9. 09The arm_64 package
  10. 10Related guides

Build Transmission from scratch on your NAS

The film below is a real run of Bucket & Code Server IDE 1.0.0-55 on a NAS with nothing set up yet. It starts at the first-run screen and ends with the QTS package Transmission signed, installed and answering in the browser, and an arm_64 build of the same package downloaded. This guide goes through the film chapter by chapter: what the person does, what the screen shows and what the run checks.

Walkthrough · 6:26. Transmission from scratch, from the first-run setup to the arm_64 package Bucket & Code Server IDE 1.0.0-55 · x86_64 NAS
  1. Set upmodules, builder, runtimes
  2. ProjectPackage from source
  3. Recipesfive, the gate, the service
  4. Buildtwo apps, make qpkg
  5. Installsignature, Test deploy, arm_64

The pictures are frames of the run, from the panel and the editor; only the Overview’s tiles come from version 1.0.0-62. The NAS's address and name are masked in every frame and show as nas.local and NAS.

01What the film shows, what you need

The run took 25 min 7 s; the film lasts 6:26. It cuts the middle out of every wait longer than 10 seconds and marks the cut with the wait's real length, and it plays a stretch of more than 10 seconds without a click at four times the speed, marked 4×.

A script drives the browser: it clicks through the panel, types each file of the finished project into the editor and checks every step against the panel's API before it goes on. The panel, the editor, the build and the packages are the real ones. The finished project is the example Transmission (BitTorrent client, own recipes) under Editor projects on the Examples tab of the Apps page; View the code shows its files.

  • A NAS with Bucket & Code Server IDE 1.0.0-55 or later on an x86_64 processor. The arm_64 package is a cross build on that NAS.
  • An administrator account in the panel. On a new installation the first-run screen makes it.
  • Internet access for the NAS: it downloads the builder's root filesystem, the toolchains and the sources of the recipes, and checks each download against its sha256.
  • For the signed package, a code-signing certificate that QNAP issued to you (section 07).

02First-run setup

Film 0:00 · in the run 4 s

A new installation has no account, so the panel opens on one screen, Set the administrator password, for the account administrator. Type a password of at least 10 characters twice and press Set the password and sign in. The screen takes the password for 60 minutes after the package starts, and only from the local network.

The run checks that the panel has signed in as administrator and no longer asks for a first administrator.

03Modules, builder, Go, Python and QDK

Film 0:06 · in the run 59 s

The Overview page shows each module as a tile, and a new installation runs only the core. Turn on Git (Forgejo) and the Editor (VS Code in the browser) with their switches until both tiles say running. Every panel account has a Forgejo account of the same name, so the New project wizard now offers administrator as the owner of a repository.

The Overview of Bucket & Code Server IDE 1.0.0-62 on x86_64: the Git, SVN & Bucket and Editor tiles running

On the Toolchains page the list of environments is empty and offers the Ubuntu 24.04 builder with one button, Create this environment. The environment ubuntu2404-builder is there after 22 seconds. In the catalog below it, Install adds Go 1.27 and Python 3.13 (the Runtimes tab) and QNAP QDK 2.5.0 (the QNAP tab). Go builds the project's gate, Python runs the tool that writes the web interface's vendor list, and QDK packs the QTS packages.

Toolchains: the environment ubuntu2404-builder, and in the catalog QNAP QDK 2.5.0 (qbuild) marked installed

The run checks that Git and the Editor are running, that ubuntu2404-builder is in the list of environments and that go-1.27-x86_64, python-3.13-x86_64 and qdk-2.5.0-x86_64 are installed.

04New project

Film 0:52 · in the run 24 s

On the Projects page, New project asks for the template first. Choose Package from source and name the project Transmission; the name becomes the package's name. In the Service step choose Web app: a background service with its web port and App Center's Open button. The Build step asks for no environment: the ENV line of the project's Makefile gives both apps the Ubuntu 24.04 builder. Leave Build right after creating off, because the starter recipe still names a placeholder source and a first build would fail. Create project makes the Forgejo repository with its first commit.

New project, the Progress step: Package from source, Transmission; the Forgejo repository and first commit done; Open the project, Open in editor and Open in Forgejo

Open in editor opens the project in the editor. Its folder holds recipes/transmission/ (the starter recipe), recipes.txt, a Makefile for two apps, licenses.txt, qpkg/ and scripts/. The run checks that the project's pipeline lists the apps transmission and transmission-arm64 and that the Explorer shows recipes.

05The recipes

Film 1:18 · in the run 12 min 12 s

The library has no recipe for Transmission or its web interface, so the project carries five of its own in recipes/, a folder each with recipe.json and build.sh: those two and libnatpmp, miniupnpc and libdeflate, which the library also has; in the project's apps the project's copies take the place of the library's. curl, OpenSSL, zlib and libevent come from the library. Your first own recipe explains the two files.

The starter recipe · 14 s

recipes/transmission/recipe.json gets Transmission 4.1.3's release archive with its sha256, the recipes it needs (curl, OpenSSL, zlib, libevent, libnatpmp, miniupnpc and libdeflate), the static link and a check. build.sh runs CMake for the daemon and for transmission-remote, transmission-create, transmission-edit and transmission-show, with the tests, translations and documentation off.

Four more recipes · 1 min 17 s

In the Command Palette, Bucket: New recipe asks for a name and writes both files from the starter. The run makes libnatpmp 20230423, miniupnpc 2.3.3, libdeflate 1.26 and transmission-web 4.1.3 this way and fills in each one's source, sha256 and build steps. Transmission links the three libraries as static archives. The web interface is HTML, CSS and JavaScript, built from web/ of the same release archive.

The editor: the project's recipes folder with libdeflate, libnatpmp, miniupnpc, transmission and transmission-web, and the build.sh of transmission-web open

The vendor list · 1 min 7 s

esbuild and Sass build the web interface, and recipes/transmission-web/vendor.txt pins their npm packages, one line of sha256, address and destination each. The editor's terminal writes the file from the release's package-lock.json, and the tool reports 30 files: 30 checked against the lockfile's sha512. The finished file has 41 lines, 11 of them comments.

eval "$(bvs use python-3.13-x86_64)"
python3 /usr/bin/bucketvs/share/bucketvs/tools/npm-vendor.py package-lock.json CACHE-DIR \
  --dev --roots esbuild esbuild-sass-plugin fast-deep-equal \
  --platform linux-x64-glibc --platform linux-arm64-glibc --allow-install-scripts \
  > recipes/transmission-web/vendor.txt

build.sh holds the sha256 of the whole file, and the build checks each package again before it unpacks it. npm never runs, and no install script runs.

The list of recipes, the gate, the scripts, the licenses and the icons · 6 min 38 s

recipes.txt names what the two apps build: transmission, transmission-web and cacert, the CA bundle that curl checks HTTPS trackers against. The App Builder adds what each of them needs.

gate/ holds trgate, a Go program with no outside modules. Transmission's own defaults have no password and take RPC calls from the NAS only, and opened to the network without a password it would serve anyone who reaches port 9091. So the package starts transmission-daemon only once you have chosen a password: trgate holds the port with a setup page, writes the password in the salted form Transmission stores and then starts the daemon on the same port. The package generates no password, so none is written to a file or to System Logs.

scripts/make-qpkg.sh is the template's packer with three places filled in: KEEP, the paths the package takes from each app; own_programs, which builds trgate for each architecture; and own_licences, which adds the license texts licenses.txt cannot give. licenses.txt lists the license of every recipe the package carries, and LICENSE is the license of the project's own code. The run types these ten files in. The three icons in qpkg/icons/ go in with Upload... on that folder in the Explorer.

The service · 40 s

On the Project view, the Service and package card holds the blocks that write the package's start and stop script and the keys of qpkg.cfg. Starting from the Web app preset, the run arrives at nine blocks: the data folder Transmission on the volume; the account transmission in the group arr, which owns that folder (mode 700); the web port 9091; trgate as the account's daemon, with 40 seconds to stop; a wait for port 9091; a log line; and the status checks running and port_open. The Package tab sets the display name Transmission, version 4.1.3, web page path /transmission/web/, web port 9091 and 60 seconds for QTS to wait at start and at stop. Save shows the plan with each file's diff, and Commit commits it.

The Service and package card, Package tab: display name Transmission, version 4.1.3, web page path /transmission/web/, web port 9091, 60 seconds at start and at stop

The check · 30 s

Every save checks the project's recipes and lists the findings in the Problems view. The run waits for No problems have been detected in the workspace, and the project's report then lists five recipes and no error. make lint gives the same findings in the terminal.

Commit and push · 1 min 42 s

In Source Control the run stages all changes, commits them as Transmission from source and pushes. The project's remote is its Forgejo repository over HTTPS, so the editor asks for the account's name and password, which Forgejo shares with the panel. The run waits until nothing is uncommitted and nothing is ahead of the remote, then reads the three icons back from Forgejo and compares them byte for byte with the project's.

06Build and make qpkg

Film 5:13 · in the run 10 min 1 s

Build in the Project view runs the project's Makefile. It builds the two apps one after the other in the Ubuntu 24.04 builder, both static: transmission for this NAS's x86_64 processor and transmission-arm64 for aarch64, a cross build. Each app builds 13 recipes in dependency order: cacert, OpenSSL, zlib, nghttp2, zstd, c-ares, curl and libevent from the library, then libnatpmp, miniupnpc, libdeflate, transmission and transmission-web from the project. This took 8 min 1 s. The cross build's checks run only where qemu-user is registered; elsewhere the build records them as not run. The run checks that both apps' last builds are done and name the project Transmission.

The Project view after the build: Build done, and the Output panel with the lines the App Builder built transmission and the App Builder built transmission-arm64

The packages come from the editor's terminal, in the project's folder (2 min 0 s). Go has to be on the path, because make qpkg builds trgate for each architecture:

eval "$(bvs use go-1.27-x86_64)"
make qpkg

make qpkg packs the newest successful build of each app with QDK and writes Transmission_4.1.3_x86_64.qpkg and Transmission_4.1.3_arm_64.qpkg into build/qpkg/build/, about 30 MB each. A package holds Transmission's five programs, trgate, the web interface, the CA bundle, the BusyBox that the build adds to every package, and share/licenses/ with a NOTICE and the license texts of each component.

07The signature

Not in the film · in the run 3 s

This is the one step outside the panel. Test deploy installs only signed packages and never skips App Center's signature check, and the NAS of the run holds no code-signing files, so make qpkg built both packages unsigned. The run copies them to a computer that holds a code-signing certificate QNAP issued to the author of this guide, signs them there with QDK's qbuild, checks the signatures and copies the packages back to build/qpkg/build/. The certificate and its private key never go to the NAS. The Versions list then marks both packages as signed.

Versions: Transmission_4.1.3_arm_64.qpkg and Transmission_4.1.3_x86_64.qpkg, both marked signed

You sign with a certificate of your own. Put certificate and private_key, and ca_certs for the chain, beside qpkg/qpkg.cfg or in the folder QPKG_CERT_DIR names, and make qpkg signs the packages itself; the template's .gitignore keeps the files out of git. Without them the packages are unsigned and Test deploy refuses them. What a NAS does with an unsigned package is its owner's decision in App Center, and this guide does not recommend installing unsigned packages.

08Test deploy and the first sign-in

Film 5:53 · in the run 32 s

On the project's page, Test deploy (an admin's) installs the x86_64 package on this NAS with qpkg_cli, the way App Center installs a file, and the job waits until App Center confirms. The package stays installed until you remove it with Remove from this NAS or in App Center. The job took 18 s.

The Project view after Test deploy: 4.1.3 installed on this NAS, Transmission 4.1.3 installed, and the qpkg_cli lines in the Output panel

Open http://<NAS>:9091/, or press Open in App Center. The gate's page, Choose the web interface password, asks for a user name (admin unless you change it) and the password twice, at least 8 characters. Press Start Transmission. The page says Transmission is starting, then transmission-daemon takes the port and the browser asks for the user name and password you chose. The page takes them for 60 minutes after the package starts, from a computer on the NAS's own network, at the NAS's IP address or its own name.

Signed in, the browser shows Transmission's web interface with no transfers. The run checks that the page's title is Transmission Web Interface and that the RPC reports version 4.1.3 (838877323f).

09The arm_64 package

Film 6:20 · in the run 23 s

A right click on the arm_64 row of the Versions list opens its menu, and Download saves Transmission_4.1.3_arm_64.qpkg (30,290,058 bytes). The run compares the file's size with the list's.

An x86_64 NAS cannot run that package, so the run checks it under emulation. scripts/qemu-test.sh unpacks the download on a Linux computer where qemu-user is registered and runs it there. All 22 checks pass in 19 s:

  • the programs are static AArch64 executables, and BusyBox and transmission-daemon run;
  • the gate serves the setup page, transmission-daemon does not run before the password is set, and a POST without the page's header is refused (403);
  • after the setup the RPC answers, session-get reports version 4.1.3, a wrong password is refused (401), the web interface answers, and neither the output nor settings.json holds the password;
  • transmission-daemon fetches Debian's netinst .torrent over HTTPS, which needs the package's CA bundle, and the torrent is removed again;
  • a TERM to the gate ends transmission-daemon and the gate exits 0.

No ARM NAS ran the package in this run.

10Related guides

  • Your first own recipe goes through the starter recipe, the check and make qpkg with a small program, cmatrix.
  • A custom app from your own recipes builds an App Builder app that takes a project's recipes beside the library's.
  • Transmission in App Center is the published example. Its x86_64 package comes from an earlier run of the same script on 1.0.0-55; its SHA-256 is on that page.
  • The user guide of Bucket & Code Server IDE describes New project, the Project view, Toolchains, the App Builder and the code signing of a package.