This guide is for sysadmins, MSP technicians and small DevOps teams who want changes to servers and software to go through code instead of remote-desktop sessions and memory. It covers the path from a Git repository to a release you can roll back.
The short answer: keep everything in Git (GitHub, GitLab or a self-hosted Gitea), run checks and deployments from a CI/CD system (GitHub Actions, GitLab CI or Jenkins), create machines and cloud resources with Terraform or OpenTofu, and configure them with Ansible. On Windows, Chocolatey handles software, and Vagrant gives everyone the same test VM.
The short list
| Tool | Best for | Licence | Platforms | Status |
|---|---|---|---|---|
| Ansible | Agentless configuration management and scripted deployments | Free, open source (GPL-3.0) | Control node: Linux, macOS, WSL; manages Linux, Windows, network devices | Active; ansible 14.4.0 / ansible-core 2.21.4 (September 2026) |
| Chocolatey | Windows software installs, build agents, internal package feeds | Free, open source (Apache 2.0) CLI; business editions sold separately | Windows | Active; CLI 2.7.4 (August 2026) |
| Vagrant | Reproducible test and onboarding VMs | Free, source-available (BSL 1.1) | Windows, macOS, Linux | Maintained; last stable 2.4.9 (August 2025); public box registry closes end of 2026 |
| Power Automate for desktop | GUI-only steps in legacy Windows apps | Shareware (conditionally free) | Windows 10/11, Windows Server | Active; monthly builds (2609, September 2026) |
| Jenkins | Self-hosted CI/CD with a large plugin ecosystem | Free, open source (MIT) | Java; Windows, Linux, macOS, Docker, Kubernetes | Active; weekly and LTS release lines |
| GitHub Actions | CI/CD for repositories hosted on GitHub | Shareware (conditionally free) | Hosted service; self-hosted runners on Linux, Windows, macOS | Active |
| GitLab CI/CD | Pipelines built into GitLab, self-managed or GitLab.com | Community Edition free, open source (MIT); paid tiers shareware (conditionally free) | Self-managed server on Linux or Docker; runners on Linux, Windows, macOS | Active |
| Terraform | Infrastructure as code for clouds and hypervisors | Free, source-available (BSL 1.1) | Windows, macOS, Linux | Active (HashiCorp, an IBM company) |
| OpenTofu | Open-source, drop-in Terraform replacement | Free, open source (MPL-2.0) | Windows, macOS, Linux | Active; Linux Foundation project |
| Gitea | Self-hosted Git, code review, CI (Gitea Actions) and package registry | Free, open source (MIT); Enterprise and Cloud editions sold separately | Linux, Windows, macOS, FreeBSD; x86 and arm64 | Active |
| OpenAPI / Swagger UI | Describing and publishing API documentation | Free, open (Apache 2.0) | Specification plus a browser-based viewer; Docker image | Active; OpenAPI 3.2.1 (September 2026) |
Build a CI/CD pipeline that checks every change
A pipeline rejects broken changes before they merge and deploys approved ones the same way every time. The engine mostly follows where your code lives.
- GitHub Actions if the repository is on GitHub. Workflows are YAML files in
.github/workflows/. Hosted runners are free for public repositories, private ones get a monthly quota, and self-hosted runners can reach servers inside your network. - GitLab CI/CD if you run GitLab. The pipeline lives in
.gitlab-ci.yml, and the free tier includes CI/CD both on GitLab.com and self-managed, where you bring your own runners. - Jenkins when you need to run everything on your own hardware, integrate with odd internal systems, or already have years of jobs in it. Keep pipelines in a
Jenkinsfilein the repository and use the LTS line in production. - Gitea Actions if you self-host Gitea. It is built in since Gitea 1.19, uses a separate Gitea Runner, and is closely compatible with GitHub Actions syntax, so many existing actions work unchanged.
A first useful pipeline for an infrastructure repository only validates; deployment comes later. In GitHub Actions:
name: validate
on: [pull_request]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python3 -m pip install ansible
- run: ansible-playbook -i inventory.ini site.yml --syntax-check
- uses: hashicorp/setup-terraform@v3
- run: terraform fmt -check -recursive
- run: terraform init -backend=false && terraform validateMake this check required in branch protection.
Automate builds and keep build agents identical
Most “works on my machine” failures are differences between build agents, so treat the agent as code. On Windows agents, keep the toolchain in a Chocolatey packages.config file and install it with choco install C:buildpackages.config -y; pin versions the build depends on with choco pin add -n=<package> so a nightly choco upgrade all does not change a compiler under you. On Linux agents, an Ansible role that installs the SDKs does the same job.
For a disposable build or packaging VM, a Vagrantfile describes the machine and vagrant up recreates it from scratch. Build an artifact once and promote the same file through test and production, and keep build logic in scripts in the repository so it runs the same locally and in the pipeline.
Manage configuration across Windows and Linux servers
Configuration management means describing the desired state of a server (packages, services, files, users, scheduled tasks) and letting a tool enforce it. Ansible is the practical default for mixed fleets: it is agentless, talks SSH to Linux and WinRM or SSH to Windows, and its playbooks are idempotent, so running them twice changes nothing the second time. The control node must be Linux, macOS or WSL; there is no native Windows control node, so a small Linux VM is the usual answer.
On Windows hosts, Ansible and Chocolatey work together: the win_chocolatey module installs packages from your internal feed, while Ansible handles services, registry settings, features and Windows updates. Before any real run, ansible-playbook site.yml --check --diff shows what would change. Keep passwords in Ansible Vault (ansible-vault create group_vars/windows/vault.yml), never in plain inventory files.
Provision infrastructure as code with Terraform or OpenTofu
Ansible configures machines that exist; Terraform and OpenTofu create them: VMs, networks, DNS records, load balancers, cloud accounts. You declare resources in HCL files, terraform plan shows the difference against a state file, and terraform apply makes it real. OpenTofu is a fork created after HashiCorp moved Terraform from MPL 2.0 to the Business Source License in August 2023; it stays open source under the Linux Foundation, uses the tofu command, and is meant as a drop-in replacement.
Practical rules: store state remotely with locking, never in Git; run plan in the pipeline and post the output to the pull request; run apply only from the pipeline, from the main branch. Providers exist for the major clouds and for on-premises hypervisors such as Proxmox VE; see our virtualization and container tools guide for the hypervisor side.
Turn deployment checklists into playbooks
A deployment checklist in a wiki is a playbook waiting to be written. Each manual step (drain a node, copy files, restart a service, check health, move on) maps to a task, and Ansible’s serial keyword gives you a rolling deployment that stops at the first failure:
- name: Rolling deploy of the web app
hosts: web
serial: 2
max_fail_percentage: 0
become: true
tasks:
- name: Unpack the release
ansible.builtin.unarchive:
src: "releases/app-{{ app_version }}.tar.gz"
dest: /opt/app
- name: Restart the service
ansible.builtin.systemd:
name: app
state: restarted
- name: Wait until the health check passes
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:8080/health"
status_code: 200
register: health
retries: 10
delay: 6
until: health.status == 200Try it with ansible-playbook deploy.yml -e app_version=1.4.2 --limit web01 first. Keep a human checklist only for what cannot be automated, such as approvals and watching dashboards afterwards (our monitoring and log management guide covers that part).
Some legacy Windows applications have no API or command line at all, only a GUI. For those steps, Power Automate for desktop can record and replay the clicks. It is shareware (conditionally free): attended runs on your own machine come with Windows 10 and 11, while unattended runs and cloud triggers need a paid plan. It breaks when the layout changes, so use it as a last resort.
Manage releases and rollbacks
Release management for a small team comes down to a few habits. Tag every release in Git with a version number, generate the changelog from merged pull requests, and let the pipeline build the artifact from the tag. Use environment gates for production: GitHub environments with required reviewers, GitLab protected environments, or an input step in a Jenkins pipeline. A rollback should be the same deployment with the previous version (-e app_version=1.4.1), not a separate emergency procedure nobody has tested.
For Windows desktop software, the release is a package version in the internal Chocolatey feed: roll it to a pilot group first; if it goes wrong, reinstall the previous version and pin it.
Host and manage repositories
If code cannot leave your network or you want no per-user service at all, self-host. Gitea is a single binary that runs on Linux, Windows, macOS or FreeBSD with SQLite, MySQL, PostgreSQL or MS SQL, and bundles Git hosting, pull requests, issues, Gitea Actions and a package registry for more than 20 formats, including containers, npm, PyPI, Maven and Helm. Whatever you host, protect the main branch, require reviews and passing checks, and back up the repositories and database (our backup and server hardening guide covers how).
Point Chocolatey at an internal feed and disable the public source for managed machines. HashiCorp is shutting down HCP Vagrant, the public box registry, with no new boxes from 1 October 2026 and full decommissioning on 31 December 2026. Package the boxes you rely on with vagrant package and serve them from an internal web server.
Review code and infrastructure changes
Code review tools are built into every platform above: pull requests in GitHub and Gitea, merge requests in GitLab. Require at least one approval for the main branch, use a CODEOWNERS file on GitHub or GitLab so the network team must approve firewall changes.
For infrastructure, reviewers should see the effect, not only the diff. Post terraform plan output to the pull request and attach ansible-playbook --check --diff output for configuration changes. Reject secrets in clear text; they belong in Ansible Vault or the CI secret store.
Document APIs with OpenAPI and Swagger
If your team builds or consumes internal APIs, describe them in an OpenAPI file (YAML or JSON) kept in the same repository as the service. The OpenAPI Specification is published by the OpenAPI Initiative under the Linux Foundation, and Swagger UI renders the file as interactive documentation where people can try requests. To preview it locally:
docker run -p 8080:8080 -e SWAGGER_JSON=/spec/openapi.yaml -v "$PWD":/spec swaggerapi/swagger-uiPublish the rendered docs from the pipeline so they match the deployed version.
Onboard new engineers in a day, not a week
A new team member should be able to clone one repository and run a few commands: choco install packages.config -y for their Windows tools, vagrant up for a working lab that matches production, plus read access to the playbooks.
Give them a shared connection file for mRemoteNG so they do not collect server names by hand, and WinSCP for the occasional file transfer to servers that are not automated yet. Create their accounts with an Ansible role rather than by hand, so leaving is as clean as joining. For test environments and QA automation, continue with our software testing and QA tools guide.
How to choose
- Start with Git. If your code is already on GitHub or GitLab, stay there. If it must stay on-premises and the team is small, Gitea is the lightest option.
- Use the CI/CD built into that platform. Add Jenkins only if you need something the built-in engine cannot do, or you already run it.
- Automate the most frequent manual change first, usually patching or software installs: Ansible for servers, Chocolatey for Windows software.
- Add Terraform or OpenTofu when you create infrastructure often, not before. Choose OpenTofu if an OSI open-source licence matters to you; the workflows are the same.
- Give everyone a reproducible test environment with Vagrant, and host your own boxes.
- Keep GUI automation for the gaps where no API exists, and plan to replace it.
FAQ
What is the difference between Ansible and Terraform?
Terraform (or OpenTofu) creates and destroys infrastructure and tracks it in a state file. Ansible configures what runs on machines: packages, services, files, users. Most teams use Terraform to create a VM and Ansible to configure it.
Is Terraform still free, and should I switch to OpenTofu?
Terraform is free to use under the Business Source License 1.1, including internal production use; it is source-available, not OSI open source. OpenTofu is the open-source fork under MPL-2.0 and aims to be a drop-in replacement. Switch if licence terms matter to you or your customers; otherwise either works.
What is the best free CI/CD tool for a small team?
The one built into your Git platform: GitHub Actions, GitLab CI/CD or Gitea Actions. Jenkins is free and very flexible but needs a server, plugin updates and more care.
Can I run Ansible on Windows?
Ansible manages Windows hosts well over WinRM or SSH, but the control node cannot run natively on Windows. Use WSL for learning and a small Linux VM for real work.
What happens to Vagrant after the HCP Vagrant shutdown?
The Vagrant tool stays available and free. Only the public box registry is closing: no new boxes from 1 October 2026, decommissioned on 31 December 2026. Host the boxes you depend on yourself.
Last updated: 30 September 2026 · ITForgePro editorial team. Licence, version and platform details are checked against each developer's official documentation.





