Packaging
Build binaries first, then package.
Prerequisites
- dub + one of three first-class D compilers: LDC (
ldc2), DMD (dmd), GDC (gdc) - Set
COMPILER=ldc2|dmd|gdcto choose;install.sh/ PKGBUILDs /migrate-db.shauto-pick the first available if unset - Ubuntu
.deb:dpkg-deb(dpkg-dev) - CachyOS/Arch:
makepkg(base-devel) - Fedora/RHEL
.rpm:podman(rpmbuild runs inside a Fedora container) - openSUSE
.rpm:podman(rpmbuild runs inside an openSUSE container)
Local install (no package)
COMPILER="${COMPILER:-ldc2}" # ldc2 | dmd | gdc
dub build --compiler="$COMPILER"
(cd cli && dub build --compiler="$COMPILER")
(cd admin && rm -rf node_modules && npm ci && npm run build) # Vue admin → admin/dist
sudo ./packaging/install-server.sh
# client install.sh rebuilds with $COMPILER (default ldc2)
COMPILER="$COMPILER" sudo -E ./client/packaging/install.sh
Ubuntu .deb
COMPILER="${COMPILER:-ldc2}"
dub build --compiler="$COMPILER" --build=release
(cd cli && dub build --compiler="$COMPILER" --build=release)
(cd admin && rm -rf node_modules && npm ci && npm run build)
./scripts/packaging/build-deb-server.sh
(cd client && dub build --compiler="$COMPILER" --build=release)
./scripts/packaging/build-deb-client.sh
# → dist/lindir-server_*.deb dist/lindir-client_*.deb
sudo dpkg -i dist/lindir-server_*.deb
CachyOS / Arch
Fast path (from source tree) — preferred while developing:
paru -S libnss-extrausers # AUR; required for password login
sudo ./client/packaging/install.sh # from repo root: rebuilds + installs
sudo lindir-client enroll --url URL --token TOKEN --skip-vpn
sudo lindir-client sync
getent passwd alice
install.sh places /usr/bin/lindir-client, /usr/lib/lindir/configure-login.sh, and enables lindir-sync.timer. Root enroll runs configure-login; if already enrolled: sudo lindir-client configure-login.
PKGBUILD path (packaged install):
paru -S libnss-extrausers
# makedepends list ldc by default; dmd or gcc-gdc also work (COMPILER=dmd|gdc)
cd packaging/cachyos && makepkg -si
cd ../../client/packaging/cachyos && makepkg -si
PKGBUILDs build from the repository checkout (two/three levels up from the PKGBUILD). They pick COMPILER if set, otherwise the first available of ldc2 / dmd / gdc. The client PKGBUILD depends on libnss-extrausers.
Fedora / RHEL (.rpm via Podman)
Binaries are compiled on the host; rpmbuild runs in a Fedora container so you do not need rpm-build on Arch/Ubuntu. Host COMPILER (default ldc2) is passed through:
COMPILER="${COMPILER:-ldc2}"
dub build --compiler="$COMPILER" --build=release
(cd cli && dub build --compiler="$COMPILER" --build=release)
./scripts/packaging/build-rpm-server.sh
# → dist/lindir-server-*.rpm
(cd client && dub build --compiler="$COMPILER" --build=release)
./scripts/packaging/build-rpm-client.sh
# → dist/lindir-client-*.rpm
Specs and units: packaging/fedora/, client/packaging/fedora/.
Note: an RPM built on the host glibc may not run on older RHEL/Rocky; for matching glibc, build the client inside an image that matches the target distribution.
Server unit and the database
Packaged lindir-server.service files use After=… postgresql.service mysql.service … so the server orders after common database units when they are on the same machine. They do not use Requires= / BindsTo=. If PostgreSQL or MySQL is stopped or fails to start, lindir-server can still come up and then serve empty or broken Admin/OIDC responses (for example a hung or blank login). On production hosts, add a drop-in:
# /etc/systemd/system/lindir-server.service.d/db.conf
[Unit]
Requires=postgresql.service
# or: Requires=mariadb.service / mysqld.service
Then systemctl daemon-reload && systemctl restart lindir-server. Remote databases need monitoring and startup ordering outside this unit instead.
openSUSE (.rpm via Podman)
COMPILER="${COMPILER:-ldc2}"
(cd client && dub build --compiler="$COMPILER" --build=release)
./scripts/packaging/build-rpm-client-opensuse.sh
# → dist/lindir-client-*.rpm
Spec: client/packaging/opensuse/.
