Typr-Companion

Typr-Companion

apps.detail.types.app from max.prime's Repository

apps.detail.sections.overview

Optional native LaTeX, TeXpresso, and scoped workspace service for Typr. Stateless by default; one dedicated workspace can be mapped explicitly. Trusted LAN/VPN use only; never expose it publicly.

Install Typr Companion on Unraid

Typr Companion can run on Unraid from the official ghcr.io/max-prime-math/typr-server image. It is stateless by default. One dedicated host directory can optionally be mapped for explicit manual project sync; browser-local Typr remains authoritative.

The service has no authentication. Use it only on a trusted LAN or private VPN, with mutually trusted users and documents. Never expose it to the public Internet, through router port forwarding, a public tunnel, or a public reverse proxy. TLS improves transport and browser compatibility; it does not add application authentication.

Stock Unraid kernels may not provide Landlock. This template therefore opts into a narrowly limited fallback: Companion may run without its native filesystem sandbox only while it is stateless and has no host workspace mounted. Keep this mode limited to mutually trusted documents. If any workspace is configured, Companion still requires Landlock and refuses startup when it is unavailable.

Install the template

Until the template is listed in Community Applications, install it as a user template:

  1. Open an Unraid terminal.

  2. Download unraid/typr-companion.xml:

    curl -fsSL \
      https://raw.githubusercontent.com/max-prime-math/typr-server/main/unraid/typr-companion.xml \
      -o /boot/config/plugins/dockerMan/templates-user/typr-companion.xml
    
  3. Open Docker → Add Container and select Typr-Companion.

  4. Keep bridge networking and container port 8484.

  5. Add the exact self-hosted Typr origin to Allowed Typr origins if needed.

  6. Leave Workspace directory and Workspace API root blank for the default stateless deployment. The prefilled Workspace ID is ignored while the root is blank.

  7. Keep Allow stateless Unraid fallback set to 1 on a stock Unraid kernel. This does not permit a mapped workspace without Landlock.

  8. Apply the template and wait for a healthy container.

The template enforces UID 1000, non-privileged operation, dropped capabilities, no-new-privileges, a read-only root, 512 MiB no-exec tmpfs, 256 PIDs, 2 GiB memory/swap, and two CPUs. The image probes its Landlock launcher before listening. When that probe fails, the explicit template opt-in permits only the volume-free stateless fallback and logs a prominent trusted-document warning. Without that opt-in, or whenever a workspace is mapped, startup fails closed.

Optional mapped workspace

Configure all three advanced workspace fields together:

This mode requires an Unraid kernel with working Landlock support. Stock kernels that return Landlock is unavailable cannot safely enable the mapped workspace; leave the directory and API root blank. The stateless fallback never bypasses this check.

  • Workspace directory: one newly created dedicated directory, mounted RW to /workspace.
  • Workspace API root: exactly /workspace.
  • Workspace ID: a stable opaque identifier such as home-workspace.

The host directory must be readable and writable by UID 1000. Do not map /, /mnt, /mnt/user, an entire share, an appdata root, a symlinked directory, or the Docker socket. Create a narrowly named subdirectory and grant UID 1000 only the access it needs.

The API exposes regular files below that exact root; it does not expose the host path or arbitrary browsing. Browser storage remains the primary copy and sync is manual. Unlinking or removing the container does not delete mapped files, but an explicit file-API deletion does delete that selected host file. Keep independent backups.

Verify the container

From Unraid:

curl -fsS http://127.0.0.1:8484/api/v1/status

The response reports protocol version 1, native compile capabilities, and projectStorage: false unless all mapped-workspace fields are valid. The WebUI link opens the same status response. In fallback mode, the container log states that the native filesystem sandbox is unavailable and that trusted documents are required. Startup failures are visible in the same log.

Add trusted HTTPS

In a browser on another device, 127.0.0.1 means that browser device, not the Unraid server. An HTTPS Typr page also cannot call a plain HTTP/WS Companion because the browser blocks mixed content. Create a dedicated client-trusted HTTPS hostname restricted by firewall or VPN to trusted clients. Forward it to http://UNRAID-IP:8484, enable WebSocket upgrades, use a long read timeout, and allow request bodies of at least 25 MiB. For example:

location / {
    proxy_pass http://UNRAID-IP:8484;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
    client_max_body_size 25m;
}

Keep the hostname unreachable from the public Internet. Plain HTTP on a non-loopback LAN address is not a secure context and a self-hosted Typr page will lose service-worker/PWA and filesystem-related features. A self-signed certificate must be trusted by every client before it is useful.

Private HTTPS with Tailscale Serve

Install and connect the official Tailscale plugin on the Unraid host. Keep the Typr-Companion container's per-container Use Tailscale switch off. That Unraid feature injects a mounted startup hook which requires root privileges; Companion deliberately runs as UID 1000 with a read-only root, and its stateless fallback rejects unexpected mounts. Enabling the switch therefore causes a restart loop rather than a working tailnet endpoint.

With Companion running normally on host port 8484, use host-level Tailscale Serve instead:

tailscale serve --bg --https=8443 http://127.0.0.1:8484
tailscale serve status

