<?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/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Linux - Ryan Daniels</title>
	<atom:link href="https://ryandaniels.ca/blog/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>https://ryandaniels.ca/blog/category/linux/</link>
	<description></description>
	<lastBuildDate>Fri, 17 Jan 2025 02:33:13 +0000</lastBuildDate>
	<language>en-CA</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://ryandaniels.ca/wp-content/uploads/2019/07/img_5907-small-blur-square-100x100.jpg</url>
	<title>Linux - Ryan Daniels</title>
	<link>https://ryandaniels.ca/blog/category/linux/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">22628916</site>	<item>
		<title>bootc (Bootable Containers): One Container Image to rule them all</title>
		<link>https://ryandaniels.ca/blog/bootc-bootable-containers-one-container-image-to-rule-them-all/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Fri, 17 Jan 2025 02:13:15 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Atomic]]></category>
		<category><![CDATA[bootc]]></category>
		<category><![CDATA[Fedora]]></category>
		<category><![CDATA[Immutable]]></category>
		<category><![CDATA[RHEL]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=4319</guid>

					<description><![CDATA[<p>bootc has the potential to be groundbreaking (for Enterprise server Linux). A scalable and immutable OS for servers. (Although I like the term Atomic better).</p>
<p>The post <a href="https://ryandaniels.ca/blog/bootc-bootable-containers-one-container-image-to-rule-them-all/">bootc (Bootable Containers): One Container Image to rule them all</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>bootc has the potential to be groundbreaking (for Enterprise server Linux). A scalable and immutable OS for servers. (Although I like the term Atomic better).</p>



<p>Earlier in 2024 Red Hat announced <a href="https://www.redhat.com/en/blog/introducing-image-mode-red-hat-enterprise-linux">&#8220;Image Mode&#8221; for Red Hat Enterprise Linux</a>. Currently Image Mode is in &#8220;Technology Preview&#8221; for RHEL. This is powered by Bootable Containers (or bootc for short). Fedora is also using this new technology, and they have great <a href="https://docs.fedoraproject.org/en-US/bootc/getting-started/">documentation</a>.</p>



<p>To summarize what bootc does,<br>from the Fedora Documentation:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The <a href="https://containers.github.io/bootc/">bootc documentation</a> summarizes bootable containers as &#8220;transactional, in-place operating system updates using OCI/Docker container images&#8221;. In other words, updates to the operating system (OS) are shipped by using container images. That implies that the Linux kernel, the bootloader, drivers, etc. are all part of the container image which renders the container image &#8220;bootable&#8221;.</p>
</blockquote>



<p>These deployments are atomic, meaning they are (mostly) read-only by default.</p>



<p>Updates are easy, just re-build the Container Image and by default the bootc host will update (and reboot) on it&#8217;s own.</p>



<figure class="wp-block-image size-thumbnail"><a href="https://ryandaniels.ca/wp-content/uploads/2024/12/bootc_updates.png" rel="lightbox[4319]"><img fetchpriority="high" decoding="async" width="300" height="178" src="https://ryandaniels.ca/wp-content/uploads/2024/12/bootc_updates-300x178.png" alt="bootc update flow" class="wp-image-4347" srcset="https://ryandaniels.ca/wp-content/uploads/2024/12/bootc_updates-300x178.png 300w, https://ryandaniels.ca/wp-content/uploads/2024/12/bootc_updates.png 658w" sizes="(max-width: 300px) 100vw, 300px" /></a><figcaption class="wp-element-caption">Image Credit: <a href="https://docs.fedoraproject.org/en-US/bootc/getting-started/#_updating_bootable_containers">Fedora docs</a></figcaption></figure>



<h2 class="wp-block-heading">What makes bootc so exciting?</h2>



<p>One Container Image to rule them all.<br>Sorry, I meant to say: One Container Image to keep every server up to date, automatically.</p>



<p>Every server automatically checks for a new container image. When there&#8217;s a new image, the server automatically updates. If the update or reboot fails, no problem. It will &#8220;auto-heal&#8221;. (there&#8217;s a buzz word I haven&#8217;t heard in a while!)</p>



<p>There is also no chance of a different package version being installed during a rolling update of many servers (when external repositories are not in your control).</p>



<p>If you need more than one image (if you have many different workloads on your servers then don&#8217;t put everything into one image!), it&#8217;s pretty simple to have a single &#8220;base image&#8221; and many specialized images built from that.</p>



<h2 class="wp-block-heading">What could be better?</h2>



<ul class="wp-block-list">
<li>Updates require a reboot.. for any update, any package install.</li>



<li>There is still possibility for configuration drift in /etc</li>



<li>Initial install can be difficult.</li>



<li>Can&#8217;t easily add extra (non-root) disk (via the Dockerfile/Containerfile).</li>



<li>Some packages can&#8217;t be installed into a Container.</li>



<li>No release notes or changelog to see what packages change.</li>



<li>Day 2 configuration changes are somewhat painful. Redeploying the entire OS isn&#8217;t great if you want to be truly immutable.</li>



<li>Ansible doesn&#8217;t detect a bootc server any different from a normal RHEL or Fedora installation. But trying to install a package on a bootc server will obviously fail the Ansible Playbook. This makes re-using Ansible Roles difficult.</li>



<li>Simple things like user management are not simple considering <a href="https://containers.github.io/bootc/building/users-and-groups.html">issues with drift</a>. This means using <a href="https://ryandaniels.ca/blog/ansible-user-management/">Ansible for User Management</a> doesn&#8217;t really make sense anymore.</li>



<li>Advanced automatic update mechanism not included, like rolling updates of a 5 node cluster.</li>
</ul>



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



<p>I think bootc has the potential for amazing things in 2025 (and beyond). An Atomic server OS that scales. Even with the above somewhat long list of needed improvements, I&#8217;m still very excited. Is it too early to start using Bootable Containers in production? I don&#8217;t think so.</p>



<p></p>
<p>The post <a href="https://ryandaniels.ca/blog/bootc-bootable-containers-one-container-image-to-rule-them-all/">bootc (Bootable Containers): One Container Image to rule them all</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4319</post-id>	</item>
		<item>
		<title>Run different Linux program based on current directory (using Bash shell)</title>
		<link>https://ryandaniels.ca/blog/run-different-linux-program-based-on-current-directory-using-bash-shell/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Sun, 26 Nov 2023 20:47:29 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Bash]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2901</guid>

					<description><![CDATA[<p>This provides a way for using different versions of a program based on the current directory name. By adding this example code to the .bashrc file, users can run a unique terraform version based on the directory name.</p>
<p>The post <a href="https://ryandaniels.ca/blog/run-different-linux-program-based-on-current-directory-using-bash-shell/">Run different Linux program based on current directory (using Bash shell)</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Sometimes I want to use a specific version of a program, depending on the directory I&#8217;m currently in. With no obvious solution from <a href="https://stackoverflow.com/questions/tagged/linux+shell" target="_blank" rel="noreferrer noopener">Stack Overflow</a>, I&#8217;ll document my own.</p>



<p>I find this useful for my infrastructure as code configuration with terraform. Each directory is a different environment or site, and I can use different versions of terraform based on the name of the directory.</p>



<p>This is for bash shell on Linux. Tested on bash version 4.3 or newer. Might work on older version too.</p>



<p>Add this code to your .bashrc file:</p>



<pre class="wp-block-code"><code>function terraform () {
  case "${PWD##*/}" in
    *env-2023*) ~/terraform_1.6.2 "$@";;
    *) ~/terraform_0.11.15 "$@";; # default case
  esac
}</code></pre>



<p>Then log out and log back in.</p>



<h2 class="wp-block-heading">What is this doing?</h2>



<p>When you run the command &#8220;terraform&#8221;, your current directory is checked. If you are in a directory that has &#8220;env-2023&#8221; anywhere in it, then terraform_1.6.2 will run. Otherwise the (really) old version will run.</p>



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



<p>With this in your .bashrc file, you can have multiple directory patterns in the case syntax, each running a specific version of an application. I find this helpful when in the process of upgrading terraform config for all of my different environments for my infrastructure as code.</p>



<p>Here are some <a href="https://ryandaniels.ca/blog/tag/linux/">more Linux related posts</a>.</p>
<p>The post <a href="https://ryandaniels.ca/blog/run-different-linux-program-based-on-current-directory-using-bash-shell/">Run different Linux program based on current directory (using Bash shell)</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2901</post-id>	</item>
		<item>
		<title>Raspberry Pi 3 B+ is the last Raspberry Pi you need (Why the Raspberry Pi 5 sucks)</title>
		<link>https://ryandaniels.ca/blog/raspberry-pi-3-b-is-the-last-raspberry-pi-you-need-why-the-raspberry-pi-5-sucks/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Sun, 19 Nov 2023 21:52:49 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2911</guid>

					<description><![CDATA[<figure class="alignleft size-full is-resized"><img src="https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025-300x195.png" alt="" class="wp-image-2925" width="150" height="150"/></figure>
<p>The Raspberry Pi 5 is critiqued for its high price and limited HEVC GPU video decoding. The Raspberry Pi 3B+ is recommended for small projects, while a Beelink Mini S12 Pro is suggested as an alternative that offers more power and comparable price without being on pre-order. For those wary of expenditure, a cheap laptop is also a viable option.</p>
<p>The post <a href="https://ryandaniels.ca/blog/raspberry-pi-3-b-is-the-last-raspberry-pi-you-need-why-the-raspberry-pi-5-sucks/">Raspberry Pi 3 B+ is the last Raspberry Pi you need (Why the Raspberry Pi 5 sucks)</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Okay, sucks is a strong word to use for the Raspberry Pi 5. The Raspberry Pi 5 is going in the wrong direction in my opinion. It&#8217;s expensive, and only has HEVC GPU video decoding. Stick with the Raspberry Pi 3 B+, or buy a cheap x86 box like a Beelink instead if you need more than a Pi 3B+.</p>



<h2 class="wp-block-heading">Raspberry Pi 3 B+</h2>


<div class="wp-block-image">
<figure class="alignright size-full"><a href="https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025.png" rel="lightbox[2911]"><img decoding="async" width="800" height="520" src="https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025.png" alt="Raspberry Pi 3B+" class="wp-image-2925" srcset="https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025.png 800w, https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025-300x195.png 300w, https://ryandaniels.ca/wp-content/uploads/2023/11/Raspberry_Pi_3_B_39906369025-768x499.png 768w" sizes="(max-width: 800px) 100vw, 800px" /></a><figcaption class="wp-element-caption">Raspberry Pi 3B+ by Gareth Halfacree from Bradford, UK, CC BY-SA 2.0 <a href="https://commons.wikimedia.org/wiki/File:Raspberry_Pi_3_B%2B_(39906369025).png" target="_blank" rel="noreferrer noopener" rel="lightbox[2911]">via Wikimedia Commons</a></figcaption></figure></div>


<p>The ARM architecture uses minimal power. It&#8217;s only 1GB of RAM and a slow 4-core CPU. But for a small project, it&#8217;s perfect. Plus it has great Linux support (for an ARM based architecture).</p>



<p>Pi 3 B+ works great for <a href="https://pi-hole.net/" target="_blank" rel="noreferrer noopener">Pi-hole</a> and <a href="https://pivpn.io/" target="_blank" rel="noreferrer noopener">PiVPN</a> (with OpenVPN or WireGuard)! <a href="https://ryandaniels.ca/blog/openvpn-ad-blocking/">Check out my old post about setting up PiVPN with OpenVPN</a>.</p>



<h2 class="wp-block-heading">Raspberry Pi 4</h2>



<p>What About the Pi 4? It depends. It does have a faster CPU, and more RAM options compared to a Pi 3B+. But I don&#8217;t want active cooling. And the Pi 4 needs a fan.</p>



<h2 class="wp-block-heading">Raspberry Pi 5 &#8211; Only HEVC GPU video decoding</h2>



<p>The Raspberry Pi 5 only supports HEVC decoding. And no hardware encoding at all! HEVC is also known as &#8220;H.265&#8221;. This means no &#8220;H.264&#8221; (AVC) GPU decoding. Why does this matter? H.264 is still widely used. And that means the Pi 5 needs the use the CPU to decode H.264 (AVC), which uses more power and causes more heat in the Pi.</p>



<h2 class="wp-block-heading">Raspberry Pi 5 Alternatives &#8211; Beelink Mini S12 Pro (x86)</h2>



<p>I want a quiet and small headless home server type of solution that fits behind my TV. <br>I found the <a href="https://www.bee-link.com/beelink-mini-s12-pro-n100-mini-pc-clone-1" target="_blank" rel="noreferrer noopener">Beelink Mini S12 Pro</a> works great for me. It&#8217;s actually about the same price as a Pi 5 with a basic setup! (with a case, sd card, power from <a href="https://www.canakit.com/canakit-raspberry-pi-5-starter-kit-red-white.html" target="_blank" rel="noreferrer noopener">CanaKit</a> for $214.95). I got my <a href="https://amzn.to/47DikVL" target="_blank" rel="noreferrer noopener sponsored nofollow">Beelink Mini S12 Pro from Amazon</a> currently on sale for $219 (CAD). Plus you can actually get this today, and not on pre-order like the Pi.<br>The Beelink Mini S12 Pro has:</p>



<ul class="wp-block-list">
<li>4 core x86 CPU (<a href="https://ark.intel.com/content/www/us/en/ark/products/231803/intel-processor-n100-6m-cache-up-to-3-40-ghz.html" target="_blank" rel="noreferrer noopener">Intel 12th Gen Processor Alder Lake N100</a>)</li>



<li>16GB RAM</li>



<li>500GB NVMe disk for storage!</li>



<li>6W TDP</li>
</ul>



<p>I&#8217;d recommend re-installing the OS though.<br>Linux installs and works on it just fine (tried with Linux Kernel 6.5, and 6.6). But note that WiFi and Bluetooth don&#8217;t work because of the Intel AX101 chip&#8217;s terrible Linux support. But for me that wasn&#8217;t an issue, I just use Ethernet.<br>This will give you way more power than a Pi 5, and not much more power usage. Yes it does use active cooling (fan), but I&#8217;ve never heard it.</p>



<p>However, if you don&#8217;t want to spend that much, then instead get a cheap laptop. Trade off is that it will likely use more power.</p>



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



<p>Stick with a Raspberry Pi 3B+ for any small projects. If you need something more powerful, go x86. Something like a <a href="https://amzn.to/47DikVL" target="_blank" rel="noreferrer noopener sponsored nofollow">Beelink Mini S12 Pro from Amazon</a>, or even a cheap laptop will be better than a Raspberry Pi 5.</p>
<p>The post <a href="https://ryandaniels.ca/blog/raspberry-pi-3-b-is-the-last-raspberry-pi-you-need-why-the-raspberry-pi-5-sucks/">Raspberry Pi 3 B+ is the last Raspberry Pi you need (Why the Raspberry Pi 5 sucks)</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2911</post-id>	</item>
		<item>
		<title>Docker and Trouble with Red Hat Enterprise Linux 9: iptables</title>
		<link>https://ryandaniels.ca/blog/docker-and-trouble-with-red-hat-enterprise-linux-9-iptables/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Sun, 19 Mar 2023 19:18:17 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[RHEL]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2846</guid>

					<description><![CDATA[<p>Red Hat Enterprise Linux 9 (RHEL 9) and Docker don't get along very well. Running a container that requires older iptables (and not nftables) can be a problem.</p>
<p>The post <a href="https://ryandaniels.ca/blog/docker-and-trouble-with-red-hat-enterprise-linux-9-iptables/">Docker and Trouble with Red Hat Enterprise Linux 9: iptables</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Red Hat Enterprise Linux 9 (RHEL 9) and Docker don&#8217;t get along very well sometimes. It turns out, running a container that requires older iptables (and not nftables) can be a problem.<br>This is a problem for other Operating Systems too that use nftables, but let&#8217;s focus on RHEL 9 today. </p>



<h2 class="wp-block-heading">Problem with running a newer OS (like RHEL 9)</h2>



<p>Wow, RHEL 9 is using a modern kernel and toolchain. Ok, now I can continue.</p>



<p>Some newer Linux Operating Systems are moving away from <a href="https://en.wikipedia.org/wiki/Iptables" target="_blank" rel="noreferrer noopener">iptables</a> and changing to <a href="https://en.wikipedia.org/wiki/Nftables" target="_blank" rel="noreferrer noopener">nftables</a>. This can be a problem when an app is expecting iptables. Normally the OS can load the older iptables, but you can run into problems when running containers. </p>



<h3 class="wp-block-heading">Error from GitLab Runner</h3>



<p>It&#8217;s even more fun trying to figure out what&#8217;s going on when running on a GitLab Runner.</p>



<p>This is the error from a GitLab Runner job:</p>



<pre class="wp-block-code"><code>ERROR: error during connect: Get https://docker:2376/v1.40/info: dial tcp: lookup docker on 8.8.8.8:53: server misbehaving</code></pre>



<h3 class="wp-block-heading">Error when running Docker container</h3>



<p>This is the error when running a container using Docker:</p>



<pre class="wp-block-code"><code># docker run --rm -it --privileged --name dind docker:19.03-dind

...
INFO&#91;2023-03-18T21:03:46.764203869Z] Loading containers: start.                   
WARN&#91;2023-03-18T21:03:46.774269934Z] Running iptables --wait -t nat -L -n failed with message: `iptables v1.8.4 (legacy): can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.`, error: exit status 3 
INFO&#91;2023-03-18T21:03:46.801647539Z] stopping event stream following graceful shutdown  error="&lt;nil&gt;" module=libcontainerd namespace=moby
...
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables -t nat -N DOCKER: iptables v1.8.4 (legacy): can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
 (exit status 3)</code></pre>



<p>So here we can see the problem. Our container is trying to use iptables and it&#8217;s not working.</p>



<p>But, if you run a newer Docker in Docker (DinD) container, it works! And then the old container also starts to work (this is, until a reboot of the host). The culprit? iptables, and a clever trick in newer DinD containers to workaround this issue..</p>



<h2 class="wp-block-heading">Enable iptables from inside a Container</h2>



<p>If you run a container as privileged, you can actually trigger the host OS to load the iptables kernel modules! </p>



<p>This was found from Docker in Docker (DinD) adding a <a href="https://github.com/docker-library/docker/blob/849b56e6c81dc509da780121352f844e8f26bb7a/23.0/cli/modprobe.sh" target="_blank" rel="noreferrer noopener">custom modprobe script</a> (called from the <a href="https://github.com/docker-library/docker/blob/94129ecd12de7acbc9d5a15d25d535ee091770b1/23.0/dind/dockerd-entrypoint.sh#L152" target="_blank" rel="noreferrer noopener">entrypoint script</a>), which is essentially just running this command:</p>



<pre class="wp-block-code"><code># ip link show ip_tables</code></pre>



<p>The Docker in Docker modprobe script gives credit to:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="550" height="273" src="https://ryandaniels.ca/wp-content/uploads/2023/02/Luca_Bruno-ip_link_show_module-dark.png" alt="Loading Linux kernel modules the 'alternative' way: 'ip link show $module'. No need for modprobe binary, kernel object files. This fixes the problem with RHEL 9 and iptables with Docker" class="wp-image-2847" srcset="https://ryandaniels.ca/wp-content/uploads/2023/02/Luca_Bruno-ip_link_show_module-dark.png 550w, https://ryandaniels.ca/wp-content/uploads/2023/02/Luca_Bruno-ip_link_show_module-dark-300x149.png 300w" sizes="(max-width: 550px) 100vw, 550px" /></figure></div>


<h2 class="wp-block-heading">Enable iptables on Red Hat Enterprise Linux 9</h2>



<p>But if your container isn&#8217;t using this &#8216;ip link show ip_tables&#8217; trick, the container will have problems. You need to enable the iptables legacy module on your host OS.</p>



<p>To have iptables loaded and ready to go, you can also run the above trick directly on the host. But the &#8220;proper&#8221; way is to use modprobe when the OS boots.</p>



<pre class="wp-block-code"><code># modprobe ip_tables</code></pre>



<p>That will dynamically enable the older iptables. But after a reboot the change is gone, so to make a persistent change:</p>



<pre class="wp-block-code"><code>echo ip_tables &gt; /etc/modules-load.d/ip_tables.conf</code></pre>



<p>Reboot and check:</p>



<pre class="wp-block-code"><code># lsmod|grep -E "^ip_tables|^iptable_filter|^iptable_nat"
ip_tables              28672  0</code></pre>



<p>Now the older containers will also work (that need iptables (legacy).</p>



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



<p>Red Hat doesn&#8217;t recommend running Docker (instead they recommend Podman). Probably for these reasons. And I wonder if this problem also has something to do with the underlying and undocumented way that <a href="https://ryandaniels.ca/blog/docker-iptables-input-chain/">Docker uses iptables INPUT chain</a>.</p>
<p>The post <a href="https://ryandaniels.ca/blog/docker-and-trouble-with-red-hat-enterprise-linux-9-iptables/">Docker and Trouble with Red Hat Enterprise Linux 9: iptables</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2846</post-id>	</item>
		<item>
		<title>Secure Docker with iptables firewall and Ansible</title>
		<link>https://ryandaniels.ca/blog/secure-docker-with-iptables-firewall-and-ansible/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Sun, 24 May 2020 19:11:41 +0000</pubDate>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[Guide]]></category>
		<category><![CDATA[IT Automation]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2290</guid>

					<description><![CDATA[<figure class="alignleft wp-block-image size-thumbnail"><img src="https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye-200x300.jpg" alt="" class="wp-image-2489"/></figure>
<p>Out of the box, security with Docker (and Docker Swarm) over the network is bad. Okay, that's not entirely true. Out of the box when you have no containers started, it's fine. But after you start a container, and if you publish a port, they are exposed to the outside world by default. And it's not easy to fix. You need to create a custom Docker firewall with iptables.<br />
&#160;</p>
<p>The post <a href="https://ryandaniels.ca/blog/secure-docker-with-iptables-firewall-and-ansible/">Secure Docker with iptables firewall and Ansible</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Out of the box, security with Docker (and Docker Swarm) over the network is bad. Okay, that&#8217;s not entirely true. Out of the box when you have no containers started, it&#8217;s fine. But after you start a container, and if you publish a port, they are exposed to the outside world by default. And it&#8217;s not easy to fix. You need to create a custom Docker firewall with iptables.</p>



<p>Let&#8217;s discuss the background of firewall issues with Docker, and a working solution for my use case (either setup manually or using Ansible). By the end we will use a firewall on the server to lock down everything by default, only allowing my trusted IPs! With the option to open specified ports publicly (like SSH).</p>



<p>Note: This solution works with CentOS 7, RHEL 7, Ubuntu 18.04, and Ubuntu 20.04.</p>



<span id="more-2290"></span>


				<div class="wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-5708b17e-d0f5-4528-8221-706c39a8a865      "
					data-scroll= ""
					data-offset= "30"
					style=""
				>
				<div class="uagb-toc__wrap">
						<div class="uagb-toc__title">
							Table Of Contents						</div>
																						<div class="uagb-toc__list-wrap ">
						<ol class="uagb-toc__list"><li class="uagb-toc__list"><a href="#background" class="uagb-toc-link__trigger">Background</a><li class="uagb-toc__list"><a href="#roll-your-own-solution" class="uagb-toc-link__trigger">Roll your own solution</a><li class="uagb-toc__list"><a href="#problems-i-need-to-solve" class="uagb-toc-link__trigger">Problems I need to solve</a><li class="uagb-toc__list"><a href="#solution-docker-firewall-with-iptables-and-ipset" class="uagb-toc-link__trigger">Solution &#8211; Docker firewall with iptables and ipset</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#high-level-summary" class="uagb-toc-link__trigger">High level summary</a></li></ul></li><li class="uagb-toc__list"><a href="#warnings" class="uagb-toc-link__trigger">Warnings</a><li class="uagb-toc__list"><a href="#the-manual-way" class="uagb-toc-link__trigger">The manual way</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#prep" class="uagb-toc-link__trigger">Prep</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#configure-ipset" class="uagb-toc-link__trigger">Configure ipset</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#configure-iptables" class="uagb-toc-link__trigger">Configure iptables</a></li></ul></li></ul></li><li class="uagb-toc__list"><a href="#the-automatic-way-with-ansible" class="uagb-toc-link__trigger">The Automatic way with Ansible</a><li class="uagb-toc__list"><a href="#conclusion" class="uagb-toc-link__trigger">Conclusion</a><li class="uagb-toc__list"><a href="#references" class="uagb-toc-link__trigger">References</a><ul class="uagb-toc__list"><li class="uagb-toc__list"><a href="#background-for-dockers-undocumented-use-of-iptables-input-chain" class="uagb-toc-link__trigger">Background for Docker&#039;s undocumented use of iptables INPUT chain</a><li class="uagb-toc__list"><li class="uagb-toc__list"><a href="#references-and-links" class="uagb-toc-link__trigger">References and links</a></ul></ul></ul></ol>					</div>
									</div>
				</div>
			


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



<div class="wp-block-image"><figure class="alignright size-medium"><img loading="lazy" decoding="async" width="400" height="600" src="https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye-400x600.jpg" alt="Docker punches a hole through firewall" class="wp-image-2489" srcset="https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye-400x600.jpg 400w, https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye-480x720.jpg 480w, https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye-200x300.jpg 200w, https://ryandaniels.ca/wp-content/uploads/2020/05/punch_hole_eye.jpg 533w" sizes="auto, (max-width: 400px) 100vw, 400px" /><figcaption><sup>Image credit: <a rel="noreferrer noopener" href="https://www.pexels.com/photo/brown-human-eye-2873058/" target="_blank">Jonathan Borba</a></sup></figcaption></figure></div>



<p>Firstly, even if you were using a firewall like iptables, Docker makes that useless. Docker punches a whole right through your firewall!</p>



<p>And if you <a href="https://ryandaniels.ca/blog/ansible-manage-firewalld/">try another firewall, like firewalld</a>? Docker Swarm (and even regular Docker) with firewalld is a complete mess. Restart the firewalld service, or change the firewalld config, and you lost all the config that Docker needed. Now you have to restart Docker! What happens if the firewalld service failed and restarted? That Docker Swarm node is out of service.</p>



<p>Keep in mind, when I mention Docker, it means the regular Docker Engine. Docker Swarm means SwarmKit, which is the newer way of using Swarm. (The old way is the standalone solution which is old and not referenced at all here).</p>



<p>There are many attempts to solve this problem by users of Docker. Unfortunately the Docker team has been pretty quiet about these issues. They recommend a manual user solution, and to disable Docker&#8217;s use of iptables. I&#8217;m speculating here, but it seems like any future change from Docker will likely be a breaking change since this is a complicated issue to fix.</p>



<p>The attempted solutions (from users) are not very straight forward for a normal Docker user. And that&#8217;s the real issue. On top of that, out of the box (after you start one service with a published port), there is no security at the network layer. Anyone can connect to an exposed container&#8217;s port. Most importantly, even if you think you have a firewall protecting you.. Wrong, you don&#8217;t! With normal Docker, you can bind your service to your localhost which helps. But what about Docker Swarm? Nope, that doesn&#8217;t work.</p>



<p>There&#8217;s a great article about &#8220;<a rel="noreferrer noopener" href="https://utcc.utoronto.ca/~cks/space/blog/tech/SecurityChoiceProblem" data-type="URL" data-id="https://utcc.utoronto.ca/~cks/space/blog/tech/SecurityChoiceProblem" target="_blank">The problem of forcing users to make choices (in security)</a>.&#8221; Definitely worth the read!</p>



<h2 class="wp-block-heading">Roll your own solution</h2>



<p>Until this is actually addressed in Docker, our only hope is to find the simplest solution possible. And turning off iptables integration in Docker is unacceptable (which is constantly recommended by the Docker developers). The other option is to move on from Docker and/or Docker Swarm. I hear this thing called Kubernetes is pretty great. Anyways, back to Docker. <br>Many people have spent hours trying to learn, and figure out iptables as a solution to this. You need to roll your own solution apparently! So iptables is probably the best approach, since that is what Docker needs to use to do it&#8217;s magic (and most other firewalls are just a wrapper for iptables anyway depending on your OS).</p>



<p>Something <s>fun</s> I found out while testing this, <a href="https://ryandaniels.ca/blog/docker-iptables-input-chain/">Docker Swarm uses iptables in an undocumented way</a>. Docker Swarm uses the iptables INPUT chain! It&#8217;s only for encrypted overlay networks. But it&#8217;s not very fun realizing that! All of a sudden rules are being appended to the INPUT chain.</p>



<p>Okay, enough backstory. On with my futile attempt to roll my own solution. This took way longer than I thought it would! But it does work! Currently it works at least.. (That&#8217;s why I use the word futile!)</p>



<h2 class="wp-block-heading">Problems I need to solve</h2>



<ol class="wp-block-list"><li>Only allow traffic from multiple &#8220;trusted&#8221; IP addresses to my servers. Not all of these IPs will be in the same &#8220;IP block/range&#8221; either. This will be to all services running directly on the server, and also all of the Docker containers.</li><li>Let only specific ports be publicly accessible, like SSH.</li><li>I&#8217;m not managing which containers are accessible through the firewall. Meaning, I&#8217;m not manually adding ports into my firewall solution. That kind of manual work is not happening. I need a dynamic, and flexible solution that blocks by default except to my trusted IPs.</li><li>The firewall solution must be simple. More complex means more room for error.</li><li>The firewall solution must not impact performance significantly.</li><li>Restarting the firewall won&#8217;t break Docker. </li><li>Restarting Docker won&#8217;t break the firewall.</li><li>No impact to running server processes or Docker services when making a change. Things need to keep working! <br>Firewall changes need to happen online and not impact Docker. Meaning I can&#8217;t be restarting Docker because I made a firewall change.<br>Docker &#8220;changes&#8221; need to happen online. Meaning I can&#8217;t be restarting the firewall because I made a Docker change. (A Docker &#8220;change&#8221; means starting/stopping a container).</li></ol>



<p>That sounds very simple! Unfortunately, it is not with Docker (and Docker Swarm).</p>



<h2 class="wp-block-heading">Solution &#8211; Docker firewall with iptables and ipset</h2>



<p>If you don&#8217;t know much about iptables, or ipset, that&#8217;s okay. You don&#8217;t really need to know. You should have some basic understandings though, so you don&#8217;t break your servers! The <a rel="noreferrer noopener" href="https://wiki.archlinux.org/index.php/Iptables#Chains" target="_blank">Arch Linux wiki</a> has great information about iptables. Including this helpful <a rel="noreferrer noopener" href="https://www.frozentux.net/iptables-tutorial/chunkyhtml/images/tables_traverse.jpg" target="_blank" rel="lightbox[2290]">visual</a> about the iptables flow.</p>



<p>Note: This solution works with CentOS 7, RHEL 7, Ubuntu 18.04, and Ubuntu 20.04.</p>



<h3 class="wp-block-heading">High level summary</h3>



<p>iptables with ipset will handle all of this for us. And keep our servers, and Docker locked down from the network level. </p>



<p>In this solution, we will use the iptables INPUT chain to jump to another chain (let&#8217;s call our custom chain FILTERS), but return if there&#8217;s some legitimate looking traffic, so the Swarm overlay can do whatever it wants in INPUT with IPSEC, or whatever it is appending to INPUT.<br>Inside our custom chain FILTERS, we drop everything that doesn&#8217;t match our trusted list of IPs. We also allow our SSH port and the basic default iptables stuff.. You can also add any OS port to be publicly accessible.<br>The DOCKER-USER chain only needs a few entries. Any internal Docker traffic is returned, and it will drop any other traffic that&#8217;s not in our allowed IP list. You can also add any container port to be publicly accessible.</p>



<p>One of the dangers with this approach is if Docker changes it&#8217;s behaviour our firewall could break, or our Docker services could stop working. Since Docker doesn&#8217;t offer any solution for their users, we need our own solution. So keep in mind that you need to test this when upgrading to a new version of Docker. That is the trade-off with a &#8220;roll your own&#8221; solution. But what choice do we have?</p>



<p>I&#8217;ve created an <a rel="noreferrer noopener" href="https://galaxy.ansible.com/ryandaniels/iptables_docker" target="_blank">Ansible Role: iptables for Docker</a>, on <a rel="noreferrer noopener" href="https://github.com/ryandaniels/ansible-role-iptables-docker" target="_blank">GitHub</a> and <a rel="noreferrer noopener" href="https://galaxy.ansible.com/ryandaniels/iptables_docker" target="_blank">Ansible Galaxy</a>.</p>



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



<p><strong>Warning: Be sure you have everything needed in your configuration. Once the iptables firewall is started it blocks anything that wasn’t added! Don&#8217;t lock yourself out of your server. Be sure to have another way to connect, like a console.</strong></p>



<p><strong>Disclaimer: Keep in mind, you should test all of this in your lab or staging environments. I can’t guarantee this will be 100% safe and can’t be held responsible for anything going wrong!</strong></p>



<p><strong>SELinux Bug</strong>: If using SELinux, currently there&#8217;s a bug with SELinux which prevents saving the iptables rules to the iptables.save file.<br><strong>Impact</strong>: Saving the iptables rules a 2nd time will silently fail. Workaround has been added so SELinux allows chmod to interact with the iptables.save file. <a rel="noreferrer noopener" href="https://github.com/ryandaniels/ansible-role-iptables-docker/blob/master/README.md#selinux-manual-workaround-for-iptables-and-chmod" target="_blank">See notes on GitHub for SELinux workaround steps</a>. Alternatively you could disable SELinux, but that&#8217;s not recommended. Bug report: <a rel="noreferrer noopener" href="https://bugs.centos.org/view.php?id=12648" target="_blank">https://bugs.centos.org/view.php?id=12648</a></p>



<h2 class="wp-block-heading">The manual way</h2>



<p>Run the commands below. These commands are only for CentOS/RHEL 7. If you don&#8217;t want to do this manually, jump to the <a href="#the-automatic-way-with-ansible">Automatic section, using Ansible</a> (which also works with Ubuntu).</p>



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



<p>Make note of what you already have in iptables (if you are already using it). Be sure you have some background with iptables, since you could break things!</p>



<pre class="wp-block-code"><code># iptables -nvL --line-numbers</code></pre>



<p>Install the required packages for CentOS / RHEL:</p>



<pre class="wp-block-code"><code># yum install iptables iptables-services ipset ipset-service</code></pre>



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



<p>ipset allows you to add a list of IPs that you can use with iptables. In our case, we will add a list of IPs we want to be able to connect to our servers.</p>



<p>Configure ipset with a setname of <code>ip_allow</code>.<br>Add IPs you want to allow. Change the IPs below to your actual trusted/allowed IP ranges. Be sure to include your Docker server IPs here, because if you don&#8217;t they can&#8217;t communicate with eachother:</p>



<pre class="wp-block-code"><code># mkdir -p /etc/sysconfig/ipset.d
# vi /etc/sysconfig/ipset.d/ip_allow.set

create -exist ip_allow hash:ip family inet hashsize 1024 maxelem 65536
add ip_allow 192.168.1.123
add ip_allow 192.168.100.0/24
add ip_allow 192.168.101.0/24
add ip_allow 192.168.102.0/24</code></pre>



<p>Start, and Enable the ipset service:</p>



<pre class="wp-block-code"><code># systemctl status ipset
# systemctl start ipset
# systemctl enable ipset</code></pre>



<p>See what ipset has in it&#8217;s loaded configuration:</p>



<pre class="wp-block-code"><code># ipset list | head</code></pre>



<p>Important: Make note of the size of &#8220;Number of entries&#8221;. If that number is close to the maxelem size (65536), then you need to delete the ipset and re-create it with a larger max size. If you only use a few IP ranges like above, you don&#8217;t need to worry and will be well below the limit.</p>



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



<p>Next up, iptables. iptables is our solution for a firewall. We will create a file with our rules and then add those rules into iptables. The important part is to not flush the existing rules if you are already using Docker  (or Docker Swarm) on your server.</p>



<p>Create an iptables file to use with iptables-restore, to add the rules into iptables:</p>



<pre class="wp-block-code"><code># vi iptables-rules.txt</code></pre>



<p>Add below to the file. There is a lot going on here..</p>



<pre class="wp-block-code"><code>*filter
:DOCKER-USER - &#91;0:0]
:FILTERS - &#91;0:0]
#Can't flush INPUT. wipes out docker swarm encrypted overlay rules
#-F INPUT
#Use ansible or run manually once instead to add -I INPUT -j FILTERS
#-I INPUT -j FILTERS
-F DOCKER-USER
-A DOCKER-USER -m state --state RELATED,ESTABLISHED -j RETURN
-A DOCKER-USER -i docker_gwbridge -j RETURN
-A DOCKER-USER -s 172.18.0.0/16 -j RETURN
-A DOCKER-USER -i docker0 -j RETURN
-A DOCKER-USER -s 172.17.0.0/16 -j RETURN
#Below Docker ports open to everyone if uncommented
#-A DOCKER-USER -p tcp -m tcp -m multiport --dports 8000,8001 -j RETURN
#-A DOCKER-USER -p udp -m udp -m multiport --dports 9000,9001 -j RETURN
-A DOCKER-USER -m set ! --match-set ip_allow src -j DROP
-A DOCKER-USER -j RETURN
-F FILTERS
#Because Docker Swarm encrypted overlay network just appends rules to INPUT. Has to be at top unfortunately
-A FILTERS -p udp -m policy --dir in --pol ipsec -m udp -m set --match-set ip_allow src --dport 4789 -j RETURN
-A FILTERS -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FILTERS -p icmp -j ACCEPT
-A FILTERS -i lo -j ACCEPT
#Below OS ports open to everyone if uncommented
-A FILTERS -p tcp -m state --state NEW -m tcp -m multiport --dports 22 -j ACCEPT
#-A FILTERS -p udp -m udp -m multiport --dports 53,123 -j ACCEPT
-A FILTERS -m set ! --match-set ip_allow src -j DROP
-A FILTERS -j RETURN
COMMIT</code></pre>



<p>Use iptables-restore to add the above rules into iptables. The very important flag is <code>-n</code>. That makes sure we don&#8217;t flush the iptables rules if we have rules already in Docker (or Docker Swarm).</p>



<pre class="wp-block-code"><code># iptables-restore -n &lt; iptables-rules.txt</code></pre>



<p>Next, add a rule to the INPUT chain, so we start using the new rules in FILTERS. It has to be at the top, and only needs to be added once:</p>



<pre class="wp-block-code"><code># iptables -I INPUT 1 -j FILTERS</code></pre>



<p>Save the iptables rules:</p>



<pre class="wp-block-code"><code># /usr/libexec/iptables/iptables.init save</code></pre>



<p>That will save any existing and our new iptables rules to the iptables configuration file so it will be persistent after a reboot.</p>



<p>In addition, it was needed to run the above iptables command manually since we want to ensure it&#8217;s only inserted once. And we can&#8217;t flush the INPUT chain to ensure that since Docker Swarm could have rules there already.</p>



<p>Start and Enable the iptables service:</p>



<pre class="wp-block-code"><code># systemctl status iptables
# systemctl start iptables
# systemctl enable iptables</code></pre>



<p>If you want to customize the iptables rules to allow more ports to be open to everyone, just add the port to the appropriate rule in the iptables file (tcp or udp), then re-run the same commands from above:</p>



<pre class="wp-block-code"><code># iptables-restore -n &lt; iptables-rules.txt
# /usr/libexec/iptables/iptables.init save</code></pre>



<p><strong>Don&#8217;t miss the <a href="#warnings">Warnings</a> from above! Especially about SELinux.</strong></p>



<p>If you don&#8217;t want to do all of that manually, and you use Ansible, then do this instead..</p>



<h2 class="wp-block-heading">The Automatic way with Ansible</h2>



<p>Manually run all of the above, on every Docker server is not ideal. Let&#8217;s use Ansible instead!</p>



<p>I&#8217;ve created an <a rel="noreferrer noopener" href="https://galaxy.ansible.com/ryandaniels/iptables_docker" target="_blank">Ansible Role: iptables for Docker</a>, on <a rel="noreferrer noopener" href="https://github.com/ryandaniels/ansible-role-iptables-docker" target="_blank">GitHub</a> and <a rel="noreferrer noopener" href="https://galaxy.ansible.com/ryandaniels/iptables_docker" target="_blank">Ansible Galaxy</a>. </p>



<p>This works on CentOS 7, RHEL 7, Ubuntu 18.04, and Ubuntu 20.04.</p>



<p>Install the Ansible Role using Ansible Galaxy:</p>



<pre class="wp-block-code"><code>$ ansible-galaxy install ryandaniels.iptables_docker</code></pre>



<p>Or, clone the GitHub project:</p>



<pre class="wp-block-code"><code>$ git clone https://github.com/ryandaniels/ansible-role-iptables-docker.git roles/ryandaniels.iptables_docker</code></pre>



<p>Create the Ansible Playbook, called iptables_docker.yml:</p>



<pre class="wp-block-code"><code>---
- hosts: '{{ inventory }}'
  become: yes
  vars:
    # Use this role
    iptables_docker_managed: true
  roles:
  - ryandaniels.iptables_docker</code></pre>



<p>Make configuration changes to add desired IP addresses and ports as needed.</p>



<p><strong>Don&#8217;t miss the <a href="#warnings">Warnings</a> from above!</strong></p>



<p>Then run the playbook:</p>



<pre class="wp-block-code"><code>$ ansible-playbook iptables_docker.yml --extra-vars "inventory=centos7" -i hosts-dev</code></pre>



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



<p>In conclusion, now we have secured our Docker (and Docker Swarm) environments using Ansible to perform the installation and configuration of iptables! None of our Docker published ports are exposed to the world, unless we want them to be! We have created a custom Docker firewall with iptables. Hopefully, some day this will be the default behaviour and shipped with Docker out of the box! Dare to dream. Security is hard.</p>



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



<h3 class="wp-block-heading">Background for Docker&#8217;s undocumented use of iptables INPUT chain</h3>



<p><a href="https://ryandaniels.ca/blog/docker-iptables-input-chain/">See my previous post about this</a>.</p>



<h3 class="wp-block-heading">References and links</h3>



<p>References, notes, and links about the Docker firewall discussion:</p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" href="https://docs.docker.com/network/overlay/#encrypt-traffic-on-an-overlay-network" target="_blank">Docker Documentation &#8211; Overlay Networks</a></li><li><a rel="noreferrer noopener" href="https://github.com/docker/for-linux/issues/690" target="_blank">Docker bypasses ufw firewall rules</a></li><li><a rel="noreferrer noopener" href="https://unrouted.io/2017/08/15/docker-firewall/" target="_blank">unrouted</a> &#8211; Solution using iptables. Not for Swarm. It clobbers the INPUT chain, which is used by encrypted overlay with Docker Swarm</li><li><a rel="noreferrer noopener" href="https://github.com/moby/moby/issues/22054" target="_blank">The big thread about Docker and a firewall</a></li><li><a rel="noreferrer noopener" href="https://wiki.archlinux.org/index.php/Iptables#Chains" target="_blank">Arch Linux wiki to the rescue to show iptables</a> flow which links to a <a rel="noreferrer noopener" href="https://www.frozentux.net/iptables-tutorial/chunkyhtml/images/tables_traverse.jpg" target="_blank" rel="lightbox[2290]">great visual</a><br><br></li></ul>
<p>The post <a href="https://ryandaniels.ca/blog/secure-docker-with-iptables-firewall-and-ansible/">Secure Docker with iptables firewall and Ansible</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2290</post-id>	</item>
		<item>
		<title>How to fix Ubuntu 20.04 in 1 step</title>
		<link>https://ryandaniels.ca/blog/how-to-fix-ubuntu-20-04-in-1-step/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Sat, 23 May 2020 20:40:59 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2427</guid>

					<description><![CDATA[<p>There's not a lot wrong with Ubuntu 20.04. So it's pretty easy to fix the one thing that's missing! Hint: Install the Cinnamon Desktop.</p>
<p>The post <a href="https://ryandaniels.ca/blog/how-to-fix-ubuntu-20-04-in-1-step/">How to fix Ubuntu 20.04 in 1 step</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ubuntu 20.04 was recently released! <br>Overall, it&#8217;s great, and it works very well. But I did have one problem with it. It&#8217;s missing the Cinnamon Desktop.</p>



<p>I fixed it by running one command:</p>



<pre class="wp-block-code"><code>$ sudo apt install cinnamon-desktop-environment</code></pre>



<p>After it&#8217;s installed, reboot your computer. Then, before logging in, click the gear icon and change your session to Cinnamon.</p>



<p>Now everything is so much better!</p>



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



<p>This will install the <a rel="noreferrer noopener" href="https://projects.linuxmint.com/cinnamon/" target="_blank">Cinnamon Desktop Environment</a> for you. Which was initially developed for Linux Mint.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop.png" rel="lightbox[2427]"><img loading="lazy" decoding="async" width="1152" height="720" src="https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-1152x720.png" alt="Cinnamon Desktop on Ubuntu 20.04" class="wp-image-2438" srcset="https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-1152x720.png 1152w, https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-800x500.png 800w, https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-300x188.png 300w, https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-768x480.png 768w, https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop-1200x750.png 1200w, https://ryandaniels.ca/wp-content/uploads/2020/05/Ubuntu_20.04_Cinnamon_Desktop.png 1440w" sizes="auto, (max-width: 1152px) 100vw, 1152px" /></a></figure></div>



<p>The main downside with this approach is you&#8217;ll probably be using this version of Cinnamon Desktop for a while. Packages don&#8217;t update very often in Ubuntu. However, in general not being on the newest of the new does bring stability.</p>



<p>If you still use Windows you are missing out. You should think about <a href="https://ryandaniels.ca/blog/5-reasons-windows-upgrade-to-linux/">switching to Linux</a>.</p>



<p>It&#8217;s amazing! Give it a try.</p>
<p>The post <a href="https://ryandaniels.ca/blog/how-to-fix-ubuntu-20-04-in-1-step/">How to fix Ubuntu 20.04 in 1 step</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2427</post-id>	</item>
		<item>
		<title>5 Reasons Why You Should Upgrade Windows to Linux</title>
		<link>https://ryandaniels.ca/blog/5-reasons-windows-upgrade-to-linux/</link>
		
		<dc:creator><![CDATA[Ryan Daniels]]></dc:creator>
		<pubDate>Tue, 24 Dec 2019 03:27:34 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Linux Mint]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://ryandaniels.ca/?p=2042</guid>

					<description><![CDATA[<p><a href="https://ryandaniels.ca/blog/no-windows-upgrade-to-linux/"></p>
<figure class="alignleft size-thumbnail"><img src="https://ryandaniels.ca/wp-content/uploads/2019/12/tux-254x300.png" alt="Tux" class="wp-image-2052"/></figure>
<p></a>It's time. Windows users, Upgrade to Linux. Windows 7 is reaching the end. You must upgrade. Do not replace Windows 7 with Windows 10. That is not an upgrade! Upgrade Windows to Linux Mint. It's so much better!<br />
&#160;<br />
&#160;</p>
<p>The post <a href="https://ryandaniels.ca/blog/5-reasons-windows-upgrade-to-linux/">5 Reasons Why You Should Upgrade Windows to Linux</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="alignright size-thumbnail"><img loading="lazy" decoding="async" width="254" height="300" src="https://ryandaniels.ca/wp-content/uploads/2019/12/tux-254x300.png" alt="Tux" class="wp-image-2052" srcset="https://ryandaniels.ca/wp-content/uploads/2019/12/tux-254x300.png 254w, https://ryandaniels.ca/wp-content/uploads/2019/12/tux-509x600.png 509w, https://ryandaniels.ca/wp-content/uploads/2019/12/tux-611x720.png 611w, https://ryandaniels.ca/wp-content/uploads/2019/12/tux-768x905.png 768w, https://ryandaniels.ca/wp-content/uploads/2019/12/tux.png 933w" sizes="auto, (max-width: 254px) 100vw, 254px" /></figure></div>



<p>It&#8217;s time. Windows users, Upgrade to Linux. Windows 7 is reaching the <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://support.microsoft.com/en-us/help/4057281/windows-7-support-will-end-on-january-14-2020" target="_blank">end of the line</a> after January 14, 2020. Users must upgrade to something else. Do not replace Windows 7 with Windows 10. That is not an upgrade! How else can I say this? Do not downgrade from Windows 7 to Windows 10. Instead, upgrade Windows 7 to Linux!</p>



<p>In case you haven&#8217;t heard, do not use Windows 10, <a rel="noreferrer noopener" aria-label="for many reasons (opens in a new tab)" href="https://www.privacytools.io/operating-systems/#win10" target="_blank">for many reasons</a>. It&#8217;s a &#8220;Privacy Nightmare&#8221;!<br>Also, it&#8217;s actually really bad to use. They add junk into your Desktop menu at random. And it will come back even if you delete it. <br>Do you like ads? <a rel="noreferrer noopener" aria-label="Microsoft is infesting Windows 10 with annoying ads (opens in a new tab)" href="https://www.theverge.com/2017/3/17/14956540/microsoft-windows-10-ads-taskbar-file-explorer" target="_blank">Microsoft is infesting Windows 10 with annoying ads</a>. <br><strong>You are not in control</strong>.</p>



<p>And then there&#8217;s the many problems with Windows 10 updates. <a rel="noreferrer noopener" aria-label="So (opens in a new tab)" href="https://www.forbes.com/sites/gordonkelly/2019/04/17/microsoft-windows-10-problem-update-warning-upgrade-cost/" target="_blank">So</a> <a rel="noreferrer noopener" aria-label="many (opens in a new tab)" href="https://www.computerworld.com/article/3407712/microsoft-s-windows-update-system-is-broken-will-it-ever-be-fixed.html" target="_blank">many</a> <a rel="noreferrer noopener" aria-label="crazy (opens in a new tab)" href="https://www.techradar.com/news/microsoft-once-again-sends-out-the-wrong-windows-10-update-to-users" target="_blank">crazy</a> <a rel="noreferrer noopener" aria-label="problems (opens in a new tab)" href="https://www.bleepingcomputer.com/news/microsoft/windows-10-1909-kb4517245-update-causes-file-explorer-issues/" target="_blank">problems</a>! It&#8217;s just plain bad. <a rel="noreferrer noopener" aria-label="Did you know Windows 10 deleted user's personal data! (opens in a new tab)" href="https://www.forbes.com/sites/gordonkelly/2018/10/06/microsoft-windows-10-update-lost-data-upgrade-windows-7-windows-xp-free-upgrade/" target="_blank">Did you know Windows 10 deleted user&#8217;s personal data</a>! Also there are <a href="https://www.techradar.com/news/windows-10s-latest-troublesome-update-is-now-reportedly-causing-boot-failures" target="_blank" rel="noreferrer noopener" aria-label="problems with Windows 10 booting after updating (opens in a new tab)">problems with Windows 10 booting after updating</a>.</p>



<h2 class="wp-block-heading">Linux, Everybody&#8217;s doing it!</h2>



<p>There are <a rel="noreferrer noopener" aria-label="so (opens in a new tab)" href="https://www.forbes.com/sites/jasonevangelho/2018/07/23/5-reasons-you-should-switch-from-windows-to-linux-right-now/" target="_blank">so</a> <a rel="noreferrer noopener" aria-label="many (opens in a new tab)" href="https://www.lifewire.com/reasons-to-switch-to-linux-4583960" target="_blank">many</a> <a rel="noreferrer noopener" aria-label="reason (opens in a new tab)" href="https://www.forbes.com/sites/jasonevangelho/2019/03/29/shadowhammer-asus-1-million-reasons-switch-from-windows-to-linux/" target="_blank">reason</a> to upgrade to Linux. If all you do on your computer is use a web browser, occasionally open pictures, sometimes open a spreadsheet or text document then you should definitely upgrade to Linux.</p>



<p>Even if you are a power user, there&#8217;s probably a Linux application that will replace that Windows app. But, even if there isn&#8217;t, you can use software like <a rel="noreferrer noopener" aria-label="Wine (opens in a new tab)" href="https://www.winehq.org/" target="_blank">Wine</a> to run Windows apps on Linux!</p>



<p>Do you game? <a rel="noreferrer noopener" aria-label="Steam (opens in a new tab)" href="https://store.steampowered.com/linux" target="_blank">Steam</a> is an easy way to game on Linux! And it&#8217;s <a rel="noreferrer noopener" aria-label="easy to install (opens in a new tab)" href="https://itsfoss.com/install-steam-ubuntu-linux/" target="_blank">easy to install</a>.</p>



<p>And then there&#8217;s the Linux community. It is absolutely amazing. When you do have an issue, there is so much help available by just searching.</p>



<h2 class="wp-block-heading">Top 5 Reasons to switch to Linux</h2>



<ol class="wp-block-list"><li>Linux just works</li><li>Linux is more secure</li><li>Surprise, Linux is easy to upgrade</li><li>Linux works on old hardware</li><li>Linux is easy to customize</li><li>Bonus Reason: Amazing community for help</li></ol>



<h2 class="wp-block-heading">Which Linux Desktop to Choose?</h2>



<p>Linux on the Desktop has many distributions to choose from. There&#8217;s no single company to dictate what you can do!</p>



<p>With so many options to choose from, how do you pick? If it&#8217;s your first time using a Linux Desktop, try a distro that&#8217;s easy to get up and running. <br>&#8220;<a rel="noreferrer noopener" aria-label="Linux Mint (opens in a new tab)" href="https://linuxmint.com/" target="_blank">Linux Mint</a> Cinnamon Edition&#8221; is a great choice to get started!</p>



<p>Why? Linux Mint is based on Ubuntu which is very popular and easy to use. If you need help, you will be able to find an answer since Ubuntu is so popular. And Linux Mint uses a nice desktop environment by default, called Cinnamon.</p>



<figure class="wp-block-image size-medium is-style-default"><a href="https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon.png" rel="lightbox[2042]"><img loading="lazy" decoding="async" width="800" height="500" src="https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-800x500.png" alt="Linux Mint Cinnamon - No Windows Upgrade Linux" class="wp-image-2049" srcset="https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-800x500.png 800w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-1152x720.png 1152w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-300x188.png 300w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-768x480.png 768w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-1536x960.png 1536w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon-1200x750.png 1200w, https://ryandaniels.ca/wp-content/uploads/2019/12/linux_mint_cinnamon.png 1920w" sizes="auto, (max-width: 800px) 100vw, 800px" /></a><figcaption>Image Credit: Linux Mint</figcaption></figure>



<p>More screenshot can be found on the <a href="https://linuxmint.com/screenshots.php" target="_blank" rel="noreferrer noopener" aria-label="Linux Mint website (opens in a new tab)">Linux Mint website</a>.</p>



<p>Don&#8217;t want to use Linux Mint Cinnamon? Try Ubuntu instead. That&#8217;s what Linux Mint is based on after all! <a rel="noreferrer noopener" aria-label="Kubuntu (opens in a new tab)" href="https://kubuntu.org/getkubuntu/" target="_blank">Kubuntu</a> has a very nice desktop environment similar to Windows.</p>



<h2 class="wp-block-heading">How to Upgrade from Windows to Linux Mint</h2>



<h3 class="wp-block-heading">Test it out before Installing</h3>



<p>You can even try out Linux Mint before you install it to your hard drive. Actually most Linux distros can do this! Just download the ISO image and add it to a USB stick using <a rel="noreferrer noopener" aria-label="LinuxLive USB Creator (opens in a new tab)" href="https://www.linuxliveusb.com/" target="_blank">LinuxLive USB Creator</a>. Then reboot your computer and boot from the USB stick. Now you are test driving Linux Mint on your computer! Need a step by step guide? Check out their <a rel="noreferrer noopener" aria-label="documentation (opens in a new tab)" href="https://linuxmint-installation-guide.readthedocs.io/en/latest/install.html" target="_blank">documentation</a>.</p>



<h3 class="wp-block-heading">Backup Windows</h3>



<p>Before you install, be sure to backup your existing installation. A great tool for this is called <a rel="noreferrer noopener" aria-label="Macrium Reflect (opens in a new tab)" href="https://www.macrium.com/reflectfree" target="_blank">Macrium Reflect</a>. This can save an &#8220;image&#8221; of Windows to a file. Then later when running Linux Mint, you can start up your old Windows image as a virtual machine using <a rel="noreferrer noopener" aria-label="VirtualBox (opens in a new tab)" href="https://www.virtualbox.org/" target="_blank">VirtualBox</a>! </p>



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



<p>There are many guides online if you do a search. One thorough guide can be found <a rel="noreferrer noopener" aria-label="here (opens in a new tab)" href="https://www.zdnet.com/article/how-to-replace-windows-7-with-linux-mint/" target="_blank">here</a>.</p>



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



<p>After you have upgraded to Linux, you are now free from Windows! No more worrying. You are free to enjoy Linux and all it has to offer. Next maybe you want to customize a few things. Linux (and Linux Mint) make that so easy.</p>



<p>Goodbye Windows, Hello Linux Mint!</p>
<p>The post <a href="https://ryandaniels.ca/blog/5-reasons-windows-upgrade-to-linux/">5 Reasons Why You Should Upgrade Windows to Linux</a> appeared first on <a href="https://ryandaniels.ca/">Ryan Daniels</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2042</post-id>	</item>
	</channel>
</rss>
