# AWS S3 Storage

If you have the yCrash server application installed across multiple server nodes behind a load balancer then it's mandatory to store the uploaded files in some common storage solutions like AWS S3.

By default, uploaded files are stored on the local disk of the machine where the yCrash server application is running. However, the tool also provides the option to store uploaded files in S3. Some customers may prefer not to store files locally due to space limitations or concerns about availability. If you have the yCrash server installed across multiple instances behind a load balancer, it is essential to store uploaded files in AWS S3. This ensures that users can access generated reports regardless of the server instance handling their request. For example, if a user uploads a file to server node-1 and another user attempts to access the same report, the load balancer may route the request to server node-2. If the files are stored locally, the second user may encounter an HTTP 404 error. This setup will ensure that uploaded files are stored in AWS S3, enabling seamless access across all server instances.

yCrash supports two ways to authenticate with AWS S3:

Auth mode When to use Credentials in storage.xml
Static keys (default) Access key + secret key IAM user s3.accessKey and s3.secretKey (or legacy s3.secreteKey)
Instance profile EC2 / Elastic Beanstalk / ECS with an IAM role No access/secret keys. Set s3.authMode=instanceProfile

Follow the steps below based on the auth mode you choose.


# Option A: Static access key and secret key

# 1. Specify AWS S3 credentials to yCrash:

Download (opens new window) the provided template file or create a new XML file named storage.xml and place it in the uploadDir directory of yCrash server. This file specifies the S3 bucket name, access key, and secret key information as shown in the below format:

Here's a XML template file with placeholders:





 
 
 
 
 


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Storage Configurations</comment>	
    <entry key="s3.endPointURL">https://s3.YOUR_REGION.amazonaws.com</entry>
    <entry key="s3.region">YOUR_REGION</entry>
    <entry key="s3.bucketName">YOUR_BUCKET_NAME</entry>
    <entry key="s3.accessKey">YOUR_ACCESS_KEY</entry>
    <entry key="s3.secretKey">YOUR_SECRET_KEY</entry>
</properties>
1
2
3
4
5
6
7
8
9
10

In this template:

  • Replace "YOUR_REGION" with the AWS region where your S3 bucket is located (e.g., "us-west-1").
  • Replace "YOUR_BUCKET_NAME" with the name of your S3 bucket.
  • Replace "YOUR_ACCESS_KEY" and "YOUR_SECRET_KEY" with your AWS access key and secret key, respectively.

TIP

yCrash also accepts the legacy property name s3.secreteKey for backward compatibility. Prefer s3.secretKey in new configurations. If both are present, s3.secretKey is used.

Here’s a sample S3 XML file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Storage Configurations</comment>	
    <entry key="s3.endPointURL">https://s3.us-west-1.amazonaws.com</entry>
    <entry key="s3.region">us-west-1</entry>
    <entry key="s3.bucketName">my-bucket</entry>
    <entry key="s3.accessKey">my-access-key</entry>
    <entry key="s3.secretKey">my-secret-key</entry>
</properties>
1
2
3
4
5
6
7
8
9
10

# 2. Configure CORS in AWS S3 Bucket:

With static keys, the browser may upload files directly to S3. Configure CORS on your S3 bucket as follows:

  • Sign in to the AWS Management Console.

  • In the Buckets list, choose the name of the bucket where you want to configure the CORS.

  • Next choose the Permissions tab.

  • In the Cross-origin resource sharing (CORS) section, click on Edit.

  • In the CORS configuration editor text box, type or copy and paste a new CORS configuration, or edit an existing configuration.

The text that you type in the editor must be a valid JSON. Here is a sample CORS JSON. You may want to change the values based on your requirements.

[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET","POST","PUT"],
        "AllowedOrigins": ["http://www.example1.com"],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]
1
2
3
4
5
6
7
8
9

You can find more examples in the AWS documentation - https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html (opens new window)

# 3. Restart the Application:

Restart the yCrash server application to apply the changes.


# Option B: EC2 / Elastic Beanstalk instance profile (IAM role)

Use this option when you do not want to store long-lived access/secret keys in storage.xml. yCrash picks up credentials from the IAM role attached to the EC2 instance (or Elastic Beanstalk / ECS task role).

TIP

Instance profile auth works with AWS S3 endpoints only (*.amazonaws.com / *.amazonaws.com.cn). For S3-compatible stores (for example Pure Storage or Dell EMC), use static keys (Option A).

# 1. Configure storage.xml for instance profile (application side)

