Skip to content

Accounts and security

Gigahost accounts do not use an email address, a conventional username, or a password you choose. Your account is controlled by a random 256-bit account key, stored as a seed file by the ghost command-line client. For the website alone, the account key can also set a generated website password.

ghost key generate
ghost key inspect

key inspect prints the deposit memo and the public authentication, billing, and backup-recovery identities. It never prints a private key or the account key.

  • By default, the account key is stored at $XDG_CONFIG_HOME/ghost/account.seed, or ~/.config/ghost/account.seed when XDG_CONFIG_HOME is not set.
  • To use a different location, set GHOST_SEED_FILE or pass --seed-file.
  • Generation refuses to overwrite an existing account key.
  • key generate creates the account key’s directory, and any missing one above it, for your user alone (mode 0700). A directory that exists keeps its mode, so make an existing ~/.config/ghost private with chmod 700 yourself.

Back up this file offline. Then fund and activate the account.

Gigahost keeps these values separate:

Identifier Example What it is for
Account alias gh-k3m7p2qa The short, stable name shown in the website and support workflows. It grants no authority and remains the same when keys change.
Deposit memo 16 characters Derived from the current owner public key. Use it only as the exact memo on MMX deposits. It is not an account ID.
Account UUID Used only for database relationships; it is not the account identity shown in the UI.

After an account key migration, the previous deposit memo remains linked to the same account, so a payment already in flight is not lost. Use the newest memo for all new payments.

Private ghost commands derive an Ed25519 owner key from the account key and sign each request. The signature covers the method, path and query, exact body, timestamp, random nonce, and any idempotency key.

The account key and private keys never leave the client. There is no bearer token, CLI session token or website session token to copy, store or configure.

Use HTTPS for any non-loopback API endpoint. Signatures authenticate a request, but encryption is still required to hide its contents and metadata in transit.

The account can hold multiple authentication public keys. The current client uses the unrestricted owner key. List the registered and retired keys with:

ghost account auth-keys
ghost account ssh-keys add --label laptop --file ~/.ssh/id_ed25519.pub
ghost account ssh-keys list
ghost account ssh-keys remove KEY_UUID

The account saves the SSH public keys of the machines you work from, each under a label, for new instances. The website’s Account page lists them as “SSH keys”.

  • ghost instance create and ghost instance reinstall install every saved key unless --ssh-key or --ssh-key-file names the keys.
  • The website offers the saved keys, checked, beside the key field when you rent or reinstall.
  • An instance keeps the keys it was made with; changing the saved keys later changes no instance.
ghost account login

Open the returned login_url before it expires.

The first page after the login says which account you logged in as (“Logged in as gh-…”).

  • A link is short-lived and single-use: it works once, for a few minutes.
  • Its secret is carried in the URL fragment, redeemed by client-side JavaScript, and then removed from the address bar.
  • It creates a browser session without sending your account key or private key to the website. The raw login and session secrets are not stored by the backend.
  • If a link does not log you in, the login page says why: the link was already used, it was cancelled when every website session of the account was ended, or it expired. Run ghost account login for a new one; you can open it in the same tab.

A session lasts about 7 days and ends after 24 hours unused.

Rarely, right after a login, a page says that its server has not caught up with your login yet. You are still logged in, and trying again a few seconds later shows the page.

Creating another website session needs no email or password-reset workflow: the account key makes a new link, or sets a new website password.

  • Log out, in the account menu at the right of the website’s header, ends this browser’s session and clears its cookie.
  • Log out everywhere, on the Account page (/account), ends every website session of the account, including the current one, and cancels unused login URLs.
  • The Account page also lists every website session, with how it began (a login link or the website password), the key that made the link or set the password, when it was last used and when it ends, and an End button for each. It also lists the account’s authentication keys.

End every session when a browser you logged in from is lost or shared, or a login URL may have leaked.

Ending sessions affects neither the CLI’s authentication keys nor the website password: your CLI keys keep working. A website session can request a provider payout, but it cannot change the address payouts go to; see Provider payouts.

An account can also keep a password for the website, so you can log in from a browser without the CLI at hand.

ghost account set-password # draw one and show it once
ghost account set-password --expires-in 90 # one that stops working in 90 days
ghost account set-password --print # only the password, for a password manager
ghost account remove-password # turn password login off

The website’s Log in page (/login) then takes the account alias and the password.

Only the account key sets the password, with ghost (the Gigahost desktop app’s Account screen does the same). The website cannot set or change it, so someone holding a stolen website session cannot take the account over.

  • It is generated, never chosen: 16 characters of letters, digits and - . ! ? @, without characters that are easy to confuse when read (0 and O, 1, l and I).
  • ghost shows it once; keep it in a password manager. --print writes only the password.
  • The browser derives a key from the alias and the password and signs a single-use challenge with it: the password itself is never sent to Gigahost, and Gigahost does not store it. The form needs JavaScript.
  • After a few failed attempts from one address the form refuses for a while; ghost account login still works.
  • Running ghost account set-password again draws a new password: the old one stops working and the website sessions it began end. Removing it ends them too.
  • Log out everywhere and ghost account revoke-sessions end sessions but keep the password. If a lost device had it saved, set a new one as well.
  • A forgotten password cannot be reset by email; set a new one with the account key.
  • An expiry is your choice and off by default (--expires-in DAYS, 1 to 3650). ghost account show and the website’s Account page show when the password was set and when it expires.
  • An expired password no longer logs in, and the login page says so; the sessions it began keep their own end.

A password session has no more rights than one begun by a login link. What needs the account key still needs it: minting login links, setting the payout address, migrating the account key, or approving a hosted backup’s restore.

Account key migration requires both the current account key and an independently generated replacement.

  1. Generate and back up the replacement:

    ghost key generate --output "$HOME/.config/ghost/account.next.seed"
  2. Migrate:

    ghost account migrate-seed \
    --new-seed-file "$HOME/.config/ghost/account.next.seed" \
    --yes
  3. Select the replacement for subsequent commands:

    export GHOST_SEED_FILE="$HOME/.config/ghost/account.next.seed"
    ghost account show
  • The current owner key authorizes the API request, and the replacement owner key separately signs the migration statement.
  • The backend then changes the key epoch atomically, revokes every previous authentication key and web session, and installs the new public authentication, billing, and recovery keys.
  • It revokes every existing login URL and website session, and ends the website password.
  • The account alias, balance, instances, and provider history do not change.
  • A request the previous account key signs from then on, such as a --wait still following a job or ghost account activate, is refused with auth_key_retired (401), which names the time of the migration.

Keep the previous account key for old backups

Section titled “Keep the previous account key for old backups”

Authenticate with the new account key and select the old one only for recovery when restoring such a backup; see Restore after an account key migration.

What an account is charged, its instances’ balance holds and the platform’s limits are on Pricing and billing.

A provider’s earnings are held for the SLA tier’s 1-, 5-, or 20-day liability period. The provider balance shows what was earned and not paid out yet, what can be paid out now, what is still held, what is on its way, and your payout address; the website’s provider pages show them as Pending (not available yet), Available and their Total, and On the way on Payouts. Provider › Earnings (/provider/earnings) totals what your hosts earned per UTC day or month: for rentals, for local backups, the SLA credits your hosts funded, and the rest.

Every payout goes to that one MMX address. Only a request signed by ghost can set or change it; the website cannot, so a stolen website session cannot redirect your earnings. Set it, then request payouts on the website, on Provider › Payouts (/provider/payouts), or with:

ghost provider set-payout-address <MMX_ADDRESS>
ghost provider balance
ghost provider payout
ghost provider payouts

A payout request takes everything available; use --amount-microusd to request a smaller exact amount. A payout takes from your earnings exactly what it pays. A payout that has not been signed yet follows a later change of address. After the request, payouts are processed automatically. Conversion uses the active MMX/USD rate when the transaction is prepared. The backend stores the exact signed transaction before broadcasting it, sends those same bytes again while the MMX node does not know them, and settles the payout after six confirmations by default, once the chain shows that it paid your address the payout’s amount. If the wallet may have sent a payment without reporting it, the backend finds the payment on chain instead of sending another. A signed transaction that fails on chain, or expires without being included, ends the payout as action_required, and its amount can be requested again. A confirmed transaction that does not pay the payout as prepared holds it under_review, its amount still reserved, until an operator has checked it. Pending payouts and request frequency are bounded; operators can pause payout processing if the wallet or rate is unavailable.