Selectel Cloud Storage Setup
Selectel provides S3-compatible object storage in Russian datacenters. Suitable for projects requiring data storage in Russian territory (Federal Law 152-FZ).
Creating storage and access keys
In Selectel Control Panel: Control Panel → Object Storage → create bucket. Access type — private. Region — ru-1 (Saint Petersburg) or ru-2 (Moscow).
Access keys are created in "Users" → "S3 Keys". Endpoint: https://s3.ru-1.storage.selcloud.ru.
Laravel configuration
AWS_ACCESS_KEY_ID=your_selectel_key
AWS_SECRET_ACCESS_KEY=your_selectel_secret
AWS_DEFAULT_REGION=ru-1
AWS_BUCKET=myapp-uploads
AWS_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
AWS_USE_PATH_STYLE_ENDPOINT=true
// config/filesystems.php
'selectel' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'ru-1'),
'bucket' => env('AWS_BUCKET'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => true,
'throw' => true,
],
// File upload
$path = Storage::disk('selectel')->putFile('uploads/' . date('Y/m'), $request->file('document'));
// Presigned URL
$url = Storage::disk('selectel')->temporaryUrl($path, now()->addHour());
// Public URL (if bucket is public)
$url = Storage::disk('selectel')->url($path);
Node.js with AWS SDK v3
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3 = new S3Client({
region: "ru-1",
endpoint: "https://s3.ru-1.storage.selcloud.ru",
forcePathStyle: true,
credentials: {
accessKeyId: process.env.SELECTEL_KEY!,
secretAccessKey: process.env.SELECTEL_SECRET!,
},
});
// Upload
await s3.send(new PutObjectCommand({
Bucket: "myapp-uploads",
Key: `uploads/${Date.now()}-${filename}`,
Body: fileBuffer,
ContentType: mimeType,
}));
// Presigned URL for download
const url = await getSignedUrl(s3, new GetObjectCommand({
Bucket: "myapp-uploads",
Key: fileKey,
}), { expiresIn: 3600 });
Bucket access policy
For public static distribution (e.g., avatars):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadAvatars",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myapp-uploads/avatars/*"
}
]
}
Apply policy via AWS CLI with custom endpoint:
aws s3api put-bucket-policy \
--bucket myapp-uploads \
--policy file://bucket-policy.json \
--endpoint-url https://s3.ru-1.storage.selcloud.ru
Sync and backup
# Sync local folder to Selectel
aws s3 sync ./backups/ s3://myapp-backups/database/ \
--endpoint-url https://s3.ru-1.storage.selcloud.ru \
--exclude "*.tmp"
# Copy between buckets (cross-region backup)
aws s3 sync s3://myapp-uploads s3://myapp-uploads-backup \
--endpoint-url https://s3.ru-1.storage.selcloud.ru
Timeline
Selectel Object Storage integration in Laravel or Node.js project: 1 day. With access policies, CDN, and automatic backup: 2–3 days.







