Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions docs/examples/deployment/burr-ui-aws.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
..
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.


.. _burr-ui-aws-deployment:

==============================
Burr UI on AWS (Private VPC)
==============================

Deploy the Burr tracking UI server in a private VPC, reading from an existing S3 tracking bucket.
Access is via AWS SSM Session Manager port forwarding.

See the full example:

* Source: `GitHub <https://github.com/apache/burr/tree/main/examples/deployment/aws/burr-ui>`_
* ``examples/deployment/aws/burr-ui/README.md``

-----------
Quick Start
-----------

.. code-block:: bash

cd examples/deployment/aws/burr-ui/terraform
terraform init
terraform apply -var="s3_bucket_name=my-tracking-bucket"

--------------------------
Access the Private UI
--------------------------

.. code-block:: bash

INSTANCE_ID=$(terraform output -raw instance_id)
aws ssm start-session --target $INSTANCE_ID \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["7241"],"localPortNumber":["7241"]}'

Then open http://localhost:7241.

--------------
Related Guides
--------------

* :ref:`S3 Tracking on AWS <s3-tracking-aws>`
* :ref:`AWS Deployment overview <aws-deployment-example>`
1 change: 1 addition & 0 deletions docs/examples/deployment/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ have an example that would add to this guide. We have created a variety of issue
infrastructure
monitoring
aws
burr-ui-aws
28 changes: 28 additions & 0 deletions examples/deployment/aws/burr-ui/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 7241

# The S3 bucket is configured via environment variable at runtime
CMD ["burr", "--no-open", "--host", "0.0.0.0"]
142 changes: 142 additions & 0 deletions examples/deployment/aws/burr-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Deploy Burr UI on AWS (Private VPC, S3 Backend)

Deploy the Burr tracking UI server in a private VPC on AWS, reading tracking data from
an existing S3 bucket. Access is via AWS SSM Session Manager port forwarding — no public
IP, no open inbound ports.

## Overview

This deploys a single-tenant Burr UI server that:

- Runs in a private subnet inside a dedicated VPC
- Reads and indexes tracking logs from your existing S3 bucket
- Is accessible only via SSM port forwarding (no public internet exposure)
- Uses a single EC2 instance (not horizontally scaled — by design)

```mermaid
graph TB
subgraph VPC["VPC (10.0.0.0/16)"]
subgraph Private["Private Subnet"]
EC2["EC2 (t3.small)<br/>burr --no-open<br/>port 7241<br/>BURR_S3_BUCKET=..."]
end
NAT["NAT Gateway"]
SSM_EP["SSM VPC Endpoints"]
end

S3["S3 Bucket<br/>(existing tracking data)"]
User["Your Laptop<br/>http://localhost:7241"]

EC2 -->|"reads tracking logs"| S3
EC2 -->|"outbound via NAT"| NAT
EC2 --- SSM_EP
User -->|"SSM port-forward 7241"| SSM_EP
```

## Prerequisites

- AWS CLI v2 configured with credentials
- [AWS Session Manager plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) installed
- Terraform >= 1.5
- An existing S3 bucket with Burr tracking data (written by `S3TrackingClient`)

## Configure

```bash
cd examples/deployment/aws/burr-ui/terraform
cp environments/dev.tfvars my.tfvars
```

Edit `my.tfvars` and set:
- `s3_bucket_name` — your existing Burr tracking bucket name (required)
- `aws_region` — the region where your bucket lives (default: us-east-1)

## Deploy

```bash
terraform init
terraform apply -var-file=my.tfvars
```

Wait 2-3 minutes for the instance to boot, install Burr, and start indexing.

## Access the Private UI

Use SSM port forwarding (no SSH key needed, no open ports):

```bash
# Get the instance ID from Terraform output
INSTANCE_ID=$(terraform output -raw instance_id)

# Start the port forward
aws ssm start-session --target $INSTANCE_ID \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["7241"],"localPortNumber":["7241"]}'
```

Then open http://localhost:7241 in your browser.

## Verify

