#!/bin/bash set -euo pipefail # Hearth Minimal - EC2 User Data Script # Installs k3s and deploys Forgejo exec > >(tee /var/log/user-data.log) 2>&1 echo "Starting user-data script at $(date)" # ----------------------------------------------------------------------------- # Variables from Terraform # ----------------------------------------------------------------------------- DOMAIN="${domain}" LETSENCRYPT_EMAIL="${letsencrypt_email}" SSH_PORT="${ssh_port}" S3_BUCKET="${s3_bucket}" # ----------------------------------------------------------------------------- # System Setup # ----------------------------------------------------------------------------- # Update system dnf update -y # Install required packages dnf install -y docker git jq awscli # Enable and start Docker (for building if needed) systemctl enable --now docker # Move SSH to alternate port for admin access sed -i "s/#Port 22/Port $SSH_PORT/" /etc/ssh/sshd_config systemctl restart sshd # Add admin SSH key (passed from terraform) SSH_KEY="${ssh_public_key}" if [ -n "$SSH_KEY" ]; then mkdir -p /home/ec2-user/.ssh echo "$SSH_KEY" >> /home/ec2-user/.ssh/authorized_keys chown -R ec2-user:ec2-user /home/ec2-user/.ssh chmod 700 /home/ec2-user/.ssh chmod 600 /home/ec2-user/.ssh/authorized_keys fi # Enable automatic security updates dnf install -y dnf-automatic sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf systemctl enable --now dnf-automatic-install.timer # ----------------------------------------------------------------------------- # Install k3s # ----------------------------------------------------------------------------- echo "Installing k3s..." curl -sfL https://get.k3s.io | sh -s - \ --disable traefik \ --write-kubeconfig-mode 644 # Wait for k3s to be ready echo "Waiting for k3s to be ready..." until kubectl get nodes 2>/dev/null | grep -q "Ready"; do sleep 5 done echo "k3s is ready" # ----------------------------------------------------------------------------- # Install Traefik CRDs (required for IngressRouteTCP) # ----------------------------------------------------------------------------- echo "Installing Traefik CRDs..." kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.2/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml # Wait for CRDs to be established echo "Waiting for Traefik CRDs to be ready..." kubectl wait --for=condition=Established crd/ingressroutetcps.traefik.io --timeout=60s || true kubectl wait --for=condition=Established crd/ingressroutes.traefik.io --timeout=60s || true # ----------------------------------------------------------------------------- # Install Traefik with Let's Encrypt # ----------------------------------------------------------------------------- echo "Installing Traefik..." cat < /usr/local/bin/backup-forgejo.sh #!/bin/bash set -euo pipefail TIMESTAMP=$(date +%Y%m%d-%H%M%S) S3_BUCKET="$1" BACKUP_DIR="/tmp/backup-$TIMESTAMP" mkdir -p "$BACKUP_DIR" # Backup Forgejo SQLite database if [ -f /data/forgejo/gitea/gitea.db ]; then sqlite3 /data/forgejo/gitea/gitea.db ".backup '$BACKUP_DIR/gitea.db'" fi # Backup k3s state cp -r /var/lib/rancher/k3s/server/db "$BACKUP_DIR/k3s-db" 2>/dev/null || true # Create tarball tar -czf "/tmp/backup-$TIMESTAMP.tar.gz" -C "$BACKUP_DIR" . # Upload to S3 aws s3 cp "/tmp/backup-$TIMESTAMP.tar.gz" "s3://$S3_BUCKET/backups/backup-$TIMESTAMP.tar.gz" # Cleanup rm -rf "$BACKUP_DIR" "/tmp/backup-$TIMESTAMP.tar.gz" # Keep only last 7 days of backups in S3 (lifecycle policy handles older ones) echo "Backup completed: s3://$S3_BUCKET/backups/backup-$TIMESTAMP.tar.gz" BACKUP_SCRIPT chmod +x /usr/local/bin/backup-forgejo.sh # Add cron job for daily backup at 3 AM echo "0 3 * * * root /usr/local/bin/backup-forgejo.sh ${s3_bucket} >> /var/log/backup.log 2>&1" > /etc/cron.d/forgejo-backup # Initial backup /usr/local/bin/backup-forgejo.sh ${s3_bucket} || true # ----------------------------------------------------------------------------- # Done # ----------------------------------------------------------------------------- echo "User-data script completed at $(date)" echo "" echo "==========================================" echo "Forgejo deployment complete!" echo "==========================================" echo "" echo "Web URL: https://${domain}" echo "Git SSH: git@${domain}:ORG/REPO.git" echo "Admin SSH: ssh -p ${ssh_port} ec2-user@" echo "" echo "Next steps:" echo "1. Point DNS: ${domain} -> " echo "2. Wait for DNS propagation" echo "3. Visit https://${domain} to complete setup" echo "=========================================="