Archipelago — open-source initial import
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
app:
|
||||
id: podsteadr
|
||||
name: podsteadr
|
||||
version: "1.0.0"
|
||||
description: Self-hosted, nostr-native podcast publishing and livestreaming. Log in with Nostr, upload episodes or go live via OBS/WebRTC, publish to RSS with Podcasting 2.0 lightning payments.
|
||||
category: media
|
||||
|
||||
# Container/DNS-alias name deliberately NOT "podsteadr" — on a host whose own
|
||||
# hostname happens to be "podsteadr", the host's own /etc/hosts self-hostname
|
||||
# entry (127.0.1.1, e.g. from cloud-init) shadows the container network's DNS
|
||||
# alias for other containers looking up "podsteadr", and mediamtx's auth-webhook
|
||||
# callback resolves to the host's loopback instead of this container — every
|
||||
# RTMP publish gets rejected with "connection refused" (observed on
|
||||
# podsteadr.atobitcoin.io, 2026-07-30; see docker-compose.yml in the podsteadr
|
||||
# repo for the original writeup). Carried forward unchanged into the manifest.
|
||||
container_name: podsteadr-app
|
||||
|
||||
container:
|
||||
# Built locally from the podsteadr repo (source lives outside this tree —
|
||||
# see apps/podsteadr/README.md + build-from-prototype.sh), same pattern as
|
||||
# apps/indeedhub. Not yet pushed to the shared registry; push-to-registry.sh
|
||||
# is there for when fleet-wide install is needed.
|
||||
image: localhost/podsteadr:1.0.0
|
||||
pull_policy: if-not-present
|
||||
network: podsteadr-net
|
||||
network_aliases: [podsteadr-app]
|
||||
derived_env:
|
||||
- key: PUBLIC_URL
|
||||
template: "http://{{HOST_MDNS}}:8095"
|
||||
- key: MEDIAMTX_RTMP_PUBLIC
|
||||
template: "rtmp://{{HOST_MDNS}}:1935"
|
||||
- key: MEDIAMTX_WHIP_PUBLIC
|
||||
template: "http://{{HOST_MDNS}}:8889"
|
||||
- key: MEDIAMTX_HLS_PUBLIC
|
||||
template: "http://{{HOST_MDNS}}:8890"
|
||||
- key: BLOSSOM_URL_DEFAULT
|
||||
template: "http://{{HOST_MDNS}}:8098"
|
||||
# node:22-bookworm-slim's built-in `node` user is uid:gid 1000:1000. The
|
||||
# image's own Dockerfile chowns /data to node:node, but that only affects
|
||||
# the image layer — the actual runtime mount is the bind volume below, so
|
||||
# the host directory needs the same ownership or the read-only-root,
|
||||
# non-root `node` process can't open the SQLite DB (unverified against a
|
||||
# real node install; flagging per this repo's convention of documenting
|
||||
# bind-mount ownership assumptions, e.g. apps/botfights/manifest.yml).
|
||||
data_uid: "1000:1000"
|
||||
|
||||
dependencies:
|
||||
- app_id: podsteadr-mediamtx
|
||||
- app_id: podsteadr-blossom
|
||||
- storage: 2Gi
|
||||
|
||||
resources:
|
||||
cpu_limit: 2
|
||||
memory_limit: 1Gi
|
||||
disk_limit: 2Gi
|
||||
|
||||
security:
|
||||
capabilities: []
|
||||
readonly_root: true
|
||||
no_new_privileges: true
|
||||
network_policy: isolated
|
||||
|
||||
ports:
|
||||
- host: 8095
|
||||
container: 8095
|
||||
protocol: tcp
|
||||
auth: none
|
||||
auth_rationale: >-
|
||||
podsteadr is a public podcast/livestream server: RSS feeds and the
|
||||
marketplace/catalog API must stay fetchable by third-party podcast
|
||||
clients, crawlers, and other podsteadr instances with no Archipelago
|
||||
session, and the app already gates its own sensitive routes with
|
||||
NIP-98 signed-request auth (see server/src/plugins/nostr-auth.ts in
|
||||
the podsteadr repo). Putting the node's session gate in front would
|
||||
block every external RSS/API consumer without adding real protection.
|
||||
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /var/lib/archipelago/podsteadr
|
||||
target: /data
|
||||
options: [rw]
|
||||
# Shares podsteadr-mediamtx's recordings directory (rw there, ro here) so
|
||||
# the app can list/remux finished recordings for one-click episode
|
||||
# publishing without granting it write access to live segments.
|
||||
- type: bind
|
||||
source: /var/lib/archipelago/podsteadr/recordings
|
||||
target: /recordings
|
||||
options: [ro]
|
||||
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=8095
|
||||
- DATA_DIR=/data
|
||||
- RECORDINGS_DIR=/recordings
|
||||
- MEDIAMTX_API_URL=http://mediamtx:9997
|
||||
- BLOSSOM_URL_INTERNAL=http://blossom:3000
|
||||
- NOSTR_RELAYS=wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band
|
||||
- CASHU_MINT_URL_DEFAULT=https://mint.minibits.cash/Bitcoin
|
||||
|
||||
# podsteadr's Fastify server (fastify-static) isn't the nginx-served SPA
|
||||
# shape the platform auto-patches for NIP-07 injection (see "Nostr Signer
|
||||
# Bridge" in docs/app-developer-guide.md) — its frontend already
|
||||
# self-references /nostr-provider.js from index.html and vendors a copy at
|
||||
# build time (podsteadr commit 133558d). That vendored copy goes stale
|
||||
# across archy OTA releases, so re-copy the canonical host script over it
|
||||
# on every install/reinstall instead of trusting the baked-in one.
|
||||
hooks:
|
||||
post_install:
|
||||
- copy_from_host:
|
||||
src: "web-ui/nostr-provider.js"
|
||||
dest: /app/public/nostr-provider.js
|
||||
|
||||
health_check:
|
||||
type: http
|
||||
endpoint: http://localhost:8095
|
||||
path: /api/health
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
interfaces:
|
||||
main:
|
||||
name: Web UI
|
||||
description: Podcast dashboard, upload/live wizard, and stream management
|
||||
type: ui
|
||||
port: 8095
|
||||
protocol: http
|
||||
path: /
|
||||
|
||||
metadata:
|
||||
author: podsteadr
|
||||
icon: /assets/img/app-icons/podsteadr.png
|
||||
repo: http://146.59.87.168:3000/ssmithx/podsteadr
|
||||
license: MIT
|
||||
tags:
|
||||
- nostr
|
||||
- podcast
|
||||
- livestream
|
||||
- media
|
||||
- rss
|
||||
- lightning
|
||||
launch:
|
||||
open_in_new_tab: false
|
||||
Reference in New Issue
Block a user