Skip to content

Instantly share code, notes, and snippets.

@lonix
Created June 20, 2025 13:20
Show Gist options
  • Save lonix/fa5ee551dd8357eaf8437b0519eed499 to your computer and use it in GitHub Desktop.
Save lonix/fa5ee551dd8357eaf8437b0519eed499 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration
USERNAME="pukabyte"
GITHUB_KEYS_URL="https://github.com/pukabyte.keys"
SSH_DIR="/home/$USERNAME/.ssh"
AUTHORIZED_KEYS="$SSH_DIR/authorized_keys"
# Function to log messages
log() {
local message="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${YELLOW}[$timestamp]${NC} $message"
}
# Function to handle errors
handle_error() {
local error_msg="$1"
log "${RED}Error: $error_msg${NC}"
exit 1
}
# Function to check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
handle_error "This script must be run as root (use sudo)"
fi
}
# Function to check if user already exists
check_user_exists() {
if id "$USERNAME" &>/dev/null; then
log "${YELLOW}User $USERNAME already exists. Skipping user creation.${NC}"
return 0
fi
return 1
}
# Function to create user
create_user() {
log "${GREEN}Creating user: $USERNAME${NC}"
# Create user with home directory and bash shell
if useradd -m -s /bin/bash "$USERNAME"; then
log "${GREEN}User $USERNAME created successfully${NC}"
else
handle_error "Failed to create user $USERNAME"
fi
}
# Function to add user to groups
add_to_groups() {
log "${GREEN}Adding $USERNAME to sudo and docker groups${NC}"
# Add to sudo group
if usermod -aG sudo "$USERNAME"; then
log "${GREEN}Added $USERNAME to sudo group${NC}"
else
handle_error "Failed to add $USERNAME to sudo group"
fi
# Add to docker group
if usermod -aG docker "$USERNAME"; then
log "${GREEN}Added $USERNAME to docker group${NC}"
else
handle_error "Failed to add $USERNAME to docker group"
fi
}
# Function to setup SSH directory and permissions
setup_ssh_directory() {
log "${GREEN}Setting up SSH directory for $USERNAME${NC}"
# Create SSH directory
if mkdir -p "$SSH_DIR"; then
log "${GREEN}Created SSH directory: $SSH_DIR${NC}"
else
handle_error "Failed to create SSH directory"
fi
# Set correct ownership
if chown -R "$USERNAME:$USERNAME" "$SSH_DIR"; then
log "${GREEN}Set ownership of SSH directory${NC}"
else
handle_error "Failed to set SSH directory ownership"
fi
# Set correct permissions
if chmod 700 "$SSH_DIR"; then
log "${GREEN}Set SSH directory permissions to 700${NC}"
else
handle_error "Failed to set SSH directory permissions"
fi
}
# Function to download and setup SSH keys
setup_ssh_keys() {
log "${GREEN}Downloading SSH keys from GitHub${NC}"
# Download keys from GitHub
local temp_keys="/tmp/pukabyte_keys_$$"
if curl -s "$GITHUB_KEYS_URL" > "$temp_keys"; then
log "${GREEN}Downloaded SSH keys from GitHub${NC}"
else
handle_error "Failed to download SSH keys from GitHub"
fi
# Check if keys were downloaded
if [[ ! -s "$temp_keys" ]]; then
handle_error "No SSH keys found at $GITHUB_KEYS_URL"
fi
# Copy keys to authorized_keys
if cp "$temp_keys" "$AUTHORIZED_KEYS"; then
log "${GREEN}Copied SSH keys to authorized_keys${NC}"
else
handle_error "Failed to copy SSH keys to authorized_keys"
fi
# Set correct ownership
if chown "$USERNAME:$USERNAME" "$AUTHORIZED_KEYS"; then
log "${GREEN}Set ownership of authorized_keys${NC}"
else
handle_error "Failed to set authorized_keys ownership"
fi
# Set correct permissions
if chmod 600 "$AUTHORIZED_KEYS"; then
log "${GREEN}Set authorized_keys permissions to 600${NC}"
else
handle_error "Failed to set authorized_keys permissions"
fi
# Clean up temp file
rm -f "$temp_keys"
}
# Function to configure sudo access
configure_sudo() {
log "${GREEN}Configuring sudo access for $USERNAME${NC}"
# Create sudoers file for the user
local sudoers_file="/etc/sudoers.d/$USERNAME"
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > "$sudoers_file"
if [[ $? -eq 0 ]]; then
log "${GREEN}Created sudoers file for $USERNAME${NC}"
else
handle_error "Failed to create sudoers file"
fi
# Set correct permissions on sudoers file
if chmod 440 "$sudoers_file"; then
log "${GREEN}Set sudoers file permissions to 440${NC}"
else
handle_error "Failed to set sudoers file permissions"
fi
}
# Function to verify setup
verify_setup() {
log "${GREEN}Verifying setup...${NC}"
# Check if user exists
if id "$USERNAME" &>/dev/null; then
log "${GREEN}✓ User $USERNAME exists${NC}"
else
handle_error "User $USERNAME does not exist"
fi
# Check if user is in sudo group
if groups "$USERNAME" | grep -q sudo; then
log "${GREEN}✓ User $USERNAME is in sudo group${NC}"
else
handle_error "User $USERNAME is not in sudo group"
fi
# Check if user is in docker group
if groups "$USERNAME" | grep -q docker; then
log "${GREEN}✓ User $USERNAME is in docker group${NC}"
else
handle_error "User $USERNAME is not in docker group"
fi
# Check if SSH keys exist
if [[ -f "$AUTHORIZED_KEYS" ]]; then
local key_count=$(wc -l < "$AUTHORIZED_KEYS")
log "${GREEN}✓ SSH keys file exists with $key_count keys${NC}"
else
handle_error "SSH keys file does not exist"
fi
# Check SSH directory permissions
if [[ $(stat -c %a "$SSH_DIR") == "700" ]]; then
log "${GREEN}✓ SSH directory has correct permissions${NC}"
else
handle_error "SSH directory has incorrect permissions"
fi
# Check authorized_keys permissions
if [[ $(stat -c %a "$AUTHORIZED_KEYS") == "600" ]]; then
log "${GREEN}✓ authorized_keys has correct permissions${NC}"
else
handle_error "authorized_keys has incorrect permissions"
fi
}
# Function to get public IP address
get_public_ip() {
# Try multiple services in case one fails
local ip=""
# Try ifconfig.me first
ip=$(curl -s --connect-timeout 5 ifconfig.me 2>/dev/null)
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$ip"
return 0
fi
# Try ipinfo.io as backup
ip=$(curl -s --connect-timeout 5 ipinfo.io/ip 2>/dev/null)
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$ip"
return 0
fi
# Try icanhazip.com as another backup
ip=$(curl -s --connect-timeout 5 icanhazip.com 2>/dev/null)
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$ip"
return 0
fi
return 1
}
# Function to get SSH port
get_ssh_port() {
# Check if SSH is running and get the port
local port=$(ss -tlnp | grep sshd | grep -E ':(22|2222|2200)' | head -1 | awk '{print $4}' | cut -d':' -f2)
if [[ -n "$port" ]]; then
echo "$port"
else
# Default SSH port
echo "22"
fi
}
# Function to output connection information
output_connection_info() {
local public_ip=$(get_public_ip)
local ssh_port=$(get_ssh_port)
if [[ -n "$public_ip" ]]; then
log "${GREEN}=== CONNECTION INFORMATION ===${NC}"
log "${YELLOW}Tell this to puks the pirate:${NC}"
log "${GREEN}Public IP: $public_ip${NC}"
log "${GREEN}SSH Port: $ssh_port${NC}"
log "${GREEN}SSH Connection String:${NC}"
log "${YELLOW}ssh pukabyte@$public_ip -p $ssh_port${NC}"
log ""
log "${GREEN}Or if using a different port:${NC}"
log "${YELLOW}ssh -p $ssh_port pukabyte@$public_ip${NC}"
log "${GREEN}=== END CONNECTION INFO ===${NC}"
else
log "${RED}Warning: Could not determine public IP address${NC}"
log "${YELLOW}You may need to manually find the public IP and provide it to puks the pirate${NC}"
fi
}
# Main execution
main() {
log "${GREEN}Starting user setup for $USERNAME${NC}"
# Check if running as root
check_root
# Check if user exists
if ! check_user_exists; then
# Create user
create_user
fi
# Add user to groups
add_to_groups
# Setup SSH directory
setup_ssh_directory
# Setup SSH keys
setup_ssh_keys
# Configure sudo access
configure_sudo
# Verify setup
verify_setup
log "${GREEN}Setup completed successfully!${NC}"
log "${GREEN}User $USERNAME can now:${NC}"
log " - SSH into the system using their GitHub SSH keys"
log " - Use sudo without password"
log " - Use Docker commands"
log ""
# Output connection information
output_connection_info
log "${YELLOW}Note: You may need to restart the SSH service or reboot for all changes to take effect.${NC}"
}
# Run main function
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment