#  Basic configuration
user nginx;
worker_processes auto;
error_log /dev/stderr info;
pid /var/run/nginx.pid;
load_module "modules/ngx_mail_module.so";

events {
    worker_connections  1024;
}

http {
    # Standard HTTP configuration with slight hardening
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /dev/stdout;
    sendfile on;
    keepalive_timeout  65;
    server_tokens off;
    absolute_redirect off;
    resolver {{ RESOLVER }} valid=30s;

    {% if REAL_IP_HEADER %}
    real_ip_header {{ REAL_IP_HEADER }};
    {% endif %}

    {% if REAL_IP_FROM %}{% for from_ip in REAL_IP_FROM.split(',') %}
    set_real_ip_from {{ from_ip }};
    {% endfor %}{% endif %}

    # Header maps
    map $http_x_forwarded_proto $proxy_x_forwarded_proto {
      default $http_x_forwarded_proto;
      ''      $scheme;
    }

    {% if KUBERNETES_INGRESS != 'true' and TLS_FLAVOR in [ 'letsencrypt', 'cert' ] %}
    # Enable the proxy for certbot if the flavor is letsencrypt and not on kubernetes
    # 
    server {
      # Listen over HTTP
      listen 80;
      listen [::]:80;
      {% if TLS_FLAVOR == 'letsencrypt' %}      
      location ^~ /.well-known/acme-challenge/ {
          proxy_pass http://127.0.0.1:8008;
      }
      {% endif %}
      # redirect to https
      location / {
        return 301 https://$host$request_uri;
      }
    }
    {% endif %}

    # Main HTTP server
    server {
      # Favicon stuff
      root /static;
      # Variables for proxifying
      set $admin {{ ADMIN_ADDRESS }};
      set $antispam {{ ANTISPAM_WEBUI_ADDRESS }};
      {% if WEBMAIL_ADDRESS %}
      set $webmail {{ WEBMAIL_ADDRESS }};
      {% endif %}
      {% if WEBDAV_ADDRESS %}
      set $webdav {{ WEBDAV_ADDRESS }};
      {% endif %}

      # Listen on HTTP only in kubernetes or behind reverse proxy
      {% if KUBERNETES_INGRESS == 'true' or TLS_FLAVOR in [ 'mail-letsencrypt', 'notls',  'mail' ] %}
      listen 80;
      listen [::]:80;
      {% endif %}

      # Only enable HTTPS if TLS is enabled with no error and not on kubernetes
      {% if KUBERNETES_INGRESS != 'true' and TLS and not TLS_ERROR %}
      listen 443 ssl http2;
      listen [::]:443 ssl http2;

      include /etc/nginx/tls.conf;
      ssl_stapling on;
      ssl_stapling_verify on;
      ssl_session_cache shared:SSLHTTP:50m;
      add_header Strict-Transport-Security 'max-age=31536000';

      {% if not TLS_FLAVOR in [ 'mail', 'mail-letsencrypt' ] %}
      if ($proxy_x_forwarded_proto = http) {
        return 301 https://$host$request_uri;
      }
      {% endif %}
      {% endif %}

      # Remove headers to prevent duplication and information disclosure
      proxy_hide_header X-XSS-Protection;
      proxy_hide_header X-Powered-By;
      
      add_header X-Frame-Options 'SAMEORIGIN';
      add_header X-Content-Type-Options 'nosniff';
      add_header X-Permitted-Cross-Domain-Policies 'none';
      add_header X-XSS-Protection '1; mode=block';
      add_header Referrer-Policy 'same-origin';

      {% if TLS_FLAVOR == 'mail-letsencrypt' %}      
      location ^~ /.well-known/acme-challenge/ {
          proxy_pass http://127.0.0.1:8008;
      }
      {% endif %}

      # If TLS is failing, prevent access to anything except certbot
      {% if KUBERNETES_INGRESS != 'true' and TLS_ERROR and not (TLS_FLAVOR in [ 'mail-letsencrypt', 'mail' ]) %}
      location / {
        return 403;
      }
      {% else %}

      include /overrides/*.conf;

      # Actual logic
      {% if WEB_WEBMAIL != '/' %}
      location / {
      {% if WEBROOT_REDIRECT %}
        try_files $uri {{ WEBROOT_REDIRECT }};
      {% else %}
        try_files $uri =404;
      {% endif %}
      }
      {% endif %}

      {% if WEBMAIL != 'none' %}
      location {{ WEB_WEBMAIL }} {
        {% if WEB_WEBMAIL != '/' %}
        rewrite ^({{ WEB_WEBMAIL }})$ $1/ permanent;
        rewrite ^{{ WEB_WEBMAIL }}/(.*) /$1 break;
        {% endif %}
        include /etc/nginx/proxy.conf;
        client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
        proxy_pass http://$webmail;
      {% if ADMIN == 'true' %}
        auth_request /internal/auth/user;
        error_page 403 @webmail_login;
      }

      location {{ WEB_WEBMAIL }}/sso.php {
        {% if WEB_WEBMAIL != '/' %}
        rewrite ^({{ WEB_WEBMAIL }})$ $1/ permanent;
        rewrite ^{{ WEB_WEBMAIL }}/(.*) /$1 break;
        {% endif %}
        include /etc/nginx/proxy.conf;
        client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
        auth_request /internal/auth/user;
        auth_request_set $user $upstream_http_x_user;
        auth_request_set $token $upstream_http_x_user_token;
        proxy_set_header X-Remote-User $user;
        proxy_set_header X-Remote-User-Token $token;
        proxy_pass http://$webmail;
        error_page 403 @webmail_login;
      }

      location @webmail_login {
        return 302 {{ WEB_ADMIN }}/ui/login?next=ui.webmail;
      }
      {% else %}
      }
      {% endif %}{% endif %}
      {% if ADMIN == 'true' %}
      location {{ WEB_ADMIN }} {
        return 301 {{ WEB_ADMIN }}/ui;
      }

      location ~ {{ WEB_ADMIN }}/(ui|static) {
        rewrite ^{{ WEB_ADMIN }}/(.*) /$1 break;
        include /etc/nginx/proxy.conf;
        proxy_set_header X-Forwarded-Prefix {{ WEB_ADMIN }};
        proxy_pass http://$admin;
      }

      location {{ WEB_ADMIN }}/antispam {
        rewrite ^{{ WEB_ADMIN }}/antispam/(.*) /$1 break;
        auth_request /internal/auth/admin;
        proxy_set_header X-Real-IP "";
        proxy_set_header X-Forwarded-For "";
        proxy_pass http://$antispam;
      }
      {% endif %}

      {% if WEBDAV != 'none' %}
      location /webdav {
        rewrite ^/webdav/(.*) /$1 break;
        auth_request /internal/auth/basic;
        auth_request_set $user $upstream_http_x_user;
        include /etc/nginx/proxy.conf;
        proxy_set_header X-Remote-User $user;
        proxy_set_header X-Script-Name /webdav;
        proxy_pass http://$webdav;
      }

      location ~ ^/.well-known/(carddav|caldav) {
        return 301 /webdav/;
      }
      {% endif %}
      {% endif %}

      location /internal {
        internal;

        proxy_set_header Authorization $http_authorization;
        proxy_pass_header Authorization;
        proxy_pass http://$admin;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
      }

      location /health {
        return 204;
      }
    }

    # Forwarding authentication server
    server {
      # Variables for proxifying
      set $admin {{ ADMIN_ADDRESS }};

      listen 127.0.0.1:8000;

      location / {
        proxy_pass http://$admin/internal$request_uri;
      }
    }
}

mail {
    server_name {{ HOSTNAMES.split(",")[0] }};
    auth_http http://127.0.0.1:8000/auth/email;
    proxy_pass_error_message on;
    resolver {{ RESOLVER }} valid=30s;

    {% if TLS and not TLS_ERROR %}
    include /etc/nginx/tls.conf;
    ssl_session_cache shared:SSLMAIL:50m;
    {% endif %}

    # Advertise real capabilites of backends (postfix/dovecot)
    smtp_capabilities PIPELINING SIZE {{ MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN;
    pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER;
    imap_capabilities IMAP4 IMAP4rev1 UIDPLUS SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+;

    # Default SMTP server for the webmail (no encryption, but authentication)
    server {
      listen 10025;
      protocol smtp;
      smtp_auth plain;
    }

    # Default IMAP server for the webmail (no encryption, but authentication)
    server {
      listen 10143;
      protocol imap;
      smtp_auth plain;
    }

    # SMTP is always enabled, to avoid losing emails when TLS is failing
    server {
      listen 25;
      listen [::]:25;
      {% if TLS and not TLS_ERROR %}
      ssl_protocols TLSv1 TLSv1.1 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:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
      ssl_prefer_server_ciphers on;
      starttls on;
      {% endif %}
      protocol smtp;
      smtp_auth none;
    }

    # All other protocols are disabled if TLS is failing
    {% if not TLS_ERROR %}
    server {
      listen 143;
      listen [::]:143;
      {% if TLS %}
      starttls only;
      {% endif %}
      protocol imap;
      imap_auth plain;
    }

    server {
      listen 110;
      listen [::]:110;
      {% if TLS %}
      starttls only;
      {% endif %}
      protocol pop3;
      pop3_auth plain;
    }

    server {
      listen 587;
      listen [::]:587;
      {% if TLS %}
      starttls only;
      {% endif %}
      protocol smtp;
      smtp_auth plain login;
    }

    {% if TLS %}
    server {
      listen 465 ssl;
      listen [::]:465 ssl;
      protocol smtp;
      smtp_auth plain login;
    }

    server {
      listen 993 ssl;
      listen [::]:993 ssl;
      protocol imap;
      imap_auth plain;
    }

    server {
      listen 995 ssl;
      listen [::]:995 ssl;
      protocol pop3;
      pop3_auth plain;
    }
    {% endif %}
    {% endif %}
}