<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>install &#8211; Best DevOps</title>
	<atom:link href="https://www.bestdevops.com/tag/install/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bestdevops.com</link>
	<description>Lets Learn, Do it &#38; Share! Thats a Best DevOps!!!</description>
	<lastBuildDate>Tue, 13 Oct 2026 18:24:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>
	<item>
		<title>Kubernetes Without Scale: Setting Up a Personal Cluster on a Single EC2 Instance (Part 2)</title>
		<link>https://www.bestdevops.com/kubernetes-without-scale-setting-up-a-personal-cluster-part-2/</link>
					<comments>https://www.bestdevops.com/kubernetes-without-scale-setting-up-a-personal-cluster-part-2/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Fri, 25 Oct 2019 06:51:26 +0000</pubDate>
				<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[IT applications]]></category>
		<category><![CDATA[kubernete]]]></category>
		<category><![CDATA[repository]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=8856</guid>

					<description><![CDATA[Learn how to run a personal Kubernetes cluster on a single AWS EC2 t2.small instance using KIND, kubectl, Helm, cert-manager, and nginx-ingress — then deploy HackMD as a real-world example.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">This is Part 2 of a series on running Kubernetes at personal scale. In Part 1, we covered the rationale: Kubernetes is worth running even for low-traffic, single-user workloads because it makes installing third-party apps as simple as <code>helm install</code> and gives you strong infrastructure-as-code foundations. Here we walk through the full setup — from launching an EC2 instance to deploying a real application.</p>



<p class="wp-block-paragraph">Our target environment is a single <strong>t2.small</strong> EC2 instance (2 GB RAM, 1 vCPU, ~$15/month) running Ubuntu 18.04. We will use <a href="https://kind.sigs.k8s.io/">KIND (Kubernetes IN Docker)</a> to run the cluster, add <strong>cert-manager</strong> and <strong>nginx-ingress</strong> for TLS and routing, and finish by deploying <strong>HackMD</strong> — an open-source collaborative Markdown editor — as a proof of concept.</p>



<h2 class="wp-block-heading">Set Up a Machine</h2>



<p class="wp-block-paragraph">These instructions target AWS EC2, but the same approach works on any cloud provider or bare-metal host that can run Docker.</p>



<h3 class="wp-block-heading">Launch the Instance</h3>



<ol class="wp-block-list">
<li>Open the <strong>EC2 console</strong> and click <em>Launch Instance</em>.</li>
<li>Choose <strong>Ubuntu Server 18.04 LTS</strong> as the AMI.</li>
<li>Select the <strong>t2.small</strong> instance type. Do not go smaller — Kubernetes has significant baseline memory overhead. If you plan to run memory-hungry workloads (databases, CI runners, etc.) consider t2.medium or larger.</li>
<li>Increase the root volume from the default if you intend to store significant data on the node.</li>
<li>In the security group, open <strong>port 22</strong> (SSH), <strong>port 80</strong> (HTTP), and <strong>port 443</strong> (HTTPS).</li>
<li>Download and store your SSH key pair safely.</li>
</ol>



<h3 class="wp-block-heading">Assign an Elastic IP</h3>



<p class="wp-block-paragraph">EC2 instances get a new public IP every time they restart. An Elastic IP gives your instance a stable address that you can map to a DNS name.</p>



<ol class="wp-block-list">
<li>In the EC2 console, go to <em>Elastic IPs</em> → <em>Allocate Elastic IP address</em>.</li>
<li>Associate the new address with your new instance.</li>
</ol>



<h3 class="wp-block-heading">Create DNS Records</h3>



<p class="wp-block-paragraph">Head to <a href="https://console.aws.amazon.com/route53/home">Route 53</a> (or your DNS provider) and create two <strong>A records</strong>:</p>



<ul class="wp-block-list">
<li><code>*.example.com</code> → your Elastic IP (wildcard record covers every subdomain)</li>
<li><code>example.com</code> → your Elastic IP (optional, for the apex domain)</li>
</ul>



<p class="wp-block-paragraph">With DNS in place, every subdomain you configure on the cluster will automatically resolve to your server.</p>



<h2 class="wp-block-heading">Install Dependencies</h2>



<p class="wp-block-paragraph">SSH into your instance, then install the following tools in order.</p>



<h3 class="wp-block-heading">Docker</h3>



<p class="wp-block-paragraph">KIND runs Kubernetes inside Docker containers, so Docker is the foundational dependency.</p>


<pre class="wp-block-code"><span><code class="hljs language-php">sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https:<span class="hljs-comment">//download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</span>
sudo add-apt-repository <span class="hljs-string">"deb &#91;arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"</span>
sudo apt update
sudo apt install -y docker-ce
sudo usermod -aG docker $USER
newgrp docker</code></span></pre>


<h3 class="wp-block-heading">KIND</h3>



<p class="wp-block-paragraph">KIND (Kubernetes IN Docker) creates a fully functional Kubernetes cluster using Docker containers as nodes. This is ideal for a single-machine setup.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">curl -Lo ./kind https:<span class="hljs-comment">//github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-$(uname)-amd64</span>
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind</code></span></pre>


<h3 class="wp-block-heading">kubectl</h3>



<p class="wp-block-paragraph"><code>kubectl</code> is the primary CLI for communicating with any Kubernetes cluster. It reads your kubeconfig to know which cluster to talk to.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">curl -LO <span class="hljs-string">"https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"</span>
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl</code></span></pre>


<h3 class="wp-block-heading">Helm</h3>



<p class="wp-block-paragraph">Helm is the package manager for Kubernetes. Helm charts package up all the manifests needed to deploy an application (WordPress, Ghost, MySQL, GitLab, etc.) into a single, versioned, configurable unit.</p>


<pre class="wp-block-code"><span><code class="hljs">sudo snap install helm --classic</code></span></pre>


<h3 class="wp-block-heading">Reckoner</h3>



<p class="wp-block-paragraph">Reckoner is a Python tool that lets you declare multiple Helm releases in a single YAML file (called a <em>course file</em>), making it easier to manage several charts together with shared configuration and install hooks.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">sudo apt-<span class="hljs-keyword">get</span> install -y python3 python3-pip
export PATH=$PATH:~/.local/bin/
pip3 install reckoner</code></span></pre>


<h3 class="wp-block-heading">Dependency Summary</h3>



<ul class="wp-block-list">
<li><strong>Docker</strong> — runs isolated containers (and hosts the KIND cluster nodes).</li>
<li><strong>KIND</strong> — bootstraps a Kubernetes control plane and worker node inside Docker.</li>
<li><strong>kubectl</strong> — CLI for managing Kubernetes resources.</li>
<li><strong>Helm</strong> — installs and upgrades packaged Kubernetes applications.</li>
<li><strong>Reckoner</strong> — manages multiple Helm charts declaratively from a single YAML file.</li>
</ul>



<h2 class="wp-block-heading">Build the Cluster</h2>



<p class="wp-block-paragraph">Create a file called <code>cluster.yaml</code>. Storing this in version control is strongly recommended — it is a complete description of your cluster topology.</p>



<h3 class="wp-block-heading">cluster.yaml</h3>


<pre class="wp-block-code"><span><code class="hljs language-javascript">kind: Cluster
<span class="hljs-attr">apiVersion</span>: kind.sigs.k8s.io/v1alpha3
<span class="hljs-attr">nodes</span>:
- role: control-plane
- role: worker
  <span class="hljs-attr">extraMounts</span>:
  - containerPath: <span class="hljs-regexp">/opt/</span>local-path-provisioner
    <span class="hljs-attr">hostPath</span>: <span class="hljs-regexp">/home/u</span>buntu/kind-disk
  <span class="hljs-attr">extraPortMappings</span>:
  - containerPort: <span class="hljs-number">80</span>
    <span class="hljs-attr">hostPort</span>: <span class="hljs-number">80</span>
    <span class="hljs-attr">listenAddress</span>: <span class="hljs-string">"0.0.0.0"</span>
  - containerPort: <span class="hljs-number">443</span>
    <span class="hljs-attr">hostPort</span>: <span class="hljs-number">443</span>
    <span class="hljs-attr">listenAddress</span>: <span class="hljs-string">"0.0.0.0"</span></code></span></pre>


<p class="wp-block-paragraph">Key decisions in this config:</p>



<ul class="wp-block-list">
<li><strong>Two roles</strong> — a <code>control-plane</code> node runs the Kubernetes API server, scheduler, and controller manager; the <code>worker</code> node runs your application pods.</li>
<li><strong>Persistent storage mount</strong> — <code>/home/ubuntu/kind-disk</code> on the host is mounted into the worker container so database volumes survive pod restarts. Adjust this path to suit your environment.</li>
<li><strong>Port mappings</strong> — ports 80 and 443 are forwarded from the host into the worker container so external HTTP/HTTPS traffic reaches the cluster.</li>
</ul>



<p class="wp-block-paragraph">Create the cluster and point <code>kubectl</code> at it:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">kind create cluster --config cluster.yaml
<span class="hljs-keyword">export</span> KUBECONFIG=<span class="hljs-string">"$(kind get kubeconfig-path --name='kind')"</span></code></span></pre>


<p class="wp-block-paragraph">Verify both nodes are ready (this can take a minute or two):</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">kubectl <span class="hljs-keyword">get</span> nodes</code></span></pre>


<p class="wp-block-paragraph">Expected output:</p>


<pre class="wp-block-code"><span><code class="hljs language-css"><span class="hljs-selector-tag">NAME</span>                 <span class="hljs-selector-tag">STATUS</span>   <span class="hljs-selector-tag">ROLES</span>    <span class="hljs-selector-tag">AGE</span>    <span class="hljs-selector-tag">VERSION</span>
<span class="hljs-selector-tag">kind-control-plane</span>   <span class="hljs-selector-tag">Ready</span>    <span class="hljs-selector-tag">master</span>   109<span class="hljs-selector-tag">s</span>   <span class="hljs-selector-tag">v1</span><span class="hljs-selector-class">.15</span><span class="hljs-selector-class">.3</span>
<span class="hljs-selector-tag">kind-worker</span>          <span class="hljs-selector-tag">Ready</span>    &lt;<span class="hljs-selector-tag">none</span>&gt;   73<span class="hljs-selector-tag">s</span>    <span class="hljs-selector-tag">v1</span><span class="hljs-selector-class">.15</span><span class="hljs-selector-class">.3</span></code></span></pre>


<h2 class="wp-block-heading">Configure the Cluster</h2>



<h3 class="wp-block-heading">Install Tiller (Helm&#8217;s In-Cluster Component)</h3>



<p class="wp-block-paragraph">Helm 2 requires a server-side component called Tiller. We create a dedicated namespace and give it cluster-admin privileges via RBAC.</p>



<p class="wp-block-paragraph"><strong>tiller.rbac.yaml</strong></p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">apiVersion: v1
<span class="hljs-attr">kind</span>: Namespace
<span class="hljs-attr">metadata</span>:
  name: tiller
---
apiVersion: v1
<span class="hljs-attr">kind</span>: ServiceAccount
<span class="hljs-attr">metadata</span>:
  name: tiller
  <span class="hljs-attr">namespace</span>: tiller
---
kind: ClusterRoleBinding
<span class="hljs-attr">apiVersion</span>: rbac.authorization.k8s.io/v1beta1
<span class="hljs-attr">metadata</span>:
  name: tiller-clusterrolebinding
<span class="hljs-attr">subjects</span>:
- kind: ServiceAccount
  <span class="hljs-attr">name</span>: tiller
  <span class="hljs-attr">namespace</span>: tiller
<span class="hljs-attr">roleRef</span>:
  kind: ClusterRole
  <span class="hljs-attr">name</span>: cluster-admin
  <span class="hljs-attr">apiGroup</span>: <span class="hljs-string">""</span></code></span></pre>

<pre class="wp-block-code"><span><code class="hljs language-javascript">kubectl apply -f tiller.rbac.yaml
<span class="hljs-keyword">export</span> TILLER_NAMESPACE=tiller
helm init --service-account tiller</code></span></pre>


<h3 class="wp-block-heading">Configure Persistent Storage</h3>



<p class="wp-block-paragraph">KIND ships with a default <code>standard</code> storage class that does not persist data across container restarts. We replace it with Rancher&#8217;s <a href="https://github.com/rancher/local-path-provisioner">local-path-provisioner</a>, which writes data to the host directory we mounted in <code>cluster.yaml</code>.</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># Install the local-path-provisioner</span>
kubectl apply -f https:<span class="hljs-comment">//raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml</span>

<span class="hljs-comment"># Remove the default flag from the built-in 'standard' storage class</span>
kubectl patch storageclass standard -p <span class="hljs-string">'{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false", "storageclass.beta.kubernetes.io/is-default-class":"false"}}}'</span>

<span class="hljs-comment"># Make local-path the new default</span>
kubectl patch storageclass local-path -p <span class="hljs-string">'{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true", "storageclass.beta.kubernetes.io/is-default-class":"true"}}}'</span></code></span></pre>


<h3 class="wp-block-heading">Install cert-manager and nginx-ingress</h3>



<p class="wp-block-paragraph">These two components handle the two things every public web service needs: TLS certificates and HTTP routing.</p>



<ul class="wp-block-list">
<li><strong>cert-manager</strong> — automatically provisions and renews TLS certificates from <a href="https://letsencrypt.org/">Let&#8217;s Encrypt</a>.</li>
<li><strong>nginx-ingress</strong> — proxies incoming HTTP/HTTPS requests to the correct Kubernetes service based on the hostname.</li>
</ul>



<p class="wp-block-paragraph">First, create <code>issuer.yaml</code> to tell cert-manager to use the Let&#8217;s Encrypt ACME v2 API. Replace <code>you@example.com</code> with your real email address (Let&#8217;s Encrypt uses it for expiry notices).</p>



<p class="wp-block-paragraph"><strong>issuer.yaml</strong></p>


<pre class="wp-block-code"><span><code class="hljs">apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: you@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx</code></span></pre>


<p class="wp-block-paragraph">Do not apply this manifest yet — cert-manager&#8217;s CRDs must exist first. Next, create <code>core.course.yaml</code> for Reckoner. The <code>post_install</code> hook on cert-manager applies <code>issuer.yaml</code> automatically after the chart is ready.</p>



<p class="wp-block-paragraph"><strong>core.course.yaml</strong></p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">repositories:
  jetstack:
    url: https:<span class="hljs-comment">//charts.jetstack.io</span>
namespace: <span class="hljs-keyword">default</span>
<span class="hljs-attr">charts</span>:
  cert-manager:
    hooks:
      pre_install:
      - kubectl apply --validate=<span class="hljs-literal">false</span> -f https:<span class="hljs-comment">//raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml</span>
      post_install:
      - sleep <span class="hljs-number">30</span> &amp;&amp; kubectl apply -f issuer.yaml
    <span class="hljs-attr">namespace</span>: cert-manager
    <span class="hljs-attr">repository</span>: jetstack
  nginx-ingress:
    namespace: nginx-ingress
    <span class="hljs-attr">values</span>:
      controller:
        hostNetwork: <span class="hljs-literal">true</span>
        <span class="hljs-attr">service</span>:
          type: LoadBalancer</code></span></pre>


<p class="wp-block-paragraph">Run Reckoner to install both charts:</p>


<pre class="wp-block-code"><span><code class="hljs language-css"><span class="hljs-selector-tag">reckoner</span> <span class="hljs-selector-tag">plot</span> <span class="hljs-selector-tag">core</span><span class="hljs-selector-class">.course</span><span class="hljs-selector-class">.yaml</span></code></span></pre>


<p class="wp-block-paragraph">Verify the pods are running (allow a minute or two for images to pull):</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">$ kubectl <span class="hljs-keyword">get</span> pods -n nginx-ingress
NAME                                             READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-664b77978-gbd59         1/1     Running   0          14s
nginx-ingress-default-backend-576b86996d-fjb4k   1/1     Running   0          14s

$ kubectl <span class="hljs-keyword">get</span> pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-6b78b7c997-mblt4              1/1     Running   0          18s
cert-manager-cainjector-54c4796c5d-psdgt   1/1     Running   0          18s
cert-manager-webhook-77ccf5c8b4-8tkwt      1/1     Running   0          17s</code></span></pre>


<h2 class="wp-block-heading">Install an Application: HackMD</h2>



<p class="wp-block-paragraph">To validate the full stack, we&#8217;ll deploy <strong>HackMD</strong> (now known as CodiMD/HedgeDoc), an open-source, real-time collaborative Markdown editor. It is a lightweight, self-hosted alternative to Google Docs, and it stores all data in a PostgreSQL database that will live in your <code>kind-disk</code> directory.</p>



<h3 class="wp-block-heading">Create the Ingress</h3>



<p class="wp-block-paragraph">The Ingress resource tells nginx-ingress how to route traffic for <code>hackmd.example.com</code> and instructs cert-manager to obtain a TLS certificate. Replace both occurrences of <code>example.com</code> with your real domain.</p>



<p class="wp-block-paragraph"><strong>ingress.yaml</strong></p>


<pre class="wp-block-code"><span><code class="hljs">apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    kubernetes.io/tls-acme: "true"
  name: hackmd
  namespace: hackmd
spec:
  rules:
    - host: hackmd.example.com
      http:
        paths:
          - backend:
              serviceName: hackmd
              servicePort: 3000
            path: /
  tls:
  - secretName: tls-prod-cert
    hosts:
    - hackmd.example.com</code></span></pre>


<h3 class="wp-block-heading">Create the Reckoner App Course File</h3>



<p class="wp-block-paragraph">Add HackMD to a separate course file for application-layer charts. As you deploy more apps, add them here.</p>



<p class="wp-block-paragraph"><strong>apps.course.yaml</strong></p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">namespace: <span class="hljs-keyword">default</span>
<span class="hljs-attr">charts</span>:
  hackmd:
    namespace: hackmd
    <span class="hljs-attr">hooks</span>:
      post_install:
      - kubectl apply -f ./ingress.yaml</code></span></pre>


<p class="wp-block-paragraph">Deploy it:</p>


<pre class="wp-block-code"><span><code class="hljs language-css"><span class="hljs-selector-tag">reckoner</span> <span class="hljs-selector-tag">plot</span> <span class="hljs-selector-tag">apps</span><span class="hljs-selector-class">.course</span><span class="hljs-selector-class">.yaml</span></code></span></pre>


<p class="wp-block-paragraph">After a few moments, HackMD should be accessible at <code>https://hackmd.example.com</code>. cert-manager will automatically obtain a Let&#8217;s Encrypt certificate. Data will be stored under <code>/home/ubuntu/kind-disk</code> on the host.</p>



<h2 class="wp-block-heading">Adding More Applications</h2>



<p class="wp-block-paragraph">The pattern for every future application is the same:</p>



<ol class="wp-block-list">
<li>Add a chart entry to <code>apps.course.yaml</code>.</li>
<li>Create a corresponding <code>ingress.yaml</code> pointing to your domain.</li>
<li>Run <code>reckoner plot apps.course.yaml</code>.</li>
</ol>



<p class="wp-block-paragraph">Because all your configuration lives in YAML files committed to Git, you can recreate the entire cluster — including all applications — on a new machine by replaying the same commands. This is the core value proposition of infrastructure as code at personal scale.</p>



<h2 class="wp-block-heading">Summary</h2>



<figure class="wp-block-table"><table><thead><tr><th>Component</th><th>Role</th></tr></thead><tbody><tr><td>KIND</td><td>Runs a Kubernetes cluster inside Docker on a single host</td></tr><tr><td>kubectl</td><td>CLI for all cluster interactions</td></tr><tr><td>Helm + Tiller</td><td>Installs and manages packaged Kubernetes applications</td></tr><tr><td>Reckoner</td><td>Declares multiple Helm releases in one YAML file</td></tr><tr><td>local-path-provisioner</td><td>Provides persistent storage backed by a host directory</td></tr><tr><td>nginx-ingress</td><td>Routes external HTTP/HTTPS traffic to the right service</td></tr><tr><td>cert-manager</td><td>Automatically provisions and renews Let&#8217;s Encrypt TLS certs</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Running Kubernetes at personal scale adds some operational complexity, but it pays off quickly: every application you self-host follows the same installation and upgrade pattern, your infrastructure is fully version-controlled, and migrating to a larger machine requires nothing more than replaying your playbooks.</p>



<p class="wp-block-paragraph"><em>Original article sourced from containerjournal.com (2019).</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/kubernetes-without-scale-setting-up-a-personal-cluster-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using Ansible for Windows System Management: What You Need to Know</title>
		<link>https://www.bestdevops.com/can-i-install-ansible-for-windows-system-management/</link>
					<comments>https://www.bestdevops.com/can-i-install-ansible-for-windows-system-management/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Sat, 03 Aug 2019 12:05:13 +0000</pubDate>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Windows]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=6702</guid>

					<description><![CDATA[Ansible can manage Windows hosts, but the setup is more involved than on Linux. Learn how WinRM, PowerShell, and WSL fit into the picture—and what limitations to expect.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Original source reference:</strong> searchitoperations.techtarget.com (2019)</p>



<h2 class="wp-block-heading">Can Ansible Manage Windows Systems?</h2>



<p class="wp-block-paragraph">Ansible is a widely used configuration management and automation tool with deep roots in the Linux ecosystem. However, it can also target Windows hosts for configuration, provisioning, and application lifecycle management. The catch: the setup process is noticeably more complex than it is on Linux, and there are meaningful constraints on how Windows machines can participate in an Ansible environment.</p>



<h2 class="wp-block-heading">How Ansible Communicates with Windows Hosts</h2>



<p class="wp-block-paragraph">On Linux, Ansible uses SSH to communicate with managed nodes. Because SSH is available by default on most Linux distributions, getting Ansible to control a Linux host is relatively straightforward.</p>



<p class="wp-block-paragraph">Windows is different. Rather than SSH, Ansible communicates with Windows hosts over <strong>WinRM (Windows Remote Management)</strong> using PowerShell. To prepare a Windows host for Ansible management, the following minimum requirements must be met on the managed node:</p>



<ul class="wp-block-list">
<li><strong>PowerShell 3.0 or higher</strong></li>
<li><strong>.NET Framework 4.0 or higher</strong></li>
<li>WinRM configured and enabled</li>
</ul>



<p class="wp-block-paragraph">Ansible&#8217;s official documentation includes a <code>ConfigureRemotingForAnsible.ps1</code> script that automates much of the WinRM setup on Windows managed nodes. Running this script is typically one of the first steps when onboarding a Windows host.</p>



<h2 class="wp-block-heading">Where the Ansible Control Node Must Run</h2>



<p class="wp-block-paragraph">A critical architectural point: <strong>the Ansible control node—including Ansible Tower (now AWX/Red Hat Ansible Automation Platform)—must run on Linux</strong>. Ansible itself cannot natively execute on a Windows host as the control machine.</p>



<p class="wp-block-paragraph">If your only available machine is a Windows server, you have two realistic options:</p>



<ul class="wp-block-list">
<li><strong>Run a Linux virtual machine</strong> on the Windows host and use that VM as the Ansible control node.</li>
<li><strong>Use Windows Subsystem for Linux (WSL)</strong>—a Microsoft feature available since Windows 10 that allows native Linux command-line tools to run on Windows. WSL can be installed from the Microsoft Store.</li>
</ul>



<p class="wp-block-paragraph">It is important to note that <strong>Ansible does not officially support WSL for production use</strong>. WSL may be suitable for development, testing, or learning purposes, but relying on it in a production environment is not recommended based on Ansible&#8217;s own guidance.</p>



<h2 class="wp-block-heading">What Windows Can and Cannot Do in an Ansible Environment</h2>



<p class="wp-block-paragraph">Understanding the role Windows can play helps set accurate expectations:</p>



<figure class="wp-block-table"><table><thead><tr><th>Capability</th><th>Windows Host</th></tr></thead><tbody><tr><td>Act as a <strong>managed node</strong> (receive and apply playbooks)</td><td>✅ Supported</td></tr><tr><td>Act as an <strong>Ansible control node</strong> (send playbooks to other hosts)</td><td>❌ Not natively supported</td></tr><tr><td>Run <strong>Python modules</strong> directly on the host</td><td>❌ Not supported</td></tr><tr><td>Run <strong>PowerShell modules</strong></td><td>✅ Supported</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Because Python modules cannot run directly on Windows managed nodes, teams that rely heavily on Python-based Ansible modules need to account for this. A common workaround is to run those modules on the Ansible controller itself using the <code>delegate_to: localhost</code> directive in a playbook task.</p>



<h2 class="wp-block-heading">Setting Up Ansible to Manage a Windows Host: Key Steps</h2>



<p class="wp-block-paragraph">Unlike Linux, where a single <code>apt-get install ansible</code> or <code>dnf install ansible</code> command gets you most of the way there, managing Windows with Ansible requires several configuration steps across both the control node and the managed Windows host.</p>



<h3 class="wp-block-heading">On the Windows Managed Node</h3>



<ol class="wp-block-list">
<li>Verify PowerShell 3.0+ and .NET 4.0+ are installed.</li>
<li>Enable and configure WinRM (use the Ansible-provided setup script for convenience).</li>
<li>Configure firewall rules to allow WinRM traffic (typically TCP 5985 for HTTP, 5986 for HTTPS).</li>
<li>Set up an appropriate authentication method (Basic, NTLM, Kerberos, or CredSSP depending on your environment).</li>
</ol>



<h3 class="wp-block-heading">On the Ansible Control Node (Linux)</h3>



<ol class="wp-block-list">
<li>Install Ansible on your Linux control node.</li>
<li>Install the <code>pywinrm</code> Python library, which Ansible requires to communicate with Windows hosts over WinRM: <code>pip install pywinrm</code></li>
<li>Define Windows hosts in your inventory file with the correct connection variables:</li>
</ol>


<pre class="wp-block-code"><span><code class="hljs">&#91;windows]
win-server-01 ansible_host=192.168.1.10

&#91;windows:vars]
ansible_user=Administrator
ansible_password=YourPassword
ansible_connection=winrm
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore</code></span></pre>


<p class="wp-block-paragraph">Always store credentials securely using <strong>Ansible Vault</strong> rather than plaintext in inventory files.</p>



<h2 class="wp-block-heading">Why Windows Teams Should Still Consider Ansible</h2>



<p class="wp-block-paragraph">Despite the added complexity, Ansible offers real value for organizations running Windows infrastructure:</p>



<ul class="wp-block-list">
<li><strong>Unified tooling:</strong> A single configuration management platform can manage both Linux and Windows infrastructure, reducing the number of tools teams need to learn and maintain.</li>
<li><strong>Agentless architecture:</strong> Like Linux, Windows managed nodes do not require an Ansible agent installed—only WinRM must be configured.</li>
<li><strong>Rich Windows module library:</strong> Ansible ships with many Windows-specific modules covering tasks such as managing IIS, Active Directory, Windows features, registry keys, services, and software packages.</li>
<li><strong>DevOps and automation adoption:</strong> Teams can use the same playbook-based workflows for Windows application lifecycle management as they do for Linux workloads.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ansible can absolutely be used to manage Windows systems—but Windows is strictly a <em>managed node</em>, not a control node. The Ansible controller must run on Linux (directly, via VM, or via WSL for non-production use). Windows managed nodes communicate via WinRM and PowerShell rather than SSH. The setup involves more steps than a typical Linux Ansible deployment, but the payoff is a unified automation platform capable of managing your entire infrastructure regardless of operating system.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/can-i-install-ansible-for-windows-system-management/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Install Docker on macOS Using Docker Desktop</title>
		<link>https://www.bestdevops.com/the-easiest-way-to-install-docker-on-macos/</link>
					<comments>https://www.bestdevops.com/the-easiest-way-to-install-docker-on-macos/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Thu, 04 Jul 2019 05:00:27 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[Kitematic]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=5875</guid>

					<description><![CDATA[Docker Desktop is the simplest way to get Docker running on macOS. Learn how to install Docker Desktop, pull images from the command line, and manage containers with a GUI.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a guide originally published on TechRepublic. It covers installing Docker on macOS using Docker Desktop, the official supported installer from Docker, Inc.</em></p>



<h2 class="wp-block-heading">Why Docker Desktop Is the Best Starting Point for macOS</h2>



<p class="wp-block-paragraph">macOS is a popular choice for cloud and container-based development thanks to its Unix foundation, stability, and tooling ecosystem. If you want to run Docker on a Mac, <strong>Docker Desktop</strong> is the path of least resistance. It handles the entire installation in a few clicks and sets up everything you need to start pulling images and running containers immediately.</p>



<p class="wp-block-paragraph">It is worth being clear about what Docker Desktop does and does not provide:</p>



<ul class="wp-block-list">
<li><strong>What it installs:</strong> the Docker daemon, the <code>docker</code> CLI, Docker Compose, and Docker credential helpers.</li>
<li><strong>What it adds to macOS:</strong> a menu-bar whale icon that gives quick access to preferences, sign-in to Docker Hub, and status information.</li>
<li><strong>What it does not do:</strong> provide a full Apple-native GUI for container lifecycle management out of the box. For that, a separate tool such as Kitematic (now deprecated upstream) or third-party alternatives are needed.</li>
</ul>



<h2 class="wp-block-heading">Prerequisites</h2>



<ul class="wp-block-list">
<li>A supported version of macOS (check the Docker Desktop release notes for the current minimum version requirement).</li>
<li>Administrator privileges on the Mac.</li>
<li>A free Docker Hub account if you intend to push images or access private repositories.</li>
</ul>



<h2 class="wp-block-heading">Installing Docker Desktop</h2>



<p class="wp-block-paragraph">The installation process is straightforward:</p>



<ol class="wp-block-list">
<li>Go to <a href="https://www.docker.com/products/docker-desktop/" rel="noopener">docker.com/products/docker-desktop</a> and download the macOS installer (<code>.dmg</code> file). Choose the correct chip architecture — Apple Silicon (M1/M2/M3) or Intel — for your machine.</li>
<li>Double-click the downloaded <code>.dmg</code> file to mount the disk image.</li>
<li>In the installer window, drag the Docker icon into the <strong>Applications</strong> folder.</li>
<li>Open Docker from the Applications folder. macOS will prompt you for your administrator password so the Docker daemon can be installed as a system service.</li>
<li>Wait for the whale icon to appear in the menu bar and animate. Once the animation stops and the icon is steady, Docker is running.</li>
</ol>



<p class="wp-block-paragraph">To verify the installation, open <strong>Terminal</strong> and run:</p>


<pre class="wp-block-code"><span><code class="hljs">docker --version
docker run hello-world</code></span></pre>


<p class="wp-block-paragraph">A successful <code>hello-world</code> run confirms that the daemon is reachable and images can be pulled from Docker Hub.</p>



<h2 class="wp-block-heading">Working with Docker from the Command Line</h2>



<p class="wp-block-paragraph">Once Docker Desktop is running, every standard Docker command works in Terminal. For example, to pull and run the latest NGINX image:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment"># Pull the latest NGINX image</span>
docker pull nginx

<span class="hljs-comment"># Run NGINX, mapping port 8080 on your Mac to port 80 in the container</span>
docker run -d -p <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> --name my-nginx nginx

<span class="hljs-comment"># Confirm the container is running</span>
docker ps</code></span></pre>


<p class="wp-block-paragraph">Open a browser and navigate to <code>http://localhost:8080</code> to see the NGINX welcome page served from inside the container.</p>



<h2 class="wp-block-heading">GUI-Based Container Management</h2>



<p class="wp-block-paragraph">If you prefer a graphical interface for searching Docker Hub, launching containers, and inspecting logs, there are a couple of options:</p>



<h3 class="wp-block-heading">Docker Desktop Dashboard</h3>



<p class="wp-block-paragraph">Modern versions of Docker Desktop ship with a built-in <strong>Dashboard</strong> that lets you view running containers, inspect logs, open a shell inside a container, and manage volumes and images — all without leaving the app. Click the Docker whale icon in the menu bar and select <strong>Dashboard</strong> to open it.</p>



<h3 class="wp-block-heading">Kitematic (Legacy)</h3>



<p class="wp-block-paragraph">Kitematic was a standalone GUI tool for Docker that was bundled with older versions of Docker Desktop. It has since been deprecated by Docker, Inc. and is no longer actively maintained. If you are running a recent version of Docker Desktop, the built-in Dashboard covers the same use cases. If you still need Kitematic for a legacy workflow, download it directly from the GitHub releases page rather than through the Docker menu, as the menu-bar shortcut in older versions was known to produce a broken installation.</p>



<h2 class="wp-block-heading">Optional: Installing Git</h2>



<p class="wp-block-paragraph">Most Docker-based workflows involve pulling application source code from a Git repository. If Git is not already on your Mac, the simplest installation methods are:</p>



<ul class="wp-block-list">
<li><strong>Xcode Command Line Tools:</strong> Run <code>git --version</code> in Terminal; macOS will prompt you to install the tools if Git is missing.</li>
<li><strong>Homebrew:</strong> Run <code>brew install git</code> for the latest upstream version.</li>
<li><strong>Official installer:</strong> Download from <a href="https://git-scm.com/download/mac" rel="noopener">git-scm.com/download/mac</a>.</li>
</ul>



<h2 class="wp-block-heading">Key Takeaways</h2>



<ul class="wp-block-list">
<li>Docker Desktop is the official, supported, and easiest way to install Docker on macOS.</li>
<li>After installation, verify with <code>docker run hello-world</code> before starting any real work.</li>
<li>Use the built-in Docker Desktop Dashboard for GUI-based container management on current versions.</li>
<li>Kitematic is deprecated; rely on the Dashboard or third-party tools for GUI workflows.</li>
<li>Standard <code>docker</code> and <code>docker compose</code> CLI commands work in any Terminal session once Docker Desktop is running.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/the-easiest-way-to-install-docker-on-macos/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
