prime8dev

prime8dev
git clone https://git.prime8.dev/prime8dev.git
Log | Files | Refs | README | LICENSE

commit 7409ce6d274b39af436099e96d00c3172e649590
parent 85ae0487045645646fb547fb19e307320b162543
Author: Damian Myrda <damian@prime8.dev>
Date:   Sun,  8 Feb 2026 14:11:03 -0600

feat: interactive cloud-config generator, fix sitemap

Diffstat:
Dastro.config.mjs | 16----------------
Aastro.config.ts | 18++++++++++++++++++
Dcloud_config.yml | 67-------------------------------------------------------------------
Agenerate_cloud_config.sh | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/constants/website.ts | 2+-
Msrc/pages/blog/[slug].astro | 3++-
Msrc/pages/sitemap.xml.ts | 3++-
7 files changed, 176 insertions(+), 86 deletions(-)

diff --git a/astro.config.mjs b/astro.config.mjs @@ -1,16 +0,0 @@ -import { defineConfig } from "astro/config"; -import bun from "astro-bun-adapter"; - -export default defineConfig({ - output: "server", - site: "https://prime8.dev", - adapter: bun(), - server: { - host: true, - }, - image: { - service: { - entrypoint: "astro/assets/services/noop", - }, - }, -}); diff --git a/astro.config.ts b/astro.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from "astro/config"; +import bun from "astro-bun-adapter"; +import { SITE_URL } from "./src/constants/website"; + +export default defineConfig({ + output: "server", + site: SITE_URL, + trailingSlash: "never", + adapter: bun(), + server: { + host: true, + }, + image: { + service: { + entrypoint: "astro/assets/services/noop", + }, + }, +}); 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 diff --git a/src/constants/website.ts b/src/constants/website.ts @@ -1,3 +1,3 @@ -export const SITE_DOMAIN = "prime8.dev"; +export const SITE_DOMAIN = "www.prime8.dev"; export const SITE_URL = `https://${SITE_DOMAIN}`; diff --git a/src/pages/blog/[slug].astro b/src/pages/blog/[slug].astro @@ -4,6 +4,7 @@ import Article from "../../layouts/components/Article.astro"; import { blogs } from "../../blogs"; import schemas from "../../schemas/index"; +import { SITE_URL } from "../../constants/website"; const blog = blogs.find((blog) => blog.id === Astro.params.slug); if (!blog) { @@ -22,7 +23,7 @@ const { getSchemaForBlog, getBreadcrumbSchema } = schemas.blog; title={`${blog.title} | Damian Myrda`} description={blog.description} type="article" - url={`https://prime8.dev/blog/${blog.id}`} + url={`${SITE_URL}/blog/${blog.id}`} publishedTime={blog.date} modifiedTime={blog.modifiedDate || blog.date} keywords={keywords} diff --git a/src/pages/sitemap.xml.ts b/src/pages/sitemap.xml.ts @@ -2,6 +2,7 @@ import type { APIRoute } from "astro"; import { fetchGitMetadataForProject } from "../external/git"; import { experience, projects } from "../config"; import { blogs } from "../blogs"; +import { SITE_URL } from "../constants/website"; export const GET: APIRoute = async () => { const now = new Date().toISOString().split("T")[0]; @@ -58,7 +59,7 @@ export const GET: APIRoute = async () => { ${allPages .map( (page) => ` <url> - <loc>${URL}${page.url}</loc> + <loc>${SITE_URL}${page.url}</loc> <lastmod>${page.lastmod || now}</lastmod> <changefreq>${page.changefreq}</changefreq> <priority>${page.priority}</priority>