Storage AWS

RustFS on AWS User Guide

| Product: RustFS on AWS

Overview

This image runs RustFS, a high performance, S3 compatible object storage server written in Rust and licensed under Apache 2.0. It is a MinIO-style alternative: a single binary that serves both the S3 REST API and a built-in web console for managing buckets, objects, access keys and policies. Objects are stored on a dedicated EBS data volume mounted at /var/lib/rustfs, so the storage tier can be resized independently of the operating system disk.

The image is hardened for production. RustFS binds its S3 API and its web console to the loopback interface only, and an nginx reverse proxy terminates TLS on port 443 in front of both. A browser reaches the console over HTTPS at https://<instance>/rustfs/console/, and any S3 client reaches the S3 API at the root of the same HTTPS endpoint, https://<instance>/. The raw RustFS ports are never exposed to the network. Port 80 issues a 301 redirect to port 443. The only inbound ports the security group needs are 443 for the console and API, and 22 for administration.

The RustFS access key and secret key are generated on the first boot of every deployed instance, before the storage engine starts on an empty backend. Two instances launched from the same Amazon Machine Image never share credentials. The well known rustfsadmin/rustfsadmin default that ships in upstream RustFS is never present in this image. On first boot a one shot service writes per instance values into /etc/default/rustfs (the environment file consumed by the systemd unit), generates a fresh per instance self signed TLS certificate, and stores the plain text credentials in /root/rustfs-credentials.txt with mode 0600 so that only the root user can read them.

The AWS CLI is installed at /usr/local/bin/aws for command line bucket and object management, because RustFS speaks the Amazon S3 API and any S3 client works against it unchanged apart from the endpoint URL.

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 inbound port 443 from the trusted networks that will reach the console and the S3 API
  • 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 RustFS. Select the cloudimg listing and choose Select, then Continue on the subscription summary.

Pick an instance type of m5.large 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 allows inbound port 22 from your management network and inbound port 443 from the trusted networks that will reach the console and the S3 API. Leave the root volume at the default size or larger; the dedicated data volume mounted at /var/lib/rustfs defaults to 50 GiB and can be resized independently in the EC2 console.

Select Launch instance. First boot initialisation takes approximately one minute 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 RustFS 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 443 as described above.

aws ec2 run-instances \
  --image-id <ami-id> \
  --instance-type m5.large \
  --key-name <key-name> \
  --subnet-id <subnet-id> \
  --security-group-ids <security-group-id> \
  --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=rustfs-01}]'

The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.

Step 3: Connect and Retrieve the Credentials

Connect over SSH with the key pair you selected and the public IP address from step 2. The SSH login user depends on the operating system of the AMI variant you launched:

AMI variant SSH login user
RustFS on Ubuntu 24.04 ubuntu

The first boot service runs before the SSH daemon becomes ready, so the credentials file is always in place when you log in for the first time.

sudo cat /root/rustfs-credentials.txt

You will see a plain text file containing the console URL, the S3 API URL, the RustFS access key, and the RustFS secret key. Copy these values somewhere secure such as a password manager or an encrypted vault, and do not commit them to source control.

Each command block in this guide that talks to RustFS begins by reading the credentials into shell variables, so every block is self contained:

ACCESS_KEY="$(sudo awk -F= '/^rustfs.access.key=/ {print $2}' /root/rustfs-credentials.txt)"
SECRET_KEY="$(sudo awk -F= '/^rustfs.secret.key=/ {print $2}' /root/rustfs-credentials.txt)"
echo "access key: ${ACCESS_KEY}; secret length: ${#SECRET_KEY}"

Step 4: Verify the Server is Healthy

The console sign in page is served over TLS by nginx and returns HTTP 200 with no authentication. Because the certificate is self signed, pass -k to curl to skip certificate verification when probing from the instance itself.

curl -ksS https://127.0.0.1/rustfs/console/ -o /dev/null -w "console HTTP %{http_code}\n"

You should see console HTTP 200. If you see anything else, check the service status with sudo systemctl status rustfs.service and the journal with sudo journalctl -u rustfs.service -n 50, and confirm nginx is up with sudo systemctl status nginx.service.

Step 5: Sign in to the RustFS Console

Open a browser on a workstation in the network that is allowed inbound on port 443 and browse to:

https://<public-ip>/rustfs/console/

Because the certificate is self signed, your browser will warn on the first visit; accept the warning to proceed, or install your own CA issued certificate as described in Step 8. You will see the RustFS console sign in page. Sign in on the Key Login tab with the access key in the Account field and the secret key in the Key field.

RustFS console sign in page

After signing in, the console lands on the Buckets overview, which lists every bucket on the server with its object count, size and access policy. It is empty on a fresh instance.

RustFS console buckets overview

Selecting a bucket opens the object browser, where you can upload files and folders, filter the object list, and preview, download, rename or delete individual objects.

RustFS console object browser

The Access Keys page issues additional service account keys for applications, each optionally scoped by a policy and an expiry date, so applications never need the root credentials. Click Add Access Key, and the console generates an access key and secret key for you to record.

RustFS console create access key

Step 6: Drive RustFS from the Command Line with the AWS CLI

The AWS CLI is installed at /usr/local/bin/aws. RustFS is fully S3 compatible, so the CLI works against it with only an explicit endpoint URL. The following block, run on the instance, points the CLI at the loopback S3 API with the generated credentials, creates a bucket, uploads a small object, and lists the bucket:

