20 Commits
Author SHA1 Message Date
Maksim ShulgaandMaxim Shulga 28db575c92 Add a health check for the daemon and RPC endpoint (#34)
* Add a health check for the daemon and RPC endpoint

SeafileClient.is_healthy() checks seaf-cli status and makes a real RPC
call (get_repo_list) against the daemon's Unix socket - neither needs
the Seafile server, so it works without a token or password.

healthcheck.py exposes it as a plain script for Docker's HEALTHCHECK.
Each check is a fresh process spawned by the Docker daemon as root,
unlike the long-lived start.py process, so it drops to the seafile
user with runuser before touching the RPC socket - the one place that
mechanism still belongs after the earlier in-process privilege drop.

Verified against the real image: healthcheck.py exits 0 once the real
daemon is up (through the actual main() entrypoint, not a test
fixture) and nonzero when no daemon has been started.

* Assert the return value in the daemon-down health check test

Copilot review: the test checked the RPC call was skipped but not
what is_healthy() actually returned in that case.

---------

Co-authored-by: Maxim Shulga <maxim.shulga@alludo.com>
2026-08-03 18:38:19 +00:00
Maksim ShulgaandMaxim Shulga c2a634c13f Scan the built image for vulnerabilities and fix what's fixable (#29)
* Scan the built image for vulnerabilities and fix what's fixable

Ran trivy against the built image locally: 67 HIGH/CRITICAL findings,
65 of them in debian:bookworm-slim packages with no upstream fix yet.
The remaining 2 were both setuptools 66.1.1 (CVE-2024-6345,
CVE-2025-47273) — bundled by ensurepip when the venv is created, not
pinned by requirements.txt, so nothing was upgrading it.

- Upgrade setuptools to >=78.1.1 in the Dockerfile, which fixes both
  CVEs. Verified with a local rebuild + rescan: 0 HIGH/CRITICAL
  fixable findings remain.
- Add a Trivy scan step to the CI `test` job, after the smoke test.
  Uses --ignore-unfixed so the build fails only on findings this repo
  can act on, not on upstream Debian CVEs with no available patch.
- Check off the corresponding P0 item in IMPROVEMENTS.md; note that
  scheduled (as opposed to PR/push-triggered) scanning is still open.

* Fix trivy-action tag (needs v prefix)

* Tighten scan-coverage wording per review

Copilot review on PR #29 flagged "every pull request and push" as
ambiguous: the test job's push trigger is scoped to master and tags,
not every branch. Spell that out.

---------

Co-authored-by: Maxim Shulga <maxim.shulga@alludo.com>
2026-08-03 05:16:42 +00:00
Maxim Shulga 84519cf7cc Run a container smoke test against the real seafile daemon
Startup, shutdown and secret handling were only ever checked by hand, and the
unit tests cannot check them: they stub seaf-cli, so nothing exercised the
daemon that actually ships. The GitHub runner is x86_64, which matches the
AppImage, so the image build job can run the real thing.

tests/smoke.sh starts and stops the real daemon, sends SIGTERM through docker
stop and asserts the container exits 0 within the grace period with the daemon
shut down, checks that a configuration error exits 2 naming the variable, that
a secret mounted under /run/secrets is read and stays out of the environment,
and that a default container gets exactly the documented defaults.

The pinned client version is exposed as SEAFILE_CLI_VERSION in the image,
since seaf-cli has no --version flag and there is no package manager entry
for an AppImage.
2026-08-02 19:37:26 -07:00
Maxim Shulga b75863ba51 Read the local library list as JSON instead of splitting columns
get_local_libraries unpacked "line.rsplit(maxsplit=3)" into three names, but
maxsplit=3 yields up to four fields. seaf-cli prints "name id path" separated
by whitespace, so any library whose name contains a space produced a fourth
field and raised ValueError, which nothing caught.

The failure only appeared after the first run: the list is empty until a
library has been synced, so a container would work when it was set up and then
crash on every restart.

seaf-cli list --json returns name, id and path as structured fields, which
display output cannot represent unambiguously for names or paths containing
whitespace. Its exit code is now checked and unreadable output is reported as
a daemon error instead of a traceback.

The image smoke check asserts that the installed seaf-cli offers --json and
--token, so a future version bump that drops either fails the build rather
than the container.
2026-08-02 17:29:51 -07:00
Maxim Shulga c558caba5b Keep the working directory off the CLI wrapper's search paths
Neither LD_LIBRARY_PATH nor PYTHONPATH is set in the base image, so
appending them unconditionally left a trailing ':'. An empty entry in a
colon-separated search path means the working directory, and Python
resolved it to /dsc on sys.path. Append the separator only when the
variable is already non-empty.

Reported by the automated review on #11.
2026-08-02 15:55:55 -07:00
Maxim Shulga 523a0955c4 Install Seafile CLI from AppImage instead of the APT repository
Seafile discontinued linux-clients.seafile.com: it resolves but accepts
no connections on 80 or 443, and the official docs no longer mention APT
at all. Every `docker build` has failed since. Upstream now ships the CLI
as an AppImage, so install 9.0.19 from the download site.

The AppImage is unpacked rather than executed. Running one needs FUSE and
so a privileged container, and its self-extraction also fails when the
build host cannot execute the payload's architecture. Unpacking the
appended squashfs directly avoids both.

Also add the bundled seafile/pysearpc bindings to the venv path. The APT
package installed them system-wide, where `venv --system-site-packages`
picked them up; dsc imports seafile directly for RPC, not only through
seaf-cli, so it broke when that implicit dependency went away.

Drops apt-key, pins the version, and verifies a SHA256 before unpacking.
Build-time smoke checks assert the seaf-cli subcommands and the app's own
imports.

Note: the AppImage is x86_64-only, and upstream publishes no digest or
signature, so the pinned checksum is trust-on-first-use.
2026-08-02 15:39:29 -07:00
snegov a7f351a75f Use RPC to fetch sync status 2023-10-24 22:12:02 -07:00
snegov 7f39e0f271 Initialize seafile client during container start 2023-09-16 01:27:46 -07:00
snegov 9f6c417147 Use debian as base docker image 2023-09-15 20:00:04 -07:00
snegov 724166b4a4 Support library names in configuration 2022-01-30 18:27:37 +03:00
snegov 310eb9028c Save seafile-data info in volume 2021-02-28 23:27:26 +03:00
snegov 6eadca4041 Update seafile repo URL 2021-01-30 22:59:09 +03:00
snegov 6048280983 Update installation process in Dockerfile 2020-08-25 21:30:44 +03:00
snegov e4e60c1023 Add cleanup after package install in Dockerfile 2020-06-04 21:16:58 +03:00
snegov 280979f88a Fix import error
Forgot to add local python libraries to the image.
2019-12-06 11:42:20 +03:00
snegov 4b70e9ab17 Update seafile repository to debian10 2019-08-14 12:14:50 +03:00
snegov 40827f413f rewrite start script in python 2019-04-14 12:34:20 +03:00
Ludovic Frank 9b4ed710f4 Updated Debian Version 2019-01-17 20:12:42 +01:00
Robin Grönberg 4fe9373d23 Updated so that volumes can be properly linked and still synced. 2018-04-18 20:45:25 +02:00
Robin Grönberg c85ee014f8 Added docker files. 2018-04-18 18:34:17 +02:00