Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/hassio-addon.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: "HA Add-on Build"

on:
push:
branches:
- develop
paths:
- "packaging/home-assistant/**"
- ".github/workflows/hassio-addon.yml"
tags:
- "v?[0-9]+.[0-9]+.[0-9]+"
pull_request:
paths:
- "packaging/home-assistant/**"
- ".github/workflows/hassio-addon.yml"

permissions:
contents: read
packages: write

jobs:
lint:
name: Lint add-on config
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run hassio-addon-lint
uses: frenck/action-addon-linter@v2
with:
path: "./packaging/home-assistant/etherpad"

build:
name: Build ${{ matrix.arch }}
needs: lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
arch:
- amd64
- aarch64
steps:
- uses: actions/checkout@v6

- name: Read add-on manifest
id: manifest
run: |
version=$(grep -m1 '^version:' packaging/home-assistant/etherpad/config.yaml | sed 's/version: *"\?\([^"]*\)"\?/\1/')
echo "version=${version}" >> "$GITHUB_OUTPUT"

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build (and push on non-PR)
uses: home-assistant/builder@master
with:
args: |
--${{ matrix.arch }} \
--target /data/packaging/home-assistant/etherpad \
--image "ghcr.io/ether/home-assistant-addon-etherpad-{arch}" \
--version "${{ steps.manifest.outputs.version }}" \
${{ github.event_name == 'pull_request' && '--test' || '--docker-hub-check' }}
10 changes: 10 additions & 0 deletions packaging/home-assistant/etherpad/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog

## 2.6.1 (initial)

- Initial Home Assistant add-on wrapping the upstream
`etherpad/etherpad:2.6.1` Docker image.
- Ingress support (requires `trust_proxy: true`).
- Persistent dirty DB under `/data/dirty.db`.
- Exposes `title`, `require_authentication`, `admin_password`,
`default_pad_text`, and DB backend selection as HA options.
64 changes: 64 additions & 0 deletions packaging/home-assistant/etherpad/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
ARG BUILD_FROM=ghcr.io/home-assistant/amd64-base:3.19
ARG ETHERPAD_VERSION=2.6.1

# ---------------------------------------------------------------------------
# Stage 1: grab the pre-built Etherpad tree from the official image.
# Both the upstream image and the HA base use Alpine, so /opt/etherpad-lite
# copies across cleanly without reinstalling deps.
# ---------------------------------------------------------------------------
FROM etherpad/etherpad:${ETHERPAD_VERSION} AS upstream

# ---------------------------------------------------------------------------
# Stage 2: assemble the add-on on top of the HA base (Alpine + s6-overlay v3).
# ---------------------------------------------------------------------------
FROM ${BUILD_FROM}

ARG ETHERPAD_VERSION
ENV ETHERPAD_VERSION=${ETHERPAD_VERSION} \
NODE_ENV=production \
ETHERPAD_PRODUCTION=true \
EP_DIR=/opt/etherpad-lite

