mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-05-07 21:26:45 +02:00
* ci(packaging): publish signed apt repository to etherpad.org/apt (closes #7610) Adds an `apt-publish` workflow job that turns the existing `.deb` build artefacts into a signed apt repository hosted at: https://etherpad.org/apt/ End-user install on any Debian/Ubuntu/Mint: curl -fsSL https://etherpad.org/key.asc \ | sudo gpg --dearmor -o /usr/share/keyrings/etherpad.gpg echo "deb [signed-by=/usr/share/keyrings/etherpad.gpg] \ https://etherpad.org/apt stable main" \ | sudo tee /etc/apt/sources.list.d/etherpad.list sudo apt update && sudo apt install etherpad `apt upgrade` works going forward — every tagged release republishes the repo metadata. Change type: patch (CI/distribution; no production behaviour change). ## Why etherpad.org/apt and not ether.github.io/etherpad/apt ether/etherpad's GitHub Pages is already configured as build-from-workflow on `develop` with CNAME `docs.etherpad.org`, and a repo can only have one Pages source. Pushing the apt repo to a gh-pages branch would either be ignored (Pages is reading from the docs workflow) or, if Pages were switched to it, would kill the docs site. ether/ether.github.com is a separate Next.js site that already deploys etherpad.org and serves `public/` verbatim, so cross-pushing the apt repo into `public/apt/` lands it at the canonical Etherpad URL with no infrastructure conflicts. ## What this PR ships 1. `apt-publish` job in `.github/workflows/deb-package.yml`. Runs after `release` on `v*` tag pushes: - Clones ether/ether.github.com over SSH using a deploy key. - Wipes site/public/apt/ and rebuilds it from the per-arch .deb artefacts using apt-ftparchive. - Signs Release + emits InRelease/Release.gpg using the keypair in APT_SIGNING_KEY. - Drops key.asc into site/public/key.asc. - Asserts both per-arch .debs are present before the wipe takes effect — refuses to publish a partial / empty repo if an artefact is missing or renamed. - Commits and pushes to master; the site repo's existing build pipeline picks it up. 2. `packaging/apt/key.asc` — Etherpad APT Repository public key, fingerprint 6953FA0C6431F30347D65B03AF0CD687D51A6E63. Served at https://etherpad.org/key.asc after the next release. 3. `packaging/apt/generate-signing-key.sh` — one-shot helper that generated the keypair, kept for documented future rotation. 4. `packaging/README.md` — apt-repo install recipe is now the recommended path. ## Required secrets before the next tagged release Two secrets on ether/etherpad before the next `v*` tag push: - APT_SIGNING_KEY — ASCII-armoured private key for the Etherpad APT Repository keypair (long key id AF0CD687D51A6E63), generated with packaging/apt/generate-signing-key.sh. - SITE_DEPLOY_KEY — SSH private key. The public half registered as a deploy key with WRITE access on ether/ether.github.com. If either is missing the job fails fast with a clear error. ## What this PR does not change - The release job still attaches both versioned (etherpad_<v>_<arch>.deb) and stable-aliased (etherpad-latest_<arch>.deb) artefacts to the GitHub Release. Anyone pulling from releases/latest/download/etherpad-latest_amd64.deb keeps working. - The build-job smoke test (start under systemd, /health, purge) is unchanged. - docs.etherpad.org is untouched; this PR never pushes to gh-pages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(packaging): emit unindented Release headers + tighten artefact glob Two corrections from a fresh Qodo review of the rebased apt-publish job: 1. The dists/${SUITE}/Release heredoc was indented with the workflow's YAML scope, which means the resulting file had 10-space-prefixed field lines (` Origin: Etherpad`). apt parsers reject any leading whitespace on header fields per RFC 822 / Debian control format, so the entire suite would have failed to parse on `apt update` even before checksums were appended. Replace the heredoc with `printf '%s\n' ...` so the indentation is entirely under workflow control and impossible to break with a future YAML re-indent. 2. Tighten the artefact glob from `etherpad_*_amd64.deb` to `etherpad_[0-9]*_amd64.deb`. The hyphen-separator distinction (etherpad_<v>_… vs etherpad-latest_…) already kept the alias out of the array — Qodo's analysis of a duplicate-Packages bug was incorrect. But pinning to a leading-digit version segment makes the contract explicit and defends against any future alias that accidentally lands on `dist/etherpad_<word>_<arch>.deb`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
140 lines
4.6 KiB
Markdown
140 lines
4.6 KiB
Markdown
# Etherpad Debian / RPM packaging
|
|
|
|
Produces native `.deb` (and, with the same manifest, `.rpm` / `.apk`)
|
|
packages for Etherpad using [nfpm](https://nfpm.goreleaser.com).
|
|
|
|
## Layout
|
|
|
|
```
|
|
packaging/
|
|
nfpm.yaml # nfpm package manifest
|
|
bin/etherpad # /usr/bin launcher
|
|
scripts/ # preinst / postinst / prerm / postrm
|
|
systemd/etherpad.service
|
|
systemd/etherpad.default
|
|
etc/settings.json.dist # populated in CI from settings.json.template
|
|
```
|
|
|
|
Built artefacts land in `./dist/`.
|
|
|
|
## Building locally
|
|
|
|
Prereqs: Node 24 (current LTS; `engines.node` floor is 20), pnpm 10+, nfpm.
|
|
|
|
```sh
|
|
pnpm install --frozen-lockfile
|
|
pnpm run build:etherpad
|
|
|
|
# Stage the tree the way CI does:
|
|
STAGE=staging/opt/etherpad
|
|
mkdir -p "$STAGE"
|
|
cp -a src bin package.json pnpm-workspace.yaml README.md LICENSE \
|
|
node_modules "$STAGE/"
|
|
printf 'packages:\n - src\n - bin\n' > "$STAGE/pnpm-workspace.yaml"
|
|
cp settings.json.template packaging/etc/settings.json.dist
|
|
|
|
VERSION=$(node -p "require('./package.json').version") \
|
|
ARCH=amd64 \
|
|
nfpm package --packager deb -f packaging/nfpm.yaml --target dist/
|
|
```
|
|
|
|
## End-to-end test (Docker, no real systemd needed)
|
|
|
|
`packaging/test-local.sh` builds the `.deb` and runs the same smoke
|
|
test the CI workflow does, inside a throwaway systemd-enabled
|
|
container:
|
|
|
|
```sh
|
|
packaging/test-local.sh # build + smoke + purge
|
|
packaging/test-local.sh --shell # leave the container up so you can poke around
|
|
packaging/test-local.sh --build-only # just produce dist/*.deb
|
|
```
|
|
|
|
This is the fastest way to validate that the systemd hardening, plugin
|
|
path symlinks, and tsx wrapper actually work together before pushing.
|
|
|
|
## Installing via the Etherpad apt repository (recommended)
|
|
|
|
The release workflow publishes a signed apt repository at
|
|
`https://etherpad.org/apt/` on every tagged release. Three lines on
|
|
any Debian/Ubuntu/Mint:
|
|
|
|
```sh
|
|
curl -fsSL https://etherpad.org/key.asc \
|
|
| sudo gpg --dearmor -o /usr/share/keyrings/etherpad.gpg
|
|
echo "deb [signed-by=/usr/share/keyrings/etherpad.gpg] https://etherpad.org/apt stable main" \
|
|
| sudo tee /etc/apt/sources.list.d/etherpad.list
|
|
sudo apt update && sudo apt install etherpad
|
|
```
|
|
|
|
`apt upgrade` works going forward. Repo metadata is signed with the
|
|
GPG keypair documented in `packaging/apt/key.asc` (long key id
|
|
`AF0CD687D51A6E63`).
|
|
|
|
## Installing a single .deb directly
|
|
|
|
The release page publishes both versioned and stable filenames per arch:
|
|
|
|
```sh
|
|
# Stable URL — always points at the most recent release:
|
|
curl -fsSL -o etherpad-latest_amd64.deb \
|
|
https://github.com/ether/etherpad/releases/latest/download/etherpad-latest_amd64.deb
|
|
sudo apt install ./etherpad-latest_amd64.deb
|
|
|
|
# Or pin to a specific version:
|
|
sudo apt install ./dist/etherpad_<version>_amd64.deb
|
|
|
|
sudo systemctl start etherpad
|
|
curl http://localhost:9001/health
|
|
```
|
|
|
|
`apt` will pull in `nodejs (>= 22)` (matches Etherpad's `engines.node`).
|
|
Recommended runtime is the current Node.js LTS (24); on distros without a
|
|
new enough Node, add NodeSource first:
|
|
|
|
```sh
|
|
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
|
|
```
|
|
|
|
## Configuration
|
|
|
|
- Edit `/etc/etherpad/settings.json`, then
|
|
`sudo systemctl restart etherpad`.
|
|
- Environment overrides: `/etc/default/etherpad`.
|
|
- Logs: `journalctl -u etherpad -f`.
|
|
- Data (sqlite default): `/var/lib/etherpad/etherpad.db`.
|
|
|
|
The shipped settings template defaults to `dbType: "dirty"`, which the
|
|
template itself warns is for testing only. `postinstall` rewrites the
|
|
seeded `/etc/etherpad/settings.json` to `sqlite` and points it at
|
|
`/var/lib/etherpad/etherpad.db` so fresh installs get an ACID-safe DB
|
|
out of the box. Existing `/etc/etherpad/settings.json` is never touched
|
|
on upgrade.
|
|
|
|
## Upgrading
|
|
|
|
`dpkg --install etherpad_<new>.deb` (or `apt install`) replaces the app
|
|
tree under `/opt/etherpad` while preserving `/etc/etherpad/*` and
|
|
`/var/lib/etherpad/*`. The service is restarted automatically.
|
|
|
|
## Removing
|
|
|
|
- `sudo apt remove etherpad` — keeps config and data.
|
|
- `sudo apt purge etherpad` — also removes config, data, and the
|
|
`etherpad` system user.
|
|
|
|
## Publishing to an APT repository (follow-up)
|
|
|
|
Out of scope here — requires credentials and ownership decisions.
|
|
Recipes once a repo is picked:
|
|
|
|
- **Cloudsmith** (easiest, free OSS tier):
|
|
`cloudsmith push deb ether/etherpad/any-distro/any-version dist/*.deb`
|
|
- **Launchpad PPA**: requires signed source packages (a `debian/` tree),
|
|
which nfpm does not produce — use `debuild` separately.
|
|
- **Self-hosted reprepro**:
|
|
`reprepro -b /srv/apt includedeb stable dist/*.deb`
|
|
|
|
Wire the chosen option into `.github/workflows/deb-package.yml` after
|
|
the `release` job.
|