Announcing Proliferate
Proliferate
DeployAWS

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:

curl -fsSLO https://raw.githubusercontent.com/proliferate-ai/proliferate/main/server/infra/self-hosted-aws/launch-stack.sh
less launch-stack.sh
bash launch-stack.sh --site-address proliferate.company.com

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.

FlagEffect
--stack-name NAMECloudFormation stack name. Default proliferate-self-hosted.
--version X.Y.ZPin a specific server release instead of the newest one.
--site-address HOSTPublic hostname. Required unless --eval.
--evalNo domain: sslip.io host from the Elastic IP.
--instance-type TYPEt4g.small (default), t4g.medium, or t4g.large.
--region REGIONAWS region. Default from your AWS CLI config.
--github-oauth-client-id / --github-oauth-client-secretOptional GitHub sign-in for desktops.
--param Key=ValuePass any other template parameter directly (repeatable) — see the full parameter list below.
--dry-runResolve 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:

OutputWhat it is
BaseUrlThe public HTTPS URL your deployment is live at.
SiteAddressThe hostname in use (your domain, or the sslip.io name).
SetupClaimUrlThe /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.
ReadSetupTokenCommandA ready-made SSM command that prints the one-time setup token (available only while the instance is unclaimed).
ElasticIp / PublicIpThe IP serving the deployment.
InstanceIdThe EC2 instance id.
SsmStartSessionCommandA 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:

aws ssm start-session --target <InstanceId> \
  --document-name AWS-StartInteractiveCommand \
  --parameters '{"command":["sudo docker exec $(sudo docker ps -qf name=api) cat /var/lib/proliferate/setup/setup-token"]}'

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:

aws cloudformation create-stack \
  --stack-name proliferate-self-hosted \
  --template-body file://template.yaml \
  --capabilities CAPABILITY_IAM \
  --parameters ParameterKey=UseSslipFallback,ParameterValue=true

Template parameters

ParameterWhat it does
ReleaseVersionThe 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.
SiteAddressPublic hostname for the server. Required unless UseSslipFallback is true. Point DNS at the Elastic IP.
UseSslipFallbackEvaluation mode: derive the hostname from the Elastic IP as <ip>.sslip.io, so you can launch with no domain at all.
CreateRoute53Record / HostedZoneIdCreate the A record for SiteAddress in a Route53 hosted zone you own. Cannot be combined with the sslip fallback.
ExistingVpcId / ExistingSubnetIdReuse an existing VPC and public subnet instead of creating dedicated ones. Set both or neither.
AllocateElasticIpAllocate and attach a dedicated Elastic IP (default true).
InstanceTypet4g.small (default), t4g.medium, or t4g.large.
PostgresPassword / JwtSecret / CloudSecretKeyLeave blank to auto-generate and persist on first bootstrap, exactly like the Docker flow.
GitHubOAuthClientId / GitHubOAuthClientSecretOptional GitHub sign-in for desktops. Without them, desktops sign in with email and password.
ServerImageRepositoryImage repository, default ghcr.io/proliferate-ai/proliferate-server. Private ECR mirrors are supported.
RuntimeBinaryUrl / RuntimeBinaryChecksumUrlOverrides 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 / DeployBundleChecksumUrlOverrides 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.

Info:

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.

On this page