diff --git a/deploy/docker.dev.nginx.template b/deploy/docker.dev.nginx.template new file mode 120000 index 000000000..3a92d966e --- /dev/null +++ b/deploy/docker.dev.nginx.template @@ -0,0 +1 @@ +../docker/nginx/conf.dev \ No newline at end of file diff --git a/deploy/docker.nginx.template b/deploy/docker.nginx.template new file mode 120000 index 000000000..6e4c4e716 --- /dev/null +++ b/deploy/docker.nginx.template @@ -0,0 +1 @@ +../front/docker/funkwhale.conf.template \ No newline at end of file diff --git a/deploy/nginx.template b/deploy/nginx.template index bb7782cef..8527e320b 100644 --- a/deploy/nginx.template +++ b/deploy/nginx.template @@ -1,4 +1,4 @@ -# This file was generated from funkwhale.template +# This file was generated from Funkwhale's nginx.template upstream funkwhale-api { # depending on your setup, you may want to update this @@ -10,12 +10,18 @@ server { listen [::]:80; # update this to match your instance name server_name ${FUNKWHALE_HOSTNAME}; + # useful for Let's Encrypt - location /.well-known/acme-challenge/ { allow all; } - location / { return 301 https://$host$request_uri; } + location /.well-known/acme-challenge/ { + allow all; + } + + location / { + return 301 https://$host$request_uri; + } } -# required for websocket support +# Required for websocket support. map $http_upgrade $connection_upgrade { default upgrade; '' close; @@ -24,6 +30,7 @@ map $http_upgrade $connection_upgrade { server { listen 443 ssl http2; listen [::]:443 ssl http2; + charset utf-8; server_name ${FUNKWHALE_HOSTNAME}; # TLS @@ -38,15 +45,14 @@ server { ssl_session_cache shared:SSL:10m; ssl_certificate /etc/letsencrypt/live/${FUNKWHALE_HOSTNAME}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/${FUNKWHALE_HOSTNAME}/privkey.pem; + # HSTS add_header Strict-Transport-Security "max-age=31536000"; - # If you are using S3 to host your files, remember to add your S3 URL to the - # media-src and img-src headers (e.g. img-src 'self' https:// data:) - - add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:; worker-src 'self'"; + add_header Content-Security-Policy "default-src 'self'; connect-src https: wss: http: ws: 'self' 'unsafe-eval'; script-src 'self' 'wasm-unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; media-src https: http: 'self' data:; object-src 'none'"; add_header Referrer-Policy "strict-origin-when-cross-origin"; add_header X-Frame-Options "SAMEORIGIN" always; + add_header Service-Worker-Allowed "/"; root ${FUNKWHALE_FRONTEND_PATH}; @@ -79,29 +85,22 @@ server { location / { include /etc/nginx/funkwhale_proxy.conf; - # this is needed if you have file import via upload enabled + # This is needed if you have file import via upload enabled. client_max_body_size ${NGINX_MAX_BODY_SIZE}; proxy_pass http://funkwhale-api/; } location /front/ { - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:; worker-src 'self'"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header Service-Worker-Allowed "/"; alias ${FUNKWHALE_FRONTEND_PATH}/; - expires 30d; - add_header Pragma public; - add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + expires 1d; } + location = /front/embed.html { - add_header Content-Security-Policy "connect-src https: http: 'self' 'wasm-unsafe-eval'; default-src 'self'; script-src 'self' unpkg.com 'unsafe-inline' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; + add_header Content-Security-Policy "connect-src https: http: 'self'; default-src 'self'; script-src 'self' unpkg.com 'unsafe-inline' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header X-Frame-Options "" always; alias ${FUNKWHALE_FRONTEND_PATH}/embed.html; - expires 30d; - add_header Pragma public; - add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + expires 1d; } location /federation/ { @@ -109,7 +108,7 @@ server { proxy_pass http://funkwhale-api/federation/; } - # You can comment this if you do not plan to use the Subsonic API + # You can comment this if you do not plan to use the Subsonic API. location /rest/ { include /etc/nginx/funkwhale_proxy.conf; proxy_pass http://funkwhale-api/api/subsonic/rest/; @@ -125,36 +124,27 @@ server { add_header Access-Control-Allow-Origin '*'; } - location /_protected/media/ { - # this is an internal location that is used to serve - # audio files once correct permission / authentication - # has been checked on API side + # This is an internal location that is used to serve + # media (uploaded) files once correct permission / authentication + # has been checked on API side. + # Comment the "NON-S3" commented lines and uncomment "S3" commented lines + # if you're storing media files in a S3 bucket. + location ~ /_protected/media/(.+) { internal; - alias ${MEDIA_ROOT}; + alias ${MEDIA_ROOT}/$1; # NON-S3 + # Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932. +# proxy_set_header Authorization ""; # S3 +# proxy_pass $1; # S3 add_header Access-Control-Allow-Origin '*'; } - # Comment the previous location and uncomment this one if you're storing - # media files in a S3 bucket - # location ~ /_protected/media/(.+) { - # internal; - # # Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932 - # proxy_set_header Authorization ""; - # proxy_pass $1; - # } - location /_protected/music/ { - # this is an internal location that is used to serve - # audio files once correct permission / authentication - # has been checked on API side - # Set this to the same value as your MUSIC_DIRECTORY_PATH setting + # This is an internal location that is used to serve + # local music files once correct permission / authentication + # has been checked on API side. + # Set this to the same value as your MUSIC_DIRECTORY_PATH setting. internal; alias ${MUSIC_DIRECTORY_SERVE_PATH}; add_header Access-Control-Allow-Origin '*'; } - - location /staticfiles/ { - # django static files - alias ${STATIC_ROOT}/; - } } diff --git a/docker/nginx/conf.dev b/docker/nginx/conf.dev index 928f7e682..ef6e672a4 100644 --- a/docker/nginx/conf.dev +++ b/docker/nginx/conf.dev @@ -21,28 +21,34 @@ http { access_log /var/log/nginx/access.log main; sendfile on; - #tcp_nopush on; keepalive_timeout 65; - #gzip on; - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - upstream funkwhale-api { server ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT}; } upstream funkwhale-front { server ${FUNKWHALE_FRONT_IP}:${FUNKWHALE_FRONT_PORT}; } + + # Required for websocket support. + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + server { - listen 80; + listen 80; + listen [::]:80; charset utf-8; - client_max_body_size 100M; + client_max_body_size ${NGINX_MAX_BODY_SIZE}; include /etc/nginx/funkwhale_proxy.conf; + + add_header Content-Security-Policy "default-src 'self'; connect-src https: wss: http: ws: 'self' 'unsafe-eval'; script-src 'self' 'wasm-unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; media-src https: http: 'self' data:; object-src 'none'"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header Service-Worker-Allowed "/"; + # compression settings gzip on; gzip_comp_level 5; @@ -68,73 +74,71 @@ http { text/vtt text/x-component text/x-cross-domain-policy; - - add_header Content-Security-Policy "connect-src https: wss: http: ws: 'self' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header X-Frame-Options "SAMEORIGIN" always; - - location /front/ { - add_header Content-Security-Policy "connect-src https: wss: http: ws: 'self' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header Service-Worker-Allowed "/"; - # uncomment the following line and comment the proxy-pass one - # to use the frontend build with "yarn build" - #alias /frontend/dist/; - proxy_pass http://funkwhale-front/front/; - } - location /front/embed.html { - add_header Content-Security-Policy "connect-src https: http: 'self'; default-src 'self'; script-src 'self' unpkg.com 'unsafe-inline' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header X-Frame-Options "" always; - proxy_pass http://funkwhale-front/front/embed.html; - } + # end of compression settings location / { include /etc/nginx/funkwhale_proxy.conf; - # this is needed if you have file import via upload enabled + # This is needed if you have file import via upload enabled. client_max_body_size ${NGINX_MAX_BODY_SIZE}; proxy_pass http://funkwhale-api/; } - # You can comment this if you do not plan to use the Subsonic API + location /front/ { + proxy_pass http://funkwhale-front/front/; + expires 1d; + } + + location = /front/embed.html { + add_header Content-Security-Policy "connect-src https: http: 'self'; default-src 'self'; script-src 'self' unpkg.com 'unsafe-inline' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + + proxy_pass http://funkwhale-front/front/embed.html; + expires 1d; + } + + location /federation/ { + include /etc/nginx/funkwhale_proxy.conf; + proxy_pass http://funkwhale-api/federation/; + } + + # You can comment this if you do not plan to use the Subsonic API. location /rest/ { include /etc/nginx/funkwhale_proxy.conf; proxy_pass http://funkwhale-api/api/subsonic/rest/; } + location /.well-known/ { + include /etc/nginx/funkwhale_proxy.conf; + proxy_pass http://funkwhale-api/.well-known/; + } + location /media/ { alias /protected/media/; + add_header Access-Control-Allow-Origin '*'; } - # this is an internal location that is used to serve - # audio files once correct permission / authentication - # has been checked on API side - location /_protected/media { + # This is an internal location that is used to serve + # media (uploaded) files once correct permission / authentication + # has been checked on API side. + # Comment the "NON-S3" commented lines and uncomment "S3" commented lines + # if you're storing media files in a S3 bucket. + location ~ /_protected/media/(.+) { internal; - alias /protected/media; - + alias /protected/media/$1; # NON-S3 + # Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932. +# proxy_set_header Authorization ""; # S3 +# proxy_pass $1; # S3 + add_header Access-Control-Allow-Origin '*'; } - # Comment the previous location and uncomment this one if you're storing - # media files in a S3 bucket - # location ~ /_protected/media/(.+) { - # internal; - # resolver 127.0.0.11; - # # Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932 - # proxy_set_header Authorization ""; - # proxy_set_header X-Remote-URL "$1"; - # proxy_pass $1; - # } - location /_protected/music { - # this is an internal location that is used to serve - # audio files once correct permission / authentication - # has been checked on API side - # Set this to the same value as your MUSIC_DIRECTORY_PATH setting + location /_protected/music/ { + # This is an internal location that is used to serve + # local music files once correct permission / authentication + # has been checked on API side. + # Set this to the same value as your MUSIC_DIRECTORY_PATH setting. internal; - alias /music; - } - location /staticfiles/ { - alias /staticfiles/; + alias /music/; + add_header Access-Control-Allow-Origin '*'; } } } diff --git a/front/Dockerfile b/front/Dockerfile index 358e298db..d80dbfcdf 100644 --- a/front/Dockerfile +++ b/front/Dockerfile @@ -26,4 +26,3 @@ RUN mkdir -p /var/log/nginx /var/cache/nginx /var/run/nginx && \ ENV FUNKWHALE_API_HOST=api ENV FUNKWHALE_API_PORT=5000 -ENV AWS_S3_ENDPOINT_URL= diff --git a/front/docker/funkwhale.conf.template b/front/docker/funkwhale.conf.template index f6fa357f3..d3268be22 100644 --- a/front/docker/funkwhale.conf.template +++ b/front/docker/funkwhale.conf.template @@ -2,7 +2,6 @@ upstream funkwhale-api { server ${FUNKWHALE_API_HOST}:${FUNKWHALE_API_PORT}; } - # Required for websocket support. map $http_upgrade $connection_upgrade { default upgrade; @@ -10,17 +9,44 @@ map $http_upgrade $connection_upgrade { } server { - listen 80; - server_name ${FUNKWHALE_HOSTNAME}; + listen 80; + listen [::]:80; + charset utf-8; + server_name _; + + add_header Content-Security-Policy "default-src 'self'; connect-src https: wss: http: ws: 'self' 'unsafe-eval'; script-src 'self' 'wasm-unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; media-src https: http: 'self' data:; object-src 'none'"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header Service-Worker-Allowed "/"; root /usr/share/nginx/html; - # If you are using S3 to host your files, remember to add your S3 URL to the - # media-src and img-src headers (e.g. img-src 'self' https:// data:). + # compression settings + gzip on; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' ${AWS_S3_ENDPOINT_URL} data:; font-src 'self' data:; object-src 'none'; media-src ${AWS_S3_ENDPOINT_URL} 'self' data:"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header X-Frame-Options "SAMEORIGIN" always; + gzip_types + application/javascript + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-web-app-manifest+json + font/opentype + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + # end of compression settings location / { include /etc/nginx/funkwhale_proxy.conf; @@ -30,24 +56,16 @@ server { } location /front/ { - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' ${AWS_S3_ENDPOINT_URL} data:; font-src 'self' data:; object-src 'none'; media-src ${AWS_S3_ENDPOINT_URL} 'self' data:"; - add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header Service-Worker-Allowed "/"; alias /usr/share/nginx/html/; - expires 30d; - add_header Pragma public; - add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + expires 1d; } location = /front/embed.html { - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' ${AWS_S3_ENDPOINT_URL} data:; font-src 'self' data:; object-src 'none'; media-src ${AWS_S3_ENDPOINT_URL} 'self' data:"; + add_header Content-Security-Policy "connect-src https: http: 'self'; default-src 'self'; script-src 'self' unpkg.com 'unsafe-inline' 'unsafe-eval'; style-src https: http: 'self' 'unsafe-inline'; img-src https: http: 'self' data:; font-src https: http: 'self' data:; object-src 'none'; media-src https: http: 'self' data:"; add_header Referrer-Policy "strict-origin-when-cross-origin"; - add_header X-Frame-Options "" always; alias /usr/share/nginx/html/embed.html; - expires 30d; - add_header Pragma public; - add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + expires 1d; } location /federation/ { @@ -94,9 +112,4 @@ server { alias ${MUSIC_DIRECTORY_PATH}/; add_header Access-Control-Allow-Origin '*'; } - - location /staticfiles/ { - # Django static files - alias ${STATIC_ROOT}/; - } }