commit 40f185e29994b6311cc048a15e8f9ebc805fe68d
parent 199ab2d8ca6da72206327f57a3ac4782d38b9e05
Author: Damian Myrda <damian@prime8.dev>
Date: Sun, 8 Feb 2026 14:07:05 -0600
refactor: replace static cloud-config with interactive generator script
- Add generate_cloud_config.sh script for user-customized cloud-init
- Remove hardcoded cloud_config.yml in favor of dynamic generation
- Include unattended security upgrades with email notifications
- Add swap file configuration (4GB) for server stability
- Integrate Docker and Dokploy installation
- Improve SSH hardening with AllowGroups and non-standard port
Diffstat:
| D | cloud_config.yml | | | 67 | ------------------------------------------------------------------- |
| A | generate_cloud_config.sh | | | 153 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 153 insertions(+), 67 deletions(-)
diff --git a/cloud_config.yml b/cloud_config.yml
@@ -1,67 +0,0 @@
-users:
- - name: damian
- groups: users, admin
- sudo: ALL=(ALL) NOPASSWD:ALL
- shell: /bin/bash
- ssh_authorized_keys:
- - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbhuxFr7zO5fcvLMP8dt1SQAQ1uEw0rJCeFI7o5JFULA4w1dB9yc9FotnVwxRroXpBHxmH7jTFsuCXjHj5CQFDnDb0Vq6iVrtj4WEWBg4N+juA347pmKPLVnyEofpjIHHFSj4b4U/ozk/xEfekNrAxrjhMYcREXQsMI168MNupCEqrqWAyDygokKTicwEX0YNCX2ig5Obs9dUj/nbaWL9/kWgOejuAzQd9guncC0r6Oc8yce+FHjqFpd6tApCLF1IN0KNBfj2k24WEU9JuovwwZ+mbFvKTeZF0O9aXlvuVlrKIS6yfn6Srh22GQJMEhcDMypO8t3AnsKli6vM6J7iUWJuksLf9fOty2ZfJghMOlUHYVcAaXPn2ESReNjSJfHtNOsvIlXsXMznFnTK2WL0115aF0th9Ivxn+t/9onOj6iQALgIYiRSM9tg7zKu1+vglZmU1CKsdzXGGP5P/UVeQFkxjUsYEjEebInfbIl6I246HpLLQIwkqGm/21Ge5hLAEiKYtasoFyRqcc1pWhwj96TMw096pWGrZg89CO8P0U9INhWfHbogT4c07reZpZuSH745thufYQ0CtgJQOlCTQdyilHyZL3d6yDoITNycqMIklnNPRDB9Po5tdD6qzDg7p//OurYx3d5FkhMby6H8/B/79E0+ASh3so5TRP6hiOw==
-
-package_update: true
-package_upgrade: true
-
-packages:
- - fail2ban
- - ufw
- - curl
- - ca-certificates
- - systemd-timesyncd
-
-ssh_pwauth: false
-write_files:
- - path: /etc/ssh/sshd_config.d/ssh-hardening.conf
- content: |
- Port 2222
- PermitRootLogin no
- PasswordAuthentication no
- KbdInteractiveAuthentication no
- ChallengeResponseAuthentication no
- MaxAuthTries 3
- AllowTcpForwarding no
- X11Forwarding no
- AllowAgentForwarding no
- AuthorizedKeysFile .ssh/authorized_keys
- AllowUsers damian
-
-runcmd:
- # Time sync
- - systemctl enable systemd-timesyncd
- - systemctl start systemd-timesyncd || true
-
- # Fail2ban
- - printf "[sshd]\nenabled = true\nport = 2222\nbanaction = iptables-multiport\nmaxretry = 3\nbantime = 3600\nfindtime = 600\n" > /etc/fail2ban/jail.local
- - systemctl enable fail2ban
- - systemctl restart fail2ban || true
-
- # Firewall
- - ufw allow 2222/tcp # SSH (Admin)
- - ufw allow 22/tcp # SSH (GitLab)
- - ufw allow 80/tcp # HTTP
- - ufw allow 443/tcp # HTTPS
- - ufw allow 3000/tcp # Dokploy UI
- - ufw allow 25/tcp # SMTP
- - ufw allow 465/tcp # SMTPS
- - ufw allow 587/tcp # Submission
- - ufw allow 993/tcp # IMAPS
- - ufw --force enable
-
- # Reload SSH to apply hardening
- - systemctl restart sshd || systemctl restart ssh || true
-
- # Dokploy
- - curl -sSL https://dokploy.com/install.sh | sh
-
- # Add damian to docker group
- - usermod -aG docker damian || true
-
- # Finish
- - reboot
diff --git a/generate_cloud_config.sh b/generate_cloud_config.sh
@@ -0,0 +1,153 @@
+#!/bin/bash
+set -e
+
+read -p "Enter your name: " USERNAME
+read -p "Enter your SSH public key: " SSH_KEY
+echo
+read -p "Enter your hostname: " HOSTNAME
+read -p "Enter your domain: " DOMAIN
+echo
+read -p "Enter your email address: " EMAIL_ADDRESS
+read -s -p "Enter your email password: " EMAIL_PASSWORD
+echo
+
+cat <<EOF
+#cloud-config
+
+users:
+ - name: $USERNAME
+ groups: users, admin, docker
+ sudo: ALL=(ALL) NOPASSWD:ALL
+ shell: /bin/bash
+ ssh_authorized_keys:
+ - $SSH_KEY
+
+package_update: true
+package_upgrade: true
+packages:
+ - fail2ban
+ - ufw
+ - curl
+ - ca-certificates
+ - systemd-timesyncd
+ - unattended-upgrades
+ - apt-listchanges
+ - needrestart
+ - msmtp
+ - bsd-mailx
+
+ssh_pwauth: false
+
+write_files:
+ - path: /etc/ssh/sshd_config.d/ssh-hardening.conf
+ content: |
+ Port 2222
+ PermitRootLogin no
+ PasswordAuthentication no
+ KbdInteractiveAuthentication no
+ ChallengeResponseAuthentication no
+ MaxAuthTries 3
+ AllowTcpForwarding no
+ X11Forwarding no
+ AllowAgentForwarding no
+ AuthorizedKeysFile .ssh/authorized_keys
+ AllowGroups users
+
+ - path: /etc/apt/apt.conf.d/50unattended-upgrades
+ content: |
+ Unattended-Upgrade::Allowed-Origins {
+ "\${distro_id}:\${distro_codename}-security";
+ };
+
+ Unattended-Upgrade::Package-Blacklist {};
+
+ Unattended-Upgrade::Mail "$EMAIL_ADDRESS";
+ Unattended-Upgrade::Sender "server-updates <$EMAIL_ADDRESS>";
+ Unattended-Upgrade::MailReport "on-change";
+ Unattended-Upgrade::MailOnlyOnError "true";
+
+ Unattended-Upgrade::Automatic-Reboot "true";
+ Unattended-Upgrade::Automatic-RebootTime "00:00";
+ Unattended-Upgrade::Automatic-RebootWithUsers "false";
+
+ - path: /etc/apt/apt.conf.d/20auto-upgrades
+ content: |
+ APT::Periodic::Update-Package-Lists "1";
+ APT::Periodic::Unattended-Upgrade "1";
+ APT::Periodic::AutocleanInterval "7";
+
+ # WARNING: Email password stored in plaintext here (root-only, 0600). Use secrets manager in production.
+ - path: /root/.msmtprc
+ permissions: "0600"
+ owner: root:root
+ content: |
+ account default
+ host smtp.fastmail.com
+ port 465
+ from $EMAIL_ADDRESS
+ user $EMAIL_ADDRESS
+ password $EMAIL_PASSWORD
+ auth on
+ tls on
+ tls_starttls off
+ tls_certcheck on
+ logfile /var/log/msmtp/msmtp.log
+
+ - path: /etc/logrotate.d/msmtp
+ content: |
+ /var/log/msmtp/msmtp.log {
+ daily
+ rotate 7
+ compress
+ delaycompress
+ missingok
+ notifempty
+ create 0600 root root
+ }
+
+ - path: /etc/mailname
+ content: $DOMAIN
+
+ - path: /etc/hostname
+ content: $HOSTNAME
+
+runcmd:
+ - hostnamectl set-hostname $HOSTNAME || true
+
+ - timedatectl set-timezone America/Los_Angeles || true
+ - systemctl enable --now systemd-timesyncd
+
+ - |
+ printf "[sshd]\nenabled = true\nport = 2222\nbanaction = iptables-multiport\nmaxretry = 3\nbantime = 3600\nfindtime = 600\n" > /etc/fail2ban/jail.local
+ - systemctl enable --now fail2ban
+
+ - ufw default deny incoming
+ - ufw default allow outgoing
+ - ufw allow 2222/tcp comment "SSH hardened port"
+ - ufw allow 22/tcp comment "SSH GitLab"
+ - ufw allow 80/tcp comment "HTTP - Traefik"
+ - ufw allow 443/tcp comment "HTTPS - Traefik"
+ - ufw allow 3000/tcp comment "Dokploy UI - temporary, close after setup"
+ - ufw --force enable
+
+ - systemctl restart sshd || systemctl restart ssh || true
+
+ - ln -sf /root/.msmtprc /etc/msmtprc || true
+ - grep -q "mta=/usr/bin/msmtp" /etc/mail.rc || echo "set mta=/usr/bin/msmtp" >> /etc/mail.rc
+ - echo "Automatic security updates enabled. Emails sent to $EMAIL_ADDRESS on changes. Reboots at 00:00 PT if needed." > /etc/motd.d/99-security-updates
+ - echo "Server first boot for $HOSTNAME" | mail -s "Server Setup Test" $EMAIL_ADDRESS || true
+
+ - |
+ fallocate -l 4G /swapfile || true
+ chmod 600 /swapfile || true
+ mkswap /swapfile || true
+ swapon /swapfile || true
+ echo "/swapfile none swap sw 0 0" >> /etc/fstab || true
+
+ - curl -fsSL https://get.docker.com | sh
+ - usermod -aG docker $USERNAME || true
+
+ - curl -sSL https://dokploy.com/install.sh | sh
+
+ - reboot
+EOF