Marimo on AWS User Guide
Overview
This image runs marimo, the open source reactive notebook for Python. marimo notebooks are reproducible, git friendly and deployable as scripts or web apps. Unlike traditional notebooks, marimo stores notebooks as pure Python files, runs cells reactively so the outputs are always consistent with the code, and ships with built in interactive UI elements like sliders, tables and plots.
marimo is installed into a dedicated virtualenv under /opt/marimo and runs as a dedicated unprivileged marimo system account under a systemd service that starts it on boot and restarts it on failure. The notebook workspace lives at /var/lib/marimo, which is a dedicated, independently resizable EBS data volume, and is seeded with a sample reactive notebook.
marimo's reactive notebook server binds to the loopback interface only and is never exposed directly. An nginx reverse proxy publishes the notebook editor on port 80 with WebSocket support for the live reactive updates. The editor is gated by a single access token, which is generated on the first boot of every deployed instance, so two instances launched from the same Amazon Machine Image never share a token. It is written to /root/marimo-aws-credentials.txt with mode 0600 so that only the root user can read it.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network and port 80 for the notebook editor
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Marimo. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of t3.medium or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that opens port 22 from your management network and port 80 for the notebook editor. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialisation takes a few seconds after the instance state becomes Running and the status checks pass.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Marimo Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22 and 80 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type t3.medium \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=marimo}]'
When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name from the EC2 console or with aws ec2 describe-instances.
Step 3: Connect to Your Instance
Connect over SSH using your key pair and the login user for your operating system variant.
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i <key-name>.pem ubuntu@<public-ip>
Step 4: Retrieve the Access Token
The marimo access token is unique to your instance and was generated on first boot. Read it as root:
sudo cat /root/marimo-aws-credentials.txt
The file lists the marimo URL and the generated access token. Keep this token somewhere safe.
Step 5: Sign In to the Notebook Editor
The marimo notebook editor is served on port 80 by nginx. In a browser, go to:
http://<instance-public-ip>/
You are prompted for the access token. Enter the token from the credentials file. marimo opens its home view, which lists the notebooks in the workspace and lets you create new ones.

Open the seeded sample_reactive.py notebook to see the reactive editor. The notebook has a slider whose value flows into a dataframe and a chart; move the slider and the cells below recompute automatically, because marimo tracks the dependencies between cells.

Step 6: Confirm Marimo Is Running
Over SSH, confirm the notebook server and the nginx proxy are active and that the ports are listening:
sudo systemctl is-active marimo nginx
sudo ss -tlnp | grep -E ':(80|2718) '
You should see both services reported as active, marimo listening on 127.0.0.1:2718 (loopback only), and nginx listening on port 80.
The unauthenticated health endpoint always answers 200 while the server is up. Confirm it over loopback on the instance:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/health
Step 7: Authenticate to the API with the Token
marimo's editor and admin API are gated by the access token. Without it, the protected API returns 401; with it, the same request returns 200. On the instance, read the token and exercise both paths over loopback:
TOKEN=$(sudo grep '^marimo.access.token=' /root/marimo-aws-credentials.txt | cut -d= -f2-)
echo "anonymous:" $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/api/status)
echo "with token:" $(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1/api/status?access_token=${TOKEN}")
The token is also accepted as an Authorization: Bearer header. From outside the instance, append ?access_token=<token> to any URL, or paste the token into the login prompt once and your browser session is authenticated.
Step 8: Work with the Sample Notebook
The notebook workspace is seeded with sample_reactive.py, which demonstrates marimo's reactivity. List the workspace on the instance:
sudo ls -l /var/lib/marimo
marimo notebooks are plain Python files. View the sample notebook source:
sudo head -20 /var/lib/marimo/sample_reactive.py
Because notebooks are ordinary Python, they run as scripts and diff cleanly in version control. Create new notebooks from the home view in the editor, or drop .py files into /var/lib/marimo and they appear in the file browser.
Step 9: Serve a Notebook as an App
Any marimo notebook can be served as an interactive web app, with the code hidden and only the UI elements and outputs shown. The marimo run command starts an app server for a notebook. The bundled editor also offers an app preview from the button in the bottom right of the editor.

To serve the sample notebook as an app on its own port behind the same token, run it as the marimo user (this is illustrative; adapt the port and notebook path to your needs):
sudo -u marimo /opt/marimo/venv/bin/marimo run /var/lib/marimo/sample_reactive.py \
--headless --host 127.0.0.1 --port 2719 --token-password "<your-token>"
You would then publish that port through nginx in the same way the bundled site publishes the editor.
Step 10: The Data Volume
The notebook workspace lives on a dedicated EBS volume mounted at /var/lib/marimo. This keeps your notebooks off the operating system disk and lets you resize or snapshot them independently. Confirm the mount with:
df -h /var/lib/marimo
To grow the workspace, expand the EBS volume in the AWS console, then grow the filesystem on the instance with sudo resize2fs on the underlying device.
Step 11: Manage Python Packages
marimo runs in the virtualenv at /opt/marimo/venv, which ships with marimo, pandas, numpy, polars and altair. Install additional packages into the same environment so your notebooks can import them. Confirm the bundled data libraries are present:
/opt/marimo/venv/bin/pip list | grep -iE '^(marimo|pandas|numpy|polars|altair) '
To add a package, install it into the venv (for example sudo /opt/marimo/venv/bin/pip install scikit-learn) and restart marimo with sudo systemctl restart marimo so a fresh kernel picks it up.
Step 12: Enable HTTPS
The notebook editor is served over plain HTTP on port 80 by nginx. For production use, place it behind TLS. Obtain a certificate for your domain (for example with a managed certificate on an Application Load Balancer in front of the instance, or with Certbot installed on the instance), then configure nginx to listen on 443 with your certificate and proxy to 127.0.0.1:2718 exactly as the bundled site does for port 80, keeping the WebSocket upgrade headers in place. Restrict the security group so ports 80 and 443 are reachable only from the networks that use the notebook.
Step 13: Backup and Maintenance
Back up your notebooks by snapshotting the /var/lib/marimo EBS volume, which captures the entire workspace. Because notebooks are plain Python files, you can also commit them to a git repository. Apply operating system security updates with sudo apt-get update && sudo apt-get upgrade and reboot when a new kernel is installed; marimo and nginx start automatically on boot.
Support
This image is published and supported by cloudimg. Support covers deployment, notebook authoring, the reactive execution model, UI elements, SQL integration, serving notebooks as apps, package management, TLS and storage tuning. Contact cloudimg through the support channel listed on the AWS Marketplace listing.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.