1. Pengenalan AWS S3
Amazon Simple Storage Service (S3) adalah layanan object storage yang disediakan oleh Amazon Web Services (AWS). S3 dirancang untuk menyimpan dan mengambil data dalam jumlah besar â dari beberapa byte hingga 5 TB per object â dengan durability 99.999999999% (11 nines).
S3 menggunakan model key-value store dimana setiap object disimpan dengan key (nama file) unik di dalam sebuah bucket (container). S3 menawarkan virtually unlimited storage, high availability, dan berbagai fitur keamanan yang membuatnya menjadi standar industri untuk cloud storage.
Mengapa S3 Penting?
| Keunggulan | Penjelasan |
|---|---|
| Durability | 99.999999999% (11 nines) â data hampir tidak mungkin hilang |
| Availability | 99.99% â selalu bisa diakses kapan saja |
| Scalability | Tanpa batas â dari byte hingga exabytes |
| Security | Enkripsi at-rest dan in-transit, fine-grained access control |
| Performance | High throughput, low latency untuk semua storage class |
| Cost-Effective | Pay-as-you-go, tiered pricing berdasarkan akses pattern |
| Integration | Terintegrasi dengan seluruh layanan AWS (Lambda, CloudFront, dll) |
Konsep dasar S3:
- Bucket â container untuk objects (seperti folder root)
- Object â file yang disimpan (data + metadata + key)
- Key â nama unik untuk setiap object di dalam bucket
- Region â lokasi geografis dimana bucket dibuat
- ARN â Amazon Resource Name untuk identifikasi resource
2. Membuat & Mengelola Bucket
Menggunakan AWS CLI
6. Lifecycle Management
Lifecycle rules mengotomatiskan transisi object antar storage class dan penghapusan object yang sudah tidak diperlukan. Ini sangat penting untuk mengelola biaya storage.
{
"Rules": [
{
"ID": "TransitionToIA",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 730
}
},
{
"ID": "CleanupTempFiles",
"Status": "Enabled",
"Filter": {
"Prefix": "temp/"
},
"Expiration": {
"Days": 7
}
},
{
"ID": "ManageOldVersions",
"Status": "Enabled",
"Filter": {},
"NoncurrentVersionTransitions": [
{
"NoncurrentDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"NoncurrentDays": 90,
"StorageClass": "GLACIER"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 365
}
},
{
"ID": "RemoveIncompleteMultipart",
"Status": "Enabled",
"Filter": {},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
}
]
}
# Terapkan lifecycle rules
aws s3api put-bucket-lifecycle-configuration \
--bucket my-app-storage-2026 \
--lifecycle-configuration file://lifecycle.json
# Lihat lifecycle rules
aws s3api get-bucket-lifecycle-configuration \
--bucket my-app-storage-2026
# Hapus lifecycle rules
aws s3api delete-bucket-lifecycle \
--bucket my-app-storage-2026
7. IAM Policies & Bucket Policies
Keamanan S3 diatur melalui dua jenis policy: IAM Policy (attached ke user/role) dan Bucket Policy (attached ke bucket). Keduanya bekerja bersama untuk menentukan siapa yang bisa mengakses apa.
Bucket Policy â Contoh Umum
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAppReadAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/app-role"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/*"
]
},
{
"Sid": "DenyPublicAccess",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "AllowCloudFrontAccess",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-app-storage-2026/public/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1234567890"
}
}
}
]
}
# Terapkan bucket policy
aws s3api put-bucket-policy \
--bucket my-app-storage-2026 \
--policy file://bucket-policy.json
# Lihat bucket policy
aws s3api get-bucket-policy --bucket my-app-storage-2026
# Hapus bucket policy
aws s3api delete-bucket-policy --bucket my-app-storage-2026
IAM Policy untuk User/Role
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/uploads/*",
"arn:aws:s3:::my-app-storage-2026/public/*"
]
},
{
"Sid": "DenyDeleteProduction",
"Effect": "Deny",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my-app-storage-2026/production/*"
}
]
}
Jangan pernah membuat bucket S3 public kecuali Anda benar-benar tahu apa yang Anda lakukan. Banyak kebocoran data terjadi karena bucket S3 yang tidak sengaja di-public-kan. Selalu gunakan BlockPublicAcls dan akses melalui CloudFront atau presigned URLs.
8. Presigned URLs
Presigned URLs memungkinkan Anda memberikan akses sementara ke object S3 tanpa perlu membuat object tersebut public. URL ini memiliki waktu kedaluwarsa dan bisa digunakan untuk upload maupun download.
Menggunakan AWS CLI
# Generate presigned URL untuk download (berlaku 1 jam)
aws s3 presign s3://my-app-storage-2026/photos/photo.jpg \
--expires-in 3600
# https://my-app-storage-2026.s3.ap-southeast-1.amazonaws.com/photos/photo.jpg?...
# Generate presigned URL untuk download (berlaku 7 hari)
aws s3 presign s3://my-app-storage-2026/documents/report.pdf \
--expires-in 604800
# Generate presigned URL untuk upload
aws s3 presign s3://my-app-storage-2026/uploads/new-file.jpg \
--expires-in 3600
# Gunakan URL untuk upload via curl
curl -X PUT \
-H "Content-Type: image/jpeg" \
--data-binary @photo.jpg \
"https://presigned-url-here"
Menggunakan Python (boto3)
import boto3
from botocore.config import Config
s3 = boto3.client('s3',
region_name='ap-southeast-1',
config=Config(signature_version='s3v4')
)
BUCKET = 'my-app-storage-2026'
# Generate presigned URL untuk GET (download)
def generate_download_url(key, expires_in=3600):
url = s3.generate_presigned_url(
'get_object',
Params={
'Bucket': BUCKET,
'Key': key,
'ResponseContentDisposition': f'attachment; filename="{key.split("/")[-1]}"'
},
ExpiresIn=expires_in
)
return url
# Generate presigned URL untuk PUT (upload)
def generate_upload_url(key, content_type='application/octet-stream', expires_in=3600):
url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': BUCKET,
'Key': key,
'ContentType': content_type
},
ExpiresIn=expires_in
)
return url
# Generate presigned POST (untuk browser upload â lebih fleksibel)
def generate_presigned_post(key, content_type='image/jpeg', max_size=10*1024*1024):
conditions = [
['content-length-range', 1, max_size],
['starts-with', '$Content-Type', content_type.split('/')[0]]
]
fields = {
'Content-Type': content_type,
'x-amz-meta-uploaded-by': 'beebanelabs'
}
response = s3.generate_presigned_post(
Bucket=BUCKET,
Key=key,
Fields=fields,
Conditions=conditions,
ExpiresIn=3600
)
return response
# Returns: {'url': 'https://...', 'fields': {...}}
# Contoh penggunaan
download_url = generate_download_url('photos/photo.jpg', expires_in=7200)
upload_url = generate_upload_url('uploads/new-photo.jpg')
post_data = generate_presigned_post('uploads/user-avatar.jpg')
print(f"Download URL: {download_url}")
print(f"Upload URL: {upload_url}")
print(f"POST URL: {post_data['url']}")
print(f"POST Fields: {post_data['fields']}")
Browser Upload dengan Presigned POST
// Upload file langsung dari browser ke S3
async function uploadToS3(file) {
// 1. Dapatkan presigned POST dari backend
const response = await fetch('/api/get-upload-url', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type
})
});
const { url, fields } = await response.json();
// 2. Upload langsung ke S3
const formData = new FormData();
Object.entries(fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
const uploadResponse = await fetch(url, {
method: 'POST',
body: formData
});
if (uploadResponse.ok) {
console.log('Upload berhasil!');
} else {
console.error('Upload gagal');
}
}
// Gunakan
document.getElementById('fileInput').addEventListener('change', (e) => {
uploadToS3(e.target.files[0]);
});
9. Static Website Hosting
S3 bisa digunakan untuk meng-host static website (HTML, CSS, JavaScript) tanpa perlu server. Dipadukan dengan CloudFront untuk CDN global dan custom domain.
# Enable static website hosting
aws s3 website s3://my-website-bucket \
--index-document index.html \
--error-document error.html
# Upload website files
aws s3 sync ./public/ s3://my-website-bucket/ \
--acl public-read
# Set content types
aws s3 cp ./public/index.html s3://my-website-bucket/ \
--content-type "text/html" --acl public-read
aws s3 cp ./public/css/style.css s3://my-website-bucket/css/ \
--content-type "text/css" --acl public-read
aws s3 cp ./public/js/app.js s3://my-website-bucket/js/ \
--content-type "application/javascript" --acl public-read
# Dapatkan website URL
echo "Website URL: http://my-website-bucket.s3-website-ap-southeast-1.amazonaws.com"
Redirect Rules
<!-- website-redirect-rules.xml -->
<RoutingRules>
<RoutingRule>
<Condition>
<KeyPrefixEquals>old-page/</KeyPrefixEquals>
</Condition>
<Redirect>
<ReplaceKeyPrefixWith>new-page/</ReplaceKeyPrefixWith>
<HttpRedirectCode>301</HttpRedirectCode>
</Redirect>
</RoutingRule>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName>app.example.com</HostName>
<ReplaceKeyWith>index.html</ReplaceKeyWith>
</Redirect>
</RoutingRule>
</RoutingRules>
10. Encryption & Keamanan
Enkripsi di S3
| Enkripsi | Penjelasan | Kapan Digunakan |
|---|---|---|
| SSE-S3 | S3 manage encryption keys (AES-256) | Kebanyakan use case standar |
| SSE-KMS | AWS KMS manage keys (audit trail) | Compliance, audit requirement |
| SSE-C | Customer provide encryption keys | Kontrol penuh atas keys |
| Client-Side | Enkripsi sebelum upload ke S3 | Zero-trust, end-to-end encryption |
# Set default encryption (SSE-S3)
aws s3api put-bucket-encryption \
--bucket my-app-storage-2026 \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'
# Upload dengan KMS encryption
aws s3 cp ./sensitive-data.csv s3://my-app-storage-2026/secure/ \
--sse aws:kms \
--sse-kms-key-id alias/my-s3-key
# Upload dengan AES-256 encryption
aws s3 cp ./data.csv s3://my-app-storage-2026/ \
--sse AES256
# Enable Object Lock (WORM â Write Once Read Many)
# Berguna untuk compliance
aws s3api put-object-lock-configuration \
--bucket my-app-storage-2026 \
--object-lock-configuration '{
"ObjectLockEnabled": true,
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Days": 365
}
}
}'
# Enable Transfer Acceleration (upload cepat via edge locations)
aws s3api put-bucket-accelerate-configuration \
--bucket my-app-storage-2026 \
--accelerate-configuration Status=Enabled
# Enable server access logging
aws s3api put-bucket-logging \
--bucket my-app-storage-2026 \
--bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-s3-logs",
"TargetPrefix": "access-logs/"
}
}'
11. Best Practices
Keamanan
| Praktik | Rekomendasi |
|---|---|
| Block Public Access | Selalu aktifkan Block Public Access di level bucket |
| Enkripsi Default | Aktifkan SSE-S3 atau SSE-KMS sebagai default encryption |
| Enforce HTTPS | Tambahkan bucket policy yang menolak request non-HTTPS |
| Versioning | Selalu aktifkan versioning untuk bucket production |
| MFA Delete | Aktifkan MFA Delete untuk bucket kritis |
| Access Logging | Aktifkan server access logging untuk audit |
| Least Privilege | Berikan permission seminimal mungkin sesuai kebutuhan |
| Object Lock | Gunakan untuk data compliance (WORM) |
Biaya & Performance
- Gunakan lifecycle rules untuk transisi data ke storage class yang lebih murah
- Hapus incomplete multipart upload secara otomatis
- Gunakan S3 Intelligent-Tiering jika pola akses tidak diketahui
- Gunakan CloudFront sebagai CDN untuk akses global yang cepat
- Gunakan S3 Transfer Acceleration untuk upload lintas benua
- Monitor biaya dengan AWS Cost Explorer dan S3 Storage Lens
- Gunakan prefix naming yang baik untuk high-throughput workloads
Naming Conventions
# Prefix yang baik (mudah di-manage)
photos/2026/06/26/photo.jpg
documents/reports/quarterly-report-q2-2026.pdf
users/{user_id}/avatars/avatar.jpg
backups/database/2026-06-26-dump.sql.gz
logs/app/2026/06/26/app-log-001.gz
# Hindari
PHOTO.JPG # Tidak ada hierarchy
a/b/c/d/e/f/file.txt # Terlalu dalam
file with spaces.txt # Spasi menyulitkan
S3 dirancang untuk durability 99.999999999% (11 nines) yang berarti jika Anda menyimpan 10 juta object, statistiknya hanya 1 object yang hilang per 10.000 tahun. Tapi ini bukan backup â tetap gunakan cross-region replication untuk disaster recovery.
12. Quiz Pemahaman
1. Berapa durability S3 Standard?
2. Apa itu Presigned URL?
3. Apa fungsi S3 Versioning?
4. Storage class mana yang paling murah untuk data yang sangat jarang diakses?
5. Mengapa bucket S3 sebaiknya tidak di-public-kan?