# Setting Up Ansible with Tailscale for Remote Server Management ## Overview This guide walks you through setting up Ansible to manage remote servers (like ThinkCentre units) using Tailscale for secure networking. This approach provides reliable remote access without complex port forwarding or VPN configurations. In plainer language; this allows you to manage several Changemaker nodes remotely. If you are a full time campaigner, this can enable you to manage several campaigns infrastructure from a central location while each user gets their own Changemaker box. ## What You'll Learn - How to set up Ansible for infrastructure automation - How to configure secure remote access using Tailscale - How to troubleshoot common SSH and networking issues - Why this approach is better than alternatives like Cloudflare Tunnels for simple SSH access ## Prerequisites - **Master Node**: Your main computer running Ubuntu/Linux (control machine) - **Target Nodes**: Remote servers/ThinkCentres running Ubuntu/Linux - **Both machines**: Must have internet access - **User Account**: Same username on all machines (recommended) ## Part 1: Initial Setup on Master Node ### 1. Create Ansible Directory Structure ```bash # Create project directory mkdir ~/ansible_quickstart cd ~/ansible_quickstart # Create directory structure mkdir -p group_vars host_vars roles playbooks ``` ### 2. Install Ansible ```bash sudo apt update sudo apt install ansible ``` ### 3. Generate SSH Keys (if not already done) ```bash # Generate SSH key pair ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa # Display public key (save this for later) cat ~/.ssh/id_rsa.pub ``` ## Part 2: Target Node Setup (Physical Access Required Initially) ### 1. Enable SSH on Target Node Access each target node physically (monitor + keyboard): ```bash # Update system sudo apt update && sudo apt upgrade -y # Install and enable SSH sudo apt install openssh-server sudo systemctl enable ssh sudo systemctl start ssh # Check SSH status sudo systemctl status ssh ``` **Note**: If you get "Unit ssh.service could not be found", you need to install the SSH server first: ```bash # Install OpenSSH server sudo apt install openssh-server # Then start and enable SSH sudo systemctl start ssh sudo systemctl enable ssh # Verify SSH is running and listening sudo ss -tlnp | grep :22 ``` You should see SSH listening on port 22. ### 2. Configure SSH Key Authentication ```bash # Create .ssh directory mkdir -p ~/.ssh chmod 700 ~/.ssh # Create authorized_keys file nano ~/.ssh/authorized_keys ``` Paste your public key from the master node, then: ```bash # Set proper permissions chmod 600 ~/.ssh/authorized_keys ``` ### 3. Configure SSH Security ```bash # Edit SSH config sudo nano /etc/ssh/sshd_config ``` Ensure these lines are uncommented: ``` PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 ``` ```bash # Restart SSH service sudo systemctl restart ssh ``` ### 4. Configure Firewall ```bash # Check firewall status sudo ufw status # Allow SSH through firewall sudo ufw allow ssh # Fix home directory permissions (required for SSH keys) chmod 755 ~/ ``` ## Part 3: Test Local SSH Connection Before proceeding with remote access, test SSH connectivity locally: ```bash # From master node, test SSH to target ssh username@ ``` **Common Issues and Solutions:** - **Connection hangs**: Check firewall rules (`sudo ufw allow ssh`) - **Permission denied**: Verify SSH keys and file permissions - **SSH config errors**: Ensure `PubkeyAuthentication yes` is set ## Part 4: Set Up Tailscale for Remote Access ### Why Tailscale Over Alternatives We initially tried Cloudflare Tunnels but encountered complexity with: - DNS routing issues - Complex configuration for SSH - Same-network testing problems - Multiple configuration approaches with varying success **Tailscale is superior because:** - Zero configuration mesh networking - Works from any network - Persistent IP addresses - No port forwarding needed - Free for personal use ### 1. Install Tailscale on Master Node ```bash # Install Tailscale curl -fsSL https://tailscale.com/install.sh | sh # Connect to Tailscale network sudo tailscale up ``` Follow the authentication URL to connect with your Google/Microsoft/GitHub account. ### 2. Install Tailscale on Target Nodes **On each target node:** ```bash # Install Tailscale curl -fsSL https://tailscale.com/install.sh | sh # Connect to Tailscale network sudo tailscale up ``` Authenticate each device through the provided URL. ### 3. Get Tailscale IP Addresses **On each machine:** ```bash # Get your Tailscale IP tailscale ip -4 ``` Each device receives a persistent IP like `100.x.x.x`. ## Part 5: Configure Ansible ### 1. Create Inventory File ```bash # Create inventory.ini cd ~/ansible_quickstart nano inventory.ini ``` **Content:** ```ini [thinkcenter] tc-node1 ansible_host=100.x.x.x ansible_user=your-username tc-node2 ansible_host=100.x.x.x ansible_user=your-username [all:vars] ansible_ssh_private_key_file=~/.ssh/id_rsa ansible_host_key_checking=False ``` Replace: - `100.x.x.x` with actual Tailscale IPs - `your-username` with your actual username ### 2. Test Ansible Connectivity ```bash # Test connection to all nodes ansible all -i inventory.ini -m ping ``` **Expected output:** ``` tc-node1 | SUCCESS => { "changed": false, "ping": "pong" } ``` ## Part 6: Create and Run Playbooks ### 1. Simple Information Gathering Playbook ```bash mkdir -p playbooks nano playbooks/info-playbook.yml ``` **Content:** ```yaml --- - name: Gather Node Information hosts: all tasks: - name: Get system information setup: - name: Display basic system info debug: msg: | Hostname: {{ ansible_hostname }} Operating System: {{ ansible_distribution }} {{ ansible_distribution_version }} Architecture: {{ ansible_architecture }} Memory: {{ ansible_memtotal_mb }}MB CPU Cores: {{ ansible_processor_vcpus }} - name: Show disk usage command: df -h / register: disk_info - name: Display disk usage debug: msg: "Root filesystem usage: {{ disk_info.stdout_lines[1] }}" - name: Check uptime command: uptime register: uptime_info - name: Display uptime debug: msg: "System uptime: {{ uptime_info.stdout }}" ``` ### 2. Run the Playbook ```bash ansible-playbook -i inventory.ini playbooks/info-playbook.yml ``` ## Part 7: Advanced Playbook Example ### System Setup Playbook ```bash nano playbooks/setup-node.yml ``` **Content:** ```yaml --- - name: Setup ThinkCentre Node hosts: all become: yes tasks: - name: Update package cache apt: update_cache: yes - name: Install essential packages package: name: - htop - vim - curl - git - docker.io state: present - name: Add user to docker group user: name: "{{ ansible_user }}" groups: docker append: yes - name: Create management directory file: path: /opt/management state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" ``` ## Troubleshooting Guide ### SSH Issues **Problem: SSH connection hangs** - Check firewall: `sudo ufw status` and `sudo ufw allow ssh` - Verify SSH service: `sudo systemctl status ssh` - Test local connectivity first **Problem: Permission denied (publickey)** - Check SSH key permissions: `chmod 600 ~/.ssh/authorized_keys` - Verify home directory permissions: `chmod 755 ~/` - Ensure SSH config allows key auth: `PubkeyAuthentication yes` **Problem: Bad owner or permissions on SSH config** ```bash chmod 600 ~/.ssh/config ``` ### Ansible Issues **Problem: Host key verification failed** - Add to inventory: `ansible_host_key_checking=False` **Problem: Ansible command not found** ```bash sudo apt install ansible ``` **Problem: Connection timeouts** - Verify Tailscale connectivity: `ping ` - Check if both nodes are connected: `tailscale status` ### Tailscale Issues **Problem: Can't connect to Tailscale IP** - Verify both devices are authenticated: `tailscale status` - Check Tailscale is running: `sudo systemctl status tailscaled` - Restart Tailscale: `sudo tailscale up` ## Scaling to Multiple Nodes ### Adding New Nodes 1. **Install Tailscale on new node** 2. **Set up SSH access** (repeat Part 2) 3. **Add to inventory.ini:** ```ini [thinkcenter] tc-node1 ansible_host=100.125.148.60 ansible_user=bunker-admin tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin ``` ### Group Management ```ini [webservers] tc-node1 ansible_host=100.x.x.x ansible_user=bunker-admin tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin [databases] tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin [all:vars] ansible_ssh_private_key_file=~/.ssh/id_rsa ansible_host_key_checking=False ``` Run playbooks on specific groups: ```bash ansible-playbook -i inventory.ini -l webservers playbook.yml ``` ## Best Practices ### Security - Use SSH keys, not passwords - Keep Tailscale client updated - Regular security updates via Ansible - Use `become: yes` only when necessary ### Organization ``` ansible_quickstart/ ├── inventory.ini ├── group_vars/ ├── host_vars/ ├── roles/ └── playbooks/ ├── info-playbook.yml ├── setup-node.yml └── maintenance.yml ``` ### Monitoring and Maintenance Create regular maintenance playbooks: ```yaml - name: System maintenance hosts: all become: yes tasks: - name: Update all packages apt: upgrade: dist update_cache: yes - name: Clean package cache apt: autoclean: yes autoremove: yes ``` ## Alternative Approaches We Considered ### Cloudflare Tunnels - **Pros**: Good for web services, handles NAT traversal - **Cons**: Complex SSH setup, DNS routing issues, same-network problems - **Use case**: Better for web applications than SSH access ### Traditional VPN - **Pros**: Full network access - **Cons**: Complex setup, port forwarding required, router configuration - **Use case**: When you control the network infrastructure ### SSH Reverse Tunnels - **Pros**: Simple concept - **Cons**: Requires VPS, single point of failure, manual setup - **Use case**: Temporary access or when other methods fail ## Conclusion This setup provides: - **Reliable remote access** from anywhere - **Secure mesh networking** with Tailscale - **Infrastructure automation** with Ansible - **Easy scaling** to multiple nodes - **No complex networking** required The combination of Ansible + Tailscale is ideal for managing distributed infrastructure without the complexity of traditional VPN setups or the limitations of cloud-specific solutions. ## Quick Reference Commands ```bash # Check Tailscale status tailscale status # Test Ansible connectivity ansible all -i inventory.ini -m ping # Run playbook on all hosts ansible-playbook -i inventory.ini playbook.yml # Run playbook on specific group ansible-playbook -i inventory.ini -l groupname playbook.yml # Run single command on all hosts ansible all -i inventory.ini -m command -a "uptime" # SSH to node via Tailscale ssh username@100.x.x.x ```