Skip to content

About

StartOS package for mirall-relay

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Mirall Logo


Mirall Relay on StartOS

Everything not listed in this document should behave the same as upstream mirall-relay. If a feature, setting, or behavior is not mentioned here, the upstream documentation is accurate and fully applicable — see the Documentation section of instructions.md for links.

A blind relay for Mirall: it bridges two already-encrypted streams between peers that cannot hole-punch to each other, and can read neither side. Upstream source: https://github.com/ok/mirall-relay.

The one thing to know before installing: a relay is only useful if peers on the internet can reach its UDP port. On a home server behind NAT that means a port forward. Without one the service still runs, but the Internet Reachability health check fails and nothing is relayed.


Where to Get It

This package is published to a community-run registry at registry.zsapping.net, built for x86_64 and aarch64. It is not on Start9's own registry, so the registry is added once and then the service installs like any other:

  1. Open Marketplace and click the registry name at the top of the list.
  2. Under Saved Registries choose Add, enter registry.zsapping.net, and save. StartOS warns that it cannot vouch for a custom registry — that is expected of any registry outside Start9's, and a fair reminder that you are trusting whoever runs this one.
  3. Select that registry, find Mirall Relay, and install.

To sideload instead, download the .s9pk for the target architecture from the releases and use the Sideload page.

The identity is derived during install, before the relay has ever started, so Show Relay Public Key returns a key immediately — see Installation and First-Run Flow. The port forward that makes any of it useful is Limitations and Differences § 1–3; note in particular that the external port must be exactly 49737.


Table of Contents


Image and Container Runtime

The package builds upstream's own Dockerfile from a pinned git submodule rather than pulling a published image, so the relay binary and its runtime are upstream's, unmodified.

Property Value
Image Built from the upstream Dockerfile (git submodule)
Architectures x86_64, aarch64
Base Upstream's distroless Node base, unmodified
Entrypoint Upstream's — node bin/mirall-relay.js via useEntrypoint()
Runtime user uid 65532 (nonroot), as upstream intends

The service runs in one long-lived subcontainer, mirall-relay-sub — the one to attach to on a running install. Two short-lived subcontainers also appear: init-identity during install and restore, and show-relay-key when that action has to derive the key from the seed. Neither outlives its task.

The base is distroless — no shell, no coreutils. Every in-container helper this package needs is therefore a node -e one-liner rather than a shell command, and attaching to a subcontainer gives you Node rather than a prompt.

Volume and Data Layout

One volume holds everything durable: the relay's identity and the package's own settings.