Enter the resulting base URL, such as https://UNRAID-NAME.TAILNET.ts.net:8443, in Typr. Serve terminates trusted TLS and proxies both the HTTP API and WebSocket upgrade within the tailnet. The browser device must be connected to that tailnet and allowed by its access rules. Keep Tailscale Funnel disabled: Funnel would make this unauthenticated service public. If Typr itself uses a Tailscale HTTPS origin, add that exact scheme, hostname, and port to Allowed Typr origins.

Connect Typr

  1. Open Typr in the browser that will use Companion.
  2. Open Settings → Editor → Typr Companion.
  3. Enter the browser-reachable HTTPS URL and select Apply.
  4. If a workspace is configured, open Settings → Sync and explicitly link the selected project.

The URL is saved only in that browser. Allowed origins contain exact scheme, host, and port values with no path or trailing slash. CORS is not authentication. Chrome or Edge may also request Local Network Access permission.

If the status remains unavailable, inspect the browser console, Companion logs, reverse-proxy WebSocket settings, firewall/VPN rules, certificate trust, and TYPR_COMPANION_ALLOWED_ORIGINS.

Update, pin, roll back, or remove

Use Unraid's normal container update action for latest. For reproducible native TeX behavior, change Repository to a complete version after it is published, for example:

ghcr.io/max-prime-math/typr-server:0.1.4

Rollback uses the same field with the prior known-good version. Removing the container removes no browser-local projects and no mapped host directory.

The template remains a direct user template until both public image tags exist, it passes install/update/rollback/removal and HTTPS/WebSocket tests on a real Unraid host, and a maintained support destination appears in the template's Support field. An optional profile Forum field may point to the same destination. Then run npm run test:unraid -- --submission-ready and the portal's Validate and Scan actions before the maintainer explicitly approves Community Applications submission.

apps.marketingCta.appInstallTitle

apps.marketingCta.appInstallDescription

apps.installHelp.stepOpen apps.installHelp.stepSearchApp apps.installHelp.stepReview apps.installHelp.stepInstall

apps.detail.sections.requirements

Use only on a trusted LAN or private VPN with mutually trusted documents. Never expose this unauthenticated service to the public Internet. Remote browser use requires a client-trusted HTTPS reverse proxy with WebSocket support and firewall/VPN restriction. For Tailscale, keep the container's Use Tailscale switch off and use host-level Tailscale Serve; never use Funnel. Stock Unraid may use the explicit volume-free stateless fallback; any mapped workspace requires working Landlock support and otherwise fails closed.

apps.detail.sections.categories

apps.detail.sections.related

apps.detail.sections.details

apps.detail.details.repository
ghcr.io/max-prime-math/typr-server:latest
apps.detail.details.lastUpdated2026-08-13
apps.detail.details.firstSeen2026-08-12

apps.detail.sections.runtime

apps.detail.details.webui
http://[IP]:[PORT:8484]/api/v1/status
apps.detail.details.network
bridge
apps.detail.details.shell
sh
apps.detail.details.privileged
false
apps.detail.details.extraParams
--restart=unless-stopped --user=1000:1000 --read-only --tmpfs=/tmp:rw,nosuid,nodev,noexec,size=536870912 --cap-drop=ALL --security-opt=no-new-privileges:true --pids-limit=256 --memory=2g --memory-swap=2g --cpus=2

apps.detail.sections.configuration

Companion portPorttcp

Host port used by the reverse proxy and local status checks. Container port must remain 8484.

apps.detail.config.target
8484
apps.detail.config.default
8484
apps.detail.config.value
8484
Allowed Typr originsVariable

Comma-separated exact browser origins, including scheme, host, and port with no path or trailing slash. Add the self-hosted Typr origin. CORS is not authentication.

apps.detail.config.target
TYPR_COMPANION_ALLOWED_ORIGINS
apps.detail.config.default
https://typr.ca,https://beta.typr.ca,https://dev.typr.ca
apps.detail.config.value
https://typr.ca,https://beta.typr.ca,https://dev.typr.ca
Allow stateless Unraid fallbackVariable

Keep exactly 1 on stock Unraid: if Landlock is unavailable, allow trusted-document compilation only when no host workspace is mounted. A mapped workspace always fails closed without Landlock.

apps.detail.config.target
TYPR_COMPANION_ALLOW_UNSANDBOXED_STATELESS
apps.detail.config.default
1
apps.detail.config.value
1
Workspace directoryPathrw

Optional one exact dedicated project directory. Never map /, /mnt, /mnt/user, a broad share, appdata root, symlinked root, or the Docker socket. UID 1000 needs read/write access.

apps.detail.config.target
/workspace
Workspace API rootVariable

Set exactly /workspace only when Workspace directory is configured. Leave blank to disable the file API.

apps.detail.config.target
TYPR_COMPANION_WORKSPACE_ROOT
Workspace IDVariable

Stable opaque letters/numbers/dot/underscore/hyphen identifier for browser bindings; never put a host path here. Ignored while the API root is blank.

apps.detail.config.target
TYPR_COMPANION_WORKSPACE_ID
apps.detail.config.default
unraid-workspace
apps.detail.config.value
unraid-workspace