mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-11 13:28:57 +00:00
chore(unraid): remove unraid/ directory (template moved to PerpetualSoftware/unraid-templates) (#430)
The Unraid CA template has its own home now: https://github.com/PerpetualSoftware/unraid-templates That repo is required for the new ca.unraid.net/submit portal flow (needs ca_profile.xml + dedicated repo per submission). Pad has been submitted and auto-approved pending the next CA build, so the old pad/unraid/ files have no remaining consumers: - Docs (pad-web /docs/self-hosting/unraid) already point at the new repo's raw URLs (#96, merged 2026-05-06) - Forum support thread + ca_profile.xml + pad/pad.xml in the templates repo all reference the canonical new location - No CI / GoReleaser / Docker / Make targets touch unraid/ — verified with rg before deletion Refs IDEA-1184, PLAN-1185, TASK-1191.
This commit is contained in:
@@ -1,166 +0,0 @@
|
||||
# Pad on Unraid
|
||||
|
||||
Run [Pad](https://getpad.dev) on your Unraid server — local-first project management for developers and AI coding agents. Single Go binary, SQLite by default, your data stays on your box.
|
||||
|
||||
This directory holds the [Community Applications](https://forums.unraid.net/topic/38582-plug-in-community-applications/) (CA) template (`pad.xml`) and supporting docs. The full install walkthrough lives at <https://getpad.dev/docs/self-hosting/unraid>.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Unraid 6.12 or later.
|
||||
- Community Applications plugin installed.
|
||||
|
||||
## Install
|
||||
|
||||
Once Pad is approved in the CA index (tracked in [PLAN-1166](https://github.com/PerpetualSoftware/pad)), the easy path:
|
||||
|
||||
1. Open **Apps** in the Unraid web UI.
|
||||
2. Search for **Pad**.
|
||||
3. Click **Install** → adjust the form fields if you want non-default ports / appdata path → **Apply**.
|
||||
4. Wait ~10 seconds for the container to come up healthy.
|
||||
5. Click the container's **Logs** button. Look for the box that starts with `Pad first-run setup` and copy the URL — it looks like `http://<your-tower>:7777/setup#token=<TOKEN>`.
|
||||
6. Paste that URL into your browser. The token is read from the URL fragment (browser-only — never sent to a server log) and stripped from the address bar before you create the admin account. Fill in email, name, password → done.
|
||||
|
||||
### Pre-CA install (manual, for early adopters)
|
||||
|
||||
Before Pad lands in the CA index, you have two routes for installing the template manually. The "Add Repository" / "Template Repositories" feature in older Unraid versions [was removed in Unraid 6.10.0-rc1](https://forums.unraid.net/topic/114809-i-want-to-make-my-own-private-template-repository-but-it-doesnt-work/) and is not coming back, so the recommended path is now a direct sideload.
|
||||
|
||||
#### Route A — CA Private Folder (recommended)
|
||||
|
||||
The closest experience to what you'll get post-CA-approval. The template appears under CA's **Private** category and uses the same install form CA users will see.
|
||||
|
||||
```bash
|
||||
ssh root@<your-tower>
|
||||
mkdir -p /boot/config/plugins/community.applications/private/perpetualsoftware
|
||||
wget -O /boot/config/plugins/community.applications/private/perpetualsoftware/pad.xml \
|
||||
https://raw.githubusercontent.com/PerpetualSoftware/pad/main/unraid/pad.xml
|
||||
```
|
||||
|
||||
Then in the Unraid web UI: open **Apps**, search for "Pad" (or browse to the **Private** category). The listing shows the icon + Overview just like a CA-published app. Click **Install** → form → **Apply** — same flow as a CA-approved install.
|
||||
|
||||
To remove later: delete the file. To update: re-run the `wget` (CA picks up the new file on next page load).
|
||||
|
||||
#### Route B — Docker tab sideload (CA-less fallback)
|
||||
|
||||
If you don't have CA installed, or want to skip CA's listing UI entirely:
|
||||
|
||||
```bash
|
||||
ssh root@<your-tower>
|
||||
wget -O /boot/config/plugins/dockerMan/templates-user/my-pad.xml \
|
||||
https://raw.githubusercontent.com/PerpetualSoftware/pad/main/unraid/pad.xml
|
||||
```
|
||||
|
||||
Then in the Unraid web UI: **Docker** tab → **Add Container** → **Template** dropdown → pick **Pad**.
|
||||
|
||||
Functionally identical container behavior; just skips the CA UX surface.
|
||||
|
||||
## First-admin setup
|
||||
|
||||
By default, the container generates a one-time bootstrap token at first start and logs it inside a banner you grab from **Logs**. That token is required to claim the first admin account from a remote browser.
|
||||
|
||||
Two ways to skip the token-copy step on a trusted network:
|
||||
|
||||
- **Open setup (web UI form)** — set the **Bypass Setup Token** template field to `true` (env var `PAD_BYPASS_SETUP_TOKEN=true`). Browse to `http://<your-tower>:7777/setup` and create the first admin directly — no token, no `docker exec`. The setting only matters before any user exists; once you've claimed an admin, the bootstrap surface is closed regardless of this flag.
|
||||
- **Local CLI** — `docker exec -it Pad pad auth setup` from the Unraid console. Loopback-only so it works without a token.
|
||||
|
||||
WARNING: leaving **Bypass Setup Token** on while the WebUI port is exposed to the open internet means anyone who reaches it first can claim the admin account. Use it on LAN-only / Tailscale-only / firewalled deployments.
|
||||
|
||||
Cloud mode (`PAD_CLOUD=true` or `PAD_MODE=cloud`) ignores `PAD_BYPASS_SETUP_TOKEN` — cloud bootstrap stays loopback-only by design.
|
||||
|
||||
## Where your data lives
|
||||
|
||||
All persistent state lives under your appdata path (default `/mnt/user/appdata/pad/`):
|
||||
|
||||
| Path | What | Critical? |
|
||||
| --- | --- | --- |
|
||||
| `pad.db` + `pad.db-wal` + `pad.db-shm` | SQLite database | yes |
|
||||
| `encryption.key` | Encryption key for sensitive fields (TOTP seeds, OAuth tokens) | **yes — losing this bricks encrypted data** |
|
||||
| `attachments/` | Uploaded attachment blobs | yes |
|
||||
| `logs/server.log` | Server log | nice-to-have |
|
||||
| `config.toml` | Workspace config | nice-to-have |
|
||||
| `pad.pid` | PID file | ephemeral |
|
||||
| `.bootstrap-token` | First-run setup token (auto-deleted on first admin claim) | one-time |
|
||||
|
||||
One mount, complete coverage. The default appdata field in the template gives you all of this without thinking about it.
|
||||
|
||||
## Backups
|
||||
|
||||
Always stop the container first so SQLite isn't mid-write. Then:
|
||||
|
||||
```bash
|
||||
# Backup
|
||||
tar -C /mnt/user/appdata -czf "pad-backup-$(date +%F).tar.gz" pad/
|
||||
|
||||
# Restore
|
||||
tar -C /mnt/user/appdata -xzf "pad-backup-2026-05-06.tar.gz"
|
||||
```
|
||||
|
||||
The `-C` flag makes both archive and restore relative to `/mnt/user/appdata`, so the `pad/` directory inside the tarball always lands at `/mnt/user/appdata/pad/` regardless of where you run the command. Without `-C`, GNU tar warns "Removing leading /" and stores relative paths anyway, but extracting from a different cwd would scatter the data — easy to get wrong.
|
||||
|
||||
The container's entrypoint runs a `chown -R` to your configured `PUID:PGID` on every start, so PUID/PGID don't have to match between source and destination Unraid hosts.
|
||||
|
||||
## Upgrading
|
||||
|
||||
In Unraid → **Docker** → click the Pad container → **Force Update**. CA pulls a fresh `:latest`, recreates the container, and your appdata persists.
|
||||
|
||||
Pad releases are at <https://github.com/PerpetualSoftware/pad/releases>. Watching that repo on GitHub gets you a notification when a new version ships.
|
||||
|
||||
## Reverse proxy
|
||||
|
||||
If you front Pad with **SWAG** or **NGINX Proxy Manager** (recommended for HTTPS + a real hostname):
|
||||
|
||||
1. In the template's **Public URL** field, enter your external URL: `https://pad.example.com`.
|
||||
2. In your reverse proxy, point `pad.example.com` at `<unraid-host>:7777`.
|
||||
3. Standard reverse-proxy headers are fine — Pad doesn't need any special config.
|
||||
|
||||
The **Public URL** is required if you want emailed invitations to point at your real hostname (otherwise links point at `http://<unraid-ip>:7777`, which recipients can't reach).
|
||||
|
||||
## Email (optional)
|
||||
|
||||
If you want Pad to send workspace invitations by email, fill in:
|
||||
|
||||
- **Maileroo API Key** — sign up at <https://maileroo.com> (free tier is fine).
|
||||
- **Email From** — sender address on a domain you control.
|
||||
- **Email From Name** — display name (defaults to "Pad").
|
||||
|
||||
Without these, invitations fall back to copyable join codes you paste into the invitee's CLI. Not worse — just different.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Port 7777 already in use** → change the **WebUI Port** field to a free port (e.g. 7778).
|
||||
- **`/data` write errors in the logs** → the entrypoint validates `PUID`/`PGID` and rejects 0 or non-numeric. Stick to defaults (99/100) unless you have a specific reason; the entrypoint chowns appdata on every start, so a wrong-uid recovery is a single restart away.
|
||||
- **Image won't pull** → verify GHCR is publicly pullable: `docker pull ghcr.io/perpetualsoftware/pad:latest` from any machine.
|
||||
- **Reverse proxy returns 502** → the **Public URL** field must match the public-facing scheme + host (e.g. `https://pad.example.com`, not `http://`); also verify your proxy passes the request to the container's mapped port.
|
||||
- **First-run banner not showing in logs** → it logs once on first start when zero users exist. If users already exist (you've already bootstrapped), the banner is suppressed. Restart only re-shows it on a fresh / wiped appdata.
|
||||
|
||||
## Support
|
||||
|
||||
- **Forum thread** *(once opened — see HT-1174)*: link will be added here and in the template's `<Support>` field.
|
||||
- **GitHub Issues**: <https://github.com/PerpetualSoftware/pad/issues> for bug reports and feature requests.
|
||||
- **Documentation**: <https://getpad.dev/docs/self-hosting/unraid> *(landing via TASK-1172 / pad-web PR #93)*.
|
||||
|
||||
## Icon
|
||||
|
||||
`unraid/icon.png` is a 256×256 PNG downsampled (LANCZOS) from `web/static/icon-512.png` — Pad's existing app icon. Reused rather than designed afresh so the CA listing matches getpad.dev favicons + PWA icons. Update both files in lockstep if the brand mark changes.
|
||||
|
||||
## Template format conformity
|
||||
|
||||
The Unraid wiki ([Docker Template Schema](https://wiki.unraid.net/DockerTemplateSchema)) is explicit:
|
||||
|
||||
> "the only supported XML format is that which is generated by Unraid's docker tab when hitting SAVE on the template. Any manual editing of the XML files may present compatibility issues for CA and if they turn out to be incompatible, will result in the template being blacklisted within CA until brought into conformity with the dockerMan generated files."
|
||||
|
||||
To stay safely on Squid's good side, keep `pad.xml` aligned with what dockerMan emits when an operator hits **Apply** on the install form. If you're editing this file by hand, validate by:
|
||||
|
||||
1. Sideload your edited copy via the Route A path above.
|
||||
2. Open it in CA, hit **Apply** to install it.
|
||||
3. Diff your edited copy against `/boot/config/plugins/dockerMan/templates-user/<container-name>.xml` (the post-SAVE serialized version).
|
||||
4. Migrate any structural diff (added/removed/renamed elements, attribute-form changes) back into the canonical file. Cosmetic diffs (line endings, em dash → numeric entity) are XML-equivalent and OK to leave.
|
||||
|
||||
Things to know about dockerMan's serializer that bit us on the first round:
|
||||
|
||||
- **XML comments don't survive a SAVE round-trip** — dockerMan strips `<!-- ... -->`. Don't embed maintainer notes inside `pad.xml`; put them here in this README instead.
|
||||
- **`<Description>` is not a recognized field** — dockerMan drops it. `<Overview>` is the canonical CA-displayed text.
|
||||
- **BBCode (`[b]...[/b]`) is stripped from `<Overview>`** — use plain text for emphasis.
|
||||
- **Empty `<Config>` elements should be self-closing** (`<Config .../>` not `<Config></Config>`).
|
||||
- **The schema includes empty marker elements** — `<MyMAC/>`, `<ReadMe/>`, `<Requires/>`, `<TailscaleStateDir/>` etc. dockerMan emits them all even when empty.
|
||||
|
||||
Last verified against Unraid 7.x dockerMan output on 2026-05-06.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<Container version="2">
|
||||
<Name>Pad</Name>
|
||||
<Repository>ghcr.io/perpetualsoftware/pad:latest</Repository>
|
||||
<Registry>https://github.com/PerpetualSoftware/pad/pkgs/container/pad</Registry>
|
||||
<Network>bridge</Network>
|
||||
<MyIP/>
|
||||
<MyMAC/>
|
||||
<Shell>sh</Shell>
|
||||
<Privileged>false</Privileged>
|
||||
<Support>https://forums.unraid.net/topic/PLACEHOLDER-pad-support-thread/</Support>
|
||||
<Project>https://getpad.dev</Project>
|
||||
<ReadMe/>
|
||||
<Overview>
|
||||
Pad is local-first project management for developers and AI coding agents.
|
||||
Single Go binary, SQLite by default, MCP-ready (Claude Code / Cursor / Windsurf).
|
||||
Your data stays on your Unraid box — no telemetry, no account required, no
|
||||
cloud lock-in.
|
||||
|
||||
After install, click the container's Logs button to grab the
|
||||
first-run bootstrap token, then visit the WebUI to claim the first admin.
|
||||
See the install guide for screenshots: https://getpad.dev/docs/self-hosting/unraid
|
||||
</Overview>
|
||||
<Category>Productivity: AI:</Category>
|
||||
<WebUI>http://[IP]:[PORT:7777]/</WebUI>
|
||||
<TemplateURL>https://raw.githubusercontent.com/PerpetualSoftware/pad/main/unraid/pad.xml</TemplateURL>
|
||||
<Icon>https://raw.githubusercontent.com/PerpetualSoftware/pad/main/unraid/icon.png</Icon>
|
||||
<ExtraParams/>
|
||||
<PostArgs/>
|
||||
<CPUset/>
|
||||
<DateInstalled/>
|
||||
<DonateText/>
|
||||
<DonateLink/>
|
||||
<Requires/>
|
||||
<Config Name="WebUI Port" Target="7777" Default="7777" Mode="tcp" Description="Pad web UI. Browse to http://[your-tower]:[port]/ after install." Type="Port" Display="always" Required="true" Mask="false">7777</Config>
|
||||
<Config Name="Appdata" Target="/data" Default="/mnt/user/appdata/pad/" Mode="rw" Description="Pad's persistent data: SQLite database, attachments, encryption key, logs, and config. Back this up to keep your workspace safe." Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/pad/</Config>
|
||||
<Config Name="PUID" Target="PUID" Default="99" Mode="" Description="User ID the pad process runs as. Default 99 (nobody) matches Unraid's appdata permissions. Change only if you know what you're doing — must be a positive integer." Type="Variable" Display="advanced" Required="false" Mask="false">99</Config>
|
||||
<Config Name="PGID" Target="PGID" Default="100" Mode="" Description="Group ID the pad process runs as. Default 100 (users) matches Unraid's appdata permissions. Change only if you know what you're doing — must be a positive integer." Type="Variable" Display="advanced" Required="false" Mask="false">100</Config>
|
||||
<Config Name="Log Level" Target="PAD_LOG_LEVEL" Default="info" Mode="" Description="Verbosity for the server log. One of: debug, info, warn, error." Type="Variable" Display="advanced" Required="false" Mask="false">info</Config>
|
||||
<Config Name="Bypass Setup Token" Target="PAD_BYPASS_SETUP_TOKEN" Default="false" Mode="" Description="If true, the first admin account can be created directly from the web UI (browse to http://[your-tower]:[port]/setup) without copying a bootstrap token from the container logs. Convenient for trusted home networks. Default false (token required from logs). WARNING: while no users exist, anyone who can reach the WebUI port can claim the first admin account — only set true on networks you trust (LAN behind a firewall, Tailscale, etc.). Once an admin exists this setting has no effect." Type="Variable" Display="always" Required="false" Mask="false">false</Config>
|
||||
<Config Name="Public URL" Target="PAD_URL" Default="" Mode="" Description="External URL when pad is behind a reverse proxy (SWAG / NGINX Proxy Manager / etc.). Required for emailed invitation links to point at the right host. Example: https://pad.example.com" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="Maileroo API Key" Target="PAD_MAILEROO_API_KEY" Default="" Mode="" Description="Optional. Enables transactional email (workspace invitations). Without it, invites use copyable join codes via the CLI. Sign up at maileroo.com." Type="Variable" Display="advanced" Required="false" Mask="true"/>
|
||||
<Config Name="Email From" Target="PAD_EMAIL_FROM" Default="" Mode="" Description="Sender address for invitation emails. Required if Maileroo API Key is set. Must be on a domain you control." Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="Email From Name" Target="PAD_EMAIL_FROM_NAME" Default="Pad" Mode="" Description="Display name on outbound emails (the human-friendly part before the address). Defaults to 'Pad'." Type="Variable" Display="advanced" Required="false" Mask="false">Pad</Config>
|
||||
<TailscaleStateDir/>
|
||||
</Container>
|
||||
Reference in New Issue
Block a user