Skip to content

Skerry Sync: new service - #359

Closed
IFindMe wants to merge 0 commit into
tailscale-dev:mainfrom
IFindMe:main
Closed

IFindMe wants to merge 0 commit into
tailscale-dev:mainfrom
IFindMe:main

Conversation

@IFindMe

@IFindMe IFindMe commented Oct 3, 2026

Copy link
Copy Markdown

Adds services/skerry-sync/ from templates/service-template:

  • secherkasov/skerry-sync:latest, internal port 8080, Tailnet-only (Serve proxies https://<host>.<tailnet>.ts.net to http://127.0.0.1:8080).
  • SQLite default (./skerry-sync-data/data:/data, image runs as 999:999); PostgreSQL intentionally not wired in.
  • SKERRY_JWT_SECRET required with placeholder safe value; SKERRY_ADMIN_TOKEN empty closes /console and /admin/*.
  • App healthcheck not overridden: image defines HEALTHCHECK (wget -qO- http://localhost:8080/healthz).
  • Service README documents secrets setup, 999:999 pre-create, Tailnet URLs (/, /account, /console), and TLS-via-Serve.
  • Root README.md: Skerry Sync row under Productivity and Collaboration (alphabetized).

Related Issues

  • None.

Verification

  • docker compose config --quiet in services/skerry-sync: PASS.
  • git diff --check: PASS.
  • rumdl check --config .markdownlint.yml README.md services/skerry-sync/README.md: not run, rumdl not installed.
  • Live stack start + Tailnet reachability (/, /account, /console, app register/sync, persistence): not run, needs TS_AUTHKEY and Tailnet access.

Checklist

  • I have performed a self-review of my code and followed the templates structure.
  • I have added verification that the stack works as expected.
  • I have updated necessary documentation (e.g. frontpage README.md ).
  • I have selected the correct label(s) for this PR.

Additional Context

  • Upstream treats trusted-LAN cleartext as acceptable (E2E-encrypted payload), but requires a TLS terminator off-host; here Tailscale Serve provides that HTTPS layer.
  • Upstream refs: server README, guide, image.
  • Note: pushed commit c9541bd is currently on main of the fork; open the PR from that branch.

@jackspiering

Copy link
Copy Markdown
Collaborator

Thanks for the contribution, and for the detailed README work on Skerry Sync. I tested Skerry Sync and Termix on a live Tailnet. Both start healthy and are reachable through Serve, so the substance is good. Several things need to change before merge. The template changed after you branched (#372, #373, #380), so a rebase will pull in most of the structural updates.

Scope and branch

  • The PR holds four services and a script, but it's titled for one. Please open one PR per service, each from its own branch (not your fork's main), and title each as Service: what changes, per CONTRIBUTING.md.
  • Please drop util/cert-export.sh from these PRs. It writes private keys into the current directory. If you want it in the repo, open a separate PR or issue to discuss it first.
  • Please rebase on current main. The PR conflicts today, and the root README.md rows changed in Docs: rework the README and fix the service tables #373 and Docs: remove emojis and tighten the README #380 (no emojis, new table layout). Insert your row alphabetically by bold name, ignoring case.
  • The commits are authored as Your Name <you@example.com>. Please set your git identity.

Skerry Sync

  • Blocking: .env sets SKERRY_JWT_SECRET="REPLACE_WITH_STABLE_SECRET". The server starts with that placeholder (I confirmed this), so anyone who doesn't edit it runs on a secret that is public in the repo, and the :? check never fires. Leave it empty, add a # Required: comment above it (for example # Required: signs the sessions. Generate it with: openssl rand -base64 48), and keep ${SKERRY_JWT_SECRET:?Set SKERRY_JWT_SECRET in .env} in compose.yaml. See CONTRIBUTING.md step 2. The same goes for the commented SKERRY_DB_PASSWORD and POSTGRES_PASSWORD placeholders.
  • Data folder ownership: without a pre-created folder owned by 999:999, the app crash-loops with SQLITE_CANTOPEN. I reproduced it. Please move that step into "Before you start" and keep the fix under the optional "Troubleshooting" section.
  • README structure: please use the template headings in order: At a glance, Before you start, Deviations from the standard setup, First run, optional sections, Links. "Configuration Overview", "Prerequisites", "Volumes", "Tailnet access", "Ports", "Service-specific notes" and "Files to check" are not template headings. The optional PostgreSQL block is a deviation: list it there.
  • .env and compose cleanup: remove #version=1.1, put the TZ comment on its own line, and update the opening comment in compose.yaml to match the current template (it now says "unless it has a default such as ${VAR:-value}").
  • Description: it says PostgreSQL is "intentionally not wired in", but the second commit adds an optional block. Please make the two agree. The checklist items for validation and rumdl are also unchecked.
  • What worked: the image health check (wget on /healthz) passes inside the container, Serve works, /console and /admin/* stay closed without a token, and the database survives a recreate. I couldn't test account registration, because it needs the Skerry client.

Termix

  • README: same template restructure as above. The mkdir and chown step is unnecessary, since the image's entrypoint chowns /app/data itself.
  • .env: the commented DATABASE_URL has quotes inside the URL. Please check that the example works as written.
  • PORT: it's in .env and is also hard-coded in the Serve JSON, which is correct. Say in a comment that the two must match, or drop PORT since the image defaults to 8080.
  • Image path: upstream's compose file uses ghcr.io/termix-ssh/termix:latest. Please confirm which path is canonical.
  • What worked: healthy containers, Serve returns 200, the first account becomes admin, and login works again after a recreate.

Nextcloud and Matrix (not run; please fix and open as separate PRs)

  • Both: neither has a README or a row in the root README.md; their .env and compose.yaml files have trailing whitespace (git diff --check fails); ${SERVICE} appears inside comments, so write "the service".
  • Nextcloud:
    • TS_AUTHKEY= # ... and TAILNET_NAME= # ... set the variables to the comment text, which also breaks OVERWRITECLI_URL. Put comments on their own line.
    • MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD and NEXTCLOUD_ADMIN_PASSWORD are empty with no :? and no # Required: comment.
    • redis:alpine and mariadb:lts need a major or major.minor pin.
    • The commented ports line hard-codes 8085, dns: and TS_ACCEPT_DNS=true are enabled, and the application health check isn't commented per template step 5.
  • Matrix:
    • AllowFunnel is true, which exposes it to the public internet. The standard setup is Tailnet-only, so either turn it off or document it as a deviation with the reason.
    • The Serve Static handlers point to /config/well-known-matrix-*.json, and nothing creates those files.
    • The database container is named db-${SERVICE} instead of app-${SERVICE}-<role>, its data folder is nested inside Synapse's ./${SERVICE}-data mount, and Synapse is never configured to use it. Document the homeserver.yaml setup.
    • POSTGRES_PASSWORD has no :?.
    • Check latest for Synapse and postgres:16-alpine against the upstream recommendation.

Happy to re-test once the split PRs are up.

@jackspiering jackspiering added the new service request to add a new service label Oct 13, 2026
@IFindMe IFindMe closed this Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new service request to add a new service

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants