Proxima Gateway
Admin

Creating customers

Onboard a new client with one form

In Proxima Gateway, every customer owns exactly one server. Creating a customer therefore provisions both the user account and the server stub in a single transaction.

The flow

Admin → Users → Add User opens a small form:

FieldRequiredNotes
UsernameYesLowercase, must be unique
PasswordYesCustomer can change later
Display NameNoShown in the sidebar profile
Login URL SlugNoGives the customer a personal /login/<slug> link
RoleYesCustomer (owns one server) or Admin (no server)
Server nameNoDefaults to <username>'s Server if blank

Click Create User. Inside one Postgres transaction, the system:

  1. Creates the User row (bcrypt-hashed password)
  2. Creates a Server row owned by that user
  3. Generates a 256-bit apiKey (the license key) and stores it on the server row
  4. Generates a 256-bit apiSecret (used for dashboard → proxy auth on the proxy's :6060 endpoints)

If any step fails, the whole thing rolls back — you never end up with a half-provisioned customer.

What the customer sees

When they log in for the first time:

  • Their server is already in their list — /app shows it with status "Not installed"
  • A Connect your server card asks for SSH credentials
  • Once they save credentials and click Install, the runner uses the apiKey/apiSecret you provisioned — they never see or type them

What you don't have to do

  • ❌ Generate API keys by hand (the old openssl rand -hex 32 flow is retired — they're auto-generated)
  • ❌ Email the keys to the customer
  • ❌ Pre-create a server entry separately
  • ❌ Set up SSH keys for them — they enter their own root password into the dashboard

Editing later

Admin → Users → Edit lets you change the username, password, display name, role, or login slug. The license key and server settings live in their own card on the same page — see Managing licenses.

To delete a customer, click the trash icon on the users list. The related server row is cascade-deleted; the proxy on their box keeps running but its heartbeat will start returning 401 (treated as Expired on the proxy side, so it shuts down on next heartbeat).