Create or update storage.xml in the yCrash server uploadDir directory. Set s3.authMode to instanceProfile and omit access/secret keys:

Here's a XML template file with placeholders:





 
 
 
 


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Storage Configurations - IAM instance profile</comment>
    <entry key="s3.endPointURL">https://s3.YOUR_REGION.amazonaws.com</entry>
    <entry key="s3.region">YOUR_REGION</entry>
    <entry key="s3.bucketName">YOUR_BUCKET_NAME</entry>
    <entry key="s3.authMode">instanceProfile</entry>
</properties>
1
2
3
4
5
6
7
8
9

In this template:

  • Replace "YOUR_REGION" with the AWS region where your S3 bucket is located (e.g., "us-west-1").
  • Replace "YOUR_BUCKET_NAME" with the name of your S3 bucket.
  • Do not add s3.accessKey or s3.secretKey / s3.secreteKey.
  • s3.endPointURL, s3.region, s3.bucketName, and s3.authMode=instanceProfile are required.

Here’s a sample S3 XML file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Storage Configurations - IAM instance profile</comment>
    <entry key="s3.endPointURL">https://s3.us-west-1.amazonaws.com</entry>
    <entry key="s3.region">us-west-1</entry>
    <entry key="s3.bucketName">my-bucket</entry>
    <entry key="s3.authMode">instanceProfile</entry>
</properties>
1
2
3
4
5
6
7
8
9

TIP

  1. With this mode, the browser uploads to the yCrash server first. The server then writes the file to S3 using the instance role.
  2. Because of that, S3 bucket CORS is not required (unlike Option A).

# 2. Attach an IAM role / instance profile (AWS / DevOps)

Create and attach the IAM role to yCrash host that can read and write the S3 bucket. No access keys are stored in config.

Replace these placeholders with your values:

Placeholder Meaning Example
YOUR_ACCOUNT_ID Your 12-digit AWS account ID 123456789012
YOUR_ROLE_NAME Name you choose for the IAM role ycrash-s3-role
YOUR_INSTANCE_PROFILE_NAME Name you choose for the instance profile (usually same as the role name) ycrash-s3-profile
YOUR_BUCKET_NAME The S3 bucket where yCrash stores uploaded files ycrash-reports
YOUR_REGION AWS region where that bucket lives us-west-1
YOUR_INSTANCE_ID EC2 instance ID running yCrash i-0abc1234def567890
YOUR_ENV_NAME Elastic Beanstalk environment name (skip if not on EB) ycrash-prod
YOUR_KMS_KEY_ARN KMS key ARN (only if your bucket uses SSE-KMS encryption) arn:aws:kms:us-west-1:123456789012:key/abcd-...

Run all AWS CLI commands from a machine where you are logged in as an admin IAM identity (aws configure with permissions for IAM + EC2 + Elastic Beanstalk).

# 2.1 Create the IAM role and instance profile

An instance profile is just a container that allows EC2 to hand an IAM role's temporary credentials to your application. You need one role that trusts EC2.

AWS Console: IAM → Roles → Create role → trusted entity AWS service → EC2 → create the role → create an instance profile and add the role to it.

CLI:

  1. Find Account ID:
aws sts get-caller-identity --query Account --output text
1

Use this value as YOUR_ACCOUNT_ID placeholder below.

  1. Save this trust policy as trust-policy.json:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { "Service": "ec2.amazonaws.com" },
            "Action": "sts:AssumeRole"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
  1. Create the role and instance profile:
aws iam create-role \
  --role-name YOUR_ROLE_NAME \
  --assume-role-policy-document file://trust-policy.json \
  --description "yCrash S3 access via instance profile"

aws iam create-instance-profile \
  --instance-profile-name YOUR_INSTANCE_PROFILE_NAME

aws iam add-role-to-instance-profile \
  --instance-profile-name YOUR_INSTANCE_PROFILE_NAME \
  --role-name YOUR_ROLE_NAME
1
2
3
4
5
6
7
8
9
10
11

TIP

Already on Elastic Beanstalk? EB usually has a default role aws-elasticbeanstalk-ec2-role (instance profile aws-elasticbeanstalk-ec2-profile). Easiest path: attach the S3 policy from step 2.3 to that role and skip creating a new one. No environment change needed.

# 2.2 Attach the role to the host

EC2 (CLI):

aws ec2 associate-iam-instance-profile \
  --instance-id YOUR_INSTANCE_ID \
  --iam-instance-profile Name=YOUR_INSTANCE_PROFILE_NAME \
  --region YOUR_REGION