RUN apk add --no-cache \
bash \
ca-certificates \
curl \
nodejs \
npm \
tini \
&& rm -rf /var/cache/apk/*

COPY --from=upstream /opt/etherpad-lite /opt/etherpad-lite

# Upstream uses pnpm as the runtime launcher for `pnpm run prod`.
RUN npm install -g pnpm@10.33.0

COPY rootfs/ /

EXPOSE 9001

ARG BUILD_ARCH
ARG BUILD_DATE
ARG BUILD_DESCRIPTION
ARG BUILD_NAME
ARG BUILD_REF
ARG BUILD_REPOSITORY
ARG BUILD_VERSION
LABEL \
io.hass.name="${BUILD_NAME}" \
io.hass.description="${BUILD_DESCRIPTION}" \
io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \
maintainer="Etherpad Foundation <contact@etherpad.org>" \
org.opencontainers.image.title="${BUILD_NAME}" \
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
org.opencontainers.image.vendor="Etherpad" \
org.opencontainers.image.authors="Etherpad Foundation" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.url="https://etherpad.org" \
org.opencontainers.image.source="https://github.com/ether/etherpad-lite" \
org.opencontainers.image.documentation="https://etherpad.org/doc" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.revision=${BUILD_REF} \
org.opencontainers.image.version=${BUILD_VERSION}
74 changes: 74 additions & 0 deletions packaging/home-assistant/etherpad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Home Assistant Add-on: Etherpad

Realtime collaborative document editor, wrapped as a one-click Home
Assistant add-on.

## Installation

1. In Home Assistant, go to **Settings → Add-ons → Add-on Store**.
2. Click the three-dot menu (top right) → **Repositories**.
3. Add: `https://github.com/ether/etherpad-lite` (or the dedicated
`ether/home-assistant-addon-etherpad` repo once published — see the
PR description that introduced this add-on).
4. Find **Etherpad** in the store, click **Install**, then **Start**.
5. Use **Open Web UI** to launch Etherpad through HA ingress, or browse
directly to `http://<ha-host>:9001`.
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.

## Configuration

| Option | Description |
| ----------------------- | --------------------------------------------------------------------- |
| `title` | Instance name shown in the browser tab. |
| `require_authentication`| If `true`, all pads require login. |
| `admin_password` | Password for the built-in `admin` user (access to `/admin`). |
| `user_password` | Password for the built-in `user` account. |
| `default_pad_text` | Text inserted into every newly-created pad. |
| `db_type` | One of `dirty` (default, file-backed), `mysql`, `postgres`, `sqlite`. |
| `db_host`/`db_port`/... | Used only when `db_type` is not `dirty`. |
| `trust_proxy` | Leave `true` so Home Assistant ingress works correctly. |
| `log_level` | Etherpad log verbosity. |

### Data persistence

When `db_type` is `dirty` (the default), pads are stored in
`/data/dirty.db` inside the add-on's persistent volume. Other DB types
expect an external database you operate yourself.

### Ingress

This add-on is ingress-enabled: Home Assistant proxies requests to
Etherpad behind authentication, and Etherpad's `trustProxy` setting
ensures cookies and client IPs work correctly. Keep `trust_proxy` set to
`true` for ingress to function.

If ingress misbehaves (Etherpad does not currently support a configurable
URL base path), disable it by editing `config.yaml` and use the direct
port 9001 instead.

## Security notes

- **Admin passwords are stored in plaintext** in Home Assistant's
supervisor database (the `options.json` that the add-on reads). For
stronger secret handling, install the `ep_hash_auth` Etherpad plugin
and supply a bcrypt hash via a hand-edited `settings.json` (advanced).
- The direct port (9001) bypasses Home Assistant authentication.
Firewall it off, or leave only ingress enabled if you care.

## Links

- Etherpad: <https://etherpad.org>
- Upstream repo: <https://github.com/ether/etherpad-lite>
- Docker image: <https://hub.docker.com/r/etherpad/etherpad>
- Report bugs: <https://github.com/ether/etherpad-lite/issues>
- HA add-on docs: <https://developers.home-assistant.io/docs/add-ons/>

## Icon and logo

This scaffold ships without `icon.png` / `logo.png`. Add before
publishing:

- `icon.png` — 128×128 square, shown in the add-on list.
- `logo.png` — 250×100 wide, shown on the add-on detail page.

Source: see Etherpad brand assets at
<https://github.com/ether/etherpad-lite>.
63 changes: 63 additions & 0 deletions packaging/home-assistant/etherpad/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Etherpad
version: "2.6.1"
slug: etherpad
description: Realtime collaborative document editor
url: https://etherpad.org
# Arch list matches .github/workflows/docker.yml's upstream matrix
# (linux/amd64, linux/arm64). armv7/armhf would require upstream Docker
# CI to build those first.
arch:
- aarch64
- amd64
startup: application
boot: auto
init: false
hassio_api: false
homeassistant_api: false
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
Outdated
host_network: false
ingress: true
ingress_port: 9001
ingress_stream: true
panel_icon: mdi:file-document-edit-outline
panel_title: Etherpad
ports:
"9001/tcp": 9001
ports_description:
"9001/tcp": Etherpad web UI (direct access, bypasses ingress)
map:
- addon_config:rw
- share:rw
options:
title: Etherpad
require_authentication: false
admin_password: ""
user_password: ""
default_pad_text: |
Welcome to Etherpad!

This pad text is synchronized as you type, so that everyone viewing this
page sees the same text. This allows you to collaborate seamlessly on
documents!
db_type: dirty
db_host: ""
db_port: 0
db_name: ""
db_user: ""
db_password: ""
trust_proxy: true
log_level: INFO
schema:
title: str
require_authentication: bool
admin_password: password
user_password: password
default_pad_text: str
db_type: list(dirty|mysql|postgres|sqlite)
db_host: str?
db_port: port?
db_name: str?
db_user: str?
db_password: password?
trust_proxy: bool
log_level: list(DEBUG|INFO|WARN|ERROR)
image: ghcr.io/ether/home-assistant-addon-etherpad-{arch}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Home Assistant Add-on: Etherpad
# Renders a shell env file from /data/options.json so that Etherpad's built-in
# ${ENV_VAR:default} substitution in settings.json picks up user config.
# ==============================================================================
set -e

ENV_FILE=/etc/etherpad/env
mkdir -p "$(dirname "${ENV_FILE}")"

{
echo "export TITLE=$(bashio::config 'title' | jq -Rr @sh)"
echo "export REQUIRE_AUTHENTICATION=$(bashio::config 'require_authentication')"
echo "export TRUST_PROXY=$(bashio::config 'trust_proxy')"
echo "export LOGLEVEL=$(bashio::config 'log_level')"
echo "export DEFAULT_PAD_TEXT=$(bashio::config 'default_pad_text' | jq -Rr @sh)"

admin_pw=$(bashio::config 'admin_password')
if bashio::var.has_value "${admin_pw}"; then
echo "export ADMIN_PASSWORD=$(printf '%s' "${admin_pw}" | jq -Rr @sh)"
else
echo "export ADMIN_PASSWORD=null"
fi

user_pw=$(bashio::config 'user_password')
if bashio::var.has_value "${user_pw}"; then
echo "export USER_PASSWORD=$(printf '%s' "${user_pw}" | jq -Rr @sh)"
else
echo "export USER_PASSWORD=null"
fi

db_type=$(bashio::config 'db_type')
echo "export DB_TYPE=${db_type}"
if [ "${db_type}" = "dirty" ]; then
# Persist the dirty DB under /data so pads survive restarts.
echo "export DB_FILENAME=/data/dirty.db"
else
echo "export DB_HOST=$(bashio::config 'db_host')"
echo "export DB_PORT=$(bashio::config 'db_port')"
echo "export DB_NAME=$(bashio::config 'db_name')"
echo "export DB_USER=$(bashio::config 'db_user')"
echo "export DB_PASS=$(bashio::config 'db_password' | jq -Rr @sh)"
fi
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
Outdated

# Ingress: HA proxies through a random base path; Etherpad picks up
# X-Forwarded-* headers when trustProxy is true.
echo "export PORT=9001"
echo "export IP=0.0.0.0"
} > "${ENV_FILE}"

chmod 0600 "${ENV_FILE}"
bashio::log.info "Etherpad configuration rendered to ${ENV_FILE}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Home Assistant Add-on: Etherpad
# Cleanup when the Etherpad service exits. Exit code 256 = signaled;
# anything else is a real fault — tell s6 to bring the container down so
# the supervisor can restart it cleanly.
# ==============================================================================
if [[ "${1}" -ne 0 ]] && [[ "${1}" -ne 256 ]]; then
bashio::log.warning "Etherpad crashed (exit=${1}), halting add-on."
exec /run/s6/basedir/bin/halt
fi
bashio::log.info "Etherpad service stopped cleanly."
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Home Assistant Add-on: Etherpad
# Starts Etherpad as a long-running service under s6-overlay.
# ==============================================================================
set -e

# Load rendered config from cont-init.
# shellcheck source=/dev/null
. /etc/etherpad/env

cd "${EP_DIR}"

bashio::log.info "Starting Etherpad ${ETHERPAD_VERSION} on port ${PORT}..."
exec pnpm run prod
3 changes: 3 additions & 0 deletions packaging/home-assistant/repository.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: Etherpad Add-ons
url: https://github.com/ether/etherpad-lite
maintainer: Etherpad Foundation <contact@etherpad.org>
Loading