Pass data to an instance to configure it or run scripts after it starts.
Find a file
2025-07-08 21:18:32 +00:00
ripcord Add ripcord/README.md 2025-07-06 07:17:35 +00:00
synterloper linux fixes 2025-07-07 19:48:20 +00:00
LICENSE Initial commit 2025-07-06 06:44:59 +00:00
README.md example 2025-07-08 21:18:32 +00:00

Unified First-Boot Server Setup Script

A complete, self-contained provisioning script for automated server deployment that combines both Ripcord and SYNterloper with system hardening tasks (user creation, SSH setup, sudoers) in one idempotent user-data script.


🔧 Purpose

This script automates the following tasks on first boot:

  • Creates a non-root user with SSH access and sudo privileges
  • Installs Ansible-ready Python packages
  • Deploys Ripcord (emergency disk space reserve)
  • Deploys SYNterloper (rolling SSH connection logger)
  • Validates each step with .flag files
  • Leaves all components ready for manual management

➡️ For tool-specific details, see individual READMEs:


📦 Repository Structure

.
├── user-data.sh     # This script
├── ripcord/
│   ├── ripcord.sh
│   └── README.md
├── synterloper/
│   ├── synterloper.sh
│   └── README.md
└── README.md               # You are here

🚀 Installation

Paste this script into your cloud provider's User Data field during instance creation:

#!/bin/bash
set -e  # Exit on any error

# Define user and flag locations
USRNAME=fastsoul
FLAG_DIR=/var/lib/cloud/scripts/user
mkdir -p "$FLAG_DIR"

# --- Step 1: Create user ---
if [ ! -f "$FLAG_DIR/.user_created.flag" ]; then
    echo "Creating user: $USRNAME"
    if ! id "$USRNAME" &>/dev/null; then
        useradd "$USRNAME" -s /bin/bash -d /home/"$USRNAME" -m || { echo "User creation failed"; exit 1; }
        chown -R "$USRNAME":"$USRNAME" /home/"$USRNAME"
    else
        echo "User $USRNAME already exists. Skipping creation."
    fi
    touch "$FLAG_DIR/.user_created.flag"
fi

# --- Step 2: Create SSH directory and authorized_keys file ---
if [ ! -f "$FLAG_DIR/.ssh_setup.flag" ]; then
    echo "Setting up SSH for $USRNAME"
    mkdir -p "/home/$USRNAME/.ssh"
    touch "/home/$USRNAME/.ssh/authorized_keys"
    chown -R "$USRNAME":"$USRNAME" "/home/$USRNAME/.ssh"
    chmod 700 "/home/$USRNAME/.ssh"
    chmod 600 "/home/$USRNAME/.ssh/authorized_keys"
    touch "$FLAG_DIR/.ssh_setup.flag"
fi

# --- Step 3: Add SSH keys to authorized_keys ---
if [ ! -f "$FLAG_DIR/.ssh_keys_added.flag" ]; then
    echo "Adding SSH keys to authorized_keys"
    cat << EOF >> /home/$USRNAME/.ssh/authorized_keys
cert-authority ssh-rsa AAAAB3NzaXXXX== user@example.com

ssh-rsa AAAAB3NzaYYYYYYYYYYYYYYYYYYYYYYYYYYYYQ==

ssh-rsa AAAAB3NzaXXXXXXXXXXXXXXXXXXXXXXXXXXXXQ==
EOF

    if [ $? -eq 0 ]; then
        chown -R "$USRNAME":"$USRNAME" "/home/$USRNAME/.ssh/authorized_keys"
        touch "$FLAG_DIR/.ssh_keys_added.flag"
    else
        echo "Failed to write SSH keys to authorized_keys"
        exit 1
    fi
fi

# --- Step 4: Set NOPASSWD sudoers ---
if [ ! -f "$FLAG_DIR/.sudoers_set.flag" ]; then
    echo "Setting up NOPASSWD sudo for $USRNAME"
    echo "$USRNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/"$USRNAME" || { echo "Failed to write sudoers file"; exit 1; }
    touch "$FLAG_DIR/.sudoers_set.flag"
fi

# --- Step 5: Install python3-apt for Ansible support ---
if [ ! -f "$FLAG_DIR/.python_installed.flag" ]; then
    echo "Updating APT and installing python3-apt"
    apt update -y || { echo "APT update failed"; exit 1; }
    apt install -y python3-apt || { echo "Failed to install python3-apt"; exit 1; }
    touch "$FLAG_DIR/.python_installed.flag"
