Close the remaining "secrets touch a plaintext file" gap. The unattended
restart mode now SEALS the operator-chosen wallet password to the host with
`systemd-creds encrypt` (ciphertext at rest, read via LoadCredentialEncrypted,
decrypted into a tmpfs credentials dir at each start), so no plaintext wallet
key is written to disk. When systemd-creds is unavailable it falls back to the
legacy root-owned 0400 plaintext file with a loud warning, and re-running
`setup --reconfigure` once it is available upgrades to encryption.
- wizard: seal via systemd-creds (injectable for tests), write the
encrypted.conf drop-in, keep the manual.conf tmpfs path unchanged;
reconfiguring a till that keeps no readable password on disk (encrypted or
manual) now prompts for the existing password to reopen the wallet.
- startup: loud deprecation warning when a money secret (GP_MNEMONIC,
GP_WALLET_PASSWORD, GP_NSEC) is supplied INLINE rather than via a *_FILE or
systemd credential; the value is never logged, only the variable name.
- docs: README, .env.example, install.sh, and the systemd unit updated to the
encrypted-at-rest default and the honest fallback/trade-off.
Tests: gp-core config + gp-core/gp-server setup cover the inline-secret warning,
the encrypted drop-in, the sealed-vs-plaintext shapes, and encrypted
reconfigure. Full workspace suite green; fmt introduces no new drift; clippy
-D warnings clean on the workspace crates.
- gp-server.service: drop the GP_MNEMONIC credential from the default unit
(the seed lives only encrypted at rest + the operator's written backup);
keep GP_WALLET_PASSWORD_FILE via LoadCredential. A commented first-boot-only
bootstrap remains for the no-wizard path.
- install.sh: end by offering to run `gp-server setup` (no longer pre-writes
the env file, which would block the wizard's re-run guard).
- package-woocommerce.sh: build goblinpay-woocommerce.zip (single top-level
folder) as a release artifact.
- WooCommerce plugin: fix the default server URL port (8192 -> 8080) to match
the server's default bind; same fix in the connector README/INSTALL.
Production has run GP_NYM=off for over a day: GoblinPay already reaches its
relays over clearnet, which is the end state the ecosystem's Nym → Tor move
aims for. This removes the now-dead ported Nym client and its plumbing. Pure
subtraction — the code path that remains is exactly the one already running
live, so there is no behavior change beyond "GoblinPay still boots and still
moves money." Per TOR-MIGRATION-PLAN.md.
Removed:
- crates/gp-nostr/src/nym/ (mod, transport, nymproc, dns — 599 lines).
- smolmix + hickory-proto (and the nym-only rand) deps from gp-nostr, and
their transitive tree from Cargo.lock.
- GP_NYM config plumbing (gp-core config: field, parse, default, summary),
the opts.nym service branch, the main.rs warm-up wiring, and the admin
dashboard Nym row.
- The nym leg of the CI sibling-checkout gate (.github + .gitea), the
`COPY nym` / sibling mentions in Dockerfile/compose/install.sh, and the
GP_NYM copy in README, .env.example, and the three connector docs.
GoblinPay does not gain a Tor transport of its own: it is receive-only
infrastructure, and the sender privacy that matters rides the paying
customer's own Goblin Wallet. Content encryption (NIP-44 in a NIP-59
gift-wrap) and the slatepack (grin1) path are untouched. The optional
onion-dialing and relay-list trim the plan flags are left for the owner.
Multi-stage non-root Dockerfile (builds -p gp-server against the nip44/nym siblings; excludes the goblin-tree dev crate), a full docker-compose (server + bundled nostr-rs-relay + auto-HTTPS Caddy), a hardened systemd unit (DynamicUser, ProtectSystem=strict, NoNewPrivileges, seed via LoadCredential), an install.sh bare-metal bootstrap, .env.example, and an fmt+clippy+test CI workflow for Gitea and GitHub.