diff --git a/cloudinit.yml b/cloudinit.yml index 1c0102f..166cd6f 100644 --- a/cloudinit.yml +++ b/cloudinit.yml @@ -10,12 +10,22 @@ groups: - nginxgroup users: - - name: cl - groups: users, admin - sudo: ALL=(ALL) NOPASSWD:ALL - shell: /bin/bash - ssh_authorized_keys: - - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6xSH5nE0uy0C0kglpp4EqrbbW2CrBeAIj+X6Sf2pd0 XPS-8930-Ubuntu_22 +- name: nginxuser + system: true + shell: /usr/sbin/nologin + groups: nginxgroup + sudo: null +# Create a new user named 'cl' +- name: cl + # Add the user to the 'users' and 'admin' groups + groups: users, admin + # Allow the user to execute any command with sudo without entering a password + sudo: ALL=(ALL) NOPASSWD:ALL + # Set the user's default shell to /bin/bash + shell: /bin/bash + # Add the user's public SSH key for key-based authentication + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJCknACoboXvy6C0DNVR+OI0Kb+YZkanh0B2pXLqbauV marcus@fw-linux-01 packages: - detachtty @@ -40,59 +50,237 @@ package_update: true package_upgrade: true write_files: - - path: /etc/apt/apt.conf.d/20auto-upgrades - content: | - APT::Periodic::Update-Package-Lists "1"; - APT::Periodic::Download-Upgradeable-Packages "1"; - APT::Periodic::AutocleanInterval "7"; - APT::Periodic::Unattended-Upgrade "1"; - - path: /etc/ssh/sshd_config - content: | - Include /etc/ssh/sshd_config.d/*.conf - MaxAuthTries 3 - AuthorizedKeysFile .ssh/authorized_keys - PasswordAuthentication no - AuthenticationMethods publickey - PubkeyAuthentication yes - PermitRootLogin no - KbdInteractiveAuthentication no - UsePAM yes - AllowAgentForwarding no - AllowTcpForwarding yes - X11Forwarding no - PrintMotd no - KexAlgorithms curve25519-sha256@libssh.org - Ciphers chacha20-poly1305@openssh.com - MACs hmac-sha2-512-etm@openssh.com - AcceptEnv LANG LC_* - Subsystem sftp /usr/lib/openssh/sftp-server - AllowUsers cl - - path: /etc/fail2ban/jail.local - content: | - [DEFAULT] - bantime = 3600 - findtime = 600 - maxretry = 3 - banaction = ufw +# AUTO UPGRADES +- path: /etc/apt/apt.conf.d/20auto-upgrades + content: | + APT::Periodic::Update-Package-Lists "1"; + APT::Periodic::Download-Upgradeable-Packages "1"; + APT::Periodic::AutocleanInterval "7"; + APT::Periodic::Unattended-Upgrade "1"; +# SSHD CONFIG +- path: /etc/ssh/sshd_config + content: | + # Include additional configuration files from the specified directory + Include /etc/ssh/sshd_config.d/*.conf + # Set the maximum number of authentication attempts allowed per connection + MaxAuthTries 3 + # Specifies the file containing public keys for user authentication + AuthorizedKeysFile .ssh/authorized_keys + # Disables password authentication + PasswordAuthentication no + # Specifies the authentication method(s) to use (public key authentication in this case) + AuthenticationMethods publickey + # Enables public key authentication + PubkeyAuthentication yes + # Disables root login via SSH + PermitRootLogin no + # Disables keyboard-interactive authentication + KbdInteractiveAuthentication no + # Enables the Pluggable Authentication Module (PAM) for authentication + UsePAM yes + # Disables agent forwarding for SSH connections + AllowAgentForwarding no + # Enables TCP forwarding for SSH connections + AllowTcpForwarding yes + # Disables X11 forwarding for SSH connections + X11Forwarding no + # Disables printing of the message of the day (MOTD) when a user logs in + PrintMotd no + # Specifies the key exchange algorithms to use + KexAlgorithms curve25519-sha256@libssh.org + # Specifies the ciphers allowed for protocol version 2 + Ciphers chacha20-poly1305@openssh.com + # Specifies the message authentication code (MAC) algorithms in order of preference + MACs hmac-sha2-512-etm@openssh.com + # Specifies environment variables sent by the client to the server + AcceptEnv LANG LC_* + # Specifies the command to use for the SFTP subsystem + Subsystem sftp /usr/lib/openssh/sftp-server + # Specifies the user(s) allowed to log in via SSH (in this case, only the user "marcus") + AllowUsers cl +# FAIL2BAN +- path: /etc/fail2ban/jail.local + content: | + [DEFAULT] + # Ban time (in seconds) for an IP after reaching the max number of retries. + bantime = 3600 + # Time window (in seconds) in which 'maxretry' failures must occur. + findtime = 600 + # Maximum number of failed login attempts before an IP gets banned. + maxretry = 3 + # Ban action to use (ufw in this case). + banaction = ufw - [sshd] - enabled = true - port = 22 - logpath = /var/log/auth.log + [sshd] + # Enable the sshd jail. + enabled = true + # Specify the port for the sshd service. + port = 22 + # Path to the log file for the sshd service. + logpath = /var/log/auth.log - [sshd-ddos] - filter = sshd - enabled = true - port = ssh - logpath = /var/log/auth.log - maxretry = 5 - bantime = 600 + [sshd-ddos] + # Specify the filter to use (created earlier) + filter = sshd + # Enable the sshd-ddos jail. + enabled = true + # Specify the port for the sshd service. + port = ssh + # Path to the log file for the sshd service. + logpath = /var/log/auth.log + # Maximum number of failed login attempts before an IP gets banned (for DDoS protection). + maxretry = 5 + # Ban time (in seconds) for an IP after reaching the max number of retries (for DDoS protection). + bantime = 600 + + [nginx-http-auth] + # Enable the jail + enabled = true + # Specify the filter to use (created earlier) + # filter = nginx-http-auth + # Define the action to take (using UFW) + action = ufw + # Specify the log file to monitor + logpath = /var/log/nginx/error.log + # Set the maximum number of failed attempts before banning + maxretry = 6 + # Set the ban time in seconds (1 hour) + bantime = 3600 + # Set the time window for failed attempts in seconds (10 minutes) + findtime = 600 +# NGINX CONF +- path: /etc/nginx/nginx.conf + content: | + user nginxuser; + worker_processes auto; + pid /run/nginx.pid; + include /etc/nginx/modules-enabled/*.conf; + events { + worker_connections 768; + # multi_accept on; + } + http { + ## + # Basic Settings + ## + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + # server_tokens off; + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + include /etc/nginx/mime.types; + default_type application/octet-stream; + ## + # SSL Settings + ## + ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + ## + # Logging Settings + ## + log_format csv '$time_iso8601,$remote_addr,$remote_user,"$request",$status,$body_bytes_sent,$http_referer,"$http_user_agent"'; + access_log /var/log/nginx/access.csv csv; + error_log /var/log/nginx/error.log; + ## + # Gzip Settings + ## + gzip on; + # 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; + ## + # Dont send nginx version number + ## + server_tokens off; + ## + # Virtual Host Configs + ## + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; + } + +# Write reverse-proxy configuration file +- path: /etc/nginx/sites-available/reverse-proxy.conf + content: | + # Listen on port 80 + server { + listen 80; + # Set your domain name + server_name code.metalisp.dev; + # Redirect all requests to HTTPS + return 301 https://$host$request_uri; + } + + # Listen on port 443 with SSL + server { + listen 443 ssl; + # Set your domain name + server_name code.metalisp.dev; + + # Include SSL certificate managed by Certbot + ssl_certificate /etc/letsencrypt/live/$host/fullchain.pem; + # Include SSL certificate key managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/$host/privkey.pem; + # Include SSL options provided by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; + # Include DH parameters provided by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + # Proxy settings for the location + location / { + # Set backend server address and port + proxy_pass http://localhost:3000; + # Set Host header + proxy_set_header Host $host; + # Set X-Real-IP header + proxy_set_header X-Real-IP $remote_addr; + # Set X-Forwarded-For header + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # Set X-Forwarded-Proto header + proxy_set_header X-Forwarded-Proto $scheme; + } + } runcmd: - - ufw default deny incoming - - ufw default allow outgoing - - ufw allow 22/tcp - - ufw allow mosh - - ufw enable - - systemctl enable fail2ban && systemctl start fail2ban - - systemctl restart sshd +# Run Certbot to obtain SSL certificates and configure Nginx +- certbot certonly --nginx -d code.metalisp.dev --non-interactive --agree-tos --email post@metalisp.dev --redirect +# Add cron job for automatic certificate renewal (runs once a month) +- echo '0 0 1 * * root certbot renew --post-hook "systemctl reload nginx" >> /var/log/letsencrypt/letsencrypt-auto-renew.log' > /etc/cron.d/letsencrypt-renew +# Download DHPARAM + +# The Diffie-Hellman algorithm is used to establish a shared secret between two +# parties (typically a client and a server) over a public channel, and is a +# fundamental part of many cryptographic protocols, including HTTPS. + +# However, generating Diffie-Hellman parameters can be computationally expensive, +# so pre-generated parameters are often used. Mozilla provides such pre-generated +# parameters, and they are considered to be trustworthy. + +# The downloaded parameters are saved in a file named ssl-dhparam.pem in the +# /etc/letsencrypt directory. This file is then referenced in the configuration +# of services that use Diffie-Hellman key exchange, such as your Nginx server, to +# establish secure communications. + +# This step is part of a broader effort to set up SSL/TLS securely on your +# server, enhancing the security of your connections. + +- curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/letsencrypt/ssl-dhparam.pem +# Create a symlink for the configuration file +- ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/ +# Remove default Nginx configuration +- rm /etc/nginx/sites-enabled/default +# Reload Nginx configuration +- systemctl reload nginx +# Allow Nginx Full (HTTP and HTTPS) through the firewall +- ufw allow 'Nginx Full' +- ufw default deny incoming +- ufw default allow outgoing +- ufw allow 22/tcp +- ufw allow mosh +- ufw enable +- systemctl enable fail2ban && systemctl start fail2ban +- systemctl restart sshd diff --git a/infrastructure.org b/infrastructure.org index b2d225c..44c203d 100644 --- a/infrastructure.org +++ b/infrastructure.org @@ -52,13 +52,24 @@ groups: Create and configure users. Here we're creating two users: a system user for Nginx and a regular user for administration. #+BEGIN_SRC yaml -users: + users: + - name: nginxuser + system: true + shell: /usr/sbin/nologin + groups: nginxgroup + sudo: null + # Create a new user named 'cl' - name: cl + # Add the user to the 'users' and 'admin' groups groups: users, admin + # Allow the user to execute any command with sudo without entering a password sudo: ALL=(ALL) NOPASSWD:ALL + # Set the user's default shell to /bin/bash shell: /bin/bash + # Add the user's public SSH key for key-based authentication ssh_authorized_keys: - - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6xSH5nE0uy0C0kglpp4EqrbbW2CrBeAIj+X6Sf2pd0 XPS-8930-Ubuntu_22 + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJCknACoboXvy6C0DNVR+OI0Kb+YZkanh0B2pXLqbauV marcus@fw-linux-01 + #+END_SRC ** Package Installation @@ -93,54 +104,202 @@ package_upgrade: true Write configuration files and scripts to the instance. #+BEGIN_SRC yaml -write_files: + write_files: + # AUTO UPGRADES - path: /etc/apt/apt.conf.d/20auto-upgrades content: | APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "7"; APT::Periodic::Unattended-Upgrade "1"; + # SSHD CONFIG - path: /etc/ssh/sshd_config content: | + # Include additional configuration files from the specified directory Include /etc/ssh/sshd_config.d/*.conf + # Set the maximum number of authentication attempts allowed per connection MaxAuthTries 3 + # Specifies the file containing public keys for user authentication AuthorizedKeysFile .ssh/authorized_keys + # Disables password authentication PasswordAuthentication no + # Specifies the authentication method(s) to use (public key authentication in this case) AuthenticationMethods publickey + # Enables public key authentication PubkeyAuthentication yes + # Disables root login via SSH PermitRootLogin no + # Disables keyboard-interactive authentication KbdInteractiveAuthentication no + # Enables the Pluggable Authentication Module (PAM) for authentication UsePAM yes + # Disables agent forwarding for SSH connections AllowAgentForwarding no + # Enables TCP forwarding for SSH connections AllowTcpForwarding yes + # Disables X11 forwarding for SSH connections X11Forwarding no + # Disables printing of the message of the day (MOTD) when a user logs in PrintMotd no + # Specifies the key exchange algorithms to use KexAlgorithms curve25519-sha256@libssh.org + # Specifies the ciphers allowed for protocol version 2 Ciphers chacha20-poly1305@openssh.com + # Specifies the message authentication code (MAC) algorithms in order of preference MACs hmac-sha2-512-etm@openssh.com + # Specifies environment variables sent by the client to the server AcceptEnv LANG LC_* + # Specifies the command to use for the SFTP subsystem Subsystem sftp /usr/lib/openssh/sftp-server + # Specifies the user(s) allowed to log in via SSH (in this case, only the user "marcus") AllowUsers cl + # FAIL2BAN - path: /etc/fail2ban/jail.local content: | [DEFAULT] + # Ban time (in seconds) for an IP after reaching the max number of retries. bantime = 3600 + # Time window (in seconds) in which 'maxretry' failures must occur. findtime = 600 + # Maximum number of failed login attempts before an IP gets banned. maxretry = 3 + # Ban action to use (ufw in this case). banaction = ufw [sshd] + # Enable the sshd jail. enabled = true + # Specify the port for the sshd service. port = 22 + # Path to the log file for the sshd service. logpath = /var/log/auth.log [sshd-ddos] + # Specify the filter to use (created earlier) filter = sshd + # Enable the sshd-ddos jail. enabled = true + # Specify the port for the sshd service. port = ssh + # Path to the log file for the sshd service. logpath = /var/log/auth.log + # Maximum number of failed login attempts before an IP gets banned (for DDoS protection). maxretry = 5 + # Ban time (in seconds) for an IP after reaching the max number of retries (for DDoS protection). bantime = 600 + + [nginx-http-auth] + # Enable the jail + enabled = true + # Specify the filter to use (created earlier) + # filter = nginx-http-auth + # Define the action to take (using UFW) + action = ufw + # Specify the log file to monitor + logpath = /var/log/nginx/error.log + # Set the maximum number of failed attempts before banning + maxretry = 6 + # Set the ban time in seconds (1 hour) + bantime = 3600 + # Set the time window for failed attempts in seconds (10 minutes) + findtime = 600 + # NGINX CONF + - path: /etc/nginx/nginx.conf + content: | + user nginxuser; + worker_processes auto; + pid /run/nginx.pid; + include /etc/nginx/modules-enabled/*.conf; + events { + worker_connections 768; + # multi_accept on; + } + http { + ## + # Basic Settings + ## + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + # server_tokens off; + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + include /etc/nginx/mime.types; + default_type application/octet-stream; + ## + # SSL Settings + ## + ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + ## + # Logging Settings + ## + log_format csv '$time_iso8601,$remote_addr,$remote_user,"$request",$status,$body_bytes_sent,$http_referer,"$http_user_agent"'; + access_log /var/log/nginx/access.csv csv; + error_log /var/log/nginx/error.log; + ## + # Gzip Settings + ## + gzip on; + # 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; + ## + # Dont send nginx version number + ## + server_tokens off; + ## + # Virtual Host Configs + ## + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; + } + + # Write reverse-proxy configuration file + - path: /etc/nginx/sites-available/reverse-proxy.conf + content: | + # Listen on port 80 + server { + listen 80; + # Set your domain name + server_name code.metalisp.dev; + # Redirect all requests to HTTPS + return 301 https://$host$request_uri; + } + + # Listen on port 443 with SSL + server { + listen 443 ssl; + # Set your domain name + server_name code.metalisp.dev; + + # Include SSL certificate managed by Certbot + ssl_certificate /etc/letsencrypt/live/$host/fullchain.pem; + # Include SSL certificate key managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/$host/privkey.pem; + # Include SSL options provided by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; + # Include DH parameters provided by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + # Proxy settings for the location + location / { + # Set backend server address and port + proxy_pass http://localhost:3000; + # Set Host header + proxy_set_header Host $host; + # Set X-Real-IP header + proxy_set_header X-Real-IP $remote_addr; + # Set X-Forwarded-For header + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # Set X-Forwarded-Proto header + proxy_set_header X-Forwarded-Proto $scheme; + } + } + #+END_SRC ** Run Commands @@ -148,7 +307,38 @@ write_files: Execute commands after the instance has been set up. #+BEGIN_SRC yaml -runcmd: + runcmd: + # Run Certbot to obtain SSL certificates and configure Nginx + - certbot certonly --nginx -d code.metalisp.dev --non-interactive --agree-tos --email post@metalisp.dev --redirect + # Add cron job for automatic certificate renewal (runs once a month) + - echo '0 0 1 * * root certbot renew --post-hook "systemctl reload nginx" >> /var/log/letsencrypt/letsencrypt-auto-renew.log' > /etc/cron.d/letsencrypt-renew + # Download DHPARAM + + # The Diffie-Hellman algorithm is used to establish a shared secret between two + # parties (typically a client and a server) over a public channel, and is a + # fundamental part of many cryptographic protocols, including HTTPS. + + # However, generating Diffie-Hellman parameters can be computationally expensive, + # so pre-generated parameters are often used. Mozilla provides such pre-generated + # parameters, and they are considered to be trustworthy. + + # The downloaded parameters are saved in a file named ssl-dhparam.pem in the + # /etc/letsencrypt directory. This file is then referenced in the configuration + # of services that use Diffie-Hellman key exchange, such as your Nginx server, to + # establish secure communications. + + # This step is part of a broader effort to set up SSL/TLS securely on your + # server, enhancing the security of your connections. + + - curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/letsencrypt/ssl-dhparam.pem + # Create a symlink for the configuration file + - ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/ + # Remove default Nginx configuration + - rm /etc/nginx/sites-enabled/default + # Reload Nginx configuration + - systemctl reload nginx + # Allow Nginx Full (HTTP and HTTPS) through the firewall + - ufw allow 'Nginx Full' - ufw default deny incoming - ufw default allow outgoing - ufw allow 22/tcp