AWS
Launch the self-hosted stack on EC2 with CloudFormation, with a real one-command launch script.
The AWS path is a CloudFormation stack that provisions a single EC2 host and runs the standard Docker deployment on it. You get the same stack as any other install; CloudFormation just handles the infrastructure and keeps the deployment updated.
What the stack provisions
One EC2 instance (Amazon Linux 2023, arm64, t4g.small by default, 20 GB
gp3 disk), an Elastic IP, a dedicated VPC with a security group opening
80/443 (or your existing VPC and subnet), an optional Route53 A record, and
an IAM role that allows SSM shell access. On first boot the instance writes
the deploy files to /opt/proliferate/server/deploy and runs the same
bootstrap.sh described in
Docker on any server. The stack sets
PROLIFERATE_TELEMETRY_MODE=self_managed for you, and because the default
instance types are all Graviton (arm64), it defaults to the aarch64 runtime
build from the matching release.
Launch
Run launch-stack.sh
launch-stack.sh is a genuine one-command launch: it resolves the newest
server-v* release itself (or a version you pin), downloads and
checksum-verifies the published CloudFormation template from that release,
validates it, and runs aws cloudformation deploy with your AWS CLI
credentials. Inspect it first, then run it:
No domain to test with yet? bash launch-stack.sh --eval launches with no
SiteAddress at all; the stack derives a hostname from the Elastic IP
(<ip>.sslip.io) and still gets real Let's Encrypt TLS.
| Flag | Effect |
|---|---|
--stack-name NAME | CloudFormation stack name. Default proliferate-self-hosted. |
--version X.Y.Z | Pin a specific server release instead of the newest one. |
--site-address HOST | Public hostname. Required unless --eval. |
--eval | No domain: sslip.io host from the Elastic IP. |
--instance-type TYPE | t4g.small (default), t4g.medium, or t4g.large. |
--region REGION | AWS region. Default from your AWS CLI config. |
--github-oauth-client-id / --github-oauth-client-secret | Optional GitHub sign-in for desktops. |
--param Key=Value | Pass any other template parameter directly (repeatable) — see the full parameter list below. |
--dry-run | Resolve and validate the template; do not deploy. |
Prefer the AWS Console, or need parameters launch-stack.sh doesn't expose as
flags yet? See Launch from the console below —
same template either way.
Wait for CREATE_COMPLETE
Bootstrap runs automatically on first boot. The stack sets
PROLIFERATE_PUBLIC_HEALTHCHECK_URL itself, so CloudFormation only reaches
CREATE_COMPLETE once the advertised HTTPS endpoint actually responds
(20-minute timeout). launch-stack.sh waits on this for you; from the console
watch the stack's Events tab.
Stack outputs:
| Output | What it is |
|---|---|
BaseUrl | The public HTTPS URL your deployment is live at. |
SiteAddress | The hostname in use (your domain, or the sslip.io name). |
SetupClaimUrl | The /setup claim page. Open it in a browser with the setup token to create the admin account; it returns 404 once the instance is claimed. |
ReadSetupTokenCommand | A ready-made SSM command that prints the one-time setup token (available only while the instance is unclaimed). |
ElasticIp / PublicIp | The IP serving the deployment. |
InstanceId | The EC2 instance id. |
SsmStartSessionCommand | A ready-made aws ssm start-session command to open a shell on the host. |
Get the setup token and claim your instance
Run the command from the ReadSetupTokenCommand output (aws cloudformation describe-stacks --stack-name proliferate-self-hosted, or read it off the
console's Outputs tab). It opens an SSM session that prints the one-time
setup token and exits:
The token also appears in /var/log/cfn-init-cmd.log on the host, and you
can always reprint it with the Docker flow's health gate: open a shell with
the SsmStartSessionCommand output, then
cd /opt/proliferate/server/deploy && sudo ./wait-for-health.sh.
Open the SetupClaimUrl output in a browser and enter an email, a password,
an optional organization name (blank derives one from your email domain), and
the token. That account becomes the owner of the instance organization, and
the page returns 404 forever after.
Work from a browser, or connect the desktop app
The stack's BaseUrl already serves the Web app: sign in there to work. If
you or your teammates need local repositories or a local AnyHarness runtime,
also point the desktop app at BaseUrl. See
Connect the desktop app.
Launch from the console
Launch the template
Launch the CloudFormation template (server/infra/self-hosted-aws/template.yaml,
published with each server-v* release) and fill in the stack parameters.
For a production install, set SiteAddress and point DNS at the Elastic IP
(or let the stack do it with CreateRoute53Record). For a quick evaluation,
set UseSslipFallback to true and leave SiteAddress blank.
The template is a template-body-eligible size, so the CLI equivalent works directly with no S3 upload step:
Template parameters
| Parameter | What it does |
|---|---|
ReleaseVersion | The release to run, unprefixed (for example 0.3.0). Sets the server image tag and downloads the matching runtime binaries and deploy bundle from the server-v<ReleaseVersion> GitHub release. |
SiteAddress | Public hostname for the server. Required unless UseSslipFallback is true. Point DNS at the Elastic IP. |
UseSslipFallback | Evaluation mode: derive the hostname from the Elastic IP as <ip>.sslip.io, so you can launch with no domain at all. |
CreateRoute53Record / HostedZoneId | Create the A record for SiteAddress in a Route53 hosted zone you own. Cannot be combined with the sslip fallback. |
ExistingVpcId / ExistingSubnetId | Reuse an existing VPC and public subnet instead of creating dedicated ones. Set both or neither. |
AllocateElasticIp | Allocate and attach a dedicated Elastic IP (default true). |
InstanceType | t4g.small (default), t4g.medium, or t4g.large. |
PostgresPassword / JwtSecret / CloudSecretKey | Leave blank to auto-generate and persist on first bootstrap, exactly like the Docker flow. |
GitHubOAuthClientId / GitHubOAuthClientSecret | Optional GitHub sign-in for desktops. Without them, desktops sign in with email and password. |
ServerImageRepository | Image repository, default ghcr.io/proliferate-ai/proliferate-server. Private ECR mirrors are supported. |
RuntimeBinaryUrl / RuntimeBinaryChecksumUrl | Overrides for the runtime binary tarball and its checksum file. Leave blank to use the matching release assets (the aarch64 build, matching the Graviton instance types). |
DeployBundleUrl / DeployBundleChecksumUrl | Overrides for the proliferate-deploy.tar.gz bundle and its checksum file. Leave blank to use the matching release assets. |
Any add-on this parameter list doesn't cover yet (the model gateway,
the GitHub App, instance branding) is still configurable: open an SSM
session with the SsmStartSessionCommand output, edit
/opt/proliferate/server/deploy/.env.static directly, and run
sudo ./update.sh. It's the same file the Docker flow edits.
Updating
Update the stack with a new ReleaseVersion parameter value (aws cloudformation update-stack or the console). The instance runs cfn-hup,
which polls the stack metadata every few minutes, notices the change, and
runs update.sh in place (pull the new image, run migrations, restart the
stack). No shell access needed for routine updates.
You can also update manually: open an SSM session and run
cd /opt/proliferate/server/deploy && sudo ./update.sh. Both paths are the
same script.
See Updates & versioning for pinning strategy.