Organize a Git Repository Structure for Scripts
In this post, I’ll share my way to organize a Git repository for Bash, MikroTik, FortiGate, and other scripts, based on the real-world needs I faced while managing multiple systems and configurations.
Over time, I’ve accumulated a large collection of scripts: Bash automation tools, MikroTik router configs, FortiGate CLI triggers, Docker projects, and Ansible playbooks. At first, they were scattered across multiple servers and folders — each one a bit different, hard to track, and easy to lose.
Eventually, I realized I needed a better way to manage all of this. That’s where Git came in.
This post shares the structure I’m using to organize everything in one Git repository — not as a universal standard, but as a proven method that works for my workflow.
Why I Started Using Git
When working across multiple servers, it’s easy to fall into the trap of:
- Copying files manually
- Forgetting which version is where
- Breaking something and not knowing how to undo it
These were exactly the kinds of problems I ran into. Git helped me:
- Maintain consistent versions of scripts across machines
- Track changes over time
- Experiment with changes without fear of breaking something
- Keep everything organized in one central place
Even if you’re working solo, Git is an invaluable tool for keeping your infrastructure scripts under control.
Benefits of Using Git for Scripts and Automation
Here’s why using Git for managing Bash scripts, network automation, and infrastructure configs is a game-changer:
- Version control: Easily revert to working versions when something breaks
- Centralization: All your scripts live in one place
- Change history: Know what changed, when, and why
- Multi-environment use: Clone the repo to staging, production, and lab systems
- Safe experimentation: Use Git branches to try new ideas
- Portability and backup: Sync with GitHub, GitLab, or your own private Git server
How I Organized My Git Repository
I grouped my scripts and configs into folders by technology and purpose. This makes it easier to find what I need, avoid duplication, and manage things long-term.
Here’s the structure I use:
my-scripts/
│
├── mikrotik/
│ ├── config_backup.sh
│ ├── firewall_reset.sh
│ └── snmp_setup.sh
│
├── fortigate/
│ ├── backup_config.sh
│ ├── get_routing_table.sh
│ └── apply_policy_via_ssh.sh
│
├── linux/
│ ├── backup/
│ │ ├── db_backup.sh
│ │ ├── rsync_home.sh
│ │ └── logrotate_setup.sh
│ ├── monitoring/
│ │ ├── cpu_temp_check.sh
│ │ ├── disk_space_alert.sh
│ │ └── uptime_report.sh
│ ├── network/
│ │ ├── ddos_blocker.sh
│ │ ├── ip_blocker.sh
│ │ └── ping_sweep.sh
│ └── misc/
│ ├── repeat_command.sh
│ ├── clean_tmp_files.sh
│ └── update_all.sh
│
├── docker/
│ ├── wordpress_rpi4/
│ │ ├── docker-compose.yml
│ │ ├── .env
│ │ └── README.md
│ ├── ddos_proxy/
│ │ ├── Dockerfile
│ │ ├── nginx.conf
│ │ └── README.md
│ └── portainer_stack/
│ ├── docker-compose.yml
│ └── README.md
│
├── ansible/
│ ├── inventories/
│ │ ├── production/
│ │ │ └── hosts
│ │ └── staging/
│ │ └── hosts
│ ├── playbooks/
│ │ ├── fortigate_backup.yml
│ │ ├── deploy_monitoring.yml
│ │ └── update_packages.yml
│ ├── roles/
│ │ ├── common/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── handlers/
│ │ │ └── main.yml
│ │ └── nginx/
│ │ └── tasks/
│ │ └── install.yml
│ └── group_vars/
│ └── all.yml
│
├── shared_libs/
│ ├── logging.sh # Unified logging for all scripts
│ ├── common_functions.sh # General-purpose functions
│ ├── error_handler.sh # Trap and exit handling
│ └── ssh_wrapper.sh # Wrapper for SSH-based scripts
│
└── README.md
Explanation of Each Folder
mikrotik/
Scripts for interacting with MikroTik routers – backups, SNMP setup, firewall rules, etc.
fortigate/
Automating FortiGate tasks from Linux: triggering backups, pulling config, checking routes.
linux/
A variety of Bash scripts:
backup/
: rsync, database backups, log rotationmonitoring/
: CPU temperature, uptime, disk spacenetwork/
: ping sweepers, IP blockingmisc/
: general-purpose utilities
docker/
Each subfolder is its own project:
- WordPress on Raspberry Pi
- Proxy server for DDoS protection
- Any other containerized tools
ansible/
Structured for real automation:
inventories/
for different environmentsplaybooks/
for specific tasksroles/
for reusable logic
shared_libs/
Contains shared shell functions (e.g., logging, error handling) used across multiple scripts
Conclusion
Having a well-organized Git repository has made managing my infrastructure tools and scripts much easier. It helps me avoid duplication, work safely, and track everything in one place.
This structure isn’t carved in stone — it grows and evolves as my work does. But since adopting Git and organizing things this way, I’ve had far fewer problems and a lot more confidence in my automation.
If you’ve been dealing with scattered scripts or repeated errors from inconsistent versions, I highly recommend setting up a Git repository like this. You don’t need to know everything to get started — just begin organizing and commit as you go.