Path Contents
/data The main volume
/data/seed The relay identity. 64-hex, mode 0600, owned by uid 65532
/data/members.json The invite roster. Mode 0600 — holds every member's seed
/data/admin-token Bearer token for /admin/*. Mode 0600, minted on first start
/data/store.json StartOS-side settings and a cached copy of the public key

/data/seed and /data/members.json are the secrets. The seed's public key is the relay's address, so losing it strands every client configured with it; the roster holds one seed per member, so losing it revokes everyone and leaking it hands over every membership. Both are covered by Backups and Restore.

Upstream defaults the roster and the token to ./.keys/ under the working directory. The image's own ENV already redirects all three files to /data, and StartOS layers the daemon's environment over the image's rather than replacing it, so those defaults would survive — but relayEnv sets MIRALL_RELAY_SEED_FILE, MIRALL_RELAY_ROSTER_FILE and MIRALL_RELAY_ADMIN_TOKEN_FILE explicitly anyway. Off the volume these files would be recreated on every container replacement, losing the relay's address and every membership with it, and nothing in the build would catch it.

A StartOS volume is mounted owned by root, but the image runs as uid 65532. A prepare-identity oneshot runs as root before the relay starts and chowns /data recursively to the runtime user. It runs on every start, is idempotent, and the recursion is what makes a restore work: a backup returns the whole volume owned by root, and upstream throws on an admin-token it cannot read rather than minting a replacement, so a single root-owned file stops the relay from starting.

MIRALL_RELAY_SEED_SECRET_FILE is left at its upstream default. Nothing is mounted at /run/secrets/relay_seed, so the seed file is authoritative.

File Models

The package owns one file, store.json, and writes no upstream configuration at all — every upstream option is delivered as an environment variable instead.

/data/store.json (JSON, on the main volume) holds StartOS-side state: the cached public key plus every setting exposed by Configure Relay. It is seeded during init with the derived public key, and rewritten whenever Configure Relay is saved. Show Relay Public Key also writes back to it if it had to derive the key from the seed because the cache was empty.

Ownership splits cleanly. The configuration keys — access, region, operator, caps, allowlist, banlist, log level, assume-reachable — belong to you: nothing re-asserts them, and they persist until you change them again. The publicKey key belongs to the package; it is derived from the seed and re-derived whenever it is missing, so overwriting it by hand is pointless rather than harmful.

A hand edit to store.json survives on disk, but it does not reach a running relay. Upstream reads its configuration only from the environment, and this package builds that environment from store.json once, when the daemon starts. A hand edit therefore takes effect on the next service restart and not before; use Configure Relay, which restarts the relay for you.

Dependencies

None. The relay talks to the public HyperDHT and to its peers, and needs no other service on the server.

Network Access and Interfaces

Two interfaces are exported: the UDP port peers dial, and one UI carrying the operator status page and the members page.

Interface Id Type Port Path Protocol Exported
Relay Endpoint relay api 49737/udp — Noise (raw) Yes
Relay UI admin ui 9200/tcp / HTTP Yes

admin is the one UI interface. It opens upstream's anonymous status page at /; the token-gated members page, where invites are created and revoked, is /admin/ on the same binding and is reached from the Status | Members nav both pages carry. It used to be exported as a second members interface, which only turned one UI into two launch points in StartOS's Open UI menu. Nothing about exposure changes: /admin/ has always been served on this port, and it follows whatever addresses the user enables for this interface.

Upstream 0.3.0 also links the members page from the status page's own two-item nav, in every access mode (pageNav in src/operator/status/page.js). Before 0.3.0 that link appeared only once access.mode was already invite, which — since this package ships the default open mode — meant there was no way in except typing the path by hand.

The path needs its trailing slash: upstream 308s /admin to admin/ because the page's asset URLs are document-relative.

The relay interface is bound with no protocol and secure: { ssl: false } — the same shape StartOS uses for ssh: encrypted by the protocol itself, not by TLS, so StartOS neither terminates nor wraps it. Such a bind becomes a plain port forward, and StartOS installs those for TCP and UDP alike, which is what HyperDHT needs.

Tor and .local addresses are meaningless here: peers reach the relay by UDP at its public IP, not by hostname. What matters is that UDP 49737 arrives at this server. StartOS enables LAN addresses only, so switch on a Public address under Interfaces → Relay Endpoint: StartTunnel's (with the Outbound Gateway set to match), a router's (with the port forwarded), or a public-IP host's (Choosing a Setup).

The relay binds its admin server to 0.0.0.0 inside the container (MIRALL_RELAY_ADMIN_HOST) so the StartOS proxy can serve the status page; the health checks and actions still reach it on 127.0.0.1. That surface splits in two:

  • Anonymous reads — the status page at /, plus /healthz, /readyz, /metrics and /.well-known/mirall-relay.json. Upstream's rule is that these show numbers, never names or secrets: no member labels, no tickets, no seed.
  • /admin/ — the members page: a browser UI to create, re-show and revoke invites. The shell and its static assets are served without the token (/admin/, /admin/style.css, /admin/app.js, /admin/copy-button.js), and deliberately so — a <link> cannot send an Authorization header, so requiring one there would mean no page could ever load to collect the token. The shell is static markup with empty slots; it carries no member data.
  • Everything else under /admin/ — the membership write surface, gated by upstream on a bearer token read from /data/admin-token. Without the token it answers 401. Every label, key and ticket the page shows arrives over one of these authenticated fetches. The token lives in the tab's sessionStorage rather than a cookie, so it is not carried on requests the page did not make.

The anonymous half has no authentication of its own, which is what makes where you expose it an operator decision rather than a package one. StartOS controls that: add the LAN or Tor addresses you want on the Status Page interface and it is reachable there. Do not bind it to a public gateway — nothing in this package prevents it, and doing so publishes your traffic counters and DHT state to anyone who finds the address.

Because the interface is exported, /metrics is scrapable from wherever you have made the interface reachable — a change from earlier revisions of this package, which kept the surface on container loopback.

Upstream's DNS-rebinding Host guard is inert here by design: it engages only on a loopback bind or when MIRALL_RELAY_ADMIN_ALLOWED_HOSTS is set, and a proxy legitimately sets its own Host.

Expect a warning in the logs on every start, beginning "the /admin/* write surface is bound off loopback…". It is upstream telling you that the bearer token is the only thing in front of /admin/*, which is true and is the design here — StartOS decides who reaches the port, and the token decides who may write. It is not a fault and needs no action. This package leaves MIRALL_RELAY_ADMIN_WRITE at upstream's default of true rather than disabling the surface, because it is the only way to manage invites on StartOS short of start-cli package attach. Set MIRALL_RELAY_ADMIN_WRITE=false in relayEnv if you would rather the write surface did not exist; nothing in this package uses it.

Installation and First-Run Flow

Upstream expects an operator to run mirall-relay keygen, store the seed, and publish the printed public key. This package does that for you, and the identity exists before the relay has ever started.

  1. On install — and again on restore — init derives the identity inside a temporary container, creating the seed if there is none, and caches the public key in store.json. The key is therefore available while the service is still stopped, so you can hand it out while the port forward is still being sorted.
  2. Nothing blocks the first start. An earlier revision raised a critical task asking the operator to look at the public key; it is gone. See Tasks.
  3. instructions.md — the Instructions tab in StartOS — states the port-forwarding requirement and the consequence of losing the seed. StartOS has no per-package lifecycle alerts, so that is where those warnings live.

There is no admin account, no password, and no first-run wizard: the relay's public key is its whole identity, and it is meant to be published.

Actions

Three actions, none of them destructive. The relay's identity is never rotated or regenerated by any of them.

Show Relay Public Key — run it whenever you need the key to paste into Mirall, including while the service is stopped. It normally reads the cached value from store.json and returns instantly; if the cache is empty it spins up a temporary container to derive the key from the seed, which takes a few seconds and writes the result back. It changes nothing else, never interrupts the running relay, and is safe to repeat. Returns the z-base-32 key, copyable and as a QR code.

Show Admin Token — run it to unlock the members page. It shows the token directly, with no confirmation step; the caution about treating it like a password sits beside the token. Upstream mints the bearer token for /admin/* on the first boot of the relay and logs it exactly once, on that boot, because an operator on StartOS has no shell; after that line scrolls away there is no second chance. This action reads the token from /data/admin-token in a temporary container with the volume mounted read-only, and returns it masked and copyable. It mints nothing and rotates nothing — upstream refuses to write a second token over an existing file precisely so your copy cannot be silently invalidated, and the read-only mount keeps that guarantee here. Allowed while the service is stopped, which is when an operator who has lost the token is most likely to be looking. Before the relay's first successful start there is no token, and the action says so rather than returning an empty value.

Test Reachability — run it when the Internet Reachability health check is red and you want the underlying detail, or after changing a port forward. It queries the relay's own admin endpoint and reports whether peers can connect to it directly (firewalled, port unstable, or still learning its address, each with its own explanation), the address the relay believes the internet sees (Seen from outside as: host:port, host (port changes per destination), host:31562 (listens on 49737) or not known yet), and the version and caps the relay advertises to clients. It distinguishes measured from asserted: with Assume Reachable on, firewalled: false is something the relay was told rather than something it found out, and the action says so instead of reporting success. Read-only, instant, safe to repeat, and requires the service to be running.

Configure Relay — run it to set whether the relay is public or private (Access, which becomes MIRALL_RELAY_ACCESS), the operator labels, the traffic caps, the banlist and static keys, the log level, or Assume Reachable. Saving writes the form to store.json and restarts the relay, which drops in-flight relayed connections; clients re-establish, falling back to a direct path where one exists. The seed and the public key are untouched, so the relay's address does not change. Safe to repeat.

Tasks

None. The package raises no tasks.

It used to raise one critical task on install and on every restore, asking the operator to run Show Relay Public Key. It was removed: a critical task blocks the service from starting, and this one only asked someone to look at a key that Show Relay Public Key displays at any time, including while the service is stopped. Worse, it re-raised on every reinstall, so a routine package update refused to start until somebody acknowledged a prompt that told them nothing new.

If a support conversation mentions a task blocking startup, the install predates 0.1.0:2 and the fix is to update.

Health Checks

Three checks. The first two are kept separate so that a relay which is running but unreachable is visibly distinct from one that is not running at all; the third says who the relay admits.

Check Method Grace Meaning
Relay UDP 49737 listening (/proc/net) 10 s The process is up and bound
Internet Reachability GET /readyz on 127.0.0.1:9200 120 s state: reachable: listening, bootstrapped, not firewalled, with a stable public address
Access GET /status.json on 127.0.0.1:9200 — Public, private with its member count, or restricted

Relay failing means the process did not start or could not bind — check the logs for a configuration error, since upstream refuses to boot on a malformed cap or key list rather than starting with a bad value.

Internet Reachability failing is the common case and usually not a fault in the package. It reports a failure when HyperDHT finds the relay firewalled; a firewalled relay serves 503 on /readyz upstream too, and bridges nothing. The fix is a switched-on Public address with a working path to it (StartTunnel with a matching Outbound Gateway, or a router forward), or Assume Reachable if the host genuinely has a public IP and it is the probe that is wrong. The long grace period is deliberate: the node has to join the DHT and have its address confirmed by other nodes before it can know, so red for the first minute or two means nothing.

It also fails when the relay is not firewalled but its port is unstable (state: port-unstable from upstream 0.4.2): something between the relay and the internet rewrites its outbound UDP port, so HyperDHT stops advertising a public address and peers cannot connect directly. This used to read green. See limitation 12.

While the relay is re-learning its public address after an IP change (state: unknown), the check shows loading, not failure, for up to 10 minutes (UNKNOWN_GRACE_MS in startos/main.ts), then fails. A home line with a dynamic IP goes through this on every reconnect; a server with a static IP never does. The timer lives in the health-check process, so a restart starts it over, which is right because the relay itself restarts through starting. Against an upstream older than 0.4.2, /readyz has no state and the check falls back to the firewalled flag alone.

While it is failing the check is re-run every 30 seconds, not at the SDK's default of every second: each failure is a log line, and a firewalled relay stays that way for minutes or hours, which buried the relay's own log under one line per second.

Access never fails. A private relay with no members reports success with "nobody can connect": that is a state the operator chose, and also what revoking the last member produces, so it is labelled rather than painted red.

Backups and Restore

The strategy is sdk.Backups.ofVolumes('main') — the whole volume copied wholesale, nothing dumped and replayed. That captures /data/seed, /data/members.json, /data/admin-token and /data/store.json. A backup of this service therefore contains the relay's identity and every member's seed; treat the backup with the care those two secrets deserve.

Nothing is deliberately excluded, because nothing on the volume is a cache: the relay's sessions, links and meter samples are all in memory and disposable by design.

Back this service up. The seed is not recoverable by any other means, and without it the relay comes back with a different public key that no existing client is configured for. Losing members.json separately revokes every member, since each membership is its seed.

A restored instance re-derives the same key, repairs file ownership automatically — see the recursive chown under Volume and Data Layout — and needs nothing re-entered. It raises no task. The port forward has to exist wherever it now runs.

Choosing a Setup

A relay is at its best on a host with a public IP. StartOS installs every interface with its public addresses off (only LAN addresses are on), and the SDK gives a package no way to change that, so every setup below includes switching a Public address on under Interfaces → Relay Endpoint. Three setups work, in order of preference:

  1. A server with a public IPv4 on its interface (dedicated server, a VPS running StartOS). Switch on its Public address. Nothing to forward. Outbound Gateway: default.
  2. A home server published through StartTunnel (recommended for home servers). The VPS's IP is fixed, no router change is needed, and it works behind CGNAT and DS-Lite. Switch on the Public address under the StartTunnel gateway and set the Outbound Gateway to StartTunnel as well (limitation 12). Recheck the Outbound Gateway after every install or update (limitation 10).
  3. A home router, only with a static public IPv4. Forward UDP 49737 to the server, with the external port also 49737 (some routers silently pick another if that one is taken, and a different external port shows as Port unstable), and switch on the Public address under the router's gateway. Outbound Gateway: default. On a line whose IP changes this setup breaks at every change (limitation 9), so use setup 2 there.

Behind CGNAT or DS-Lite (the router's WAN IPv4 differs from what an external "what is my IP" service shows, or is in 100.64.0.0/10), setup 3 is impossible and setup 2 is the only option. IPv6 does not help: the DHT is IPv4-only.

Limitations and Differences

  1. The relay is not public until the user makes it so. StartOS enables LAN addresses only; a Public address must be switched on by hand, and on a home router the port forwarded too. The package cannot do either. For a home server, StartTunnel is the recommended setup, and a router forward only suits a static public IPv4 (Choosing a Setup). The Internet Reachability failure message says so.

  2. Symmetric NAT cannot be worked around. If your router rewrites the port of outbound UDP, HyperDHT cannot keep a stable mapping and the relay stays unusable. A host with a public IP is the only fix. A tunnel counts: anything between the relay and the internet that rewrites its outbound port has the same effect as a symmetric router, and shows as Port unstable (limitation 12).

  3. The external port must be 49737, not merely forwarded. StartOS prefers 49737 but falls back to another port if it is already taken, and a fallback cannot work: HyperDHT probes reachability by asking remote nodes to send packets to its local socket port at the observed public IP, so an external port that differs can never pass. Check the Relay Endpoint interface after install, and if it did not get 49737, free that port rather than forwarding the one it shows.

  4. Invites are managed on upstream's members page, not by a StartOS action. Members are created, re-shown and revoked on the members page — Open UI, then Members — which is /admin/ on the UI's binding. Auth is the admin token from /data/admin-token — get it from the Show Admin Token action, which is there because upstream logs the token exactly once, on the boot that mints it.

    No Create Invite action is wrapped around this on purpose: upstream's page already does the job the actions would, and duplicating it would put two writers on the roster with no gain. mirall-relay invite … also still works through start-cli package attach.

    Finding the page used to be the hard part: before upstream 0.3.0 the only on-page link appeared once access.mode was already invite, and this package ships the default open mode — so there was nothing to click, while minting members is precisely what you must do before switching the mode. 0.3.0's pageNav (src/operator/status/page.js) links it in every mode, and this package exports it as its own interface on top of that, so it is reachable without going through the status page at all.

    The mode itself is Configure Relay → Access, which sets MIRALL_RELAY_ACCESS to open (Public) or invite (Private). There is no precondition: Private with an empty roster saves, and the relay then refuses every connection by design until the first member exists. The Access health check and the status page both say so. Members can be minted before or after the switch; minting first means going private disconnects nobody.

    The mirall://relay/… ticket a member receives is a bearer credential — whoever holds it is that member — and needs a Mirall client that understands tickets.

  5. scripts/probe.js is not exposed as an action. It needs outbound DHT access and two throwaway nodes; use Test Reachability, or run the probe from another machine against the public key.

  6. The allowlist cannot pin end users, exactly as upstream documents: a Mirall client's DHT node key is regenerated on every app start, so the Static Keys (advanced) field in Configure Relay only pins infrastructure whose DHT identity you control. Upstream's answer to a private relay for people is invite membership, where the member's identity derives from the seed in their ticket and is therefore stable — see limitation 4 for its status here.

  7. No seed rotation action. Rotating the seed changes the relay's address and strands every configured client, so it is deliberately not a button. To do it anyway, uninstall and reinstall.

  8. Upstream's remaining knobs are not exposed. --bootstrap, --ephemeral, --max-link-ms, --max-pending, --session-rate, --over-rate-grace-ms, --meter-ms, --admin-write and --admin-ui are left at their upstream defaults and have no form field.

  9. A changed WAN IP switches the relay's router address off. StartOS records an enabled Public address as a literal IP (addresses.enabled holds e.g. "87.122.156.81:49737"), so when the ISP assigns a new IP the new address appears in Interfaces switched off, and StartOS forwards the port from the LAN only. The relay then reads firewalled until someone switches the new address on; a restart does not help. Seen on 2026-09-22 after a daily reconnect. The old address also stays listed as enabled in the database, invisible in the UI. StartOS's own docs note there is no dynamic-DNS equivalent for raw IPs. Mirall peers find the relay by key, so nothing else depends on the IP; this is purely the forward being dropped. Use StartTunnel on any line whose IP changes. While the DHT re-learns an address after a change, upstream 0.4.2 reports state: unknown and Internet Reachability shows loading for up to 10 minutes.

  10. An install or update drops the Outbound Gateway, and neither a Restart nor a Stop/Start reliably brings it back. Confirmed with a routing capture on a live box (2026-09-20). A package install or update gives the service a new LXC container with a new IP. StartOS removes the policy-routing rule for the old IP (ip rule from <container IP> lookup <1000 + gateway ifindex>) and does not create one for the new IP, while its database still reports the gateway as set. The relay's egress then leaves via the default WAN, HyperDHT observes the home address, the reachability probe is aimed at it, and the relay reports firewalled: true although the forward is intact. The tell is reachability.publicHost in /status.json (the Status Page's Seen from outside as) showing the home IP.

A Restart reuses the container, so it neither causes nor repairs this. Stop then Start is not a reliable repair: it was seen to work once and to fail once on the same box on the same day, the container and its missing rule surviving it. What repaired it every time is clearing and re-setting the gateway (start-cli package set-outbound-gateway mirall-relay, then again with the gateway id, or the Set Outbound Gateway action twice); setting the same value again without clearing is a no-op. Once the route is right the relay recovers unattended through upstream's re-probe, but only after HyperDHT's view of its own address settles — 28 minutes in the observed case, because it samples its address only when it meets new nodes. A restart at that point takes under a minute. This is a StartOS defect, not something the package can work around from inside the container. 11. The status page has no authentication of its own. StartOS is what stands in front of it. Exposing the Status Page interface on a public gateway publishes the relay's traffic counters and DHT state — see Network Access and Interfaces. 12. The relay must send and receive through the same public gateway, and that gateway must not rewrite its port. Published on StartTunnel → Outbound Gateway StartTunnel. Published on the router → Outbound Gateway default. A mismatch receives on one IP and sends from another, and StartOS allows it without a warning.

Even with matching gateways the outbound port can be rewritten on the way out. In the case that prompted this limitation, the relay was published through StartTunnel, and the server's own NAT into the tunnel rewrote the relay's outbound source port after a network change; the tunnel then preserved the rewritten port. Inbound traffic still arrived on 49737, so the old health check stayed green while members could not connect: HyperDHT offers peers a direct connection only when the port it is seen on is the port it listens on.

How to recognise it: Internet Reachability red with "outbound port is being rewritten"; the status page shows Port unstable; /readyz and /status.json report state: "port-unstable", with either portRandomized: true or a publicPort different from the listening port; the relay log says outbound UDP port is being rewritten.

What to try, in order (cheapest and UI-only first; this is not a ranking of how common each cause is):

  1. Gateway mismatch. Set the Outbound Gateway to the gateway the relay's public address is on. Recheck after every install or update (limitation 10).
  2. Stale NAT state after a network change. Restart the relay. If it is still red after about five minutes, clear and re-set the Outbound Gateway (the limitation 10 procedure), then restart. With SSH: sudo conntrack -D -p udp -s <relay container IP>.
  3. A NAT that really rewrites ports (some CGNAT, some mobile routers, some VPS NATs). Not fixable on this server: use a router forward on a line with a public IPv4, or StartTunnel.

Which UI-only step reliably clears stale NAT state is not yet established; the SSH command always does.


Quick Reference for AI Consumers

package_id: mirall-relay
image: built from upstream Dockerfile (submodule ./mirall-relay)
architectures: [x86_64, aarch64]
subcontainers: [mirall-relay-sub]
volumes:
  main: /data
file_models:
  - store.json
startos_managed_env_vars:
  - MIRALL_RELAY_SEED_FILE
  - MIRALL_RELAY_ROSTER_FILE
  - MIRALL_RELAY_ADMIN_TOKEN_FILE
  - MIRALL_RELAY_PORT
  - MIRALL_RELAY_ADMIN_HOST
  - MIRALL_RELAY_ADMIN_PORT
  - MIRALL_RELAY_REGION
  - MIRALL_RELAY_OPERATOR
  - MIRALL_RELAY_ASSUME_REACHABLE
  - MIRALL_RELAY_MAX_ACTIVE_LINKS
  - MIRALL_RELAY_MAX_SESSIONS_PER_KEY
  - MIRALL_RELAY_MAX_LINK_RATE
  - MIRALL_RELAY_MAX_LINK_BYTES
  - MIRALL_RELAY_ALLOWLIST
  - MIRALL_RELAY_BANLIST
  - MIRALL_RELAY_LOG_LEVEL
dependencies: none
interfaces:
  relay: { type: api, port: 49737, protocol: udp }
  admin: { type: ui, port: 9200, protocol: http, path: "/", name: Relay UI }
actions:
  - show-relay-key
  - show-admin-token
  - test-reachability
  - configure
admin_pages:
  "/": anonymous status page
  "/admin/": members page, bearer token from /data/admin-token (shell + assets anonymous)
tasks: none
health_checks:
  - relay
  - reachability
  - access
access_mode: open | invite   # Configure Relay → Access; open on install
secrets_on_volume:
  - /data/seed
  - /data/members.json
  - /data/admin-token

About

StartOS package for mirall-relay

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages