Skip to content

Repository files navigation

DeckShare Logo

DeckShare on StartOS

Everything not listed in this document should behave the same as upstream DeckShare. If a feature, setting, or behavior is not mentioned here, the upstream documentation is accurate and fully applicable — see the Documentation section of instructions.md for links.

DeckShare is a self-hostable, multiuser, Anki-compatible spaced-repetition server. Upstream ships no prebuilt image and no built-in migration runner or admin bootstrap — this package builds the binary from source, adds a PostgreSQL sidecar, and runs schema migrations automatically on every start.


Table of Contents


Image and Container Runtime

Two images, built for x86_64 and aarch64.

  • deckshare — built by this package's own root Dockerfile, not upstream's. Upstream's Dockerfile (in the upstream-project/ git submodule, pinned per UPDATING.md) compiles only the deckshare binary into a shell-less distroless final stage. This package's Dockerfile instead compiles deckshare and goose (the migration tool upstream's own CI installs separately, per .github/workflows/ci.yml in the submodule) into a debian:bookworm-slim final stage, and copies in the submodule's migrations/ directory at /migrations. Entrypoint is /usr/local/bin/deckshare; goose lives at /usr/local/bin/goose.
  • postgres — the stock postgres image, unmodified.

Subcontainers, all defined in startos/main.ts:

  • postgres-sub (image postgres) — runs the postgres daemon.
  • deckshare-sub (image deckshare) — runs both the migrate oneshot and the deckshare daemon; the subcontainer is shared between them since they use the same image.

Volume and Data Layout

One volume, main, with three subpaths:

  • main/postgresql → mounted at /var/lib/postgresql in postgres-sub — the PostgreSQL data directory.
  • main/media → mounted at /data/media in deckshare-sub — DeckShare's content-addressed media blob store (MEDIA_ROOT), holding imported note/card media (images, audio) referenced by the database.
  • main/store.json — this package's own file, not upstream's. Holds the generated PostgreSQL password.

There is no embedded database — the data of record lives in PostgreSQL, in the volume above.

File Models

  • store.json (startos/fileModels/store.json.ts) — JSON, holds one key:
    • pgPassword — generated once on install (startos/init/seedFiles.ts), never re-asserted afterward. There is no action to rotate it; recovering from a suspected leak means restoring the volume or reinstalling.

DeckShare itself owns no configuration file on disk — its only inputs are the four environment variables set in startos/main.ts (DATABASE_URL, MEDIA_ROOT, ADDR, ORIGIN), all re-asserted on every daemon start. ORIGIN is read fresh from the service's own interfaces each start (utils.ts's getNonLocalUrls, via sdk.host.getOwn) rather than stored — every non-local address the service is currently reachable at (LAN IP, .local, a configured domain, Tor, ...), comma-separated. Upstream v0.1.26 added support for a comma-separated ORIGIN (Jolls/deckshare#111/#112) specifically so a CSRF check doesn't have to pick one address; before that fix this package made the user choose a single primary URL via a now-removed Set Primary URL action, since every other address would 403 on state-changing requests.

Dependencies

None. PostgreSQL runs as a bundled sidecar (postgres-sub), not a StartOS dependency.

Network Access and Interfaces

One interface, ui (startos/interfaces.ts), type ui, protocol http, bound to port 3000 (DeckShare's fixed listen port — ADDR is hardcoded to :3000 in startos/main.ts, not user-configurable). Serves both the web reviewer and any HTML admin/classroom views DeckShare adds. PostgreSQL is not exposed on any interface; deckshare-sub reaches it at 127.0.0.1:5432.

Installation and First-Run Flow

On install, startos/init/seedFiles.ts generates the PostgreSQL password. startos/main.ts then starts postgres, waits for pg_isready, runs the migrate oneshot (goose ... up against /migrations — idempotent, safe on every start), and only then starts the deckshare daemon. There is no separate setup wizard: the first usable state is DeckShare's own signup screen. DeckShare has no built-in admin/superuser concept — every account is created the same way, through that screen.

Actions

None.

Tasks

None.

Health Checks

  • postgres (internal, not shown to the user) — pg_isready against 127.0.0.1:5432. A failure here blocks the migrate oneshot and, transitively, the deckshare daemon from starting; it means PostgreSQL itself hasn't finished initializing yet, not a data problem.
  • deckshare / Web InterfacecheckPortListening on port 3000. "Not ready" during normal startup means the migrate oneshot (which blocks this daemon via requires) is still running or PostgreSQL is still coming up; persistent failure after that means the deckshare process itself crashed — check its logs.

Backups and Restore

Strategy: whole-volume copy (sdk.Backups.ofVolumes('main')), not a database dump. The PostgreSQL data directory, the media blob store, and store.json are all backed up and restored byte-for-byte together, so a restore comes back with the exact same generated password it had at backup time — nothing to re-enter. Because the volume is copied rather than dumped, a restored instance needs no re-sync or replay step before it's usable; postgres simply starts against its already-populated data directory. ORIGIN is recomputed fresh from the restored instance's own addresses on first start, not restored from the backup.

Limitations and Differences

  1. No admin-password or superuser bootstrap: every account, including the first, is created through DeckShare's own signup screen. If you intend to gate signups, do so at the network level (e.g. disable public interfaces) — DeckShare has no built-in registration toggle as of this packaging.
  2. PostgreSQL is not reachable from outside the package — there is no interface for it, and no action exposes its credentials. This differs from services (e.g. Arx) that expose their database for an external client to connect to.

Quick Reference for AI Consumers

package_id: 'deckshare'
image: local-build # custom Dockerfile, no public registry tag
architectures: [x86_64, aarch64]
subcontainers: [postgres-sub, deckshare-sub]
volumes:
  main: /var/lib/postgresql, /data/media, /store.json
file_models:
  - store.json
startos_managed_env_vars:
  - DATABASE_URL
  - MEDIA_ROOT
  - ADDR
  - ORIGIN
dependencies: none
interfaces:
  ui: { type: ui, port: 3000 }
actions: none
tasks: none
health_checks:
  - postgres
  - deckshare

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages