events {
    worker_connections 1024;
}

http {

    server {
        listen 80;
        server_name {{domain}};
        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
        location / {
            return 301 https://$host$request_uri;
        }
    }

    proxy_cache_path /var/cache/peertube_frontend levels=1:2 keys_zone=peertube_frontend_cache:10m max_size=100m                 use_temp_path=off;
    proxy_cache_path /var/cache/peertube_video    levels=1:2 keys_zone=peertube_video_cache:10m    max_size={{ cache_size_gb }}g use_temp_path=off;

    geo $bad_user {
        default 0;
        103.114.191.0/24 1;
    }

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name {{domain}};

        # Block all requests from Gab instances
        # https://soteria.mastodon.host/notice/9ke8a2nybZ0yPiHBJY
        if ($http_user_agent ~* "GabSocial") {
            return 404;
        }
        # Block all requests from Kiwifarms IP range
        # https://glitch.social/@kyzh/102435853605463552
        if ($bad_user) {
            return 404;
        }

        ssl_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/{{domain}}/privkey.pem;

        # Various TLS hardening settings
        # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:TLS_RSA_WITH_AES_256_CBC_SHA';
        ssl_session_timeout  10m;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
        ssl_stapling on;
        ssl_stapling_verify on;

        # Hide nginx version
        server_tokens off;

        # Enable compression for JS/CSS/HTML bundle, for improved client load times.
        # It might be nice to compress JSON, but leaving that out to protect against potential
        # compression+encryption information leak attacks like BREACH.
        gzip on;
        gzip_types text/css application/javascript text/vtt image/svg+xml;
        gzip_vary on;

        # Enable HSTS
        # Tells browsers to stick with HTTPS and never visit the insecure HTTP
        # version. Once a browser sees this header, it will only visit the site over
        # HTTPS for the next 2 years: (read more on hstspreload.org)
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

        add_header Referrer-Policy "same-origin";

        location / {
            proxy_pass              http://peertube:9000;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        Host $host;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            client_max_body_size    2G;
            proxy_connect_timeout   600;
            proxy_send_timeout      600;
            proxy_read_timeout      600;
            send_timeout            600;

            # https://www.nginx.com/blog/nginx-caching-guide/
            proxy_cache             peertube_frontend_cache;
            proxy_cache_use_stale   error timeout http_500 http_502 http_503 http_504;
            proxy_cache_revalidate  on;
            proxy_cache_lock        on;
            proxy_cache_min_uses    5;
            #add_header              X-Cached $upstream_cache_status;

            location ~ ^/client/(.*\.(js|css|woff2|otf|ttf|woff|eot))$ {
                proxy_pass  http://peertube:9000;
                add_header  Cache-Control "public, max-age=31536000, immutable";
            }
        }
        location ~ ^/static/(webseed|redundancy|streaming-playlists)/ {
            # NOTE: Its not possible to use proxy_cache for files that are served from disk without complicated workarounds
            #       Anyway caching is not a great idea because files are changed on disk after transcoding.
            #slice                   1m;
            #proxy_cache             peertube_video_cache;
            #proxy_cache_valid       206 1h;
            #proxy_cache_key         $uri$is_args$args$slice_range;
            #proxy_set_header        Range $slice_range;
            #proxy_http_version      1.1;
            #proxy_pass              http://peertube:9000;
            # required workaround for https://github.com/Chocobozzz/PeerTube/issues/1777
            #proxy_ignore_headers    Cache-Control;
            # for debugging
            #add_header              X-Cache-Status $upstream_cache_status;

            # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
            set $peertube_limit_rate 800k;

            # Increase rate limit in HLS mode, because we don't have multiple simultaneous connections
            if ($request_uri ~ -fragmented.mp4$) {
                set $peertube_limit_rate 5000k;
            }

            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }

            if ($request_method = 'GET') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

                # Don't spam access log file with byte range requests
                access_log off;
            }

            root /data-external;

            rewrite ^/static/webseed/(.*)$ /videos/$1 break;
            rewrite ^/static/redundancy/(.*)$ /redundancy/$1 break;
            rewrite ^/static/streaming-playlists/(.*)$ /streaming-playlists/$1 break;

            try_files $uri /;
        }
        # Websocket tracker
        location /tracker/socket {
            # Peers send a message to the tracker every 15 minutes
            # Don't close the websocket before this time
            proxy_read_timeout 1200s;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_pass http://peertube:9000;
        }
        location /socket.io {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;

            proxy_pass http://peertube:9000;

            # enable WebSockets
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
        location = /robots.txt {
            add_header  Content-Type  text/plain;
            return 200 "User-agent: *\nDisallow: /\n";
        }
    }

    # Anonymize IP addresses
    # https://www.supertechcrew.com/anonymizing-logs-nginx-apache/
    map $remote_addr $remote_addr_anon {
        ~(?P<ip>\d+\.\d+\.\d+)\.    $ip.0;
        ~(?P<ip>[^:]+:[^:]+):       $ip::;
        127.0.0.1                   $remote_addr;
        ::1                         $remote_addr;
        default                     0.0.0.0;
    }
    log_format main '$remote_addr_anon - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" "$http_user_agent"';
    access_log /dev/stdout main;
}