diff --git a/ansible/roles/mastodon/tasks/main.yaml b/ansible/roles/mastodon/tasks/main.yaml index 4aadcdd..d6d011f 100644 --- a/ansible/roles/mastodon/tasks/main.yaml +++ b/ansible/roles/mastodon/tasks/main.yaml @@ -127,11 +127,11 @@ # or https://docs.joinmastodon.org/admin/tootctl/#accounts-create - name: check for any tables at all - command: docker exec -it mastodon_db psql -U postgres mastodon_production -P pager=off -c '\dt' + command: docker exec -t mastodon_db psql -U postgres mastodon_production -P pager=off -c '\dt' register: hazschema - name: initialize mastodon database - command: docker compose run -it --rm mastodon_web bundle exec rails db:setup + command: docker compose run -t --rm mastodon_web bundle exec rails db:setup args: chdir: /srv/mastodon when: hazschema.stdout is match("Did not find any relations") @@ -143,6 +143,18 @@ when: envfile.changed or compose.changed +## add nginx config + +- name: copy nginx config + template: + src: templates/nginx.conf + dest: /srv/nginx/conf.d/mastodon.conf + register: nginxconf + +- name: reload nginx + command: docker exec -t nginx nginx -s reload + when: nginxconf.changed + ## --- diff --git a/ansible/roles/mastodon/templates/docker-compose.mastodon.yaml b/ansible/roles/mastodon/templates/docker-compose.mastodon.yaml index f58432e..4729b61 100644 --- a/ansible/roles/mastodon/templates/docker-compose.mastodon.yaml +++ b/ansible/roles/mastodon/templates/docker-compose.mastodon.yaml @@ -67,7 +67,7 @@ services: command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" networks: - mastodon - #- nginx + - nginx healthcheck: # prettier-ignore test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1'] @@ -91,7 +91,7 @@ services: command: node ./streaming networks: - mastodon - #- nginx + - nginx healthcheck: # prettier-ignore test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1'] @@ -116,7 +116,7 @@ services: - mastodon_redis networks: - mastodon - #- nginx + - nginx volumes: - ./src/public/system:/mastodon/public/system healthcheck: diff --git a/ansible/roles/mastodon/templates/nginx.conf b/ansible/roles/mastodon/templates/nginx.conf new file mode 100644 index 0000000..016faaa --- /dev/null +++ b/ansible/roles/mastodon/templates/nginx.conf @@ -0,0 +1,222 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream backend { + server mastodon_web:3000 fail_timeout=0; +# server mastodon_web_2:3000 fail_timeout=0; +} + +upstream streaming { + server mastodon_streaming:5000 fail_timeout=0; +} + +proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g; + +server { + server_name {{ domain_name }}; + listen 80; + listen [::]:80; + root /srv/mastodon/live/public; + location /.well-known/acme-challenge/ { + allow all; + root /var/www/certbot; + } + location / { return 301 https://$host$request_uri; } +} + +server { + server_name {{ domain_name }}; + listen 443 ssl http2; + listen [::]:443 ssl http2; + listen 8448 ssl http2 default_server; + listen [::]:8448 ssl http2 default_server; + +# ssl_protocols TLSv1.2 TLSv1.3; +# ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; +# ssl_prefer_server_ciphers on; +# ssl_session_cache shared:SSL:10m; +# ssl_session_tickets off; + + # Uncomment these lines once you acquire a certificate: + # ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; + # ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/www.poorsquinky.com-0002/chain.pem; + ssl_certificate /etc/letsencrypt/live/www.poorsquinky.com-0002/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.poorsquinky.com-0002/privkey.pem; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + 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:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers off; + # In case of an old server with an OpenSSL version of 1.0.2 or below, + # leave only prime256v1 or comment out the following line. + ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; + ssl_stapling on; + ssl_stapling_verify on; + + keepalive_timeout 70; + sendfile on; + client_max_body_size 80m; + + root /srv/mastodon/live/public; + + gzip on; + gzip_disable "msie6"; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon; + + + location / { + try_files $uri @proxy; + } + + # If Docker is used for deployment and Rails serves static files, + # then needed must replace line `try_files $uri =404;` with `try_files $uri @proxy;`. + location = sw.js { + add_header Cache-Control "public, max-age=604800, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/assets/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/avatars/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/emoji/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/headers/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/packs/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/shortcuts/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/sounds/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + try_files $uri @proxy; + } + + location ~ ^/system/ { + add_header Cache-Control "public, max-age=2419200, immutable"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + add_header X-Content-Type-Options nosniff; + add_header Content-Security-Policy "default-src 'none'; form-action 'none'"; + try_files $uri @proxy; + } + + location ^~ /api/v1/streaming/ { + 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 Proxy ""; + + proxy_pass http://streaming; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + + tcp_nodelay on; + } + + location ~ ^(/_matrix|/_synapse/client) { + # note: do not add a path (even a single /) after the port in `proxy_pass`, + # otherwise nginx will canonicalise the URI and cause signature verification + # errors. + proxy_pass http://synapse:8008; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; + + # Nginx by default only allows file uploads up to 1M in size + # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml + client_max_body_size 50M; + + # Synapse responses may be chunked, which is an HTTP/1.1 feature. + proxy_http_version 1.1; + } + + location /.well-known/matrix/server { + access_log off; + add_header Access-Control-Allow-Origin *; + default_type application/json; + return 200 '{"m.server": "{{ domain_name }}:443"}'; + } + + location /.well-known/matrix/client { + access_log off; + add_header Access-Control-Allow-Origin *; + default_type application/json; + return 200 '{"m.homeserver": {"base_url": "https://{{ domain_name }}"}}'; + } + + location @proxy { + 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 Proxy ""; + proxy_pass_header Server; + + proxy_pass http://mastodon_web:3000; + proxy_buffering on; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + proxy_cache CACHE; + proxy_cache_valid 200 7d; + proxy_cache_valid 410 24h; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; + add_header X-Cached $upstream_cache_status; + + tcp_nodelay on; + } + +# location /phanpy/ { +# # X-Auth-Request-Redirect +# #add_header X-Auth-Request-Redirect "https://{{ domain_name }}/phanpy"; +# autoindex off; +# alias /phanpy/; +# include /etc/nginx/mime.types; +# } + + error_page 404 500 501 502 503 504 /500.html; +} + +