forked from sagnik/Project_Velocity
feat: Ipad app production readiness, Colony orchestration, Social posting (#44)
#38 Ipad app production readiness, Colony orchestration, Social posting Co-authored-by: Sayan Datta <sayan@Sayans-MacBook-Air.local> Reviewed-on: sagnik/Project_Velocity#44
This commit is contained in:
198
infrastructure/aws/setup_s3_media_bucket.sh
Executable file
198
infrastructure/aws/setup_s3_media_bucket.sh
Executable file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if ! command -v aws >/dev/null 2>&1; then
|
||||
echo "aws CLI is required. Install AWS CLI v2 and authenticate before running." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AWS_REGION="${AWS_REGION:-ap-south-1}"
|
||||
AWS_ACCOUNT_ID="${AWS_ACCOUNT_ID:-$(aws sts get-caller-identity --query Account --output text)}"
|
||||
BUCKET_NAME="${VELOCITY_MEDIA_BUCKET:-velocity-media-${AWS_ACCOUNT_ID}-${AWS_REGION}}"
|
||||
IAM_USER_NAME="${VELOCITY_MEDIA_IAM_USER:-velocity-media-app}"
|
||||
IAM_POLICY_NAME="${VELOCITY_MEDIA_IAM_POLICY_NAME:-VelocityMediaBucketReadWriteObjects}"
|
||||
CORS_ORIGIN="${VELOCITY_MEDIA_CORS_ORIGIN:-https://velocity.desineuron.in}"
|
||||
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
cleanup() {
|
||||
rm -rf "${TMP_DIR}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
bucket_exists() {
|
||||
aws s3api head-bucket --bucket "${BUCKET_NAME}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
create_bucket() {
|
||||
if bucket_exists; then
|
||||
echo "S3 bucket already exists: ${BUCKET_NAME}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Creating private S3 bucket: ${BUCKET_NAME} (${AWS_REGION})"
|
||||
if [[ "${AWS_REGION}" == "us-east-1" ]]; then
|
||||
aws s3api create-bucket --bucket "${BUCKET_NAME}" --region "${AWS_REGION}" >/dev/null
|
||||
else
|
||||
aws s3api create-bucket \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--region "${AWS_REGION}" \
|
||||
--create-bucket-configuration "LocationConstraint=${AWS_REGION}" >/dev/null
|
||||
fi
|
||||
|
||||
aws s3api wait bucket-exists --bucket "${BUCKET_NAME}"
|
||||
}
|
||||
|
||||
secure_bucket() {
|
||||
echo "Applying private bucket controls"
|
||||
aws s3api put-public-access-block \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--public-access-block-configuration \
|
||||
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
|
||||
|
||||
aws s3api put-bucket-ownership-controls \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--ownership-controls '{
|
||||
"Rules": [
|
||||
{
|
||||
"ObjectOwnership": "BucketOwnerEnforced"
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
aws s3api put-bucket-encryption \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--server-side-encryption-configuration '{
|
||||
"Rules": [
|
||||
{
|
||||
"ApplyServerSideEncryptionByDefault": {
|
||||
"SSEAlgorithm": "AES256"
|
||||
},
|
||||
"BucketKeyEnabled": true
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
aws s3api put-bucket-versioning \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--versioning-configuration Status=Enabled
|
||||
}
|
||||
|
||||
apply_cors() {
|
||||
local cors_file="${TMP_DIR}/cors.json"
|
||||
cat >"${cors_file}" <<JSON
|
||||
{
|
||||
"CORSRules": [
|
||||
{
|
||||
"AllowedOrigins": ["${CORS_ORIGIN}"],
|
||||
"AllowedMethods": ["GET", "PUT", "HEAD"],
|
||||
"AllowedHeaders": ["Authorization", "Content-Type", "Content-MD5", "x-amz-*"],
|
||||
"ExposeHeaders": ["ETag", "x-amz-request-id", "x-amz-version-id"],
|
||||
"MaxAgeSeconds": 3000
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
echo "Applying CORS policy for ${CORS_ORIGIN}"
|
||||
aws s3api put-bucket-cors \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--cors-configuration "file://${cors_file}"
|
||||
}
|
||||
|
||||
apply_https_only_bucket_policy() {
|
||||
local bucket_policy_file="${TMP_DIR}/bucket-policy.json"
|
||||
cat >"${bucket_policy_file}" <<JSON
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "DenyInsecureTransport",
|
||||
"Effect": "Deny",
|
||||
"Principal": "*",
|
||||
"Action": "s3:*",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::${BUCKET_NAME}",
|
||||
"arn:aws:s3:::${BUCKET_NAME}/*"
|
||||
],
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"aws:SecureTransport": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
echo "Applying HTTPS-only bucket policy"
|
||||
aws s3api put-bucket-policy \
|
||||
--bucket "${BUCKET_NAME}" \
|
||||
--policy "file://${bucket_policy_file}"
|
||||
}
|
||||
|
||||
ensure_iam_user() {
|
||||
if aws iam get-user --user-name "${IAM_USER_NAME}" >/dev/null 2>&1; then
|
||||
echo "IAM user already exists: ${IAM_USER_NAME}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Creating IAM user: ${IAM_USER_NAME}"
|
||||
aws iam create-user \
|
||||
--user-name "${IAM_USER_NAME}" \
|
||||
--tags Key=Project,Value=Velocity Key=Purpose,Value=MediaStorage >/dev/null
|
||||
}
|
||||
|
||||
attach_restricted_policy() {
|
||||
local policy_file="${TMP_DIR}/iam-policy.json"
|
||||
cat >"${policy_file}" <<JSON
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "VelocityMediaObjectReadWriteOnly",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"s3:PutObject"
|
||||
],
|
||||
"Resource": "arn:aws:s3:::${BUCKET_NAME}/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
echo "Attaching restricted inline IAM policy: ${IAM_POLICY_NAME}"
|
||||
aws iam put-user-policy \
|
||||
--user-name "${IAM_USER_NAME}" \
|
||||
--policy-name "${IAM_POLICY_NAME}" \
|
||||
--policy-document "file://${policy_file}"
|
||||
}
|
||||
|
||||
print_summary() {
|
||||
cat <<SUMMARY
|
||||
|
||||
Project Velocity media bucket provisioning complete.
|
||||
|
||||
Bucket: ${BUCKET_NAME}
|
||||
Region: ${AWS_REGION}
|
||||
CORS origin: ${CORS_ORIGIN}
|
||||
IAM user: ${IAM_USER_NAME}
|
||||
Inline policy: ${IAM_POLICY_NAME}
|
||||
|
||||
Environment values for backend/.env.production:
|
||||
AWS_REGION=${AWS_REGION}
|
||||
AWS_S3_BUCKET=${BUCKET_NAME}
|
||||
AWS_S3_MEDIA_PREFIX=velocity-production
|
||||
|
||||
This script does not print or create long-lived access keys. Use your preferred
|
||||
AWS credential vending path for production secrets.
|
||||
SUMMARY
|
||||
}
|
||||
|
||||
create_bucket
|
||||
secure_bucket
|
||||
apply_cors
|
||||
apply_https_only_bucket_policy
|
||||
ensure_iam_user
|
||||
attach_restricted_policy
|
||||
print_summary
|
||||
@@ -1,60 +1,154 @@
|
||||
{
|
||||
email admin@desineuron.in
|
||||
admin 127.0.0.1:2019
|
||||
auto_https enable_redirects
|
||||
servers {
|
||||
protocols h1 h2 h3
|
||||
}
|
||||
log {
|
||||
output file /var/log/caddy/admin.log
|
||||
format json
|
||||
}
|
||||
}
|
||||
|
||||
office.desineuron.in, git.desineuron.in, cloud.desineuron.in, projects.desineuron.in, talk.desineuron.in, vpn.desineuron.in {
|
||||
tls /etc/caddy/tls/fullchain.pem /etc/caddy/tls/privkey.pem
|
||||
(velocity_security_headers) {
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
-Server
|
||||
}
|
||||
}
|
||||
|
||||
(velocity_proxy_headers) {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-Port {server_port}
|
||||
}
|
||||
|
||||
api.desineuron.in {
|
||||
import velocity_security_headers
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
output file /var/log/caddy/api.desineuron.in.access.log
|
||||
format json
|
||||
}
|
||||
|
||||
reverse_proxy https://127.0.0.1:8443 {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
@websockets {
|
||||
header Connection *Upgrade*
|
||||
header Upgrade websocket
|
||||
}
|
||||
|
||||
reverse_proxy @websockets 127.0.0.1:8001 127.0.0.1:8000 {
|
||||
import velocity_proxy_headers
|
||||
flush_interval -1
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
versions 1.1
|
||||
dial_timeout 30s
|
||||
read_timeout 3600s
|
||||
write_timeout 3600s
|
||||
}
|
||||
}
|
||||
|
||||
reverse_proxy 127.0.0.1:8001 127.0.0.1:8000 {
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
versions 1.1
|
||||
dial_timeout 30s
|
||||
read_timeout 3600s
|
||||
write_timeout 3600s
|
||||
}
|
||||
lb_policy first
|
||||
health_uri /health
|
||||
health_interval 15s
|
||||
}
|
||||
}
|
||||
|
||||
dreamweaver.desineuron.in {
|
||||
import velocity_security_headers
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/dreamweaver.desineuron.in.access.log
|
||||
format json
|
||||
}
|
||||
|
||||
reverse_proxy 127.0.0.1:8082 {
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
versions 1.1
|
||||
dial_timeout 30s
|
||||
read_timeout 3600s
|
||||
write_timeout 3600s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
velocity.desineuron.in {
|
||||
import velocity_security_headers
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
output file /var/log/caddy/velocity.desineuron.in.access.log
|
||||
format json
|
||||
}
|
||||
|
||||
import /etc/caddy/managed/llm_upstream.caddy_inc
|
||||
|
||||
handle /api/* {
|
||||
reverse_proxy 127.0.0.1:8001 127.0.0.1:8000 {
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
versions 1.1
|
||||
dial_timeout 30s
|
||||
read_timeout 3600s
|
||||
write_timeout 3600s
|
||||
}
|
||||
lb_policy first
|
||||
health_uri /health
|
||||
health_interval 15s
|
||||
}
|
||||
}
|
||||
|
||||
handle {
|
||||
reverse_proxy https://127.0.0.1:8443 {
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ops.desineuron.in {
|
||||
import velocity_security_headers
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/ops.desineuron.in.access.log
|
||||
format json
|
||||
}
|
||||
|
||||
reverse_proxy https://127.0.0.1:8443 {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ops.desineuron.in {
|
||||
office.desineuron.in, git.desineuron.in, cloud.desineuron.in, projects.desineuron.in, talk.desineuron.in, vpn.desineuron.in {
|
||||
tls /etc/caddy/tls/fullchain.pem /etc/caddy/tls/privkey.pem
|
||||
import velocity_security_headers
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
format json
|
||||
}
|
||||
|
||||
reverse_proxy https://127.0.0.1:8443 {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
import velocity_proxy_headers
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
|
||||
@@ -1,21 +1,95 @@
|
||||
# Project Velocity production API ingress.
|
||||
#
|
||||
# Install into /etc/nginx/sites-available/api.desineuron.in.conf and symlink to
|
||||
# sites-enabled when Nginx is the public TLS terminator. Do not enable this
|
||||
# 80/443 vhost at the same time as the Caddy public terminator for this domain.
|
||||
|
||||
map $http_upgrade $velocity_connection_upgrade {
|
||||
default upgrade;
|
||||
"" close;
|
||||
}
|
||||
|
||||
upstream velocity_fastapi_backend {
|
||||
server 127.0.0.1:8001 max_fails=3 fail_timeout=10s;
|
||||
server 127.0.0.1:8000 backup max_fails=3 fail_timeout=10s;
|
||||
keepalive 64;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name api.desineuron.in;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/desineuron-infra/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/desineuron-infra/privkey.pem;
|
||||
|
||||
access_log /var/log/nginx/api.desineuron.in.access.log;
|
||||
error_log /var/log/nginx/api.desineuron.in.error.log;
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
default_type "text/plain";
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name api.desineuron.in;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/api.desineuron.in/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/api.desineuron.in/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:VelocityAPI:20m;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
|
||||
client_max_body_size 250m;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_connect_timeout 30s;
|
||||
|
||||
access_log /var/log/nginx/api.desineuron.in.access.log;
|
||||
error_log /var/log/nginx/api.desineuron.in.error.log warn;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
location = /health {
|
||||
proxy_pass http://velocity_fastapi_backend/health;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
}
|
||||
|
||||
location ~ ^/(api/sentinel/ws|api/oracle/ws|ws|api/.*/ws) {
|
||||
proxy_pass http://velocity_fastapi_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $velocity_connection_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://velocity_fastapi_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $velocity_connection_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Request-ID $request_id;
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user