# File Deployment & GitOps Management A simple, generic Ansible-based system to deploy and manage files on multiple servers using Git as the single source of truth. --- ## Overview This repository uses **Ansible** to: - **Deploy** files from Git to target servers - **Check Drift** to ensure servers stay in sync with the repository - **Validate** that deployed files are correct No rsyslog-specific code. Just simple file deployment that works for any file or service. --- ## Project Structure ``` . ├── README.md # This file ├── ansible.cfg # Ansible configuration ├── .woodpecker.yml # CI/CD pipeline configuration │ ├── ansible/ │ ├── inventory/ │ │ ├── hosts.yml # Define target servers │ │ └── group_vars/ │ │ └── all.yml # Global variables (SSH credentials, etc.) │ │ │ └── playbooks/ │ ├── apply.yml # Deploy file to servers │ ├── drift-check.yml # Check if servers are in sync with repo │ └── validate.yml # Verify file exists on server │ └── files/ └── dvir.txt # The file to deploy (edit this to your needs) ``` --- ## How It Works (Simple Version) 1. **You edit the file** in `files/dvir.txt` 2. **You commit to Git** (the source of truth) 3. **Run `apply.yml`** to deploy to all servers 4. **Run `drift-check.yml`** anytime to verify servers match Git 5. **If drift is detected**, run `apply.yml` again to fix it That's it! --- ## Quick Start ### 1. Edit the file you want to deploy Open `files/dvir.txt` and add your content: ```bash nano files/dvir.txt ``` To deploy a **different file**, rename it or update the paths in the playbooks. ### 2. Add target servers Edit `ansible/inventory/hosts.yml`: ```yaml all: children: servers: hosts: server1: ansible_host: 192.168.10.161 server2: ansible_host: 192.168.10.162 ``` ### 3. Run the playbooks #### Deploy the file: ```bash ansible-playbook ansible/playbooks/apply.yml ``` #### Check if servers are in sync: ```bash ansible-playbook ansible/playbooks/drift-check.yml ``` #### Validate file on server: ```bash ansible-playbook ansible/playbooks/validate.yml ``` --- ## Playbook Breakdown ### `apply.yml` - Deploy Files **What it does:** - Copies `files/dvir.txt` to `/tmp/dvir.txt` on all target servers - Sets file ownership to `root:root` with permissions `0644` **When to use:** - Initial deployment of the file - After updating the file in Git **Example:** ```bash ansible-playbook ansible/playbooks/apply.yml ``` --- ### `drift-check.yml` - Detect Configuration Drift **What it does:** - Reads the file from the Git repository (local) - Reads the file from each target server (`/tmp/dvir.txt`) - Compares the content byte-for-byte - Reports `SYNCED` or `OUT_OF_SYNC` **When to use:** - Verify servers match the repository state - Detect if someone manually changed the file on the server - Run periodically (via cron or CI/CD) to monitor compliance **Example:** ```bash ansible-playbook ansible/playbooks/drift-check.yml ``` **Output:** ``` ✓ dvir.txt is synced # Files match ✗ dvir.txt is out of sync # Files differ or file missing ``` --- ### `validate.yml` - Validate Deployment **What it does:** - Checks that `/tmp/dvir.txt` exists on the server - Verifies the file is readable - Fails if the file is missing or not readable **When to use:** - After running `apply.yml` to verify success - To confirm the deployment was successful **Example:** ```bash ansible-playbook ansible/playbooks/validate.yml ``` --- ## Configuration ### Inventory: `ansible/inventory/hosts.yml` Define which servers to manage: ```yaml all: children: servers: hosts: server1: ansible_host: 192.168.10.161 server2: ansible_host: 192.168.10.162 ``` ### Global Variables: `ansible/inventory/group_vars/all.yml` SSH and connection settings: ```yaml ansible_user: root ansible_ssh_private_key_file: "~/.ssh/id_rsa" ansible_ssh_common_args: "-o StrictHostKeyChecking=no" ``` ### Ansible Config: `ansible.cfg` Global Ansible settings (host checking, plugins, etc.) --- ## Workflow Examples ### Example 1: Deploy a new file ```bash # 1. Edit the file echo "new config content" > files/dvir.txt # 2. Commit to Git git add files/dvir.txt git commit -m "Update deployment file" git push # 3. Deploy to servers ansible-playbook ansible/playbooks/apply.yml # 4. Verify success ansible-playbook ansible/playbooks/validate.yml ``` ### Example 2: Monitor for drift (continuous compliance) ```bash # Run drift check periodically (cron job) 0 */6 * * * cd /path/to/repo && ansible-playbook ansible/playbooks/drift-check.yml ``` ### Example 3: Detect and fix manual changes ```bash # Someone manually edited /tmp/dvir.txt on server1 # Check for drift ansible-playbook ansible/playbooks/drift-check.yml # Output: ✗ dvir.txt is out of sync # Restore from Git ansible-playbook ansible/playbooks/apply.yml # Verify it's fixed ansible-playbook ansible/playbooks/drift-check.yml # Output: ✓ dvir.txt is synced ``` --- ## Prerequisites - **Ansible** installed on your machine - **SSH access** to all target servers (password or key-based) - **Root or sudo access** on target servers (for writing to `/tmp`) ### Install Ansible ```bash # macOS brew install ansible # Ubuntu/Debian apt-get install ansible # RHEL/CentOS yum install ansible # Python pip pip install ansible ``` --- ## Customization ### Deploy to a different path Edit `ansible/playbooks/apply.yml`: ```yaml - name: Copy file to destination copy: src: ../../files/dvir.txt dest: /your/custom/path/filename.txt # ← Change this owner: root group: root mode: "0644" ``` ### Deploy multiple files Add more tasks to `apply.yml`: ```yaml - name: Copy file 1 copy: src: ../../files/dvir.txt dest: /tmp/dvir.txt - name: Copy file 2 copy: src: ../../files/another.txt dest: /tmp/another.txt ``` ### Use different target servers Edit `hosts.yml` and use: ```bash ansible-playbook ansible/playbooks/apply.yml -i ansible/inventory/hosts.yml --limit "server2" ``` --- ## Troubleshooting ### "SSH connection refused" - Check `ansible_host` is correct in `hosts.yml` - Verify SSH key in `group_vars/all.yml` - Test manually: `ssh -i ~/.ssh/id_rsa root@192.168.10.161` ### "Permission denied" on deployment - Ensure `become: true` is in the playbook - Verify user has sudo access - Check SSH key has correct permissions: `chmod 600 ~/.ssh/id_rsa` ### Drift check shows "out of sync" but I didn't change anything - File permissions or ownership might have changed - Line endings (CRLF vs LF) might differ - The server file might be missing ### Can't read file on server - Check `/tmp/dvir.txt` exists: `ls -la /tmp/dvir.txt` - Verify permissions: `stat /tmp/dvir.txt` - Ensure file is readable: `cat /tmp/dvir.txt` --- ## Tips & Best Practices 1. **Always commit before deploying** - Use Git as the single source of truth - Never manually edit `/tmp/dvir.txt` on servers 2. **Run drift-check regularly** - Use cron or CI/CD to monitor compliance - Alert on `OUT_OF_SYNC` status 3. **Test in dev first** - Add a `dev` group in `hosts.yml` - Test playbooks on dev servers before prod 4. **Use version control for everything** - Keep all changes in Git - Easy rollback: just revert and re-run `apply.yml` --- ## License MIT (or your preferred license)