mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-15 02:33:15 -06:00
- .github/workflows/release.yml: on a v* tag - verify the tag matches VERSION (fail-fast guard), run tests, build a source tarball + the unsigned Tizen .wgt and publish a GitHub Release with generated notes, and build+push a multi-arch (amd64 + arm64) image to ghcr.io/screentinker/screentinker:<version> + :latest. The Release (artifacts) and the docker push are independent jobs, so an arm64/QEMU docker failure does not block the GitHub Release and is re-runnable. Nothing deploys to prod. APK-build-in-CI left as a TODO (keystore secret). - Dockerfile + .dockerignore: multi-stage node:20-slim image with server + frontend + VERSION + scripts; DATA_DIR=/data volume for db/uploads/jwt-secret. Verified to build, boot, serve the dashboard + web player, and persist state. - docker-compose.example.yml: /data volume, SELF_HOSTED, a node-fetch healthcheck against /api/status, and an admin-lockout recovery note (reset-admin.js). - server.js: resolve the OTA APK from DATA_DIR first (a container can mount one at /data/ScreenTinker.apk), fall back to the legacy in-repo path, 404 gracefully. - ci.yml: bump checkout/setup-node to v6 (clears the Node-20 action deprecation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.4 KiB
YAML
34 lines
1.4 KiB
YAML
# Example docker-compose for self-hosting ScreenTinker.
|
|
# cp docker-compose.example.yml docker-compose.yml # then edit to taste
|
|
# The container serves plain HTTP on 3001 - front it with a TLS-terminating
|
|
# reverse proxy or Cloudflare in production.
|
|
services:
|
|
screentinker:
|
|
image: ghcr.io/screentinker/screentinker:latest
|
|
# ...or build from source instead of pulling:
|
|
# build: .
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3001:3001"
|
|
environment:
|
|
SELF_HOSTED: "true" # first registered user becomes admin, no billing
|
|
# JWT_SECRET: "set-a-long-random-string" # else one is generated under /data/certs
|
|
# DISABLE_HOMEPAGE: "true" # redirect / to the app instead of the landing page
|
|
volumes:
|
|
- st-data:/data # db, uploads, and the jwt secret persist here
|
|
# To enable OTA APK downloads, mount a built APK read-only:
|
|
# - ./ScreenTinker.apk:/data/ScreenTinker.apk:ro
|
|
healthcheck:
|
|
# image is node:20-slim (no curl) - use node's built-in fetch
|
|
test: ["CMD", "node", "-e", "fetch('http://localhost:3001/api/status').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s # first boot runs db migrations
|
|
|
|
# Locked out of the admin account? Reset it with:
|
|
# docker exec -it screentinker node scripts/reset-admin.js
|
|
|
|
volumes:
|
|
st-data:
|