fi

# --- Step 6: Download Ripcord and SYNterloper from Git ---
if [ ! -f "$FLAG_DIR/.scripts_downloaded.flag" ]; then
    echo "Downloading Ripcord and SYNterloper scripts"
    curl -fsSL -o /usr/local/sbin/ripcord.sh https://git.r21.io/primemover/user-data/raw/branch/master/ripcord/ripcord.sh || { echo "Ripcord download failed"; exit 1; }
    curl -fsSL -o /usr/local/sbin/synterloper.sh https://git.r21.io/primemover/user-data/raw/branch/master/synterloper/synterloper.sh || { echo "SYNterloper download failed"; exit 1; }
    chmod +x /usr/local/sbin/ripcord.sh /usr/local/sbin/synterloper.sh || { echo "chmod failed"; exit 1; }
    touch "$FLAG_DIR/.scripts_downloaded.flag"
fi

# --- Step 7: Setup Ripcord systemd service ---
if [ ! -f "$FLAG_DIR/.ripcord_setup.flag" ]; then
    echo "Setting up Ripcord systemd service"
    cat << EOF | sudo tee /etc/systemd/system/ripcord.service
[Unit]
Description=Ripcord Emergency Disk Space Reserve
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/ripcord.sh
ExecStartPost=/bin/sh -c "systemctl disable ripcord.service"
[Install]
WantedBy=multi-user.target
EOF

    systemctl enable ripcord.service || { echo "Failed to enable Ripcord service"; exit 1; }
    touch "$FLAG_DIR/.ripcord_setup.flag"
fi

# --- Step 8: Install SYNterloper ---
if [ ! -f "$FLAG_DIR/.synterloper_installed.flag" ]; then
    echo "Installing SYNterloper"
    /usr/local/sbin/synterloper.sh install || { echo "SYNterloper install failed"; exit 1; }
    touch "$FLAG_DIR/.synterloper_installed.flag"
fi

# --- Final Step: Mark completion ---
if [ ! -f "$FLAG_DIR/.user_data_complete.flag" ]; then
    echo "Marking user-data completion"
    touch /root/user_data_completed.txt
    touch "$FLAG_DIR/.user_data_complete.flag"
fi

echo "All steps completed successfully."
exit 0

What Gets Installed

Component Purpose Validation Flag
User: fastsoul Primary admin account /var/lib/cloud/scripts/user/.user_created.flag
SSH Keys Cert-authority and/or deployment keys /var/lib/cloud/scripts/user/.ssh_keys_added.flag
Sudoers NOPASSWD:ALL access /var/lib/cloud/scripts/user/.sudoers_set.flag
Python 3-apt Ansible dependency /var/lib/cloud/scripts/user/.python_installed.flag
Ripcord.sh Emergency disk ballast /var/lib/cloud/scripts/user/.ripcord_setup.flag
Synterloper.sh Rolling SSH connection logger /var/lib/cloud/scripts/user/.synterloper_installed.flag

⚙️ Configuration

Edit these variables at the top of the script to customize:

# Change these to match your needs
USRNAME=fastsoul
SSH_KEYS="
cert-authority ssh-rsa AAAAB3NzaXXXXXXXXXXXXXXXXXX...user@example.com
ssh-rsa AAAAB3NzaYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYQ==
ssh-rsa AAAAB3NzaXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXQ==

🔍 Validation

All steps are validated with .flag files in /var/lib/cloud/scripts/user/:

ls -la /var/lib/cloud/scripts/user/

Expected output:

.user_created.flag
.ssh_keys_added.flag
.sudoers_set.flag
.python_installed.flag
.scripts_downloaded.flag
.ripcord_setup.flag
.synterloper_installed.flag
.user_data_complete.flag

🧹 Re-running

To re-run the script (e.g., for testing):

  1. Delete specific .flag files:
    rm /var/lib/cloud/scripts/user/.sudoers_set.flag
    
  2. Re-run the script:
    sudo /var/lib/cloud/scripts/user/user-data.sh
    

⚠️ Known Limitations

  • Debian/Ubuntu only (FreeBSD support would require separate logic)
  • Root access required (must be run via cloud-init)
  • Hardcoded SSH keys (rotate credentials for production use)

📚 For More Details


📄 License

This script is released under the MIT License. See LICENSE for details.