- The UI loads and shows a list of projects from your S3 bucket
- Navigate into a project to see tracked application runs
- If the bucket is empty, the UI shows an empty project list (no errors)

## Teardown

```bash
terraform destroy -var-file=my.tfvars
```

## Security

- **No public IP.** The instance is in a private subnet with no inbound security group rules.
- **No SSH.** Access is exclusively via SSM Session Manager (port forwarding).
- **No open ports.** The security group allows egress only (for pip install and S3 access).
- **IMDSv2 enforced.** Instance metadata requires session tokens.
- **Encrypted EBS.** Root volume uses gp3 with encryption enabled.
- **Least-privilege IAM.** The instance role has read-only access to the single specified bucket.
- **VPC endpoints for SSM.** SSM control plane traffic stays within the VPC.

## Architecture Decisions

| Decision | Rationale |
|----------|-----------|
| Single EC2 instance | Issue #391 requests single-tenant. The UI is read-heavy and not write-bound. |
| SSM over bastion/ALB | Simplest private access. No key management, no extra instances, no public endpoints. |
| NAT Gateway | Required for pip install on boot. Could be replaced with VPC endpoint for S3 + pre-baked AMI. |
| No bucket creation | Issue says "parameterizable on the S3 bucket" — assumes an existing one. |

## Troubleshooting

| Problem | Solution |
|---------|----------|
| SSM can't connect | Ensure the SSM plugin is installed and the instance has `AmazonSSMManagedInstanceCore` policy |
| UI loads but no projects | Check that `s3_bucket_name` matches your tracking bucket and the region is correct |
| Server not starting | SSM into the instance: `sudo journalctl -u burr-ui` |
| Indexing errors | Check `/var/log/burr-ui-setup.log` on the instance |

## Production Notes

- For team access, place an internal ALB in front and connect via VPN
- For HTTPS, add an ACM certificate and ALB listener
- For persistent index across restarts, enable S3 snapshot (set `BURR_LOAD_SNAPSHOT_ON_START=true`)
- See [S3 Tracking on AWS](https://burr.apache.org/concepts/aws-tracking/) for all configuration options
18 changes: 18 additions & 0 deletions examples/deployment/aws/burr-ui/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

apache-burr[tracking-server-s3,cli]
11 changes: 11 additions & 0 deletions examples/deployment/aws/burr-ui/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.tfstate
*.tfstate.backup
*.tfplan
.terraform/
.terraform.lock.hcl
crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
*.auto.tfvars
24 changes: 24 additions & 0 deletions examples/deployment/aws/burr-ui/terraform/environments/dev.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

aws_region = "us-east-1"
environment = "dev"
instance_type = "t3.small"
root_volume_size = 20

# REQUIRED — set to your existing Burr tracking bucket:
# s3_bucket_name = "my-burr-tracking-logs"
24 changes: 24 additions & 0 deletions examples/deployment/aws/burr-ui/terraform/environments/prod.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

aws_region = "us-east-1"
environment = "prod"
instance_type = "t3.small"
root_volume_size = 30

# REQUIRED — set to your existing Burr tracking bucket:
# s3_bucket_name = "my-burr-tracking-logs"
59 changes: 59 additions & 0 deletions examples/deployment/aws/burr-ui/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

provider "aws" {
region = var.aws_region

default_tags {
tags = local.common_tags
}
}

locals {
common_tags = {
Project = "burr-ui-server"
Environment = var.environment
ManagedBy = "terraform"
}
}

module "networking" {
source = "./modules/networking"

environment = var.environment
vpc_cidr = var.vpc_cidr
aws_region = var.aws_region
}

module "iam" {
source = "./modules/iam"

environment = var.environment
s3_bucket_name = var.s3_bucket_name
}

module "compute" {
source = "./modules/compute"

environment = var.environment
instance_type = var.instance_type
root_volume_size = var.root_volume_size
s3_bucket_name = var.s3_bucket_name
subnet_id = module.networking.private_subnet_id
security_group_id = module.networking.security_group_id
instance_profile_arn = module.iam.instance_profile_arn
}
Loading
Loading