Skip to content

Latest commit

 

History

History
394 lines (319 loc) · 16.3 KB

oracle-oci.md

File metadata and controls

394 lines (319 loc) · 16.3 KB

oracle oci

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJV+SFaaSS80QR0mZO5369wV+Hmvffzinbq6OWZBju3iY/Jacj/CoEmqUIaO3pNwZPs+FJkwaSlYhYiYCUrVkkA6CwqmjBinpcwPeg9hjLA1dSkyDnaNl0DqXfq6L+xag23WAD/YV+spoAs3QHC2re9WSPf7NJ+7XWK1JXIhZv2xkW4F3ss1oOEZfYtZFI3xP32CjJHFi9A1DiKjDGz7JQcCPKlqHcA0TQag9EntE1Oc50l1rKsUSh9j82mxU30IS2UL1wUS9FZWuAu+7SF/KqyjHjH0+W/UIGDwcgUh87LTgwEBFrcbNJC2yKPsLeuYZrWMaLl7nst0144hGgLWNp ssh-key-2026-01-12

compartment

ocid1.tenancy.oc1..aaaaaaaarzc3njhhyh2wro6dtbnyru3ssama2r3uf3mdufd7owup3inhs52q


oci-deploy-code-server-latest.zip-20260125063627

https://idcs-27e4092fa5e143949c5ec777a9513977.identity.oraclecloud.com:443

=============================================================================

nginx.conf — Global Performance Config

Stack : React (SPA) + .NET Web API

Author: mosgaragedev

=============================================================================

---------------------------------------------------------------------------

Worker / Process Tuning

---------------------------------------------------------------------------

user nginx; worker_processes auto; # 1 worker per CPU core worker_rlimit_nofile 65535; # match system ulimit

error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid;

