Web-app-fediwall Role¶
Description: Self-hosted Fediverse wall for showing recent public posts by hashtag or account in a live masonry grid
Variables¶
author: Kevin Veen-Birkenbach
description: Self-hosted Fediverse wall for showing recent public posts by hashtag or account in a live masonry grid
license: Infinito.Nexus Community License (Non-Commercial)
min_ansible_version: 2.9
company: Kevin Veen-Birkenbach https://www.veen.world
galaxy_tags: [‘infinito’, ‘fediverse’, ‘mastodon’, ‘wall’, ‘dashboard’, ‘webapp’]
issue_tracker_url: https://github.com/defnull/fediwall/issues
platforms: [{‘name’: ‘ArchLinux’, ‘versions’: [‘all’]}, {‘name’: ‘Debian’, ‘versions’: [‘all’]}, {‘name’: ‘EL’, ‘versions’: [‘all’]}, {‘name’: ‘Fedora’, ‘versions’: [‘all’]}, {‘name’: ‘Ubuntu’, ‘versions’: [‘all’]}]
README¶
Fediwall¶
Description¶
Fediwall is a self-hosted media wall for the Fediverse: it follows hashtags or accounts on Mastodon-compatible servers and shows the most recent public posts in a screen-filling, self-updating masonry grid.
Overview¶
Fediwall is a static, single-page web application with no backend, no
database, and no user accounts. Configuration lives in a
wall-config.json next to index.html and can be overridden
per-visitor through URL parameters.
This role bakes the upstream release artefact into a small
nginx:alpine image and supports multiple walls per deployment:
every entry under
`meta/services.yml.fediwall.walls <meta/services.yml>`__
materializes as its own path under
https://fediwall.<DOMAIN_PRIMARY>/<slug>/ with its own baked-in
wall-config.json. The root / shows a link list of all configured
walls.
A wall’s config.servers may be left empty to auto-fill with the
active Mastodon-API-compatible Fediverse siblings (web-app-mastodon,
web-app-pixelfed, web-app-friendica) that are present in the
current host’s group_names. Every other field of
wall-config.json is read verbatim from the wall’s config block.
Cosmos¶
The diagram places Fediwall in the Infinito.Nexus cosmos: the components it deploys (capabilities), the central services it consumes (dependencies), and its outward reach (federation and bridged external networks).
flowchart LR
subgraph deps [Dependencies]
dep_svc_net_tor["svc-net-tor 🐳🐝"]
dep_web_app_dashboard["web-app-dashboard 🐳🐝"]
dep_web_app_friendica["web-app-friendica 🐳🐝"]
dep_web_app_keycloak["web-app-keycloak 🐳🐝"]
dep_web_app_mastodon["web-app-mastodon 🐳🐝"]
dep_web_app_matomo["web-app-matomo 🐳🐝"]
dep_web_app_prometheus["web-app-prometheus 🐳🐝"]
dep_web_app_stalwart["web-app-stalwart 🐳🐝"]
dep_web_svc_css["web-svc-css 💻"]
end
subgraph role [web-app-fediwall 🐳🐝]
svc_logout["logout ❌"]
svc_dashboard["dashboard"]
svc_matomo["matomo"]
svc_css["css"]
svc_email["email ❌"]
svc_sso["sso ❌"]
svc_prometheus["prometheus"]
svc_mastodon["mastodon"]
svc_friendica["friendica"]
svc_fediwall["fediwall"]
svc_tor["tor"]
end
dep_svc_net_tor -. "0..1" .-> svc_tor
dep_web_app_dashboard -- "1:1" --> svc_dashboard
dep_web_app_friendica -. "0..1" .-> svc_friendica
dep_web_app_keycloak -- "0..0" --> svc_sso
dep_web_app_mastodon -. "0..1" .-> svc_mastodon
dep_web_app_matomo -- "1:1" --> svc_matomo
dep_web_app_prometheus -- "1:1" --> svc_prometheus
dep_web_app_stalwart -- "0..0" --> svc_email
dep_web_svc_css -. "0..1" .-> svc_css
linkStyle 3,7 stroke:red;Solid 1:1 edges are fixed relationships; dashed 0..1 edges are
conditional (enabled only in matching deployments); red 0..0 edges
are turned off in this role. Node markers show the role’s deploy modes
(💻 host, 🐳 compose, 🐝 swarm); ❌ marks a service that is explicitly
turned off, and ⚙️ an Ansible role dependency declared in
meta/main.yml.
Features¶
Follow hashtags, accounts, or trends across multiple Mastodon-compatible servers.
Visually pleasing, screen-filling masonry grid that scales from tablets to LED walls.
Dark mode and customizable theme.
Privacy-friendly: no server-side state, no tracking, all logic runs in the browser.
Live customization: viewers can override every setting through URL parameters and bookmark or share their personalized wall.
Multi-wall: declare multiple purpose-built walls (per event, hashtag, account set, …) under one deployment.
Quick Setup¶
Development¶
Clone, set up the workstation, and deploy Fediwall onto the local stack:
git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=web-app-fediwall full_cycle=false
Production¶
Run the published image to provision the inventory and deploy Fediwall to a managed server (the mounted volume persists the inventory):
APP=web-app-fediwall
HOST=<your-server>
DOMAIN=<your-domain>
TLS_MODE=self_signed
SSH_PUBLIC_KEY="<your-ssh-public-key>"
docker run --rm -it \
-v "$PWD/inventories:/etc/infinito.nexus/inventories" \
-e APP="$APP" -e HOST="$HOST" -e DOMAIN="$DOMAIN" -e TLS_MODE="$TLS_MODE" -e SSH_PUBLIC_KEY="$SSH_PUBLIC_KEY" \
ghcr.io/infinito-nexus/core/debian bash -c '
INVENTORY=/etc/infinito.nexus/inventories/production
infinito administration inventory provision "$INVENTORY" \
--inventory-file "$INVENTORY/devices.yml" \
--host "$HOST" \
--include "$APP" \
--vars "{\"TLS_MODE\": \"$TLS_MODE\", \"DOMAIN_PRIMARY\": \"$DOMAIN\", \"users\": {\"administrator\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}}}" &&
infinito administration deploy dedicated "$INVENTORY/devices.yml" \
--password-file "$INVENTORY/.password" \
--diff -vv'
Further Resources¶
Persona contract opt-outs¶
Both authenticated Playwright personas are blocked. Fediwall is a
read-only public wall: meta/services.yml pins sso.enabled: false
and logout.enabled: false, and the container is a plain nginx image
serving the pre-built upstream tarball. There is no account model, no
login form and no logout control.
Wall content is baked at deploy time from services.fediwall.walls,
so administration happens in Ansible rather than in an in-app admin
panel. The persona-facing coverage this role does carry lives in the
cross-fediverse scenarios that post on a Mastodon or Friendica sibling
and assert the post appears on the wall.
Credits¶
Implemented by Kevin Veen-Birkenbach. Part of the Infinito.Nexus Project and maintained by Kevin Veen-Birkenbach. Licensed under the Infinito.Nexus Community License (Non-Commercial).