Quickstart
Stand up a self-hosted Proliferate server in about 15 minutes.
This guide takes you from a fresh Linux host to a working team install: the Proliferate server (the API and database your team connects to) running under Docker Compose, the instance claimed by you as its first admin, your desktop app connected and signed in, and your first teammate invited. Budget about 15 minutes of hands-on time, plus whatever your DNS takes to propagate. The Docker page covers the server pieces in more depth.
Provision a host
Before you start, make sure you have:
- A Linux host with Docker and Compose v2 installed
- A DNS name pointed at the host (for example
proliferate.company.com) - Ports 80 and 443 reachable from your users, and from the internet so Let's Encrypt can issue certificates (also required later if you enable cloud sandboxes)
Fetch the deploy bundle
Every server release ships a small deploy bundle: the Compose file, the
Caddyfile, and the bootstrap scripts. Replace X.Y.Z with the release you
are installing (see the
releases page):
Configure the environment
Edit .env.static. Three values matter for the base install:
SITE_ADDRESS is the hostname Caddy serves and requests certificates for;
write it with or without a scheme (https is assumed when you leave it off).
Bootstrap derives API_BASE_URL, the full public URL the server embeds in
configuration it pushes to workspaces, from SITE_ADDRESS; set it explicitly
only if your public URL differs. Pin PROLIFERATE_SERVER_IMAGE_TAG to the
release you downloaded. Everything else is optional at this point; the full
list is in the
environment variable reference.
Bootstrap
bootstrap.sh generates any secrets you left blank, starts Postgres, runs
database migrations, and brings the API up behind Caddy with automatic HTTPS.
Once the health checks pass, it prints a one-time setup token and the claim
URL:
Screenshot: terminal, final bootstrap.sh output showing the setup token and claim URL
The tail of a successful bootstrap run, with the setup token and claim URL lines visible.
The token is never served over HTTP; it lives in a file inside the API
container (/var/lib/proliferate/setup/setup-token) that only someone with
shell access to the host can read, so a publicly reachable server is safe
while it waits to be claimed. It stays available until you claim the
instance; run ./wait-for-health.sh at any time to print it again.
Claim your instance
Open the claim URL in a browser and enter your email, a password, and the
setup token. The organization name field is optional: leave it blank and the
name is derived from your email domain (the derived default shows as the
placeholder). Submitting creates your account, makes you the owner of the
organization, and permanently closes open signup: after the claim, /setup
returns 404 forever.
Screenshot: browser, the /setup claim page with email, password, optional organization name, and setup token fields
The server-rendered first-run claim form before submission, with the derived organization name shown as the placeholder.
Self-hosted servers run in single-org mode out of the box: SINGLE_ORG_MODE
defaults to on whenever PROLIFERATE_TELEMETRY_MODE is not hosted_product,
so there is exactly one organization and everyone you invite joins it. No
configuration needed.
Connect the desktop app
Download the desktop app, then point it at your server by
writing ~/.proliferate/config.json:
The file is read once at startup, so restart the app to apply it. Add
"telemetryDisabled": true to the same file to turn off desktop telemetry
for that install. See
Connect the desktop app for rolling
this out across a fleet.
In-product connect (a "connect to self-hosted server" entry on the sign-in
screen) and a shareable proliferate://connect deep link are planned. Today
the config file is the supported path.
Sign in
Open the app and sign in with the email and password you set at /setup. The
desktop app asks your server which sign-in methods it offers
(GET /auth/desktop/methods); when GitHub OAuth is not configured, the email
and password form is the default. The base install needs no OAuth app at all.
Screenshot: desktop app, sign-in screen showing the email and password form against a self-hosted server
The default sign-in screen when the server has no GitHub OAuth configured.
To offer GitHub sign-in as well, create a GitHub OAuth app with callback URL
https://proliferate.company.com/auth/desktop/github/callback, set
GITHUB_OAUTH_CLIENT_ID and GITHUB_OAUTH_CLIENT_SECRET, and restart the
server. See
GitHub sign-in.
Invite your team
In the desktop app, invite each teammate by email. Registration is invite-only and proven by a token: creating an account requires the invitation token from the invite link, and the server answers any unknown or mismatched token with the same 403.
Every pending invitation in the members list has a Copy invite link action. The link points at your server's registration page with the token and email prefilled:
Share the link with your teammate. They open it in a browser, choose a
password, and get an account in your organization. Then they install the
desktop app, point it at your server with the same config.json, and sign
in. If you configure email delivery (Resend is optional), the server emails
the same link for you instead. Inviting the same email again issues a fresh
link and the old one stops working.
Invitation roles are honored: invite someone as an admin and they are an
admin the moment they register. Set ALLOWED_EMAIL_DOMAINS to additionally
require that invited emails belong to your domains.
Screenshot: desktop app, organization members view with a pending invitation and its Copy invite link action
The members list after inviting a teammate, showing the pending invite with the Copy invite link menu item.
Set ADMIN_EMAILS in .env.static to guarantee admins: every listed email
holds at least the admin role, asserted at every sign-in. It is also the
lockout recovery path: add your email to the list, restart the server, sign
in. Removing an email never demotes anyone, and the last admin can never be
demoted or removed. The flip side: listed emails are reinstated as admin at
their next sign-in even after removal, so to offboard someone on the list,
remove them from ADMIN_EMAILS too and restart.
Updating
Updating is one command on the server:
Your server reports its versions at GET /meta, and desktop update checks go
through your server (GET /desktop/updater/latest.json redirects to the
official signed build matching the version your server pins). Connected
desktop apps follow the server, so updating the server updates the whole
fleet. See
Updates & versioning.
What's not here yet
Two honest limits of self-hosting today: automations and scheduled background jobs are not available yet (the self-hosted stack does not ship a worker tier), and the web app is not self-hostable in v1. Your team uses the desktop app.
Next steps
Cloud sandboxes
Enable cloud workspaces with a GitHub App, an E2B key, and a sandbox template built in your E2B team.
Model gateway
Run a LiteLLM proxy to centralize model credentials and budgets.
OIDC SSO
Connect your identity provider.
Telemetry & privacy
What self_managed mode sends, and how to disable it entirely.