events { worker_connections 4096; # per worker; total = workers × 4096 use epoll; # Linux: most efficient I/O model multi_accept on; # accept all new connections at once }

---------------------------------------------------------------------------

HTTP Core

---------------------------------------------------------------------------

http {

# ── MIME / Encoding ──────────────────────────────────────────────────────
include       /etc/nginx/mime.types;
default_type  application/octet-stream;

charset utf-8;
charset_types text/plain text/css application/json
              application/javascript text/xml application/xml
              application/xml+rss text/javascript;

# ── Logging ──────────────────────────────────────────────────────────────
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for" '
                'rt=$request_time uct=$upstream_connect_time '
                'uht=$upstream_header_time urt=$upstream_response_time';

access_log  /var/log/nginx/access.log  main buffer=64k flush=5s;

# ── Transport Optimisation ───────────────────────────────────────────────
sendfile           on;
tcp_nopush         on;                # batch TCP packets (pairs with sendfile)
tcp_nodelay        on;                # low-latency for keep-alive connections
keepalive_timeout  75s;
keepalive_requests 1000;

# ── Compression (Gzip) ───────────────────────────────────────────────────
gzip on;
gzip_vary          on;
gzip_proxied       any;
gzip_comp_level    6;                 # sweet-spot: compression vs CPU
gzip_buffers       16 8k;
gzip_http_version  1.1;
gzip_min_length    256;               # don't compress tiny responses
gzip_types
    text/plain
    text/css
    text/javascript
    text/xml
    text/x-component
    application/json
    application/javascript
    application/x-javascript
    application/xml
    application/xhtml+xml
    application/rss+xml
    application/atom+xml
    application/vnd.ms-fontobject
    image/svg+xml
    image/x-icon
    font/truetype
    font/opentype;

# ── Brotli (requires ngx_brotli module) ─────────────────────────────────
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css application/json application/javascript
#              image/svg+xml font/opentype font/truetype;

# ── Buffer / Timeout Tuning ──────────────────────────────────────────────
client_max_body_size        50m;
client_body_buffer_size     128k;
client_header_buffer_size   4k;
large_client_header_buffers 4 16k;

client_body_timeout   30s;
client_header_timeout 30s;
send_timeout          30s;

# ── Proxy Buffering (used for API upstream) ───────────────────────────────
proxy_buffering          on;
proxy_buffer_size        16k;
proxy_buffers            8 16k;
proxy_busy_buffers_size  32k;
proxy_connect_timeout    10s;
proxy_send_timeout       30s;
proxy_read_timeout       30s;

# ── Open File Cache ───────────────────────────────────────────────────────
open_file_cache          max=10000 inactive=30s;
open_file_cache_valid    60s;
open_file_cache_min_uses 2;
open_file_cache_errors   on;

# ── Rate Limiting Zones ──────────────────────────────────────────────────
# General API zone: 30 req/s per IP
limit_req_zone  $binary_remote_addr zone=api_limit:20m   rate=30r/s;
# Auth endpoints: strict 5 req/s per IP
limit_req_zone  $binary_remote_addr zone=auth_limit:10m  rate=5r/s;
# Connection limit zone
limit_conn_zone $binary_remote_addr zone=conn_limit:20m;

# ── Upstream: .NET Web API ────────────────────────────────────────────────
upstream dotnet_api {
    least_conn;                       # route to least-busy instance

    server 127.0.0.1:5000 weight=1;
    # server 127.0.0.1:5001 weight=1; # add more instances for scale-out

    keepalive 64;                     # persistent connections to upstream
    keepalive_requests 1000;
    keepalive_timeout  75s;
}

# ── Security: hide server info ────────────────────────────────────────────
server_tokens off;

# ── Map: Cacheable static extensions ─────────────────────────────────────
map $uri $static_cache_control {
    default                                   "";
    ~*\.(js|css|woff2?|ttf|eot|otf)$         "public, max-age=31536000, immutable";
    ~*\.(png|jpg|jpeg|gif|ico|webp|avif|svg)$ "public, max-age=2592000";
    ~*\.(html)$                               "no-cache";
}

# =========================================================================
# HTTP → HTTPS redirect
# =========================================================================
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    # Allow ACME challenge for Let's Encrypt / cert-manager
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# =========================================================================
# HTTPS — Main Application
# =========================================================================
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;  # ← change this

    root /var/www/app/react/build;   # ← React production build path
    index index.html;

    # ── TLS ───────────────────────────────────────────────────────────────
    ssl_certificate     /etc/ssl/certs/yourdomain.crt;     # ← change this
    ssl_certificate_key /etc/ssl/private/yourdomain.key;   # ← change this

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
                        ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:
                        ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:
                        DHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    ssl_session_cache   shared:SSL:50m;   # ~200 000 sessions
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # OCSP Stapling — reduces TLS handshake latency
    ssl_stapling        on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 1.1.1.1 valid=300s;
    resolver_timeout 5s;

    # HSTS — enforce HTTPS for 1 year (enable after confirming TLS works)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # ── Security Headers ─────────────────────────────────────────────────
    add_header X-Content-Type-Options   "nosniff"         always;
    add_header X-Frame-Options          "SAMEORIGIN"      always;
    add_header X-XSS-Protection         "1; mode=block"   always;
    add_header Referrer-Policy          "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy       "camera=(), microphone=(), geolocation=()" always;
    add_header Content-Security-Policy
        "default-src 'self'; "
        "script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net; "
        "style-src  'self' 'unsafe-inline' fonts.googleapis.com; "
        "font-src   'self' fonts.gstatic.com data:; "
        "img-src    'self' data: blob: https:; "
        "connect-src 'self' https://api.yourdomain.com; "
        "frame-ancestors 'self';"
        always;

    # ── Rate Limit for whole server ───────────────────────────────────────
    limit_conn conn_limit 100;

    # ── API Reverse Proxy → .NET Web API ─────────────────────────────────
    location /api/ {
        limit_req  zone=api_limit burst=60 nodelay;
        limit_conn conn_limit 50;

        proxy_pass         http://dotnet_api;
        proxy_http_version 1.1;

        # Required for upstream keep-alive
        proxy_set_header Connection        "";

        # Forward real client info
        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-Host  $host;

        # Hide upstream headers that leak server details
        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;

        # Timeouts
        proxy_connect_timeout  10s;
        proxy_send_timeout     30s;
        proxy_read_timeout     30s;

        # Disable caching for API responses (use Cache-Control from .NET)
        add_header Cache-Control "no-store, no-cache, must-revalidate" always;
        proxy_no_cache          1;
        proxy_cache_bypass      1;
    }

    # ── Auth Endpoints (stricter rate limiting) ───────────────────────────
    location ~ ^/api/(auth|login|register|token)/ {
        limit_req  zone=auth_limit burst=10 nodelay;
        limit_conn conn_limit 20;

        proxy_pass         http://dotnet_api;
        proxy_http_version 1.1;
        proxy_set_header Connection        "";
        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;
    }

    # ── SignalR / WebSockets ──────────────────────────────────────────────
    location /hubs/ {
        proxy_pass         http://dotnet_api;
        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_read_timeout  3600s;   # keep long-lived WS connections alive
        proxy_send_timeout  3600s;
        proxy_connect_timeout 10s;
    }

    # ── Health Check (no logging, no auth needed) ─────────────────────────
    location = /health {
        proxy_pass http://dotnet_api/health;
        access_log off;
        proxy_set_header Host $host;
    }

    # ── React Static Assets (hashed filenames = immutable cache) ──────────
    location /static/ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header Vary "Accept-Encoding";
        access_log off;

        # Serve pre-compressed if available
        gzip_static on;
        # brotli_static on;   # enable with ngx_brotli
    }

    # ── Media / Font assets ───────────────────────────────────────────────
    location ~* \.(woff2?|ttf|eot|otf)$ {
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
        add_header Access-Control-Allow-Origin "*";
        access_log off;
    }

    location ~* \.(png|jpg|jpeg|gif|ico|webp|avif|svg)$ {
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
        access_log off;
    }

    # ── React SPA fallback (client-side routing) ──────────────────────────
    location / {
        try_files $uri $uri/ /index.html;

        # index.html must never be cached by the browser
        location = /index.html {
            add_header Cache-Control "no-cache, no-store, must-revalidate";
            add_header Pragma        "no-cache";
            add_header Expires       "0";
        }
    }

    # ── Block common exploit probes ───────────────────────────────────────
    location ~* \.(php|asp|aspx|jsp|cgi|env|git|svn)$ {
        deny all;
        return 404;
    }

    location ~ /\. {
        deny all;
        return 404;
    }

    # ── Custom Error Pages ────────────────────────────────────────────────
    error_page 404              /index.html;   # SPA handles its own 404s
    error_page 500 502 503 504  /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
        internal;
    }
}

# =========================================================================
# Optional: Separate API subdomain (api.yourdomain.com)
# Uncomment and adjust if you prefer subdomain routing over path routing
# =========================================================================
# server {
#     listen 443 ssl http2;
#     server_name api.yourdomain.com;
#
#     ssl_certificate     /etc/ssl/certs/yourdomain.crt;
#     ssl_certificate_key /etc/ssl/private/yourdomain.key;
#     ssl_protocols       TLSv1.2 TLSv1.3;
#     ssl_ciphers         HIGH:!aNULL:!MD5;
#
#     add_header Strict-Transport-Security "max-age=31536000" always;
#     add_header X-Content-Type-Options "nosniff" always;
#
#     location / {
#         limit_req  zone=api_limit burst=60 nodelay;
#         proxy_pass http://dotnet_api;
#         proxy_http_version 1.1;
#         proxy_set_header Connection        "";
#         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;
#     }
# }

} # end http