diff --git a/roles/authelia-and-nginx/templates/conf.j2 b/roles/authelia-and-nginx/templates/conf.j2 index bd0cbeb..231a61d 100644 --- a/roles/authelia-and-nginx/templates/conf.j2 +++ b/roles/authelia-and-nginx/templates/conf.j2 @@ -15,6 +15,7 @@ server { ssl_certificate /etc/ssl/fullchains/{{var_authelia_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_authelia_and_nginx_domain}}.pem; + include /etc/nginx/ssl-hardening.conf; location / { ## Headers diff --git a/roles/authelia/templates/conf-main.json.j2 b/roles/authelia/templates/conf-main.json.j2 index 0f163af..475cda4 100644 --- a/roles/authelia/templates/conf-main.json.j2 +++ b/roles/authelia/templates/conf-main.json.j2 @@ -56,7 +56,7 @@ {% else %} "disable": true, {% endif %} - "custom_url": "{{password_reset_custom_url}}" + "custom_url": "{{var_authelia_password_reset_custom_url}}" }, "refresh_interval": "5m", "file": { @@ -128,7 +128,7 @@ "cookies": [ { "domain": "{{var_authelia_session_domain}}", - "authelia_url": "{{var_authelia_domain}}", + "authelia_url": "https://{{var_authelia_domain}}/", "default_redirection_url": "{{var_authelia_redirect_url}}" } ] diff --git a/roles/dokuwiki-and-nginx/templates/conf.j2 b/roles/dokuwiki-and-nginx/templates/conf.j2 index cd9c68d..514ceab 100644 --- a/roles/dokuwiki-and-nginx/templates/conf.j2 +++ b/roles/dokuwiki-and-nginx/templates/conf.j2 @@ -14,8 +14,7 @@ server { {% if var_dokuwiki_and_nginx_tls_enable %} ssl_certificate /etc/ssl/fullchains/{{var_dokuwiki_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_dokuwiki_and_nginx_domain}}.pem; - ssl_session_timeout 5m; - ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; + include /etc/nginx/ssl-hardening.conf; {% endif %} # Maximum file upload size is 4MB - change accordingly if needed diff --git a/roles/element-and-nginx/templates/conf.j2 b/roles/element-and-nginx/templates/conf.j2 index 312df8b..08330a6 100644 --- a/roles/element-and-nginx/templates/conf.j2 +++ b/roles/element-and-nginx/templates/conf.j2 @@ -8,6 +8,7 @@ server { ssl_certificate /etc/ssl/fullchains/{{var_element_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_element_and_nginx_domain}}.pem; + include /etc/nginx/ssl-hardening.conf; root {{var_element_and_nginx_path}}; } diff --git a/roles/gitlab-and-nginx/templates/conf.j2 b/roles/gitlab-and-nginx/templates/conf.j2 index eabfcb9..4208162 100644 --- a/roles/gitlab-and-nginx/templates/conf.j2 +++ b/roles/gitlab-and-nginx/templates/conf.j2 @@ -51,21 +51,7 @@ server { ssl_certificate /etc/ssl/fullchains/{{var_gitlab_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_gitlab_and_nginx_domain}}.pem; - - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:10m; - ssl_session_tickets off; - - ssl_protocols TLSv1.3; - ssl_prefer_server_ciphers off; - - # ssl_stapling on; - # ssl_stapling_verify on; - # ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt; - # resolver 208.67.222.222 208.67.222.220 valid=300s; # Can change to your DNS resolver if desired - # resolver_timeout 5s; - - # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + include /etc/nginx/ssl-hardening.conf; real_ip_header X-Real-IP; real_ip_recursive off; diff --git a/roles/hedgedoc-and-nginx/templates/conf.j2 b/roles/hedgedoc-and-nginx/templates/conf.j2 index 0760df4..08e630c 100644 --- a/roles/hedgedoc-and-nginx/templates/conf.j2 +++ b/roles/hedgedoc-and-nginx/templates/conf.j2 @@ -11,20 +11,21 @@ server { ssl_certificate /etc/ssl/certs/{{var_hedgedoc_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_hedgedoc_and_nginx_domain}}.pem; + include /etc/nginx/ssl-hardening.conf; location / { proxy_pass http://localhost:3000; - 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 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; } location /socket.io/ { proxy_pass http://localhost:3000; - 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 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 Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; diff --git a/roles/lighttpd/tasks/main.json b/roles/lighttpd/tasks/main.json index 1b6af91..d29fcdf 100644 --- a/roles/lighttpd/tasks/main.json +++ b/roles/lighttpd/tasks/main.json @@ -27,6 +27,35 @@ "dest": "/etc/lighttpd/conf-enabled/10-ssl-custom.conf" } }, + { + "name": "ufw | check", + "check_mode": true, + "become": true, + "community.general.ufw": { + "state": "enabled" + }, + "register": "ufw_enable_check" + }, + { + "name": "ufw | allow port 80", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "80", + "proto": "tcp" + } + }, + { + "name": "ufw | allow port 443", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "443", + "proto": "tcp" + } + }, { "name": "restart service", "become": true, diff --git a/roles/murmur/tasks/main.json b/roles/murmur/tasks/main.json index 7341ac8..1b9ed12 100644 --- a/roles/murmur/tasks/main.json +++ b/roles/murmur/tasks/main.json @@ -25,6 +25,25 @@ "cmd": "murmurd -ini /etc/mumble-server.ini -supw {{var_murmur_admin_password}}" } }, + { + "name": "ufw | check", + "check_mode": true, + "become": true, + "community.general.ufw": { + "state": "enabled" + }, + "register": "ufw_enable_check" + }, + { + "name": "ufw | allow port", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "{{var_murmur_port | string}}", + "proto": "tcp" + } + }, { "name": "service", "become": true, diff --git a/roles/nginx/defaults/main.json b/roles/nginx/defaults/main.json index bfd870e..997702e 100644 --- a/roles/nginx/defaults/main.json +++ b/roles/nginx/defaults/main.json @@ -1,3 +1,3 @@ { + "var_nginx_auto_reload_interval": null } - diff --git a/roles/nginx/files/ssl-hardening.conf b/roles/nginx/files/ssl-hardening.conf new file mode 100644 index 0000000..1d5f5f4 --- /dev/null +++ b/roles/nginx/files/ssl-hardening.conf @@ -0,0 +1,18 @@ +ssl_session_timeout 1d; +ssl_session_cache shared:MozSSL:10m; # about 40000 sessions +ssl_session_tickets off; + +# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam +ssl_dhparam /etc/nginx/dhparam; + +# intermediate configuration +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:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; +ssl_prefer_server_ciphers off; + +# HSTS (ngx_http_headers_module is required) (63072000 seconds) +add_header Strict-Transport-Security "max-age=63072000" always; + +# OCSP stapling +ssl_stapling on; +ssl_stapling_verify on; diff --git a/roles/nginx/tasks/main.json b/roles/nginx/tasks/main.json index c8e2b40..5d7135b 100644 --- a/roles/nginx/tasks/main.json +++ b/roles/nginx/tasks/main.json @@ -5,10 +5,85 @@ "ansible.builtin.apt": { "update_cache": true, "pkg": [ - "nginx" + "nginx", + "openssl" ] } }, + { + "name": "generate dhparams file", + "ansible.builtin.command": "openssl dhparam -out /etc/nginx/dhparam 4096", + "args": { + "creates": "/etc/nginx/dhparam" + } + }, + { + "name": "place hardening config", + "become": true, + "ansible.builtin.copy": { + "src": "ssl-hardening.conf", + "dest": "/etc/nginx/ssl-hardening.conf" + } + }, + { + "name": "ufw | check", + "become": true, + "check_mode": true, + "community.general.ufw": { + "state": "enabled" + }, + "register": "ufw_enable_check" + }, + { + "name": "ufw | allow port 80", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "80", + "proto": "tcp" + } + }, + { + "name": "ufw | allow port 443", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "443", + "proto": "tcp" + } + }, + { + "name": "auto reload", + "when": "var_nginx_auto_reload_interval == None", + "become": true, + "ansible.builtin.cron": { + "name": "nginx_auto_reload", + "disabled": true, + "minute": "0", + "hour": "*/{{var_nginx_auto_reload_interval | string}}", + "day": "*", + "month": "*", + "weekday": "*", + "job": "systemctl reload nginx" + } + }, + { + "name": "auto reload", + "when": "var_nginx_auto_reload_interval != None", + "become": true, + "ansible.builtin.cron": { + "name": "nginx_auto_reload", + "disabled": false, + "minute": "0", + "hour": "*/{{var_nginx_auto_reload_interval | string}}", + "day": "*", + "month": "*", + "weekday": "*", + "job": "systemctl reload nginx" + } + }, { "name": "restart service", "become": true, diff --git a/roles/nginx/vardef.json b/roles/nginx/vardef.json new file mode 100644 index 0000000..c03ddc6 --- /dev/null +++ b/roles/nginx/vardef.json @@ -0,0 +1,8 @@ +{ + "auto_reload_interval": { + "description": "in hours", + "nullable": true, + "type": "integer", + "mandatory": false + } +} diff --git a/roles/proftpd/tasks/main.json b/roles/proftpd/tasks/main.json index d277bc0..e5bf9a0 100644 --- a/roles/proftpd/tasks/main.json +++ b/roles/proftpd/tasks/main.json @@ -8,5 +8,34 @@ "proftpd-core" ] } + }, + { + "name": "ufw | check", + "check_mode": true, + "become": true, + "community.general.ufw": { + "state": "enabled" + }, + "register": "ufw_enable_check" + }, + { + "name": "ufw | allow port 20", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "20", + "proto": "tcp" + } + }, + { + "name": "ufw | allow port 21", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "21", + "proto": "tcp" + } } ] diff --git a/roles/synapse-and-nginx/templates/conf.j2 b/roles/synapse-and-nginx/templates/conf.j2 index b9b94c6..e59fb99 100644 --- a/roles/synapse-and-nginx/templates/conf.j2 +++ b/roles/synapse-and-nginx/templates/conf.j2 @@ -12,7 +12,8 @@ server { ssl_certificate /etc/ssl/fullchains/{{var_synapse_and_nginx_domain}}.pem; ssl_certificate_key /etc/ssl/private/{{var_synapse_and_nginx_domain}}.pem; - + include /etc/nginx/ssl-hardening.conf; + location ~ ^(/_matrix|/_synapse/client) { proxy_pass http://localhost:8008; proxy_set_header X-Forwarded-For $remote_addr; diff --git a/roles/synapse/tasks/main.json b/roles/synapse/tasks/main.json index fd44ce1..63e0e78 100644 --- a/roles/synapse/tasks/main.json +++ b/roles/synapse/tasks/main.json @@ -58,6 +58,25 @@ "dest": "/etc/matrix-synapse/homeserver.yaml" } }, + { + "name": "ufw | check", + "become": true, + "check_mode": true, + "community.general.ufw": { + "state": "enabled" + }, + "register": "ufw_enable_check" + }, + { + "name": "ufw | allow port", + "when": "not ufw_enable_check.changed", + "become": true, + "community.general.ufw": { + "rule": "allow", + "port": "8448", + "proto": "tcp" + } + }, { "name": "restart service", "become": true, diff --git a/roles/system_basics/handlers/main.json b/roles/system_basics/handlers/main.json new file mode 100644 index 0000000..ba5eace --- /dev/null +++ b/roles/system_basics/handlers/main.json @@ -0,0 +1,17 @@ +[ + { + "name": "restart sshd", + "ansible.builtin.service": { + "name": "sshd", + "state": "restarted" + } + }, + { + "name": "restart journal", + "ansible.builtin.service": { + "name": "systemd-journald", + "state": "restarted", + "enabled": true + } + } +] diff --git a/roles/ufw/tasks/main.json b/roles/ufw/tasks/main.json new file mode 100644 index 0000000..003e4b6 --- /dev/null +++ b/roles/ufw/tasks/main.json @@ -0,0 +1,45 @@ +[ + { + "name": "install ufw", + "become": true, + "ansible.builtin.apt": { + "update_cache": true, + "pkg": [ + "ufw" + ] + } + }, + { + "name": "ufw deny incoming", + "become": true, + "community.general.ufw": { + "direction": "incoming", + "proto": "any", + "policy": "deny" + } + }, + { + "name": "ufw allow outgoing", + "become": true, + "community.general.ufw": { + "direction": "outgoing", + "proto": "any", + "policy": "allow" + } + }, + { + "name": "ufw allow and rate-limit ssh", + "become": true, + "community.general.ufw": { + "rule": "limit", + "name": "ssh" + } + }, + { + "name": "enable ufw service", + "become": true, + "community.general.ufw": { + "state": "enabled" + } + } +] diff --git a/roles/unattended_upgrades/files/20auto-upgrades b/roles/unattended_upgrades/files/20auto-upgrades new file mode 100644 index 0000000..8d6d7c8 --- /dev/null +++ b/roles/unattended_upgrades/files/20auto-upgrades @@ -0,0 +1,2 @@ +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; diff --git a/roles/unattended_upgrades/tasks/main.json b/roles/unattended_upgrades/tasks/main.json new file mode 100644 index 0000000..014209d --- /dev/null +++ b/roles/unattended_upgrades/tasks/main.json @@ -0,0 +1,48 @@ +[ + { + "name": "install packages", + "become": true, + "ansible.builtin.apt": { + "update_cache": true, + "pkg": [ + "unattended-upgrades", + "apt-listchanges" + ] + } + }, + { + "name": "Allow unattended reboots (1)", + "become": true, + "ansible.builtin.lineinfile": { + "dest": "/etc/apt/apt.conf.d/50unattended-upgrades", + "regexp": "^(//)?Unattended-Upgrade::Automatic-Reboot ", + "line": "Unattended-Upgrade::Automatic-Reboot \"true\";" + } + }, + { + "name": "Allow unattended reboots (2)", + "become": true, + "ansible.builtin.lineinfile": { + "dest": "/etc/apt/apt.conf.d/50unattended-upgrades", + "regexp": "^(//)?Unattended-Upgrade::Automatic-Reboot-Time ", + "line": "Unattended-Upgrade::Automatic-Reboot-Time \"23:55\";" + } + }, + { + "name": "Allow more origins for updates", + "become": true, + "ansible.builtin.lineinfile": { + "dest": "/etc/apt/apt.conf.d/50unattended-upgrades", + "regexp": "^(//\\s*)?\"\\$\\{distro_id\\}:\\$\\{distro_codename\\}-updates\";", + "line": "\"${distro_id}:${distro_codename}-updates\";" + } + }, + { + "name": "Enable unattended upgrades", + "become": true, + "ansible.builtin.copy": { + "src": "20auto-upgrades", + "dest": "/etc/apt/apt.conf.d/20auto-upgrades" + } + } +]