ACCESS_KEY="$(sudo awk -F= '/^rustfs.access.key=/ {print $2}' /root/rustfs-credentials.txt)"
SECRET_KEY="$(sudo awk -F= '/^rustfs.secret.key=/ {print $2}' /root/rustfs-credentials.txt)"
export AWS_ACCESS_KEY_ID="${ACCESS_KEY}"
export AWS_SECRET_ACCESS_KEY="${SECRET_KEY}"
export AWS_EC2_METADATA_DISABLED=true
export AWS_DEFAULT_REGION=us-east-1
EP="http://127.0.0.1:9000"
aws --endpoint-url "${EP}" s3 mb s3://my-first-bucket
echo "hello from cloudimg" > /tmp/hello.txt
aws --endpoint-url "${EP}" s3 cp /tmp/hello.txt s3://my-first-bucket/hello.txt
aws --endpoint-url "${EP}" s3 ls s3://my-first-bucket/

You can browse the same bucket and the same object in the console. To remove the object and the bucket again:

ACCESS_KEY="$(sudo awk -F= '/^rustfs.access.key=/ {print $2}' /root/rustfs-credentials.txt)"
SECRET_KEY="$(sudo awk -F= '/^rustfs.secret.key=/ {print $2}' /root/rustfs-credentials.txt)"
export AWS_ACCESS_KEY_ID="${ACCESS_KEY}"
export AWS_SECRET_ACCESS_KEY="${SECRET_KEY}"
export AWS_EC2_METADATA_DISABLED=true
export AWS_DEFAULT_REGION=us-east-1
EP="http://127.0.0.1:9000"
aws --endpoint-url "${EP}" s3 rm s3://my-first-bucket/hello.txt
aws --endpoint-url "${EP}" s3 rb s3://my-first-bucket

Step 7: Use the S3 API from a Remote Client

From a workstation that has the AWS CLI installed and inbound network access to port 443 of the instance, point the CLI at the HTTPS endpoint. Because the shipped certificate is self signed, add --no-verify-ssl (or install your own certificate as in Step 8). Replace <access-key>, <secret-key> and <public-ip> with the values from /root/rustfs-credentials.txt:

# Run on a workstation that has the AWS CLI v2 installed.
AWS_ACCESS_KEY_ID=<access-key> \
AWS_SECRET_ACCESS_KEY=<secret-key> \
aws --endpoint-url https://<public-ip> --no-verify-ssl s3 mb s3://app-bucket

AWS_ACCESS_KEY_ID=<access-key> \
AWS_SECRET_ACCESS_KEY=<secret-key> \
aws --endpoint-url https://<public-ip> --no-verify-ssl s3 ls

In production you should not use the root credentials directly from application code. Issue a dedicated service account key on the console Access Keys page (Step 5), scope it to the least privilege the application needs, and use that access key in the application. Rotate the access key on a schedule that suits your security posture.

Step 8: Replace the Self Signed Certificate

The image ships with a per instance self signed certificate at /etc/rustfs/tls/cert.pem and /etc/rustfs/tls/key.pem so the console and API are encrypted out of the box. For production, replace it with a certificate that clients trust. The simplest pattern on AWS is to attach an Elastic Load Balancer in front of the instance, terminate TLS on the load balancer with an AWS Certificate Manager certificate, and forward to the instance on port 443.

To terminate TLS on the instance itself, obtain a certificate for a DNS name that points at the instance (for example with the certbot CLI and a certbot certonly challenge), then replace cert.pem and key.pem under /etc/rustfs/tls/ with the issued certificate and private key and reload nginx:

sudo cp /etc/letsencrypt/live/<your-domain>/fullchain.pem /etc/rustfs/tls/cert.pem
sudo cp /etc/letsencrypt/live/<your-domain>/privkey.pem   /etc/rustfs/tls/key.pem
sudo systemctl reload nginx

Step 9: Backup and Maintenance

The simplest backup strategy is to sync buckets to another S3 compatible target on a schedule with the AWS CLI. The target can be another RustFS instance, an Amazon S3 bucket, or any other S3 compatible service. Run aws s3 sync from the instance with two profiles or two sets of credentials, one for the local RustFS endpoint and one for the destination.

Routine maintenance of the operating system uses the standard Ubuntu package manager. Apply security updates with sudo apt-get update && sudo apt-get -y dist-upgrade and reboot the instance when a kernel update is installed.

To grow the storage tier, resize the EBS data volume in the EC2 console and run sudo resize2fs /dev/<device> on the instance. RustFS picks up the new capacity immediately. The root volume and the data volume are independent, so growing the storage tier does not require touching the operating system disk.

Troubleshooting

If the console is not reachable at https://<public-ip>/rustfs/console/, confirm that the security group allows inbound port 443 from your workstation, that nginx is running with sudo systemctl status nginx.service, and that RustFS is running with sudo systemctl status rustfs.service. The nginx error log at /var/log/nginx/error.log and the RustFS journal sudo journalctl -u rustfs.service -n 100 are the first places to look.

The RustFS S3 API and console bind to loopback only, so sudo ss -tln should show them on 127.0.0.1:9000 and 127.0.0.1:9001 and nginx on 0.0.0.0:443 and 0.0.0.0:80. If the S3 API is not answering, confirm the rustfs.service is active and that /var/lib/rustfs is mounted with findmnt /var/lib/rustfs.

If you have forgotten the credentials, recover them by reading /root/rustfs-credentials.txt as root over SSH. If that file has been deleted on a running instance, recover the values from /etc/default/rustfs, which holds the live RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY. To rotate the credentials, edit /etc/default/rustfs with sudo, replace the values, restart the service with sudo systemctl restart rustfs.service, and update any S3 clients that hold the old key.


Support

cloudimg includes 24/7 technical support for RustFS deployment, access key and policy configuration, S3 client integration, TLS certificate replacement, performance tuning and storage administration. Reach the support team by email at support@cloudimg.co.uk or by chat from the cloudimg website. For upstream RustFS product documentation, see https://docs.rustfs.com/.

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.