1
2
3
4

If the instance already has a different profile, replace it from EC2 → Instances → Actions → Security → Modify IAM role, or use replace-iam-instance-profile-association as shown below.

EC2 (CLI):

aws ec2 describe-instances --instance-ids YOUR_INSTANCE_ID --region YOUR_REGION \
   --query "Reservations[0].Instances[0].IamInstanceProfile" --output table

aws ec2 replace-iam-instance-profile-association \
   --iam-instance-profile Name=YOUR_INSTANCE_PROFILE_NAME \
   --association-id <value-from-describe-output> \
   --region YOUR_REGION
1
2
3
4
5
6
7

Elastic Beanstalk (CLI):

aws elasticbeanstalk update-environment \
  --region YOUR_REGION \
  --environment-name YOUR_ENV_NAME \
  --option-settings \
    Namespace=aws:autoscaling:launchconfiguration,OptionName=IamInstanceProfile,Value=YOUR_INSTANCE_PROFILE_NAME
1
2
3
4
5

Or in the console: EB → Environments → your environment → Configuration → Instances → IAM instance profile.

WARNING

Changing the EB instance profile recycles instances. Prefer rolling deployments, or attach the S3 policy to the default EB role instead (see tip in 2.1) to avoid that.

If the environment was created through the EB console or EB CLI, this option cannot be set in .ebextensions config files as the console/EB CLI override it. Use the command above or the console

If you use a custom role on EB, also copy the default EB role policies onto it, or health checks and deployments can break.

# 2.3 IAM policy for the yCrash bucket

The following configuration grants exactly what the yCrash server needs: write new uploads, read them back for report viewing, and clean up. Save it as ycrash-s3-policy.json (replace YOUR_BUCKET_NAME in both places):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "YCrashObjectReadWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:AbortMultipartUpload",
                "s3:ListMultipartUploadParts"
            ],
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        },
        {
            "Sid": "YCrashBucketList",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Create and attach the policy:

aws iam create-policy \
  --policy-name YCrashS3LeastPrivilege \
  --policy-document file://ycrash-s3-policy.json

aws iam attach-role-policy \
  --role-name YOUR_ROLE_NAME \
  --policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/YCrashS3LeastPrivilege
1
2
3
4
5
6
7

If you selected an existing role or the EB default role in step 2.1, replace YOUR_ROLE_NAME accordingly.

# 2.4 Bucket policy, KMS, and networking

Same-account bucket: the role policy above is usually enough. No bucket policy change needed.

Cross-account bucket: allow the role in the bucket policy:

{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:role/YOUR_ROLE_NAME" },
    "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
    "Resource": [
        "arn:aws:s3:::YOUR_BUCKET_NAME",
        "arn:aws:s3:::YOUR_BUCKET_NAME/*"
    ]
}
1
2
3
4
5
6
7
8
9

KMS: if the bucket uses a customer-managed KMS key (SSE-KMS with your key), also allow:

{
    "Sid": "YCrashKmsForS3",
    "Effect": "Allow",
    "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:GenerateDataKey"
    ],
    "Resource": "YOUR_KMS_KEY_ARN"
}
1
2
3
4
5
6
7
8
9
10

AES256 / AWS-managed aws/s3 keys do not need extra KMS permissions.

Networking: the instance only needs outbound HTTPS to S3. Public subnet with internet access, or a private subnet with NAT / S3 gateway endpoint, is enough. No inbound rules are required for S3. Leave Block Public Access enabled.

# 2.5 Verify

From the instance (SSH or eb ssh):

# 1. Get IMDSv2 session token
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Should print your role name
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

# Should print instance profile ARN
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/info

# Should show assumed-role/YOUR_ROLE_NAME
aws sts get-caller-identity

# Should succeed against your bucket
echo "test" > /tmp/ycrash-test.txt
aws s3 cp /tmp/ycrash-test.txt s3://YOUR_BUCKET_NAME/ycrash-test.txt --region YOUR_REGION

# Should fail with AccessDenied (proves the policy is scoped to YOUR_BUCKET_NAME only)
aws s3 cp /tmp/ycrash-test.txt s3://some-other-bucket/test.txt --region YOUR_REGION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 3. Restart the Application:

Restart the yCrash server application to apply the changes.


Note: All configuration files, including license.lic, *.xml, and *.json related to yCrash server settings, will continue to remain and be maintained in the uploadDir path.