<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Centos on Major Hayden</title><link>https://major.io/tags/centos/</link><description>Recent content in Centos on Major Hayden</description><generator>Hugo</generator><language>en</language><managingEditor>major@mhtx.net (Major Hayden)</managingEditor><webMaster>major@mhtx.net (Major Hayden)</webMaster><copyright>All content licensed [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)</copyright><lastBuildDate>Sun, 07 Jun 2026 23:39:03 +0000</lastBuildDate><atom:link href="https://major.io/tags/centos/index.xml" rel="self" type="application/rss+xml"/><item><title>Texas Linux Fest 2024 recap 🤠</title><link>https://major.io/p/texas-linux-fest-2024-recap/</link><pubDate>Tue, 16 Apr 2024 00:00:00 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/texas-linux-fest-2024-recap/</guid><description>&lt;p&gt;The 2024 &lt;a href="https://2024.texaslinuxfest.org/"&gt;Texas Linux Festival&lt;/a&gt; just ended last weekend and it was a fun event as always.
It&amp;rsquo;s one my favorite events to attend because it&amp;rsquo;s really casual.
You have plenty of opportunities to see old friends, meet new people, and learn a few things along the way.&lt;/p&gt;
&lt;p&gt;I was fortunate enough to have two talks accepted for this year&amp;rsquo;s event.
One was focused on containers while the other was a (very belated) addition to my &lt;a href="https://major.io/p/impostor-syndrome-talk-faqs-and-follow-ups/"&gt;impostor syndrome talk&lt;/a&gt; from 2015.&lt;/p&gt;
&lt;p&gt;This was also my first time building slides with &lt;a href="https://github.com/webpro/reveal-md"&gt;reveal-md&lt;/a&gt;, a &amp;ldquo;batteries included&amp;rdquo; package for making &lt;a href="https://revealjs.com/"&gt;reveal.js&lt;/a&gt; slides.
Nothing broke too badly and that was a relief.&lt;/p&gt;
&lt;h2 id="containers-talk"&gt;Containers talk&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve wanted to share more of what I&amp;rsquo;ve done with CoreOS in low-budget container deployments and this seemed like a good time to share it with the world out loud.
My talk, &lt;a href="https://txlf24-containers.major.io/#/"&gt;Automated container updates with GitHub and CoreOS&lt;/a&gt;, walked the audience through how to deploy containers on CoreOS, keep them updated, and update the container image source.&lt;/p&gt;
&lt;p&gt;My goal was to keep it as low on budget as possible.
Much of it was centered around a stack of &lt;a href="https://major.io/p/caddy-porkbun/"&gt;caddy&lt;/a&gt;, librespeed, and docker-compose.
All of it was kept up to date with &lt;a href="https://major.io/p/watchtower/"&gt;watchtower&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My custom Caddy container needed support for &lt;a href="https://porkbun.com/"&gt;Porkbun&amp;rsquo;s&lt;/a&gt; DNS API and I used GitHub Actions to build that container and serve it to the internet using GitHub&amp;rsquo;s package hosting.
&lt;em&gt;This also gave me the opportunity to share how awesome Porkbun is for registering domains, including their &lt;a href="https://porkbun.com/tld/jobs"&gt;customized pig artwork&lt;/a&gt; for every TLD imaginable.&lt;/em&gt; 🐷&lt;/p&gt;
&lt;p&gt;We had a great discussion afterwards about how CoreOS &lt;strong&gt;does indeed live on&lt;/strong&gt; as &lt;a href="https://fedoraproject.org/coreos/"&gt;Fedora CoreOS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="tech-career-talk"&gt;Tech career talk&lt;/h2&gt;
&lt;p&gt;This talk made me nervous because it had a lot of slides to cover, but I also wanted to leave plenty of time for questions.
&lt;a href="https://txlf24-tech-career.major.io/#/"&gt;Five tips for a thriving technology career&lt;/a&gt; built upon my old impostor syndrome talk by sharing some of the things I&amp;rsquo;ve learned over the year that helped me succeed in my career.&lt;/p&gt;
&lt;p&gt;I managed to end early with time for questions, and boy did the audience have questions! 📣
Some audience members helped me answer some questions, too!&lt;/p&gt;
&lt;p&gt;We talked a lot about office politics, tribal knowledge, and toxic workplaces.
The audience generally agreed that most businesses tried to rub copious amounts of Confluence on their tribal knowledge problem, but it never improved. 😜&lt;/p&gt;
&lt;p&gt;The room was full with people standing in the back and I&amp;rsquo;m tremendously humbled by everyone who came.
I received plenty of feedback afterwards and that&amp;rsquo;s the best gift I could ever get. 🎁&lt;/p&gt;
&lt;h2 id="other-talks"&gt;Other talks&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/anitazha"&gt;Anita Zhang&lt;/a&gt; had an excellent keynote talk on the second day about her unusual path into the world of technology.
Her slides were pictures of her dog that lined up with various parts of her story.
That was a great idea.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/kyle-davis-linux/?originalSubdomain=ca"&gt;Kyle Davis&lt;/a&gt; offered talks on &lt;a href="https://github.com/valkey-io/valkey"&gt;valkey&lt;/a&gt; and &lt;a href="https://github.com/bottlerocket-os/bottlerocket"&gt;bottlerocket&lt;/a&gt;.
There was plenty about the redis and valkey story that I didn&amp;rsquo;t know and the context was useful.
It looks like you can simply drop valkey into most redis environments without much disruption.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/thomascameron/"&gt;Thomas Cameron&lt;/a&gt; talked about running OKD on Fedora CoreOS in his home lab.
There were quite a few steps, but he did a great job of connecting the dots between what needed to be done and why.&lt;/p&gt;
&lt;h2 id="around-the-exhibit-hall"&gt;Around the exhibit hall&lt;/h2&gt;
&lt;p&gt;I helped staff the Fedora/CoreOS booth and we had plenty of questions.
Most questions were around the M1 Macbook running &lt;a href="https://asahilinux.org/"&gt;Asahi Linux&lt;/a&gt; that was on the table. 😉&lt;/p&gt;
&lt;p&gt;There were still quite a few misconceptions around the CentOS Stream changes, as well as how AlmaLinux and Rocky Linux fit into the picture.
Our booth was right next to the AlmaLinux booth and I had the opportunity to meet &lt;a href="https://jonathanspw.com/about/"&gt;Jonathan Wright&lt;/a&gt;.
That was awesome!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I can&amp;rsquo;t wait for next year&amp;rsquo;s event.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Build a Tailscale exit node with firewalld</title><link>https://major.io/p/build-tailscale-exit-node-firewalld/</link><pubDate>Thu, 27 Oct 2022 00:00:00 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/build-tailscale-exit-node-firewalld/</guid><description>&lt;p&gt;Once upon a time, I spent hours and hours fumbling through openvpn configurations, certificates, and firewalls to get VPNs working between servers.
One small configuration error led to lots of debugging.
Adding new servers meant wallowing through this process all over again.&lt;/p&gt;
&lt;p&gt;A friend told me about &lt;a href="https://tailscale.com/"&gt;Tailscale&lt;/a&gt; and it makes private networking incredibly simple.&lt;/p&gt;
&lt;p&gt;Tailscale makes it easy to add nodes to a private network called a &lt;em&gt;tailnet&lt;/em&gt; where they can communicate.
In short, it&amp;rsquo;s a dead simple mesh network (with advanced capabilities if you&amp;rsquo;re interested).&lt;/p&gt;
&lt;p&gt;This post covers how to create an exit node for your Tailscale network using firewalld Fedora, CentOS Stream, and Red Hat Enterprise Linux (RHEL).&lt;/p&gt;
&lt;h1 id="whats-an-exit-node"&gt;What&amp;rsquo;s an exit node?&lt;/h1&gt;
&lt;p&gt;Every node on a Tailscale network, or &lt;em&gt;tailnet&lt;/em&gt;, can communicate with each other&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.
However, it can use be useful to use one of those nodes on the network as an exit node.&lt;/p&gt;
&lt;p&gt;Exit nodes allow traffic to leave the tailnet and go out to other networks or the public internet.
This allows you to join an untrusted network, such as a coffee shop&amp;rsquo;s wifi network, and send your traffic out through one of your tailnet nodes.
It works more like a traditional VPN.&lt;/p&gt;
&lt;p&gt;Tailscale does this by changing the routes on your device to use the exit node on your tailnet for all traffic.
Creating an exit node involves some configuration on the node itself and within Tailscale&amp;rsquo;s administrative interface.&lt;/p&gt;
&lt;h1 id="deploy-tailscale"&gt;Deploy Tailscale&lt;/h1&gt;
&lt;p&gt;In this example, I&amp;rsquo;ll use Fedora 36, but these instructions work for CentOS Stream and RHEL, too.&lt;/p&gt;
&lt;p&gt;Start by installing Tailscale on your system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tailscale.com/download/linux/fedora"&gt;Fedora&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailscale.com/download/linux/centos-stream-9"&gt;CentOS Stream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailscale.com/download/linux/rhel-9"&gt;RHEL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s get this going on Fedora:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/fedora/tailscale.repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Adding repo from: https://pkgs.tailscale.com/stable/fedora/tailscale.repo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo dnf install tailscale
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now tailscaled
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo tailscale up
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;To authenticate, visit:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;	https://login.tailscale.com/a/xxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Click the link to authorize the node to join your tailnet and it should appear in your list of nodes!&lt;/p&gt;
&lt;h1 id="trusting-the-tailnet"&gt;Trusting the tailnet&lt;/h1&gt;
&lt;p&gt;In my case, I treat my tailnet interfaces as trusted interfaces on each node.
&lt;em&gt;(This might not fit your use case, so please read the docs on &lt;a href="https://tailscale.com/kb/1018/acls/"&gt;Network access controls (ACLs)&lt;/a&gt; if you need extra security layers.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Start by adding the new &lt;code&gt;tailscale0&lt;/code&gt; interface as a trusted interface:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --add-interface&lt;span class="o"&gt;=&lt;/span&gt;tailscale0 --zone&lt;span class="o"&gt;=&lt;/span&gt;trusted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;success
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --list-all --zone&lt;span class="o"&gt;=&lt;/span&gt;trusted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;trusted (active)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; target: ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; icmp-block-inversion: no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; interfaces: tailscale0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; sources: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; services: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; protocols: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; forward: yes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; masquerade: no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; forward-ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; source-ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; icmp-blocks: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; rich rules: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This permits all traffic in and out of the tailscale interface.&lt;/p&gt;
&lt;h1 id="creating-an-exit-node"&gt;Creating an exit node&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s reconfigure tailscale to allow this node to serve as an exit node:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; tailscale up --advertise-exit-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Warning: IP forwarding is disabled, subnet routing/exit nodes will not work.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;See https://tailscale.com/kb/1104/enable-ip-forwarding/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Uh oh.
Tailscale is telling us that it&amp;rsquo;s happy to reconfigure itself, but we&amp;rsquo;re going to run into IP forwarding issues.
Let&amp;rsquo;s see what our primary firewall zone has:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --list-all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;public (active)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; target: default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; icmp-block-inversion: no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; interfaces: eth0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; sources: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; services: dhcpv6-client mdns ssh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; protocols: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; forward: yes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; masquerade: no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; forward-ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; source-ports: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; icmp-blocks: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; rich rules: 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can enable masquerading in firewalld and it will take care of everything for us, including NAT rules and &lt;code&gt;sysctl&lt;/code&gt; settings for IP forwarding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --add-masquerade --zone&lt;span class="o"&gt;=&lt;/span&gt;public
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;success
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --list-all &lt;span class="p"&gt;|&lt;/span&gt; grep masq
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; masquerade: yes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try the Tailscale reconfiguration once more:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; tailscale up --advertise-exit-node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Warning: IPv6 forwarding is disabled.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Subnet routes and exit nodes may not work correctly.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;See https://tailscale.com/kb/1104/enable-ip-forwarding/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We fixed the IPv4 forwarding, but IPv6 is still not configured properly.
This was done automatically in the past, but firewalld &lt;a href="https://github.com/firewalld/firewalld/issues/683"&gt;does not automatically enable IPv6 forwarding&lt;/a&gt; in recent versions.
&lt;a href="https://firewalld.org/documentation/man-pages/firewalld.richlanguage.html"&gt;Rich rules&lt;/a&gt; come to the rescue:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; firewall-cmd --add-rich-rule&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;rule family=ipv6 masquerade&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;success
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; sysctl -a &lt;span class="p"&gt;|&lt;/span&gt; grep net.ipv6.conf.all.forwarding
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;net.ipv6.conf.all.forwarding = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One more try:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; tailscale up --advertise-exit-node
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Success!
But wait, we still can&amp;rsquo;t send traffic through the exit node until we authorize it in the Tailscale admin interface:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go back to your &lt;a href="https://login.tailscale.com/admin/machines"&gt;machines list&lt;/a&gt; at Tailscale and find your exit node.&lt;/li&gt;
&lt;li&gt;Right underneath the name of the node, you should see &lt;strong&gt;Exit Node&lt;/strong&gt; followed by a circle with an exclamation point.&lt;/li&gt;
&lt;li&gt;Click the three dots on the far right of that row and click &lt;strong&gt;Edit Route Settings&amp;hellip;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When the modal appears, click the slider to the left of &lt;strong&gt;Use as exit node&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now you can test your exit node from your mobile device by choosing an exit node via the settings menu.
Another Linux machine can use it as an exit node as well just by running another &lt;code&gt;tailscale up&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Start using an exit node.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo tailscale up --exit-node my-exit-node-name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stop using an exit node.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo tailscale up --exit-node &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Tailscale offers complex access control lists (ACLs) that allow you to limit connectivity based on tons of factors.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Build a custom CentOS Stream 9 cloud image</title><link>https://major.io/p/build-custom-centos-stream-cloud-image/</link><pubDate>Fri, 06 May 2022 00:00:00 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/build-custom-centos-stream-cloud-image/</guid><description>&lt;p&gt;This is my &lt;a href="https://major.io/tags/imagebuilder/"&gt;third post&lt;/a&gt; about &lt;a href="https://www.osbuild.org/documentation/"&gt;Image Builder&lt;/a&gt;, so I guess you could say that I enjoy
using it&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;. It&amp;rsquo;s a great way to define a custom cloud image, build it, and
(optionally) ship it to a supported cloud provider.&lt;/p&gt;
&lt;p&gt;This post covers how to build a customized CentOS Stream 9 image along with a custom
repository for additional packages. In this case, that&amp;rsquo;s &lt;a href="https://docs.fedoraproject.org/en-US/epel/"&gt;Extra Packages for Enterprise
Linux (EPEL)&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="why-do-i-need-a-custom-image-anyway"&gt;Why do I need a custom image anyway?&lt;/h1&gt;
&lt;p&gt;Building your own image empowers you to choose which packages you want, which services
run at boot time, and where you deploy your image. Some cloud providers may not have an
image from the Linux distribution you enjoy most, or they might have an image with the
wrong package set.&lt;/p&gt;
&lt;p&gt;Some cloud providers build images with too many packages or too few. Sometimes they add
configuration that doesn&amp;rsquo;t exist in the OS itself. I&amp;rsquo;ve even found some that alter
cloud-init and force you to log in directly as the &lt;code&gt;root&lt;/code&gt; user. 😱&lt;/p&gt;
&lt;p&gt;I enjoy building my own images so I know exactly what it contains and I know that the
configuration came from the OS itself.&lt;/p&gt;
&lt;h1 id="first-steps"&gt;First steps&lt;/h1&gt;
&lt;p&gt;This post uses CentOS Stream 9 as an example. You will need a physical host, virtual
machine, or cloud instance running CentOS Stream 9 first. We start by installing some
packages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo dnf install osbuild-composer weldr-client
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What do these packages contain?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;osbuild-composer&lt;/em&gt; ensures you have &lt;em&gt;osbuild&lt;/em&gt;, the low-level image build component,
along with configuration and an osbuild-composer&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; worker that builds the
image.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;weldr-client&lt;/em&gt; contains the &lt;code&gt;composer-cli&lt;/code&gt; command line tool that makes it easy to
interact with &lt;em&gt;osbuild-composer&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One nice thing about this stack is that it starts via systemd&amp;rsquo;s &lt;a href="https://0pointer.de/blog/projects/socket-activation.html"&gt;socket activation&lt;/a&gt; and
it only runs when you query it. Let&amp;rsquo;s start the socket now and ensure it comes up on a
reboot:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now osbuild-composer.socket
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Verify that the API is responding:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; composer-cli status show
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;API server status:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Database version: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Database supported: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Schema version: 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; API version: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Backend: osbuild-composer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Build: NEVRA:osbuild-composer-46-1.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="adding-epel"&gt;Adding EPEL&lt;/h1&gt;
&lt;p&gt;CentOS Stream 9 has most of the packages I want, but I really love this program called
&lt;a href="https://htop.dev/"&gt;&lt;code&gt;htop&lt;/code&gt;&lt;/a&gt; that displays resource usage and allows you to introspect certain processes or
namespaces easily. This package is only available in the EPEL repository, so we need to
add that one to our list of enabled repositories for image builds.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;osbuild-composer&lt;/em&gt; comes with its own set of repositories in the package and does not
use the system&amp;rsquo;s repositories. You can list all the enabled repositories that it
knows about:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli sources list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;AppStream
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;BaseOS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;RT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to add EPEL, we can dump the configuration from one of these to a file and
edit it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli sources info AppStream &lt;span class="p"&gt;|&lt;/span&gt; tee epel.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;check_gpg = true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;check_ssl = true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;id = &amp;#34;AppStream&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;name = &amp;#34;AppStream&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;rhsm = false
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;system = true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;type = &amp;#34;yum-baseurl&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;url = &amp;#34;https://composes.stream.centos.org/production/latest-CentOS-Stream/compose/AppStream/x86_64/os/&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After editing the EPEL repository file, it should look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;check_gpg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;check_ssl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;EPEL9&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;EPEL9&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;rhsm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;yum-baseurl&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://mirrors.kernel.org/fedora-epel/9/Everything/x86_64/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can use any mirror you prefer, but the kernel mirrors are very fast for me from most
locations. Now we need to add this repository:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli sources add epel.ini
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli sources list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;AppStream
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;BaseOS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;EPEL9
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;RT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We now have &lt;code&gt;EPEL9&lt;/code&gt; in our list. 🎉&lt;/p&gt;
&lt;h1 id="define-our-image"&gt;Define our image&lt;/h1&gt;
&lt;p&gt;All image definitions, or blueprints, are in TOML format. Here&amp;rsquo;s my simple one for this
post:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Save this file as image.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;centos9&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Major&amp;#39;s awesome CentOS 9 image&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tmux&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vim&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# This is the one that comes from EPEL.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;htop&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we push our blueprint and solve the dependencies to ensure we added our EPEL
repository properly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli blueprints push image.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli blueprints depsolve centos9
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; -- SNIP --
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; 2:vim-filesystem-8.2.2637-16.el9.noarch
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; which-2.21-27.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; xz-5.2.5-7.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; xz-libs-5.2.5-7.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; zlib-1.2.11-33.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; htop-3.1.2-3.el9.x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And there&amp;rsquo;s &lt;code&gt;htop&lt;/code&gt; at the end of the list! 🎉&lt;/p&gt;
&lt;h1 id="make-the-image"&gt;Make the image&lt;/h1&gt;
&lt;p&gt;The fun part has arrived! Let&amp;rsquo;s build an image:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli compose start centos9 ami --size&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Compose ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e added to the queue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command does a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Starts an image build with our &lt;code&gt;centos9&lt;/code&gt; blueprint (from the &lt;code&gt;name&lt;/code&gt; section of my
&lt;code&gt;image.toml&lt;/code&gt; file)&lt;/li&gt;
&lt;li&gt;Outputs an image type that works well on AWS (Amazon Machine Image, or AMI)&lt;/li&gt;
&lt;li&gt;Limits the image size to 4GB (be sure this is not too large for your preferred
instance size)&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;🤔 Note that you do not need to set the size explicitly here, but I do it as a good
measure. When your instance boots, &lt;code&gt;cloud-init&lt;/code&gt; runs &lt;code&gt;growpart&lt;/code&gt; to expand the storage
to fit the disk size in your cloud instance.&lt;/p&gt;
&lt;p&gt;💣 &lt;strong&gt;However&lt;/strong&gt;, &lt;code&gt;growpart&lt;/code&gt; will not &lt;em&gt;shrink&lt;/em&gt; the disk at boot time. If you choose a
size that is larger than the disk space in your cloud instance, you will likely see an
error at provisioning time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s check the status after a few minutes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli compose status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e FINISHED Fri May 6 16:16:08 2022 centos9 0.0.1 ami 4096
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to get a copy of the image and import it yourself into your favorite cloud,
you can do that now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; composer-cli compose image ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e-image.raw
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;#&lt;/span&gt; ls -alh ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e-image.raw
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;-rw-------. 1 root root 2.7G May 6 16:20 ca57fd64-11ea-41d4-b924-9b8f5bdcaf5e-image.raw
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also let &lt;em&gt;osbuild-composer&lt;/em&gt; do this for you! I have one post on this blog about
&lt;a href="https://major.io/2020/06/19/build-aws-images-with-imagebuilder/"&gt;automatically uploading to AWS&lt;/a&gt; and another post on the Red Hat blog about &lt;a href="https://www.redhat.com/en/blog/build-rhel-images-azure-image-builder"&gt;doing the
same with Azure&lt;/a&gt;.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I once worked on the team that makes Image Builder happen, so I may be a
little bit biased. Enjoy the post anyway. 😉&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Most people at Red Hat just call it &lt;em&gt;composer&lt;/em&gt;, but I&amp;rsquo;ll use the full
name here to avoid confusion.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Allow a port range with firewalld</title><link>https://major.io/p/allow-port-range-with-firewalld/</link><pubDate>Fri, 04 Jan 2019 00:00:00 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/allow-port-range-with-firewalld/</guid><description>&lt;p&gt;Managing iptables gets a lot easier with &lt;a href="https://firewalld.org/"&gt;firewalld&lt;/a&gt;. You can manage rules for
the IPv4 and IPv6 stacks using the same commands and it provides fine-grained
controls for various &amp;ldquo;zones&amp;rdquo; of network sources and destinations.&lt;/p&gt;
&lt;h2 id="quick-example"&gt;Quick example&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s an example of allowing an arbitrary port (for &lt;a href="https://github.com/netdata/netdata"&gt;netdata&lt;/a&gt;) through the
firewall with iptables and firewalld on Fedora:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;## iptables
iptables -A INPUT -j ACCEPT -p tcp --dport 19999
ip6tables -A INPUT -j ACCEPT -p tcp --dport 19999
service iptables save
service ip6tables save

## firewalld
firewall-cmd --add-port=19999/tcp --permanent
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, &lt;code&gt;firewall-cmd&lt;/code&gt; allows us to allow a TCP port through the
firewall with a much simpler interface and the change is made permanent with
the &lt;code&gt;--permanent&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;You can always test a change with firewalld without making it permanent:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;firewall-cmd --add-port=19999/tcp
## Do your testing to make sure everything works.
firewall-cmd --runtime-to-permanent
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;--runtime-to-permanent&lt;/code&gt; argument tells firewalld to write the currently
active firewall configuration to disk.&lt;/p&gt;
&lt;h2 id="adding-a-port-range"&gt;Adding a port range&lt;/h2&gt;
&lt;p&gt;I use &lt;a href="https://mosh.org/"&gt;mosh&lt;/a&gt; with most of my servers since it allows me to reconnect to an
existing session from anywhere in the world and it makes higher latency
connections less painful. Mosh requires a range of UDP ports (60000 to 61000)
to be opened.&lt;/p&gt;
&lt;p&gt;We can do that easily in firewalld:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;firewall-cmd --add-port=60000-61000/udp --permanent
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can also see the rule it added to the firewall:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# iptables-save | grep 61000
-A IN_public_allow -p udp -m udp --dport 60000:61000 -m conntrack --ctstate NEW,UNTRACKED -j ACCEPT
# ip6tables-save | grep 61000
-A IN_public_allow -p udp -m udp --dport 60000:61000 -m conntrack --ctstate NEW,UNTRACKED -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you haven&amp;rsquo;t used firewalld yet, give it a try! There&amp;rsquo;s a lot more documentation on common use cases in the &lt;a href="https://docs.fedoraproject.org/en-US/quick-docs/firewalld/"&gt;Fedora firewalld documentation&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Install testing kernels in Fedora</title><link>https://major.io/p/install-testing-kernels-in-fedora/</link><pubDate>Wed, 28 Feb 2018 13:53:48 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/install-testing-kernels-in-fedora/</guid><description>&lt;p&gt;If you&amp;rsquo;re on the latest Fedora release, you&amp;rsquo;re already running lots of modern packages. However, there are those times when you may want to help with testing efforts or try out a new feature in a newer package.&lt;/p&gt;
&lt;p&gt;Most of my systems have the &lt;code&gt;updates-testing&lt;/code&gt; repository enabled in one way or another. This repository contains packages that package maintainers have submitted to become the next stable package in Fedora. For example, if there is a bug fix for nginx, the package maintainer submits the changes and publish a release. That release goes into the testing repositories and must sit for a waiting period or receive sufficient karma (&amp;ldquo;works for me&amp;rdquo; responses) to move into stable repositories.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started&lt;/h2&gt;
&lt;p&gt;One of the easiest ways to get started is to allow a small amount of packages to be installed from the testing repository on a regular basis. Fully enabling the testing repository for all packages can lead to trouble on occasion, especially if a package maintainer discovers a problem and submits a new testing package.&lt;/p&gt;
&lt;p&gt;To get started, open &lt;code&gt;/etc/yum.repos.d/fedora-updates-testing.repo&lt;/code&gt; in your favorite text editor (using &lt;code&gt;sudo&lt;/code&gt;). This file tells yum and dnf where it should look for packages. The stock testing repository configuration looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[updates-testing]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Fedora $releasever - $basearch - Test Updates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;failovermethod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;priority&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;metalink&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://mirrors.fedoraproject.org/metalink?repo=updates-testing-f$releasever&amp;amp;arch=$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;repo_gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;rpm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;metadata_expire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;6h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;gpgkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;skip_if_unavailable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By default, the repository is not enabled (&lt;code&gt;enabled=0&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;In this example, let&amp;rsquo;s consider a situation where you want to test the latest kernel packages as soon as they reach the testing repository. We need to make two edits to the repository configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enabled=1&lt;/code&gt; - Allow yum/dnf to use the repository&lt;/li&gt;
&lt;li&gt;&lt;code&gt;includepkgs=kernel*&lt;/code&gt; - Only allow packages matching &lt;code&gt;kernel*&lt;/code&gt; to be installed from the testing repository&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The repository configuration should now look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[updates-testing]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Fedora $releasever - $basearch - Test Updates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;failovermethod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;priority&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;metalink&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://mirrors.fedoraproject.org/metalink?repo=updates-testing-f$releasever&amp;amp;arch=$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;repo_gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;rpm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;metadata_expire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;6h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;gpgkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;skip_if_unavailable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;includepkgs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;kernel*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="getting-testing-packages"&gt;Getting testing packages&lt;/h2&gt;
&lt;p&gt;Running &lt;code&gt;dnf upgrade kernel*&lt;/code&gt; should now pull a kernel from the &lt;code&gt;updates-testing&lt;/code&gt; repository. You can verify this by checking the &lt;code&gt;Repository&lt;/code&gt; column in the dnf output.&lt;/p&gt;
&lt;p&gt;If you feel more adventurous later, you can add additional packages (separated by spaces) to the &lt;code&gt;includepkgs&lt;/code&gt; line. The truly adventurous users can leave the repo enabled but remove &lt;code&gt;includepkgs&lt;/code&gt; altogether. This will pull all available packages from the testing repository as soon as they are available.&lt;/p&gt;
&lt;h2 id="package-maintainers-need-feedback"&gt;Package maintainers need feedback!&lt;/h2&gt;
&lt;p&gt;One final note: &lt;strong&gt;package maintainers need your feedback&lt;/strong&gt; on packages. Positive or negative feedback is very helpful. You can search for the package on &lt;a href="https://bodhi.fedoraproject.org/"&gt;Bodhi&lt;/a&gt; and submit feedback there, or use the &lt;code&gt;fedora-easy-karma&lt;/code&gt; script via the &lt;code&gt;fedora-easy-karma&lt;/code&gt; package. The script will look through your installed package list and query you for feedback on each one.&lt;/p&gt;
&lt;p&gt;Submitting lots of feedback can earn you some &lt;a href="https://badges.fedoraproject.org/badge/in-search-of-the-bull-tester-i"&gt;awesome Fedora Badges&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href="http://www.arpc.afrc.af.mil/News/Article-Display/Article/365815/a-wish-come-true-colorado-native-becomes-cadet-for-a-day/"&gt;US Air Force&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Ensuring keepalived starts after the network is ready</title><link>https://major.io/p/ensuring-keepalived-starts-network-ready/</link><pubDate>Fri, 15 Dec 2017 21:18:37 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/ensuring-keepalived-starts-network-ready/</guid><description>&lt;p&gt;After a recent &lt;a href="https://github.com/openstack/openstack-ansible"&gt;OpenStack-Ansible (OSA)&lt;/a&gt; deployment on CentOS, I found that keepalived was not starting properly at boot time:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Keepalived_vrrp[801]: Cant find interface br-mgmt for vrrp_instance internal !!!
Keepalived_vrrp[801]: Truncating auth_pass to 8 characters
Keepalived_vrrp[801]: VRRP is trying to assign ip address 172.29.236.11/32 to unknown br-mgmt interface !!! go out and fix your conf !!!
Keepalived_vrrp[801]: Cant find interface br-mgmt for vrrp_instance external !!!
Keepalived_vrrp[801]: Truncating auth_pass to 8 characters
Keepalived_vrrp[801]: VRRP is trying to assign ip address 192.168.250.11/32 to unknown br-mgmt interface !!! go out and fix your conf !!!
Keepalived_vrrp[801]: VRRP_Instance(internal) Unknown interface !
systemd[1]: Started LVS and VRRP High Availability Monitor.
Keepalived_vrrp[801]: Stopped
Keepalived[799]: Keepalived_vrrp exited with permanent error CONFIG. Terminating
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OSA deployments have a management bridge for traffic between containers. These containers run the OpenStack APIs and other support services. By default, this bridge is called &lt;code&gt;br-mgmt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The keepalived daemon is starting before NetworkManager can bring up the &lt;code&gt;br-mgmt&lt;/code&gt; bridge and that is causing keepalived to fail. We need a way to tell systemd to wait on the network before bringing up keepalived.&lt;/p&gt;
&lt;h2 id="waiting-on-networkmanager"&gt;Waiting on NetworkManager&lt;/h2&gt;
&lt;p&gt;There is a special systemd target, &lt;code&gt;network-online.target&lt;/code&gt;, that is not reached until all networking is properly configured. NetworkManager comes with a handy service called &lt;code&gt;NetworkManager-wait-online.service&lt;/code&gt; that must be complete before the &lt;code&gt;network-online&lt;/code&gt; target can be reached:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rpm -ql NetworkManager | grep network-online&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/lib/systemd/system/network-online.target.wants
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/lib/systemd/system/network-online.target.wants/NetworkManager-wait-online.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Start by ensuring that the &lt;code&gt;NetworkManager-wait-online&lt;/code&gt; service starts at boot time:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl enable NetworkManager-wait-online.service
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="using-network-onlinetarget"&gt;Using network-online.target&lt;/h2&gt;
&lt;p&gt;Next, we tell the keepalived service to wait on &lt;code&gt;network-online.target&lt;/code&gt;. Bring up an editor for overriding the &lt;code&gt;keepalived.service&lt;/code&gt; unit:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl edit keepalived.service
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the editor appears, add the following text:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Wants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save the file in the editor and reboot the server. The keepalived service should come up successfully after NetworkManager signals that all of the network devices are online.&lt;/p&gt;
&lt;p&gt;Learn more by reading the upstream &lt;a href="https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/"&gt;NetworkTarget&lt;/a&gt; documentation.&lt;/p&gt;</description></item><item><title>Changes in RHEL 7 Security Technical Implementation Guide Version 1, Release 3</title><link>https://major.io/p/changes-in-rhel-7-security-technical-implementation-guide-version-1-release-3/</link><pubDate>Thu, 02 Nov 2017 15:00:25 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/changes-in-rhel-7-security-technical-implementation-guide-version-1-release-3/</guid><description>&lt;p&gt;The latest release of the Red Hat Enterprise Linux Security Technical Implementation Guide (STIG) &lt;a href="https://public.cyber.mil/stigs/"&gt;was published last week&lt;/a&gt;.
This release is Version 1, Release 3, and it contains four main changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;V-77819 - Multifactor authentication is required for graphical logins&lt;/li&gt;
&lt;li&gt;V-77821 - Datagram Congestion Control Protocol (DCCP) kernel module must be disabled&lt;/li&gt;
&lt;li&gt;V-77823 - Single user mode must require user authentication&lt;/li&gt;
&lt;li&gt;V-77825 - Address space layout randomization (ASLR) must be enabled&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="deep-dive"&gt;Deep dive&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s break down this list to understand what each one means.&lt;/p&gt;
&lt;h3 id="v-77819---multifactor-authentication-is-required-for-graphical-logins"&gt;V-77819 - Multifactor authentication is required for graphical logins&lt;/h3&gt;
&lt;p&gt;This requirement improves security for graphical logins and extends the existing requirements for multifactor authentication for logins (see V-71965, V-72417, and V-72427). The STIG recommends smartcards (since the US Government often uses &lt;a href="https://en.wikipedia.org/wiki/Common_Access_Card"&gt;CAC cards&lt;/a&gt; for multifactor authentication), and this is a good idea for high security systems.&lt;/p&gt;
&lt;p&gt;I use &lt;a href="https://www.yubico.com/products/yubikey-hardware/yubikey4/"&gt;Yubikey 4&amp;rsquo;s&lt;/a&gt; as smartcards in most situations and they work anywhere you have available USB slots.&lt;/p&gt;
&lt;h3 id="v-77821---datagram-congestion-control-protocol-dccp-kernel-module-must-be-disabled"&gt;V-77821 - Datagram Congestion Control Protocol (DCCP) kernel module must be disabled&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Datagram_Congestion_Control_Protocol"&gt;DCCP&lt;/a&gt; is often used as a congestion control mechanism for UDP traffic, but it isn&amp;rsquo;t used that often in modern networks. There have been &lt;a href="https://threatpost.com/impact-of-new-linux-kernel-dccp-vulnerability-limited/123863/"&gt;vulnerabilities&lt;/a&gt; in the past that are mitigated by disabling DCCP, so it&amp;rsquo;s a good idea to disable it unless you have a strong reason for keeping it enabled.&lt;/p&gt;
&lt;p&gt;The ansible-hardening role has been updated to &lt;a href="https://docs.openstack.org/ansible-hardening/latest/rhel7/domains/kernel.html#v-77821"&gt;disable the DCCP kernel module by default&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="v-77823---single-user-mode-must-require-user-authentication"&gt;V-77823 - Single user mode must require user authentication&lt;/h3&gt;
&lt;p&gt;Single user mode is often used in emergency situations where the server cannot boot properly or an issue must be repaired without a fully booted server. This mode can only be used at the server&amp;rsquo;s physical console, serial port, or via out-of-band management (DRAC, iLO, and IPMI). Allowing single-user mode access without authentication is a serious security risk.&lt;/p&gt;
&lt;p&gt;Fortunately, every distribution supported by the ansible-hardening role already has authentication requirements for single user mode in place. The ansible-hardening role does not make any adjustments to the single user mode unit file since any untested adjustment could cause a system to have problems booting.&lt;/p&gt;
&lt;h3 id="v-77825---address-space-layout-randomization-aslr-must-be-enabled"&gt;V-77825 - Address space layout randomization (ASLR) must be enabled&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization"&gt;ASLR&lt;/a&gt; is a handy technology that makes it more difficult for attackers to guess where a particular program is storing data in memory. It&amp;rsquo;s not perfect, but it certainly raises the difficulty for an attacker. There are multiple settings for this variable and the &lt;a href="https://www.kernel.org/doc/Documentation/sysctl/kernel.txt"&gt;kernel documentation for sysctl&lt;/a&gt; has some brief explanations for each setting (search for &lt;code&gt;randomize_va_space&lt;/code&gt; on the page).&lt;/p&gt;
&lt;p&gt;Every distribution supported by the ansible-hardening role is already setting &lt;code&gt;kernel.randomize_va_space=2&lt;/code&gt; by default, which applies randomization for the basic parts of process memory (such as shared libraries and the stack) as well as the heap. The ansible-hardening role will ensure that the default setting is maintained.&lt;/p&gt;
&lt;h2 id="ansible-hardening-is-already-up-to-date"&gt;ansible-hardening is already up to date&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re already using the ansible-hardening role&amp;rsquo;s master branch, these changes are &lt;a href="https://github.com/openstack/ansible-hardening/commit/782bb48c14c03aedaefcaf421fd5935ef5f561b8"&gt;already in place&lt;/a&gt;! Try out the new updates and &lt;a href="https://bugs.launchpad.net/openstack-ansible/+filebug"&gt;open a bug report&lt;/a&gt; if you find any problems.&lt;/p&gt;</description></item><item><title>Import RPM repository GPG keys from other keyservers temporarily</title><link>https://major.io/p/import-rpm-repository-keys-from-other-keyservers-temporarily/</link><pubDate>Wed, 20 Sep 2017 15:24:13 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/import-rpm-repository-keys-from-other-keyservers-temporarily/</guid><description>&lt;p&gt;I&amp;rsquo;ve been working through some patches to &lt;a href="https://github.com/openstack/openstack-ansible"&gt;OpenStack-Ansible&lt;/a&gt; lately to optimize how we configure yum repositories in our deployments. During that work, I ran into some issues where pgp.mit.edu was returning 500 errors for some requests to retrieve GPG keys.&lt;/p&gt;
&lt;p&gt;Ansible was returning this error:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl: (22) The requested URL returned error: 502 Proxy Error
error: http://pgp.mit.edu:11371/pks/lookup?op=get&amp;amp;search=0x61E8806C: import read failed(2)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How does the &lt;code&gt;rpm&lt;/code&gt; command know which keyserver to use? Let&amp;rsquo;s use the &lt;code&gt;--showrc&lt;/code&gt; argument to show how it is configured:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ rpm --showrc | grep hkp
-14: _hkp_keyserver http://pgp.mit.edu
-14: _hkp_keyserver_query %{_hkp_keyserver}:11371/pks/lookup?op=get&amp;amp;search=0x
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How do we change this value temporarily to test a GPG key retrieval from a different server? There&amp;rsquo;s an argument for that as well: &lt;code&gt;--define&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ rpm --help | grep define
 -D, --define=&amp;#39;MACRO EXPR&amp;#39; define MACRO with value EXPR
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can assemble that on the command line to set a different keyserver temporarily:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# rpm -vv --define=&amp;#34;%_hkp_keyserver http://pool.sks-keyservers.net&amp;#34; --import 0x61E8806C
-- SNIP --
D: adding &amp;#34;63deac79abe7ad80e147d671c2ac5bd1c8b3576e&amp;#34; to Sha1header index.
-- SNIP --
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s verify that our new key is in place:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# rpm -qa | grep -i gpg-pubkey-61E8806C
gpg-pubkey-61e8806c-5581df56
# rpm -qi gpg-pubkey-61e8806c-5581df56
Name : gpg-pubkey
Version : 61e8806c
Release : 5581df56
Architecture: (none)
Install Date: Wed 20 Sep 2017 10:17:11 AM CDT
Group : Public Keys
Size : 0
License : pubkey
Signature : (none)
Source RPM : (none)
Build Date : Wed 17 Jun 2015 03:57:58 PM CDT
Build Host : localhost
Relocations : (not relocatable)
Packager : CentOS Virtualization SIG (http://wiki.centos.org/SpecialInterestGroup/Virtualization) &amp;lt;security@centos.org&amp;gt;
Summary : gpg(CentOS Virtualization SIG (http://wiki.centos.org/SpecialInterestGroup/Virtualization) &amp;lt;security@centos.org&amp;gt;)
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: rpm-4.11.3 (NSS-3)

mQENBFWB31YBCAC4dFmTzBDOcq4R1RbvQXLkyYfF+yXcsMA5kwZy7kjxnFqBoNPv
aAjFm3e5huTw2BMZW0viLGJrHZGnsXsE5iNmzom2UgCtrvcG2f65OFGlC1HZ3ajA
8ZIfdgNQkPpor61xqBCLzIsp55A7YuPNDvatk/+MqGdNv8Ug7iVmhQvI0p1bbaZR
0GuavmC5EZ/+mDlZ2kHIQOUoInHqLJaX7iw46iLRUnvJ1vATOzTnKidoFapjhzIt
i4ZSIRaalyJ4sT+oX4CoRzerNnUtIe2k9Hw6cEu4YKGCO7nnuXjMKz7Nz5GgP2Ou
zIA/fcOmQkSGcn7FoXybWJ8DqBExvkJuDljPABEBAAG0bENlbnRPUyBWaXJ0dWFs
aXphdGlvbiBTSUcgKGh0dHA6Ly93aWtpLmNlbnRvcy5vcmcvU3BlY2lhbEludGVy
ZXN0R3JvdXAvVmlydHVhbGl6YXRpb24pIDxzZWN1cml0eUBjZW50b3Mub3JnPokB
OQQTAQIAIwUCVYHfVgIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEHrr
voJh6IBsRd0H/A62i5CqfftuySOCE95xMxZRw8+voWO84QS9zYvDEnzcEQpNnHyo
FNZTpKOghIDtETWxzpY2ThLixcZOTubT+6hUL1n+cuLDVMu4OVXBPoUkRy56defc
qkWR+UVwQitmlq1ngzwmqVZaB8Hf/mFZiB3B3Jr4dvVgWXRv58jcXFOPb8DdUoAc
S3u/FLvri92lCaXu08p8YSpFOfT5T55kFICeneqETNYS2E3iKLipHFOLh7EWGM5b
Wsr7o0r+KltI4Ehy/TjvNX16fa/t9p5pUs8rKyG8SZndxJCsk0MW55G9HFvQ0FmP
A6vX9WQmbP+ml7jsUxtEJ6MOGJ39jmaUvPc=
=ZzP+
-----END PGP PUBLIC KEY BLOCK-----
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;p&gt;If you want to override the value permanently, create a &lt;code&gt;~/.rpmmacros&lt;/code&gt; file and add the following line to it:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;%_hkp_keyserver http://pool.sks-keyservers.net
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href="https://commons.wikimedia.org/wiki/File:Close-up_of_keys.jpg"&gt;Wikipedia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>RHEL 7 STIG v1 updates for openstack-ansible-security</title><link>https://major.io/p/rhel-7-stig-v1-updates-for-openstack-ansible-security/</link><pubDate>Wed, 05 Apr 2017 17:46:17 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/rhel-7-stig-v1-updates-for-openstack-ansible-security/</guid><description>&lt;p&gt;DISA&amp;rsquo;s final release of the Red Hat Enterprise Linux (RHEL) 7 Security Technical Implementation Guide (STIG) &lt;a href="https://public.cyber.mil/stigs/"&gt;came out a few weeks ago&lt;/a&gt; and it has plenty of improvements and changes. The openstack-ansible-security role has already been updated with these changes.&lt;/p&gt;
&lt;p&gt;Quite a few duplicated STIG controls were removed and a few new ones were added. Some of the controls in the pre-release were difficult to implement, especially those that changed parameters for PKI-based authentication.&lt;/p&gt;
&lt;p&gt;The biggest challenge overall was the renumbering. The pre-release STIG used an unusual numbering convention: RHEL-07-123456. The final version used the more standardized &amp;ldquo;V&amp;rdquo; numbers, such as V-72225. This change required a &lt;a href="https://github.com/openstack/openstack-ansible-security/commit/dccce1d5cc06985a58f0ecba4fd0d977388592b2"&gt;substantial patch&lt;/a&gt; to bring the Ansible role inline with the new STIG release.&lt;/p&gt;
&lt;p&gt;All of the &lt;a href="https://docs.openstack.org/developer/openstack-ansible-security/controls-rhel7.html"&gt;role&amp;rsquo;s documentation&lt;/a&gt; is now updated to reflect the new numbering scheme and STIG changes. The key thing to remember is that you&amp;rsquo;ll need to use &lt;code&gt;--skip-tag&lt;/code&gt; with the new STIG numbers if you need to skip certain tasks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; These changes won&amp;rsquo;t be backported to the &lt;code&gt;stable/ocata&lt;/code&gt; branch, so you need to use the &lt;code&gt;master&lt;/code&gt; branch to get these changes.&lt;/p&gt;
&lt;p&gt;Have feedback? Found a bug? Let us know!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IRC: &lt;code&gt;#openstack-ansible&lt;/code&gt; on Freenode IRC&lt;/li&gt;
&lt;li&gt;Bugs: &lt;a href="https://bugs.launchpad.net/openstack-ansible"&gt;LaunchPad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;E-mail: &lt;a href="mailto:openstack-dev@lists.rackspace.com"&gt;openstack-dev@lists.rackspace.com&lt;/a&gt; with the subject line &lt;code&gt;[openstack-ansible][security]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Display auditd messages with journalctl</title><link>https://major.io/p/display-auditd-messages-with-journalctl/</link><pubDate>Thu, 05 Jan 2017 15:53:13 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/display-auditd-messages-with-journalctl/</guid><description>&lt;p&gt;All systems running &lt;code&gt;systemd&lt;/code&gt; come with a powerful tool for reviewing the system journal: &lt;a href="https://www.freedesktop.org/software/systemd/man/journalctl.html"&gt;&lt;code&gt;journalctl&lt;/code&gt;&lt;/a&gt;. It allows you to get a quick look at the system journal while also allowing you to heavily customize your view of the log.&lt;/p&gt;
&lt;p&gt;I logged into a server recently that was having a problem and I found that the audit logs weren&amp;rsquo;t going into syslog. That&amp;rsquo;s no problem - they&amp;rsquo;re in the system journal. The system journal was filled with tons of other messages, so I decided to limit the output only to messages from the &lt;code&gt;auditd&lt;/code&gt; unit:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ sudo journalctl -u auditd --boot
-- Logs begin at Thu 2015-11-05 09:20:01 CST, end at Thu 2017-01-05 09:38:49 CST. --
Jan 05 07:47:04 arsenic systemd[1]: Starting Security Auditing Service...
Jan 05 07:47:04 arsenic auditd[937]: Started dispatcher: /sbin/audispd pid: 949
Jan 05 07:47:04 arsenic audispd[949]: priority_boost_parser called with: 4
Jan 05 07:47:04 arsenic audispd[949]: max_restarts_parser called with: 10
Jan 05 07:47:04 arsenic audispd[949]: audispd initialized with q_depth=150 and 1 active plugins
Jan 05 07:47:04 arsenic augenrules[938]: /sbin/augenrules: No change
Jan 05 07:47:04 arsenic augenrules[938]: No rules
Jan 05 07:47:04 arsenic auditd[937]: Init complete, auditd 2.7 listening for events (startup state enable)
Jan 05 07:47:04 arsenic systemd[1]: Started Security Auditing Service.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This isn&amp;rsquo;t helpful. I&amp;rsquo;m seeing messages about the &lt;code&gt;auditd&lt;/code&gt; daemon itself. I want the actual output from the audit rules.&lt;/p&gt;
&lt;p&gt;Then I remembered: the kernel is the one that sends messages about audit rules to the system journal. Let&amp;rsquo;s just look at what&amp;rsquo;s coming from the kernel instead:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ sudo journalctl -k --boot
-- Logs begin at Thu 2015-11-05 09:20:01 CST, end at Thu 2017-01-05 09:40:44 CST. --
Jan 05 07:46:47 arsenic kernel: Linux version 4.8.15-300.fc25.x86_64 (mockbuild@bkernel01.phx2.fedoraproject.org) (gcc version 6.2.1 20160916 (Red Hat 6.2.1-2
Jan 05 07:46:47 arsenic kernel: Command line: BOOT_IMAGE=/vmlinuz-4.8.15-300.fc25.x86_64 root=/dev/mapper/luks-e... ro rd.luks
Jan 05 07:46:47 arsenic kernel: x86/fpu: Supporting XSAVE feature 0x001: &amp;#39;x87 floating point registers&amp;#39;
Jan 05 07:46:47 arsenic kernel: x86/fpu: Supporting XSAVE feature 0x002: &amp;#39;SSE registers&amp;#39;
Jan 05 07:46:47 arsenic kernel: x86/fpu: Supporting XSAVE feature 0x004: &amp;#39;AVX registers&amp;#39;
Jan 05 07:46:47 arsenic kernel: x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;This is worse!&lt;/strong&gt; Luckily, the system journal keeps a lot more data about what it receives than just the text of the log line. We can dig into that extra data with the &lt;code&gt;verbose&lt;/code&gt; option:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ sudo journalctl --boot -o verbose
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After running that command, search for one of the audit log lines in the output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;_UID=0
_BOOT_ID=...
_MACHINE_ID=...
_HOSTNAME=arsenic
_TRANSPORT=audit
SYSLOG_FACILITY=4
SYSLOG_IDENTIFIER=audit
AUDIT_FIELD_HOSTNAME=?
AUDIT_FIELD_ADDR=?
AUDIT_FIELD_RES=success
_AUDIT_TYPE=1105
AUDIT_FIELD_OP=PAM:session_open
_SELINUX_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
_AUDIT_LOGINUID=1000
_AUDIT_SESSION=3
AUDIT_FIELD_ACCT=root
AUDIT_FIELD_EXE=/usr/bin/sudo
AUDIT_FIELD_GRANTORS=pam_keyinit,pam_limits,pam_keyinit,pam_limits,pam_systemd,pam_unix
AUDIT_FIELD_TERMINAL=/dev/pts/4
_PID=2666
_SOURCE_REALTIME_TIMESTAMP=1483631103122000
_AUDIT_ID=385
MESSAGE=USER_START pid=2666 uid=0 auid=1000 ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg=&amp;#39;op=PAM:session_open grantors=pam_keyinit,pam_limits,pam_keyinit,pam_limits,pam_systemd,pam_unix acct=&amp;#34;root&amp;#34; exe=&amp;#34;/usr/bin/sudo&amp;#34; hostname=? addr=? terminal=/dev/pts/4 res=success&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One of the identifiers we can use is &lt;code&gt;_TRANSPORT=audit&lt;/code&gt;. Let&amp;rsquo;s pass that to &lt;code&gt;journalctl&lt;/code&gt; and see what we get:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ sudo journalctl --boot _TRANSPORT=audit
-- Logs begin at Thu 2015-11-05 09:20:01 CST. --
Jan 05 09:47:24 arsenic audit[3028]: USER_END pid=3028 uid=0 auid=1000 ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg=&amp;#39;op=PAM:session_close grantors=pam_keyinit,pam_limits,pam_keyinit,pam_limits,pam_systemd,pam_unix acct=&amp;#34;root&amp;#34; exe=&amp;#34;/usr/bin/sudo&amp;#34; hostname=? addr=? terminal=/dev/pts/4 res=success&amp;#39;
... more log lines snipped ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success! You can get live output of the audit logs by tailing the output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo journalctl -af _TRANSPORT=audit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For more details on &lt;code&gt;journalctl&lt;/code&gt;, refer to the &lt;a href="https://www.freedesktop.org/software/systemd/man/journalctl.html"&gt;online documentation&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>augenrules fails with “rule exists” when loading rules into auditd</title><link>https://major.io/p/augenrules-fails-with-rule-exists-when-loading-rules-into-auditd/</link><pubDate>Tue, 03 Jan 2017 19:01:46 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/augenrules-fails-with-rule-exists-when-loading-rules-into-auditd/</guid><description>&lt;p&gt;When I came back from the holiday break, I found that the &lt;a href="https://github.com/openstack/openstack-ansible-security"&gt;openstack-ansible-security&lt;/a&gt; role wasn&amp;rsquo;t passing tests any longer. The Ansible playbook stopped when &lt;code&gt;augenrules&lt;/code&gt; ran to load the new audit rules. The error wasn&amp;rsquo;t terribly helpful:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/usr/sbin/augenrules: No change
Error sending add rule data request (Rule exists)
There was an error in line 5 of /etc/audit/audit.rules
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="a-duplicated-rule"&gt;A duplicated rule?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been &lt;a href="http://specs.openstack.org/openstack/openstack-ansible-specs/specs/newton/security-rhel7-stig.html"&gt;working on lots of changes&lt;/a&gt; to implement the Red Hat Enterprise Linux 7 &lt;a href="https://public.cyber.mil/stigs/"&gt;Security Technical Implementation Guide (STIG)&lt;/a&gt; and I assumed I put in the same rule twice with an errant copy and paste.&lt;/p&gt;
&lt;p&gt;That wasn&amp;rsquo;t the case. I checked the input rule file in &lt;code&gt;/etc/audit/rules.d/&lt;/code&gt; and found that all of the rules were unique.&lt;/p&gt;
&lt;h2 id="is-something-missing"&gt;Is something missing?&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;augenrules&lt;/code&gt; command works by taking files from &lt;code&gt;/etc/audit/rules.d/&lt;/code&gt; and joining them together into &lt;code&gt;/etc/audit/audit.rules&lt;/code&gt;. Based on the output from &lt;code&gt;augenrules&lt;/code&gt;, the rule file checks out fine and it determined that the existing rule doesn&amp;rsquo;t need to be updated. However, &lt;code&gt;augenrules&lt;/code&gt; is still unable to load the new rules into auditd.&lt;/p&gt;
&lt;p&gt;I decided to check the first several lines of &lt;code&gt;/etc/audit/rules.d/&lt;/code&gt; to see if line 5 had a problem:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;## This file is automatically generated from /etc/audit/rules.d


-f 1
-a always,exit -F path=/usr/bin/chsh -F perm=x -F auid&amp;gt;=1000 -F auid!=4294967295 -k RHEL-07-030525
-a always,exit -F path=/usr/bin/chage -F perm=x -F auid&amp;gt;=1000 -F auid!=4294967295 -k RHEL-07-030513
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Two things looked strange to me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Line 5 is correct and it is unique&lt;/li&gt;
&lt;li&gt;Why are lines 2 and 3 blank?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I checked another CentOS 7 server and found the following in lines 2 and 3:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;-D
-b 320
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;-D&lt;/code&gt; &lt;a href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/sec-Defining_Audit_Rules_and_Controls.html"&gt;deletes all previously loaded rules&lt;/a&gt; and &lt;code&gt;-b&lt;/code&gt; increases the buffer size for busy periods. My rules weren&amp;rsquo;t loading properly because the &lt;code&gt;-D&lt;/code&gt; was missing! Those two lines normally come from &lt;code&gt;/etc/audit/rules.d/audit.rules&lt;/code&gt;, but that default file was not present.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what was going wrong:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;augenrules&lt;/code&gt; read rules from &lt;code&gt;rules.d/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;augenrules&lt;/code&gt; found that the rules in &lt;code&gt;rules.d/&lt;/code&gt; were already in the main &lt;code&gt;audit.rules&lt;/code&gt; file and didn&amp;rsquo;t need to be updated&lt;/li&gt;
&lt;li&gt;&lt;code&gt;augenrules&lt;/code&gt; attempted to load the rules into &lt;code&gt;auditd&lt;/code&gt;, but that failed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;auditd&lt;/code&gt; was rejecting the rules because at least one of them (line 5) already existed in the running rule set&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of this happened because the &lt;code&gt;-D&lt;/code&gt; wasn&amp;rsquo;t handled first before new rules were loaded.&lt;/p&gt;
&lt;h2 id="fixing-it"&gt;Fixing it&lt;/h2&gt;
&lt;p&gt;I decided to add the &lt;code&gt;-D&lt;/code&gt; line explicitly in my rules file within &lt;code&gt;rules.d/&lt;/code&gt; to catch those situations when the &lt;code&gt;audit.rules&lt;/code&gt; default file is missing. The &lt;code&gt;augenrules&lt;/code&gt; command ensures that the line appears at the top of the rules when they are loaded into &lt;code&gt;auditd&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Automated security hardening with Ansible: May updates</title><link>https://major.io/p/automated-security-hardening-with-ansible-may-updates/</link><pubDate>Fri, 27 May 2016 02:40:33 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/automated-security-hardening-with-ansible-may-updates/</guid><description>&lt;p&gt;Lots of work has gone into the &lt;a href="https://github.com/openstack/openstack-ansible-security"&gt;openstack-ansible-security&lt;/a&gt; Ansible role since I delivered &lt;a href="https://major.io/2016/04/26/talk-recap-automated-security-hardening-openstack-ansible/"&gt;a talk about it last month&lt;/a&gt; at the OpenStack Summit in Austin. Attendees asked for quite a few new features and I&amp;rsquo;ve seen quite a few bug reports (and that&amp;rsquo;s a good thing).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a list of the newest additions since the Summit:&lt;/p&gt;
&lt;h2 id="new-features"&gt;New features&lt;/h2&gt;
&lt;h3 id="ubuntu-1604-lts-xenial-support"&gt;Ubuntu 16.04 LTS (Xenial) support&lt;/h3&gt;
&lt;p&gt;The role now works with Ubuntu 16.04 and its newest features, including systemd. You can use the same variables as you used with Ubuntu 14.04 and it should take the same actions. Documentation updates are mostly merged with a few straggling reviews in the queue.&lt;/p&gt;
&lt;h3 id="centos-7-support"&gt;CentOS 7 support&lt;/h3&gt;
&lt;p&gt;With all of the work going into the role to support Ubuntu 16.04 and systemd, CentOS 7 wasn&amp;rsquo;t a huge stretch. Many of the package names and file locations were a little different, but those are now moved out into variables files to reduce the repetition of tasks. Some of the Linux Security Module tasks needed adjustments since SELinux is a different beast than AppArmor.&lt;/p&gt;
&lt;h3 id="following-the-stig-more-closely"&gt;Following the STIG more closely&lt;/h3&gt;
&lt;p&gt;One of the common questions I had at the summit was: &amp;ldquo;Can I use this thing on my non-OpenStack environments?&amp;rdquo; You definitely can, but many of the configurations were tweaked to avoid causing problems with OpenStack environments. Some users asked if the configurations could be made more generic so that they followed the STIG more closely. This would reduce some compliance headaches and allow more people to use the role.&lt;/p&gt;
&lt;p&gt;So far, I&amp;rsquo;ve been making some of these adjustments to fix more things rather than simply checking them. That should make it easier to get closer to the STIG&amp;rsquo;s requirements.&lt;/p&gt;
&lt;p&gt;Another proposed idea is to create vars files that meet different criteria. For example, one vars file might be the ultra-secure, follow-the-STIG-to-the-letter configuration. This would be good for users that already know they want to apply the STIG&amp;rsquo;s requirements fully. There could be another vars file that would apply most of the STIG&amp;rsquo;s requirements, but it would steer clear of changing anything that could disrupt a production OpenStack environment.&lt;/p&gt;
&lt;h2 id="the-future"&gt;The future&lt;/h2&gt;
&lt;p&gt;Here are a subset of the future plans and ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better reporting for users who need to feed data into vulnerability management applications or SIEMs for compliance checks&lt;/li&gt;
&lt;li&gt;Better testing, possibly with customized OpenSCAP XCCDF files&lt;/li&gt;
&lt;li&gt;Cross-referenced controls to other hardening guides, such as CIS Benchmarks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have any other ideas, feel free to stop by &lt;code&gt;#openstack-ansible&lt;/code&gt; or &lt;code&gt;#openstack-security&lt;/code&gt; on Freenode. You can find me there as &lt;em&gt;mhayden&lt;/em&gt; and I would really enjoy hearing about your use cases!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href="https://www.flickr.com/photos/89165847@N00/15843531002/"&gt;Mikecogh&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Updating Dell PowerEdge BIOS from Linux</title><link>https://major.io/p/updating-dell-poweredge-bios-from-linux/</link><pubDate>Mon, 18 Jan 2016 20:53:38 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/updating-dell-poweredge-bios-from-linux/</guid><description>&lt;p&gt;Updating Dell PowerEdge firmware from Linux is quite easy, but it isn&amp;rsquo;t documented very well. I ended up with a set of PowerEdge R710&amp;rsquo;s at work for a lab environment and the BIOS versions were different on each server.&lt;/p&gt;
&lt;h2 id="downloading-the-latest-firmware"&gt;Downloading the latest firmware&lt;/h2&gt;
&lt;p&gt;Start by heading over to &lt;a href="http://support.dell.com/"&gt;Dell&amp;rsquo;s support site&lt;/a&gt; and enter your system&amp;rsquo;s service tag. You can use &lt;code&gt;lshw&lt;/code&gt; to find your service tag:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# lshw | head
lab05
 description: Rack Mount Chassis
 product: PowerEdge R710 ()
 vendor: Dell Inc.
 serial: [service tag should be here]
 width: 64 bits
 capabilities: smbios-2.6 dmi-2.6 vsyscall32
 configuration: boot=normal chassis=rackmount uuid=44454C4C-3700-104A-8052-B2C04F564831
 *-core
 description: Motherboard
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After entering the service tag, follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Drivers &amp;amp; downloads&lt;/strong&gt; on the left&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Change OS&lt;/strong&gt; at the top right and choose &lt;strong&gt;Red Hat Enterprise Linux 7&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;BIOS&lt;/strong&gt; dropdown in the list&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Other file formats available&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Look for the file ending in &lt;strong&gt;BIN&lt;/strong&gt; and click &lt;strong&gt;Download file&lt;/strong&gt; underneath it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Copy that file to your server that needs a BIOS update.&lt;/p&gt;
&lt;h2 id="installing-firmware-update-tools"&gt;Installing firmware update tools&lt;/h2&gt;
&lt;p&gt;Start by getting the right packages installed. I&amp;rsquo;ll cover the CentOS/RHEL and Ubuntu methods here. At the moment, Fedora doesn&amp;rsquo;t build kernels with the &lt;code&gt;dell_rbu&lt;/code&gt; module enabled, but there&amp;rsquo;s a &lt;a href="https://lists.fedoraproject.org/archives/list/kernel@lists.fedoraproject.org/thread/L623WBK7HAAQWD5FG2MFBD7SIGNGXXVJ/"&gt;discussion about getting that fixed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For CentOS, you&amp;rsquo;ll need to get the Dell Linux repository configured first:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;wget http://linux.dell.com/repo/hardware/latest/bootstrap.cgi
sh bootstrap.cgi
yum -y install firmware-addon-dell
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For Ubuntu, the package is in the upstream repositories already:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt-get -y install firmware-addon-dell
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="extract-and-flash-the-bios-header"&gt;Extract and flash the BIOS header&lt;/h2&gt;
&lt;p&gt;Dell packages up a BIOS header (the actual firmware blob that needs to be flashed) within the BIN file you downloaded earlier. The latest version of the BIOS for my R710 is 6.4.0, so my file is called &lt;code&gt;R710_BIOS_4HKX2_LN_6.4.0.BIN&lt;/code&gt;. Let&amp;rsquo;s start by extracting the header file:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;bash R710_BIOS_4HKX2_LN_6.4.0.BIN --extract bios
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should now have a directory in your current directory called &lt;code&gt;bios&lt;/code&gt;. The header file is within &lt;code&gt;bios/payload/&lt;/code&gt; and you&amp;rsquo;ll use that to flash the BIOS:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# modprobe dell_rbu
# dellBiosUpdate-compat --hdr bios/payload/R710-060400.hdr --update
Supported RBU type for this system: (MONOLITHIC, PACKET)
Using RBU v2 driver. Initializing Driver.
Setting RBU type in v2 driver to: PACKET
writing (4096) to file: /sys/devices/platform/dell_rbu/packet_size
Writing RBU data (4096bytes/dot): ...........................
Done writing packet data.
Activate CMOS bit to notify BIOS that update is ready on next boot.
Update staged sucessfully. BIOS update will occur on next reboot.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It&amp;rsquo;s now time to reboot! If you watch the console via iDRAC, you&amp;rsquo;ll see a 3-4 minute delay on the next reboot while the staged BIOS image is flashed. When the server boots, use &lt;code&gt;lshw&lt;/code&gt; to verify that the BIOS version has been updated.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo Credit: &lt;a href="https://www.flickr.com/photos/21881956@N05/2466171910/"&gt;vaxomatic&lt;/a&gt; via &lt;a href="http://compfight.com"&gt;Compfight&lt;/a&gt; &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Chronicles of SELinux: Dealing with web content in unusual directories</title><link>https://major.io/p/chronicles-of-selinux-dealing-with-web-content-in-unusual-directories/</link><pubDate>Thu, 10 Sep 2015 13:40:35 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/chronicles-of-selinux-dealing-with-web-content-in-unusual-directories/</guid><description>&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://major.io/wp-content/uploads/2013/07/selinux-penguin-new_medium.png"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to start a series of posts called &amp;ldquo;Chronicles of SELinux&amp;rdquo; where I hope to educate more users on how to handle SELinux denials with finesse rather than simply &lt;a href="http://stopdisablingselinux.com/"&gt;disabling it entirely&lt;/a&gt;. To kick things off, I&amp;rsquo;ll be talking about dealing with web content in the first post.&lt;/p&gt;
&lt;h2 id="first-steps"&gt;First steps&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;d like to follow along, simply hop onto a system running Fedora 21 (or later), CentOS 7 or Red Hat Enterprise Linux 7. We need SELinux in enforcing mode on the host, so be sure to check the status with &lt;code&gt;getenforce&lt;/code&gt;. Depending on what &lt;code&gt;getenforce&lt;/code&gt; returns, you&amp;rsquo;ll need to make adjustments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Enforcing&lt;/em&gt;: No adjustments needed - you&amp;rsquo;re all set!&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Permissive&lt;/em&gt;: Run &lt;code&gt;setenforce 1&lt;/code&gt; and adjust SELinux configuration file (see below)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Disabled&lt;/em&gt;: Adjust the SELinux configuration file and reboot (see below)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To enable enforcing mode in the SELinux configuration file, edit &lt;code&gt;/etc/selinux/config&lt;/code&gt; and ensure your &lt;code&gt;SELINUX&lt;/code&gt; line has &lt;code&gt;enforcing&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If &lt;code&gt;getenforce&lt;/code&gt; returned &lt;em&gt;Disabled&lt;/em&gt; earlier, you will need to reboot to get SELinux working. Also be sure that the &lt;code&gt;selinux-policy-targeted&lt;/code&gt; package is installed and run &lt;code&gt;fixfiles onboot -B&lt;/code&gt; to relabel the system on reboot &lt;em&gt;(&lt;a href="#comment-2246455243"&gt;thanks to immanetize for the comment&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s install httpd and create a developer user:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# For Fedora
dnf -y install httpd
# For CentOS/RHEL
yum -y install httpd

useradd developer
systemctl enable httpd
systemctl start httpd
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On to the guide!&lt;/p&gt;
&lt;h2 id="hosting-content-in-an-unique-directory"&gt;Hosting content in an unique directory&lt;/h2&gt;
&lt;p&gt;On Red Hat-based systems, httpd expects to find its content in &lt;code&gt;/var/www/html&lt;/code&gt;, but some system administrators prefer to have content stored elsewhere on the system. It could be on a SAN or other remote storage, but it could also just be in a different directory to make things easier for the business.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider a situation where the web content is hosted from &lt;code&gt;/web/&lt;/code&gt;. We can create the directory:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[root@fedora22 ~]# mkdir -v /web
mkdir: created directory &amp;#39;/web&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can edit &lt;code&gt;/etc/httpd/conf/httpd.conf&lt;/code&gt; and set our new &lt;code&gt;DocumentRoot&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot &amp;#34;/web&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s reload the httpd configuration:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl reload httpd
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now we can add some amazing web content:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; /web/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It&amp;rsquo;s time to test our web server:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# curl -i localhost/index.html
HTTP/1.1 403 Forbidden
Date: Thu, 10 Sep 2015 12:54:19 GMT
Server: Apache/2.4.16 (Fedora)
Content-Length: 219
Content-Type: text/html; charset=iso-8859-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh, come on. What&amp;rsquo;s with this 403 error?&lt;/p&gt;
&lt;h2 id="investigating-the-403"&gt;Investigating the 403&lt;/h2&gt;
&lt;p&gt;The first step for any situation like this is to review some logs. Let&amp;rsquo;s check the logs for httpd:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[Thu Sep 10 12:55:04.541789 2015] [core:error] [pid 16597] (13)Permission denied: [client ::1:49860] AH00035: access to /index.html denied (filesystem path &amp;#39;/web/index.html&amp;#39;) because search permissions are missing on a component of the path
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Search permissions are missing? What? Let&amp;rsquo;s check the permissions on our web directory:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# ls -al /web
total 12
drwxr-xr-x. 2 root root 4096 Sep 10 12:53 .
dr-xr-xr-x. 19 root root 4096 Sep 10 12:51 ..
-rw-r--r--. 1 root root 21 Sep 10 12:54 index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The httpd user has the ability to get into the directory (&lt;code&gt;o+x&lt;/code&gt; is set on &lt;code&gt;/web/&lt;/code&gt;) and the httpd user can read the file (&lt;code&gt;o+r&lt;/code&gt; is set on &lt;code&gt;/web/index.html&lt;/code&gt;). Let&amp;rsquo;s check the system journal just in case:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# journalctl -n 1 | tail
-- Logs begin at Thu 2015-09-10 12:31:37 UTC, end at Thu 2015-09-10 12:55:04 UTC. --
Sep 10 12:55:04 fedora22 audit[16597]: &amp;lt;audit-1400&amp;gt; avc: denied { getattr } for pid=16597 comm=&amp;#34;httpd&amp;#34; path=&amp;#34;/web/index.html&amp;#34; dev=&amp;#34;xvda1&amp;#34; ino=524290 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s quite a long log line. Let&amp;rsquo;s break it into pieces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;avc: denied { getattr } for pid=16597 comm=&amp;quot;httpd&amp;quot;&lt;/code&gt;: httpd tried to do something and was denied&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path=&amp;quot;/web/index.html&amp;quot; dev=&amp;quot;xvda1&amp;quot; ino=524290&lt;/code&gt;: path to the file (index.html) involved in the denial&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scontext=system_u:system_r:httpd_t:s0&lt;/code&gt;: the SELinux context of the httpd process&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcontext=unconfined_u:object_r:default_t:s0&lt;/code&gt;: the SELinux contect that is actually applied to our index.html&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tclass=file&lt;/code&gt;: the denial came from accessing a file (index.html)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;permissive=0&lt;/code&gt;: we&amp;rsquo;re in enforcing mode, not permissive mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Long story short, when httpd tried to access our &lt;code&gt;/web/index.html&lt;/code&gt; file, the httpd process was labeled with &lt;code&gt;httpd_t&lt;/code&gt;, but the kernel found that the HTML file was labeled with &lt;code&gt;default_t&lt;/code&gt;. The httpd process (labeled with &lt;code&gt;httpd_t&lt;/code&gt;) isn&amp;rsquo;t allowed to read files that are labeled as &lt;code&gt;default_t&lt;/code&gt;, so the access is denied.&lt;/p&gt;
&lt;h2 id="fixing-it-the-right-way"&gt;Fixing it the right way&lt;/h2&gt;
&lt;p&gt;Since we know what SELinux expects for this file (from the log line in the journal), we can apply the right context and re-test. The &lt;code&gt;chcon&lt;/code&gt; command has a handy argument that allows you to reference a file or directory, and apply the contexts from there. Since we know that &lt;code&gt;/var/www/html&lt;/code&gt; has the right contexts already, we can use it as a reference:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# chcon -v -R --reference=/var/www/html /web
changing security context of &amp;#39;/web/index.html&amp;#39;
changing security context of &amp;#39;/web&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we see some different contexts on &lt;code&gt;/web&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# ls -alZ /web/
total 12
drwxr-xr-x. 2 root root system_u:object_r:httpd_sys_content_t:s0 4096 Sep 10 13:19 .
dr-xr-xr-x. 19 root root system_u:object_r:root_t:s0 4096 Sep 10 13:19 ..
-rw-r--r--. 1 root root system_u:object_r:httpd_sys_content_t:s0 21 Sep 10 13:19 index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s test again:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# curl -I localhost/index.html
HTTP/1.1 403 Forbidden
Date: Thu, 10 Sep 2015 13:21:22 GMT
Server: Apache/2.4.16 (Fedora)
Content-Type: text/html; charset=iso-8859-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Darn! What&amp;rsquo;s in the httpd logs?&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[Thu Sep 10 13:21:22.267719 2015] [authz_core:error] [pid 16593] [client ::1:49861] AH01630: client denied by server configuration: /web/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ah, we cleared the SELinux problem but now httpd is upset. Just below the &lt;code&gt;DocumentRoot&lt;/code&gt; line that we edited earlier, look for two &lt;code&gt;Directory&lt;/code&gt; blocks. Change &lt;code&gt;/var/www/&lt;/code&gt; and &lt;code&gt;/var/www/html&lt;/code&gt; to &lt;code&gt;/web&lt;/code&gt; in those blocks. Reload the httpd configuration and try once more:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# systemctl reload httpd
# curl -I localhost/index.html
HTTP/1.1 200 OK
Date: Thu, 10 Sep 2015 13:25:16 GMT
Server: Apache/2.4.16 (Fedora)
Last-Modified: Thu, 10 Sep 2015 13:19:47 GMT
ETag: &amp;#34;15-51f6474064d50&amp;#34;
Accept-Ranges: bytes
Content-Length: 21
Content-Type: text/html; charset=UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;h2 id="long-term-fix"&gt;Long term fix&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;chcon&lt;/code&gt; method is good for fixing one-off issues and for testing, but we need a good long term fix. SELinux has some file contexts already configured for certain directories, but not for our custom web directory. You can examine the defaults here:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# semanage fcontext -l | grep ^/var/www/html
/var/www/html(/.*)?/sites/default/files(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/sites/default/settings\.php regular file system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/uploads(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html(/.*)?/wp-content(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html/[^/]*/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/html/cgi/munin.* all files system_u:object_r:munin_script_exec_t:s0
/var/www/html/configuration\.php all files system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html/munin(/.*)? all files system_u:object_r:munin_content_t:s0
/var/www/html/munin/cgi(/.*)? all files system_u:object_r:munin_script_exec_t:s0
/var/www/html/owncloud/data(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;SELinux&amp;rsquo;s tools have a concept of &lt;em&gt;equivalency&lt;/em&gt;. This allows you to say that one directory is &lt;em&gt;equivalent&lt;/em&gt; to another one in the long term. We already used &lt;code&gt;chcon&lt;/code&gt; to apply contexts with a reference to a directory with valid contexts, but this equivalency concept gives us a longer term fix. Here&amp;rsquo;s the command to use:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;semanage fcontext --add --equal /var/www /web
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we break this down, we&amp;rsquo;re saying we want to add a new file context where &lt;code&gt;/web&lt;/code&gt; is equal to &lt;code&gt;/var/www&lt;/code&gt;. This means we want the same SELinux contexts applied in the same places and want them treated equally. After running the &lt;code&gt;semanage&lt;/code&gt; command, let&amp;rsquo;s make an &lt;code&gt;index2.html&lt;/code&gt; file to test:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; /web/index2.html
# curl -I localhost/index2.html
HTTP/1.1 200 OK
Date: Thu, 10 Sep 2015 13:35:24 GMT
Server: Apache/2.4.16 (Fedora)
Last-Modified: Thu, 10 Sep 2015 13:34:11 GMT
ETag: &amp;#34;15-51f64a78266c8&amp;#34;
Accept-Ranges: bytes
Content-Length: 21
Content-Type: text/html; charset=UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Great! We didn&amp;rsquo;t have to use &lt;code&gt;chcon&lt;/code&gt; this time around because we configured &lt;code&gt;/web&lt;/code&gt; as an equivalent directory to &lt;code&gt;/var/www&lt;/code&gt;. Let&amp;rsquo;s double check the contexts:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# ls -alZ /web
total 16
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 4096 Sep 10 13:34 .
dr-xr-xr-x. 19 root root system_u:object_r:root_t:s0 4096 Sep 10 13:33 ..
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 21 Sep 10 13:34 index2.html
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 21 Sep 10 13:33 index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Perfect! We now have all of the security benefits of SELinux in a completely custom web directory.&lt;/p&gt;</description></item><item><title>Understanding systemd’s predictable network device names</title><link>https://major.io/p/understanding-systemds-predictable-network-device-names/</link><pubDate>Fri, 21 Aug 2015 21:15:36 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/understanding-systemds-predictable-network-device-names/</guid><description>&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://major.io/wp-content/uploads/2015/08/2229782090_838eaa8574_o-e1440191509854.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I talked a bit about systemd&amp;rsquo;s network device name in my earlier post about [systemd-networkd and bonding][2] and I received some questions about how systemd rolls through the possible names of network devices to choose the final name. These predictable network device names &lt;a href="https://major.io/2014/08/06/unexpected-predictable-network-naming-systemd/"&gt;threw me a curveball last summer&lt;/a&gt; when I couldn&amp;rsquo;t figure out how the names were constructed.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s walk through this process.&lt;/p&gt;
&lt;h2 id="whats-in-a-name"&gt;What&amp;rsquo;s in a name?&lt;/h2&gt;
&lt;p&gt;Back in the systemd-networkd bonding post, I dug into a dual port Intel network card that showed up in a hotplug slot:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# udevadm info -e | grep -A 9 ^P.*eth0
P: /devices/pci0000:00/0000:00:03.2/0000:08:00.0/net/eth0
E: DEVPATH=/devices/pci0000:00/0000:00:03.2/0000:08:00.0/net/eth0
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet OCP Server Adapter X520-2)
E: ID_MODEL_ID=0x10fb
E: ID_NET_DRIVER=ixgbe
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME_MAC=enxa0369f2cec90
E: ID_NET_NAME_PATH=enp8s0f0
E: ID_NET_NAME_SLOT=ens9f0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This udev database dump shows that it came up with a few different names for the network interface:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_MAC=enxa0369f2cec90&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_PATH=enp8s0f0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_SLOT=ens9f0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where do these names come from? We can dig into systemd&amp;rsquo;s source code to figure out the origin of the names and which one is selected as the final choice.&lt;/p&gt;
&lt;h2 id="down-the-udev-rabbit-hole"&gt;Down the udev rabbit hole&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at &lt;a href="https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c"&gt;src/udev/udev-builtin-net_id.c&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/*
 * Predictable network interface device names based on:
 * - firmware/bios-provided index numbers for on-board devices
 * - firmware-provided pci-express hotplug slot index number
 * - physical/geographical location of the hardware
 * - the interface&amp;#39;s MAC address
 *
 * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
 *
 * Two character prefixes based on the type of interface:
 * en -- ethernet
 * sl -- serial line IP (slip)
 * wl -- wlan
 * ww -- wwan
 *
 * Type of names:
 * b&amp;lt;number&amp;gt; -- BCMA bus core number
 * ccw&amp;lt;name&amp;gt; -- CCW bus group name
 * o&amp;lt;index&amp;gt;[d&amp;lt;dev_port&amp;gt;] -- on-board device index number
 * s&amp;lt;slot&amp;gt;[f&amp;lt;function&amp;gt;][d&amp;lt;dev_port&amp;gt;] -- hotplug slot index number
 * x&amp;lt;MAC&amp;gt; -- MAC address
 * [P&amp;lt;domain&amp;gt;]p&amp;lt;bus&amp;gt;s&amp;lt;slot&amp;gt;[f&amp;lt;function&amp;gt;][d&amp;lt;dev_port&amp;gt;]
 * -- PCI geographical location
 * [P&amp;lt;domain&amp;gt;]p&amp;lt;bus&amp;gt;s&amp;lt;slot&amp;gt;[f&amp;lt;function&amp;gt;][u&amp;lt;port&amp;gt;][..][c&amp;lt;config&amp;gt;][i&amp;lt;interface&amp;gt;]
 * -- USB port number chain
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So here&amp;rsquo;s where our names actually begin. Ethernet cards will always start with &lt;em&gt;en&lt;/em&gt;, but they might be followed by a &lt;em&gt;p&lt;/em&gt; (for PCI slots), a &lt;em&gt;s&lt;/em&gt; (for hotplug PCI-E slots), and &lt;em&gt;o&lt;/em&gt; (for onboard cards). Scroll down just a bit more for some examples starting at line 56.&lt;/p&gt;
&lt;h2 id="real-world-examples"&gt;Real-world examples&lt;/h2&gt;
&lt;p&gt;We already looked at the hotplug slot naming from Rackspace&amp;rsquo;s OnMetal servers. They show up as &lt;em&gt;ens9f0&lt;/em&gt; and &lt;em&gt;ens9f1&lt;/em&gt;. That means they&amp;rsquo;re on a hotplug slot which happens to be slot 9. The function indexes are 0 and 1 (for both ports on the Intel 82599ES).&lt;/p&gt;
&lt;h3 id="linux-firewall-with-a-dual-port-pci-card"&gt;Linux firewall with a dual-port PCI card&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s an example of my Linux firewall at home. It&amp;rsquo;s a Dell Optiplex 3020 with an Intel I350-T2 (dual port):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# udevadm info -e | grep -A 10 ^P.*enp1s0f1
P: /devices/pci0000:00/0000:00:01.0/0000:01:00.1/net/enp1s0f1
E: DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/net/enp1s0f1
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2)
E: ID_MODEL_ID=0x1521
E: ID_NET_DRIVER=igb
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME=enp1s0f1
E: ID_NET_NAME_MAC=enxa0369f6e5227
E: ID_NET_NAME_PATH=enp1s0f1
E: ID_OUI_FROM_DATABASE=Intel Corporate
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the output from &lt;code&gt;lspci&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# lspci -s 01:00
01:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
01:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This card happens to sit on PCI bus 1 (enp1), slot 0 (s0). Since it&amp;rsquo;s a dual-port card, it has two function indexes (f0 and f1). That leaves me with two predictable names: &lt;em&gt;enp1s0f1&lt;/em&gt; and &lt;em&gt;enp1s0f0&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="1u-server-with-four-ethernet-ports"&gt;1U server with four ethernet ports&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s grab another example. Here&amp;rsquo;s a SuperMicro 1U X9SCA server with four onboard PCI ethernet cards:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# udevadm info -e | grep -A 10 ^P.*enp2s0
P: /devices/pci0000:00/0000:00:1c.4/0000:02:00.0/net/enp2s0
E: DEVPATH=/devices/pci0000:00/0000:00:1c.4/0000:02:00.0/net/enp2s0
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection
E: ID_MODEL_ID=0x10d3
E: ID_NET_DRIVER=e1000e
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME=enp2s0
E: ID_NET_NAME_MAC=enx00259025963a
E: ID_NET_NAME_PATH=enp2s0
E: ID_OUI_FROM_DATABASE=Super Micro Computer, Inc.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And here&amp;rsquo;s all four ports in &lt;code&gt;lspci&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# for i in `seq 2 5`; do lspci -s 0${i}:; done
02:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
03:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
04:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
05:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These are interesting because they&amp;rsquo;re not all on the same PCI bus. They sit on buses 2-5 in slot 0. There are no function indexes here, so they&amp;rsquo;re named &lt;em&gt;enp2s0&lt;/em&gt; through &lt;em&gt;enp5s0&lt;/em&gt;. These aren&amp;rsquo;t true &lt;em&gt;onboard&lt;/em&gt; cards, so they&amp;rsquo;re named based on their locations.&lt;/p&gt;
&lt;h3 id="storage-server-with-onboard-ethernet"&gt;Storage server with onboard ethernet&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s an example of a server with a true inboard ethernet card:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ udevadm info -e | grep -A 11 ^P.*eno1
P: /devices/pci0000:00/0000:00:19.0/net/eno1
E: DEVPATH=/devices/pci0000:00/0000:00:19.0/net/eno1
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=Ethernet Connection I217-V
E: ID_MODEL_ID=0x153b
E: ID_NET_DRIVER=e1000e
E: ID_NET_LABEL_ONBOARD=en Onboard LAN
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME_MAC=enxe03f49b159c0
E: ID_NET_NAME_ONBOARD=eno1
E: ID_NET_NAME_PATH=enp0s25
E: ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the &lt;code&gt;lspci&lt;/code&gt; output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ lspci -s 00:19.0
00:19.0 Ethernet controller: Intel Corporation Ethernet Connection I217-V (rev 05)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This card has a new name showing up in udev: &lt;code&gt;ID_NET_NAME_ONBOARD&lt;/code&gt;. The systemd udev code has some special handling for onboard cards because they usually sit on the main bus. The naming can get a bit ugly because that 19 would need to be converted into hex for the name.&lt;/p&gt;
&lt;p&gt;If systemd didn&amp;rsquo;t handle onboard cards differently, this card might be named something ugly like enp0s13 (since 19 in decimal becomes 13 in hex). That&amp;rsquo;s really confusing.&lt;/p&gt;
&lt;h2 id="picking-the-final-name"&gt;Picking the final name&lt;/h2&gt;
&lt;p&gt;As we&amp;rsquo;ve seen above, udev makes a big list of names in the udev database. However, there can only be one name in the OS when you try to use the network card.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s wander back into the code. this time we&amp;rsquo;re going to take a look in &lt;a href="https://github.com/systemd/systemd/blob/master/src/udev/net/link-config.c#L403"&gt;src/udev/net/link-config.c&lt;/a&gt; starting at around line 403:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;name_policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;NamePolicy&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name_policy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;_NAMEPOLICY_INVALID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_KERNEL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;respect_predictable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;udev_device_get_property_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ID_NET_NAME_FROM_DATABASE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_ONBOARD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;udev_device_get_property_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ID_NET_NAME_ONBOARD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_SLOT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;udev_device_get_property_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ID_NET_NAME_SLOT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_PATH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;udev_device_get_property_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ID_NET_NAME_PATH&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;NAMEPOLICY_MAC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;udev_device_get_property_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ID_NET_NAME_MAC&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we look at the overall case statement, you can see that the first match is the one that takes precedence. Working from top to bottom, udev takes the first match of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_FROM_DATABASE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_ONBOARD&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_SLOT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_PATH&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ID_NET_NAME_MAC&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we go back to our OnMetal example way at the top of the post, we can follow the logic. The udev database contained the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;E: ID_NET_NAME_MAC=enxa0369f2cec90
E: ID_NET_NAME_PATH=enp8s0f0
E: ID_NET_NAME_SLOT=ens9f0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The udev daemon would start with &lt;code&gt;ID_NET_NAME_FROM_DATABASE&lt;/code&gt;, but that doesn&amp;rsquo;t exist for this card. Next, it would move to &lt;code&gt;ID_NET_NAME_ONBOARD&lt;/code&gt;, but that&amp;rsquo;s not present. Next comes &lt;code&gt;ID_NET_NAME_SLOT&lt;/code&gt;, and we have a match! The &lt;code&gt;ID_NET_NAME_SLOT&lt;/code&gt; entry has &lt;em&gt;ens9f0&lt;/em&gt; and that&amp;rsquo;s the final name for the network device.&lt;/p&gt;
&lt;p&gt;This loop also handles some special cases. The first check is to see if someone requested for udev to not use predictable naming. If the bootloader configuration contains &lt;em&gt;net.ifnames=0&lt;/em&gt;, predictable naming logic is skipped.&lt;/p&gt;
&lt;p&gt;Another special case is &lt;code&gt;ID_NET_NAME_FROM_DATABASE&lt;/code&gt;. Those ports come from udev&amp;rsquo;s internal hardware database. That file only has one item at the moment and it&amp;rsquo;s for a particular Dell iDRAC network interface.&lt;/p&gt;
&lt;h2 id="perplexed-by-hex"&gt;Perplexed by hex&lt;/h2&gt;
&lt;p&gt;If the PCI slot numbers don&amp;rsquo;t seem to line up, be sure to &lt;a href="https://major.io/2014/08/06/unexpected-predictable-network-naming-systemd/"&gt;read my post from last summer&lt;/a&gt;. I ran into a peculiar Dell server with a dual port Intel card on PCI bus 42. The interface ended up with a name of &lt;em&gt;enp66s0f0&lt;/em&gt; and I was stumped.&lt;/p&gt;
&lt;p&gt;The name &lt;em&gt;enp66s0f0&lt;/em&gt; seems to say that we have a card on PCI bus 66, in slot 0, with multiple function index numbers (for multiple ports). However, systemd does a conversion of PCI slot numbers into hex. That means that decimal 66 becomes 42 in hex.&lt;/p&gt;
&lt;p&gt;Most servers won&amp;rsquo;t be this complicated, but it&amp;rsquo;s key to remember the hex conversion.&lt;/p&gt;
&lt;h2 id="feedback"&gt;Feedback&lt;/h2&gt;
&lt;p&gt;Are these systemd-related posts interesting? Let me know. I&amp;rsquo;m a huge fan of systemd and I enjoy writing about it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href="https://www.flickr.com/photos/mlibrary/2229782090"&gt;University of Michigan Library&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Research Paper: Securing Linux Containers</title><link>https://major.io/p/research-paper-securing-linux-containers/</link><pubDate>Fri, 14 Aug 2015 20:45:50 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/research-paper-securing-linux-containers/</guid><description>&lt;p&gt;It seems like there&amp;rsquo;s a new way to run containers every week. The advantages and drawbacks of each approach are argued about on mailing lists, in IRC channels, and in person, around the world. However, the largest amount of confusion seems to be around security.&lt;/p&gt;
&lt;h3 id="launching-secure-containers"&gt;Launching secure containers&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve written about launching secure containers on this blog many times before:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://major.io/2014/04/21/launch-secure-lxc-containers-on-fedora-20-using-selinux-and-svirt/"&gt;Launch secure LXC containers on Fedora 20 using SELinux and sVirt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://major.io/2015/06/18/improving-lxc-template-security/"&gt;Improving LXC template security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://major.io/2014/12/17/try-lxc-ansible-playbook/"&gt;Try out LXC with an Ansible playbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, my goal this time around was to do something more comprehensive and slightly more formal. After getting my &lt;a href="http://www.giac.org/certified-professional/major-hayden/138471"&gt;GSEC and GCUX&lt;/a&gt; certifications from &lt;a href="http://www.giac.org/"&gt;SANS/GIAC&lt;/a&gt;, there was an option to enhance the certification to a gold status by &lt;a href="http://www.giac.org/certifications/gold"&gt;writing a peer-reviewed research paper&lt;/a&gt; on a topic related to the exam. It was a great experience to go through the review process and get feedback on the technical material as well as the structure of the paper itself.&lt;/p&gt;
&lt;h3 id="the-paper"&gt;The paper&lt;/h3&gt;
&lt;p&gt;Without further ado, here are links to the &lt;em&gt;Securing Linux Containers&lt;/em&gt; paper:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://major.io/wp-content/uploads/2015/08/Securing-Linux-Containers-GCUX-Gold-Paper-Major-Hayden.pdf"&gt;PDF version without watermarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sans.org/reading-room/whitepapers/linux/securing-linux-containers-36142"&gt;PDF version from SANS&lt;/a&gt; &lt;em&gt;(has some watermarks and SANS/GIAC extra pages)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The paper is written for readers who have some level of familiarity with Linux and some virtualization technologies. It&amp;rsquo;s a useful paper even for people who haven&amp;rsquo;t worked with containers.&lt;/p&gt;
&lt;p&gt;It starts with an overview of Linux containers and how they differ from other types of virtualization, such as KVM or Xen. From there, it covers how to secure the host system underneath the containers and how to provide security within the containers themselves. There&amp;rsquo;s also a section on how to start a simple container on CentOS 7 and inspect the security controls inside and outside the container.&lt;/p&gt;
&lt;h3 id="licensing"&gt;Licensing&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m also very proud to announce that the paper is licensed under the &lt;a href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;Creative Commons Attribution-ShareAlike 4.0 International License (CC-BY-SA)&lt;/a&gt;. You are free to quote it as much as you like (even for commercial purposes), but I&amp;rsquo;d ask that you maintain the same license and attribute me as the author.&lt;/p&gt;
&lt;h3 id="thank-you"&gt;Thank you&lt;/h3&gt;
&lt;p&gt;This paper wouldn&amp;rsquo;t have been possible without some serious help from these awesome people:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Richard Carbone&lt;/strong&gt; was my advisor from SANS and he helped tremendously&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dan Walsh&lt;/strong&gt; reviewed the content and gave me several pointers on topics to add and adjust&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paul Voccio, Antony Messerli, and Brad McConnell&lt;/strong&gt; from Rackspace also provided feedback&lt;/li&gt;
&lt;li&gt;My mother, &lt;strong&gt;Neta Greene&lt;/strong&gt;, is the best educator I know and she fueled my interest in writing and sharing with others&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="feedback"&gt;Feedback&lt;/h3&gt;
&lt;p&gt;Please let me know if you spot any errors or areas that need clarification. This is one of my favorite topics and I enjoy talking about it. Find me on Freenode IRC as &lt;em&gt;mhayden&lt;/em&gt; and I&amp;rsquo;ll be glad to talk more there.&lt;/p&gt;</description></item><item><title>Automated testing for Ansible CIS playbook on RHEL/CentOS 6</title><link>https://major.io/p/automated-testing-for-ansible-cis-playbook-on-rhelcentos-6/</link><pubDate>Wed, 05 Aug 2015 13:13:52 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/automated-testing-for-ansible-cis-playbook-on-rhelcentos-6/</guid><description>&lt;p&gt;&lt;a href="https://major.io/wp-content/uploads/2014/08/image-ansible.png"&gt;&lt;img src="https://major.io/wp-content/uploads/2014/08/image-ansible-150x150.png" alt="Ansible logo" width="150" height="150" class="alignright size-thumbnail wp-image-5157" srcset="https://major.io/wp-content/uploads/2014/08/image-ansible-150x150.png 150w, https://major.io/wp-content/uploads/2014/08/image-ansible-300x300.png 300w, https://major.io/wp-content/uploads/2014/08/image-ansible.png 700w" sizes="(max-width: 150px) 100vw, 150px" /&gt;&lt;/a&gt;I started working on the Ansible CIS playbook for CentOS and RHEL 6 back in 2014 and I&amp;rsquo;ve made a few changes to increase quality and make it easier to use.&lt;/p&gt;
&lt;p&gt;First off, the role itself is no longer a submodule. You can now just clone the repository and get rolling. This should reduce the time it takes to get started.&lt;/p&gt;
&lt;p&gt;Also, all pull requests to the repository now go through integration testing at Rackspace. Each pull request goes through the gauntlet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax check on Travis-CI&lt;/li&gt;
&lt;li&gt;Travis-CI builds a server at Rackspace&lt;/li&gt;
&lt;li&gt;The entire Ansible playbook runs on the Rackspace Cloud Server&lt;/li&gt;
&lt;li&gt;Results are sent back to GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The testing process usually takes under five minutes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stay tuned: Updates are coming for RHEL and CentOS 7. ;)&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Allow new windows to steal focus in GNOME 3</title><link>https://major.io/p/allow-new-windows-to-steal-focus-in-gnome-3/</link><pubDate>Mon, 06 Jul 2015 12:36:05 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/allow-new-windows-to-steal-focus-in-gnome-3/</guid><description>&lt;p&gt;GNOME 3 generally works well for me but it has some quirks. One of those quirks is that new windows don&amp;rsquo;t actually pop up on the screen with focus as they do in Windows and OS X. When opening a new window, you get a “[Windowname] is ready” notification:&lt;/p&gt;
&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://major.io/wp-content/uploads/2015/07/hangouts_is_ready.png"&gt;&lt;/p&gt;
&lt;p&gt;My preference is for new windows to pop in front and steal focus. I can see why that&amp;rsquo;s not the default since it might cause you to type something in another window where you weren&amp;rsquo;t expecting to. Fortunately, you can enable what GNOME calls &lt;em&gt;strict&lt;/em&gt; window focus with a quick trip to &lt;code&gt;dconf-editor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Installing &lt;code&gt;dconf-editor&lt;/code&gt; is easy:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# RHEL/CentOS 7 and Fedora 21
yum -y install dconf-editor
# Fedora 22
dnf -y install dconf-editor
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Open &lt;code&gt;dconf-editor&lt;/code&gt; and navigate to &lt;strong&gt;org -&amp;gt; gnome -&amp;gt; desktop -&amp;gt; wm -&amp;gt; preferences&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;re there, look for &lt;em&gt;focus-new-windows&lt;/em&gt;. The default setting is &lt;em&gt;smart&lt;/em&gt; which will keep new windows in the background and alert you via a notification. If you click on &lt;em&gt;smart&lt;/em&gt;, a drop down will appear and you can select &lt;em&gt;strict&lt;/em&gt;. That will enable functionality similar to OS X and Windows where new windows will pop up in the front and steal your focus.&lt;/p&gt;
&lt;p&gt;The new setting takes effect immediately and there&amp;rsquo;s no need to logout or close and reopen windows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; If you&amp;rsquo;d like to avoid installing &lt;code&gt;dconf-editor&lt;/code&gt;, use Alexander&amp;rsquo;s suggestion below and simply run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;gsettings set org.gnome.desktop.wm.preferences focus-new-windows &amp;#39;strict&amp;#39;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Improving LXC template security</title><link>https://major.io/p/improving-lxc-template-security/</link><pubDate>Thu, 18 Jun 2015 19:52:11 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/improving-lxc-template-security/</guid><description>&lt;p&gt;&lt;a href="https://major.io/wp-content/uploads/2015/06/containers.png"&gt;&lt;img src="https://major.io/wp-content/uploads/2015/06/containers-300x276.png" alt="LXC logo" width="300" height="276" class="alignright size-medium wp-image-5669" srcset="https://major.io/wp-content/uploads/2015/06/containers-300x276.png 300w, https://major.io/wp-content/uploads/2015/06/containers.png 318w" sizes="(max-width: 300px) 100vw, 300px" /&gt;&lt;/a&gt;I&amp;rsquo;ve been getting involved with the &lt;a href="https://fedoraproject.org/wiki/Security_Team"&gt;Fedora Security Team&lt;/a&gt; lately and we&amp;rsquo;re working as a group to crush security bugs that affect Fedora, CentOS (via EPEL) and Red Hat Enterprise Linux (via EPEL). During some of this work, I stumbled upon a &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=1132001"&gt;group of Red Hat Bugzilla tickets&lt;/a&gt; talking about LXC template security.&lt;/p&gt;
&lt;p&gt;The gist of the problem is that there&amp;rsquo;s a wide variance in how users and user credentials are handled by the different LXC templates. An &lt;a href="https://fedoraproject.org/wiki/LXC_Template_Security_Improvements"&gt;inventory of the current situation&lt;/a&gt; revealed some horrifying problems with many OS templates.&lt;/p&gt;
&lt;p&gt;Many of the templates set an &lt;strong&gt;awful&lt;/strong&gt; default root password, like rooter, toor, or root. Some of the others create a regular user with sudo privileges and give it a default, predictable password unless the user specifies otherwise.&lt;/p&gt;
&lt;p&gt;There are some bright spots, though. Fedora and CentOS templates will accept a root password from the user during the build and set a randomized password for the root user if a password isn&amp;rsquo;t specified. Ubuntu Cloud takes another approach by locking out the root user and requiring cloud-init configuration data to configure the root account.&lt;/p&gt;
&lt;p&gt;I kicked off a &lt;a href="https://lists.linuxcontainers.org/pipermail/lxc-devel/2015-June/011883.html"&gt;mailing list thread&lt;/a&gt; and wrote a &lt;a href="https://github.com/lxc/lxc/pull/574"&gt;terrible pull request&lt;/a&gt; to get things underway. Stéphane Graber requested that all templates use a shared script to handle users and credentials via standardized environment variables and command line arguments. In addition, all passwords for users (regular or root) should be empty with password-less logins disabled. Those are some reasonable requests and I&amp;rsquo;m working on a shell script that&amp;rsquo;s easy to import into LXC templates.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also a push to remove sshd from all LXC templates by default, but I&amp;rsquo;m hoping to keep that one tabled until the credentials issue is solved.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to help out with the effort, let me know! I&amp;rsquo;ll probably get some code up onto Github soon and as for comments.&lt;/p&gt;</description></item><item><title>Keep old kernels with yum and dnf</title><link>https://major.io/p/keep-old-kernels-with-yum-and-dnf/</link><pubDate>Mon, 18 May 2015 14:22:56 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/keep-old-kernels-with-yum-and-dnf/</guid><description>&lt;p&gt;When you upgrade packages on Red Hat, CentOS and Fedora systems, the newer package replaces the older package. That means that files managed by RPM from the old package are removed and replaced with files from the newer package.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one exception here: kernel packages.&lt;/p&gt;
&lt;p&gt;Upgrading a kernel package with yum and dnf leaves the older kernel package on the system just in case you need it again. This is handy if the new kernel introduces a bug on your system or if you need to work through a compile of a custom kernel module.&lt;/p&gt;
&lt;p&gt;However, yum and dnf will clean up older kernels once you have more than three. The oldest kernel will be removed from the system and the newest three will remain. In some situations, you may want more than three to stay on your system.&lt;/p&gt;
&lt;p&gt;To change the setting, simply open up &lt;code&gt;/etc/yum.conf&lt;/code&gt; or &lt;code&gt;/etc/dnf/dnf.conf&lt;/code&gt; in your favorite text editor. Look for this line:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;installonly_limit=3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To keep five kernels, simply replace the 3 with a 5. If you&amp;rsquo;d like to keep every old kernel on the system forever, just change the 3 to a 0. A zero means you never want &amp;ldquo;installonly&amp;rdquo; packages (like kernels) to ever be removed from your system.&lt;/p&gt;</description></item><item><title>Creating a bridge for virtual machines using systemd-networkd</title><link>https://major.io/p/creating-a-bridge-for-virtual-machines-using-systemd-networkd/</link><pubDate>Thu, 26 Mar 2015 13:17:08 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/creating-a-bridge-for-virtual-machines-using-systemd-networkd/</guid><description>&lt;p&gt;There are plenty of guides out there for making ethernet bridges in Linux to support virtual machines using built-in network scripts or NetworkManager. I decided to try my hand with creating a bridge using only systemd-networkd and it was surprisingly easy.&lt;/p&gt;
&lt;p&gt;First off, you&amp;rsquo;ll need a version of systemd with networkd support. Fedora 20 and 21 will work just fine. RHEL/CentOS 7 and Arch Linux should also work. Much of the networkd support has been in systemd for quite a while, but if you&amp;rsquo;re looking for fancier network settings, like bonding, you&amp;rsquo;ll want at least systemd 216.&lt;/p&gt;
&lt;h3 id="getting-our-daemons-in-order"&gt;Getting our daemons in order&lt;/h3&gt;
&lt;p&gt;Before we get started, ensure that systemd-networkd will run on a reboot and NetworkManager is disabled. We also need to make a config file director for systemd-networkd if it doesn&amp;rsquo;t exist already. In addition, let&amp;rsquo;s enable the caching resolver and make a symlink to systemd&amp;rsquo;s &lt;code&gt;resolv.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl enable systemd-networkd
systemctl disable NetworkManager
systemctl enable systemd-resolved
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
mkdir /etc/systemd/network
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="configure-the-physical-network-adapter"&gt;Configure the physical network adapter&lt;/h3&gt;
&lt;p&gt;In my case, the network adapter connected to my external network is &lt;em&gt;enp4s0&lt;/em&gt; but yours will vary. Run &lt;code&gt;ip addr&lt;/code&gt; to get a list of your network cards. Let&amp;rsquo;s create &lt;code&gt;/etc/systemd/network/uplink.network&lt;/code&gt; and put the following in it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;enp4s0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Bridge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;br0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m telling systemd to look for a device called &lt;em&gt;enp4s0&lt;/em&gt; and then add it to a bridge called &lt;em&gt;br0&lt;/em&gt; that we haven&amp;rsquo;t configured yet. Be sure to change &lt;em&gt;enp4s0&lt;/em&gt; to match your ethernet card.&lt;/p&gt;
&lt;h3 id="make-the-bridge"&gt;Make the bridge&lt;/h3&gt;
&lt;p&gt;We need to tell systemd about our new bridge network device and we also need to specify the IP configuration for it. We start by creating &lt;code&gt;/etc/systemd/network/br0.netdev&lt;/code&gt; to specify the device:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[NetDev]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;br0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file is fairly self-explanatory. We&amp;rsquo;re telling systemd that we want a device called &lt;em&gt;br0&lt;/em&gt; that functions as an ethernet bridge. Now create &lt;code&gt;/etc/systemd/network/br0.network&lt;/code&gt; to specify the IP configuration for the &lt;em&gt;br0&lt;/em&gt; interface:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;br0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;DNS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;192.168.250.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;192.168.250.33/24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Gateway&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;192.168.250.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file tells systemd that we want to apply a simple static network configuration to &lt;em&gt;br0&lt;/em&gt; with a single IPv4 address. If you want to add additional DNS servers or IPv4/IPv6 addresses, just add more &lt;code&gt;DNS=&lt;/code&gt; and &lt;code&gt;Address&lt;/code&gt; lines right below the ones you see above. Yes, it&amp;rsquo;s just that easy.&lt;/p&gt;
&lt;h3 id="lets-do-this"&gt;Let&amp;rsquo;s do this&lt;/h3&gt;
&lt;p&gt;Some folks are brave enough to stop NetworkManager and start all of the systemd services here but I prefer to reboot so that everything comes up cleanly. That will also allow you to verify that future reboots will cause the server to come back online with the right configuration. After the reboot, run &lt;code&gt;networkctl&lt;/code&gt; and you&amp;rsquo;ll get something like this (with color):&lt;/p&gt;
&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://major.io/wp-content/uploads/2015/03/networkctl_screenshot.png"&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what&amp;rsquo;s in the screenshot:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;IDX LINK TYPE OPERATIONAL SETUP
 1 lo loopback carrier unmanaged
 2 enp2s0 ether off unmanaged
 3 enp3s0 ether off unmanaged
 4 enp4s0 ether degraded configured
 5 enp5s0 ether off unmanaged
 6 br0 ether routable configured
 7 virbr0 ether no-carrier unmanaged

7 links listed.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My ethernet card has four ports and only &lt;em&gt;enp4s0&lt;/em&gt; is in use. It has a &lt;em&gt;degraded&lt;/em&gt; status because there is no IP address assigned to &lt;em&gt;enp4s0&lt;/em&gt;. You can ignore that for now but it would be nice to see this made more clear in a future systemd release.&lt;/p&gt;
&lt;p&gt;Look at &lt;em&gt;br0&lt;/em&gt; and you&amp;rsquo;ll notice that it&amp;rsquo;s &lt;em&gt;configured&lt;/em&gt; and &lt;em&gt;routable&lt;/em&gt;. That&amp;rsquo;s the best status you can get for an interface. You&amp;rsquo;ll also see that my other ethernet devices are in the &lt;em&gt;unmanaged&lt;/em&gt; state. I could easily add more &lt;code&gt;.network&lt;/code&gt; files to &lt;code&gt;/etc/systemd/network&lt;/code&gt; to configure those interfaces later.&lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further reading&lt;/h3&gt;
&lt;p&gt;As usual, the &lt;a href="https://wiki.archlinux.org/index.php/systemd-networkd"&gt;Arch Linux wiki page on systemd-networkd&lt;/a&gt; is a phenomenal resource. There&amp;rsquo;s a detailed overview of all of the available systemd-networkd configuration file options over at &lt;a href="http://www.freedesktop.org/software/systemd/man/systemd.network.html"&gt;systemd&amp;rsquo;s documentation site&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Install sysstat on Fedora 21</title><link>https://major.io/p/install-sysstat-fedora-21/</link><pubDate>Fri, 12 Dec 2014 17:55:57 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/install-sysstat-fedora-21/</guid><description>&lt;p&gt;One of the first tools I learned about after working with Red Hat was &lt;a href="http://sebastien.godard.pagesperso-orange.fr/"&gt;sysstat&lt;/a&gt;. It can write down historical records about your server at regular intervals. This can help you diagnose CPU usage, RAM usage, or network usage problems. In addition, sysstat also provides some handy command line utilities like &lt;a href="http://linux.die.net/man/8/vmstat"&gt;vmstat&lt;/a&gt;, &lt;a href="http://linux.die.net/man/1/iostat"&gt;iostat&lt;/a&gt;, and &lt;a href="http://linux.die.net/man/1/pidstat"&gt;pidstat&lt;/a&gt; that give you a live view of what your system is doing.&lt;/p&gt;
&lt;p&gt;On Debian-based systems (including Ubuntu), you install the sysstat package and enable it with a quick edit to &lt;code&gt;/etc/default/sysstat&lt;/code&gt; and the cron job takes it from there. CentOS and Fedora systems call the collector process using a cron job in &lt;code&gt;/etc/cron.d&lt;/code&gt; and it&amp;rsquo;s enabled by default.&lt;/p&gt;
&lt;p&gt;Fedora 21 comes with sysstat 11 and there are now systemd unit files to control the collection and management of stats. You can find the unit files by listing the files in the sysstat RPM:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ rpm -ql sysstat | grep systemd
/usr/lib/systemd/system/sysstat-collect.service
/usr/lib/systemd/system/sysstat-collect.timer
/usr/lib/systemd/system/sysstat-summary.service
/usr/lib/systemd/system/sysstat-summary.timer
/usr/lib/systemd/system/sysstat.service
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These services and timers &lt;strong&gt;aren&amp;rsquo;t enabled by default&lt;/strong&gt; in Fedora 21. If you run &lt;code&gt;sar&lt;/code&gt; after installing sysstat, you&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# sar
Cannot open /var/log/sa/sa12: No such file or directory
Please check if data collecting is enabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All you need to do is enable and start the main sysstat service:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl enable sysstat
systemctl start sysstat
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;From there, systemd will automatically call for collection and management of the statistics using its &lt;a href="http://www.freedesktop.org/software/systemd/man/systemd.timer.html"&gt;internal timers&lt;/a&gt;. Opening up &lt;code&gt;/usr/lib/systemd/system/sysstat-collect.timer&lt;/code&gt; reveals the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /usr/lib/systemd/system/sysstat-collect.timer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (C) 2014 Tomasz Torcz &amp;lt;tomek@pipebreaker.pl&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sysstat-11.0.0 systemd unit file:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Activates activity collector every 10 minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Run system activity accounting tool every 10 minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;OnCalendar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;*:00/10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sysstat.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The timer unit file ensures that the sysstat-collect.service is called every 10 minutes based on the real time provided by the system clock. (There are other options to set timers based on relative time of when the server booted or when a user logged into the system). The familiar &lt;code&gt;sa1&lt;/code&gt; command appears in &lt;code&gt;/usr/lib/systemd/system/sysstat-collect.service&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /usr/lib/systemd/system/sysstat-collect.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# (C) 2014 Tomasz Torcz &amp;lt;tomek@pipebreaker.pl&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sysstat-11.0.0 systemd unit file:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Collects system activity data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Activated by sysstat-collect.timer unit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;system activity accounting tool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Documentation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;man:sa1(8)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/lib64/sa/sa1 1 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>httpry 0.1.8 available for RHEL and CentOS 7</title><link>https://major.io/p/httpry-rhel-centos-7/</link><pubDate>Wed, 13 Aug 2014 13:20:28 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/httpry-rhel-centos-7/</guid><description>&lt;p&gt;Red Hat Enterprise Linux and CentOS 7 users can now install &lt;a href="https://github.com/jbittel/httpry"&gt;httpry&lt;/a&gt; &lt;a href="https://github.com/jbittel/httpry/blob/master/doc/ChangeLog"&gt;0.1.8&lt;/a&gt; in EPEL 7 Beta. The new httpry version is also available for RHEL/CentOS 6 and supported Fedora versions (19, 20, 21 branched, and rawhide).&lt;/p&gt;
&lt;p&gt;Configuring EPEL on a RHEL/CentOS server is easy. &lt;a href="https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F"&gt;Follow the instructions&lt;/a&gt; on EPEL&amp;rsquo;s site and install the epel-release RPM that matches your OS release version.&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t used httpry before, &lt;a href="http://dumpsterventures.com/jason/httpry/"&gt;check the output&lt;/a&gt; on Jason Bittel&amp;rsquo;s site. It&amp;rsquo;s a handy way to watch almost any type of HTTP server and see the traffic in an easier to read (and easier to grep) format.&lt;/p&gt;</description></item><item><title>Unexpected predictable network naming with systemd</title><link>https://major.io/p/unexpected-predictable-network-naming-systemd/</link><pubDate>Wed, 06 Aug 2014 21:09:34 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/unexpected-predictable-network-naming-systemd/</guid><description>&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://major.io/wp-content/uploads/2014/08/3240995967_04d7888d5c_o-e1407359174321.jpg"&gt;&lt;/p&gt;
&lt;p&gt;While using a Dell R720 at work today, we stumbled upon a problem where the &lt;a href="http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/"&gt;predictable network device naming with systemd&lt;/a&gt; gave us some unpredictable results. The server has four onboard network ports (two 10GbE and two 1GbE) and an add-on 10GbE card with two additional ports.&lt;/p&gt;
&lt;p&gt;Running &lt;em&gt;lspci&lt;/em&gt; gives this output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# lspci | grep Eth
01:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
01:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
08:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
42:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
42:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&amp;rsquo;re not familiar with that output, it says:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two 10GbE ports on PCI bus 1 (ports 0 and 1)&lt;/li&gt;
&lt;li&gt;Two 1GbE ports on PCI bus 8 (ports 0 and 1)&lt;/li&gt;
&lt;li&gt;Two 10GbE ports on PCI bus 42 (ports 0 and 1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When the system boots up, the devices are named based on &lt;a href="http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n35"&gt;systemd-udevd&amp;rsquo;s criteria&lt;/a&gt;. Our devices looked like this after boot:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# ip addr | egrep ^[0-9]
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default
2: enp8s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
3: enp8s0f1: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
4: enp1s0f0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000
5: enp1s0f1: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
6: enp66s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
7: enp66s0f1: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Devices 2-5 make sense since they&amp;rsquo;re on PCI buses 1 and 8. However, our two-port NIC on PCI bus 42 has suddenly been named 66. We rebooted the server with the &lt;em&gt;rd.udev.debug&lt;/em&gt; kernel command line to display debug messages from systemd-udevd during boot. That gave us this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# journalctl | grep enp66s0f0
systemd-udevd[471]: renamed network interface eth0 to enp66s0f0
systemd-udevd[471]: NAME &amp;#39;enp66s0f0&amp;#39; /usr/lib/udev/rules.d/80-net-setup-link.rules:13
systemd-udevd[471]: changing net interface name from &amp;#39;eth0&amp;#39; to &amp;#39;enp66s0f0&amp;#39;
systemd-udevd[471]: renamed netif to &amp;#39;enp66s0f0&amp;#39;
systemd-udevd[471]: changed devpath to &amp;#39;/devices/pci0000:40/0000:40:02.0/0000:42:00.0/net/enp66s0f0&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the system sees that the enp66s0f0 device is actually on PCI bus 42. What gives? A quick trip to #systemd on Freenode caused a facepalm:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mhayden | weird, udev shows it on pci bus 42 but yet names it 66
 jwl | 0x42 = 66
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I didn&amp;rsquo;t expect to see hex. Sure enough, converting 42 in hex to decimal yields 66:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ printf &amp;#34;%d\n&amp;#34; 0x42
66
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That also helps to explain why the devices on buses 1 and 8 were unaffected. Converting 1 and 8 in hex to decimal gives 1 and 8. If you&amp;rsquo;re new to hex, this &lt;a href="http://ascii.cl/conversion.htm"&gt;conversion table&lt;/a&gt; may help.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo Credit: &lt;a href="https://www.flickr.com/photos/90021863@N00/3240995967/"&gt;mindfieldz&lt;/a&gt; via &lt;a href="http://compfight.com"&gt;Compfight&lt;/a&gt; &lt;a href="https://creativecommons.org/licenses/by-nc-sa/2.0/"&gt;cc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Adventures in live booting Linux distributions</title><link>https://major.io/p/adventures-in-live-booting-linux-distributions/</link><pubDate>Tue, 29 Jul 2014 13:05:54 +0000</pubDate><author>major@mhtx.net (Major Hayden)</author><guid>https://major.io/p/adventures-in-live-booting-linux-distributions/</guid><description>&lt;p&gt;We&amp;rsquo;re all familiar with live booting Linux distributions. Almost every Linux distribution under the sun has a method for making live CD&amp;rsquo;s, writing live USB sticks, or booting live images over the network. The primary use case for some distributions is on a live medium (like &lt;a href="http://www.knoppix.org/"&gt;KNOPPIX&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;However, I embarked on an adventure to look at live booting Linux for a different use case. Sure, many live environments are used for demonstrations or installations - temporary activities for a desktop or a laptop. My goal was to find a way to boot a large fleet of servers with live images. These would need to be long-running, stable, feature-rich, and highly configurable live environments.&lt;/p&gt;
&lt;p&gt;Finding off the shelf solutions wasn&amp;rsquo;t easy. Finding cross-platform off the shelf solutions for live booting servers was even harder. I worked on a solution with a coworker to create a cross-platform live image builder that we hope to open source soon. (I&amp;rsquo;d do it sooner but the code is horrific.) ;)&lt;/p&gt;
&lt;h4 id="debian-jessie-testing"&gt;Debian jessie (testing)&lt;/h4&gt;
&lt;p&gt;First off, we took a look at Debian&amp;rsquo;s &lt;a href="http://live.debian.net/"&gt;Live Systems project&lt;/a&gt;. It consists of two main parts: something to build live environments, and something to help live environments boot well off the network. At the time of this writing, the live build process leaves a lot to be desired. There&amp;rsquo;s a peculiar tree of directories that are required to get started and the documentation isn&amp;rsquo;t terribly straightforward. Although there&amp;rsquo;s a bunch of documentation available, it&amp;rsquo;s difficult to follow and it seems to skip some critical details. &lt;em&gt;(In all fairness, I&amp;rsquo;m an experienced Debian user but I haven&amp;rsquo;t gotten into the innards of Debian package/system development yet. My shortcomings there could be the cause of my problems.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The second half of the Live Systems project consist of multiple packages that help with the initial boot and configuration of a live instance. These tools work &lt;strong&gt;extremely well&lt;/strong&gt;. Version 4 (currently in alpha) has tools for doing all kinds of system preparation very early in the boot process and it&amp;rsquo;s compatible with SysVinit or systemd. The live images boot up with a simple &lt;a href="https://en.wikipedia.org/wiki/SquashFS"&gt;SquashFS&lt;/a&gt; (mounted read only) and they use AUFS to add on a writeable filesystem that stays in RAM. Reads and writes to the RAM-backed filesystem are extremely quick and you don&amp;rsquo;t run into a brick wall when the filesystem fills up (more on that later with Fedora).&lt;/p&gt;
&lt;h4 id="ubuntu-1404"&gt;Ubuntu 14.04&lt;/h4&gt;
&lt;p&gt;Ubuntu uses &lt;a href="https://help.ubuntu.com/community/LiveCDCustomizationFromScratch"&gt;casper&lt;/a&gt; which seems to precede Debian&amp;rsquo;s Live Systems project or it could be a fork (please correct me if I&amp;rsquo;m incorrect). Either way, it seemed a bit less mature than Debian&amp;rsquo;s project and left a lot to be desired.&lt;/p&gt;
&lt;h4 id="fedora-and-centos"&gt;Fedora and CentOS&lt;/h4&gt;
&lt;p&gt;Fedora 20 and CentOS 7 are very close in software versions and they use the same mechanisms to boot live images. They use &lt;a href="https://dracut.wiki.kernel.org/index.php/Main_Page"&gt;dracut&lt;/a&gt; to create the initramfs and there are a set of &lt;a href="https://git.kernel.org/cgit/boot/dracut/dracut.git/tree/modules.d/90dmsquash-live"&gt;dmsquash modules&lt;/a&gt; that handle the setup of the live image. The &lt;a href="https://git.kernel.org/cgit/boot/dracut/dracut.git/tree/modules.d/90livenet"&gt;livenet&lt;/a&gt; module allows the live images to be pulled over the network during the early part of the boot process.&lt;/p&gt;
&lt;p&gt;Building the live images is a little tricky. You&amp;rsquo;ll find good &lt;a href="https://fedoraproject.org/wiki/LiveOS_image"&gt;documentation and tools&lt;/a&gt; for standard live bootable CD&amp;rsquo;s and USB sticks, but booting a server isn&amp;rsquo;t as straightforward. Dracut expects to find a &lt;a href="https://fedoraproject.org/wiki/LiveOS_image#Operating_system_file_systems"&gt;squashfs which contains a filesystem image&lt;/a&gt;. When the live image boots, that filesystem image is connected to a loopback device and mounted read-only. A snapshot is made via device mapper that gives you a small overlay for adding data to the live image.&lt;/p&gt;
&lt;p&gt;This overlay comes with some caveats. Keeping tabs on how quickly the overlay is filling up can be tricky. Using tools like &lt;em&gt;df&lt;/em&gt; is insufficient since device mapper snapshots are concerned with blocks. As you write 4k blocks in the overlay, you&amp;rsquo;ll begin to fill the snapshot, just as you would with an LVM snapshot. When the snapshot fills up and there are no blocks left, the filesystem in RAM becomes corrupt and unusable. There are some tricks to force it back online but I didn&amp;rsquo;t have much luck when I tried to recover. The only solution I could find was to hard reboot.&lt;/p&gt;
&lt;h4 id="arch"&gt;Arch&lt;/h4&gt;
&lt;p&gt;The ArchLinux live boot environments seem very similar to the ones I saw in Fedora and CentOS. All of them use dracut and systemd, so this makes sense. Arch once used a project called &lt;a href="https://wiki.archlinux.org/index.php/larch"&gt;Larch&lt;/a&gt; to create live environments but it&amp;rsquo;s fallen out of support due to AUFS2 being removed (according to the &lt;a href="https://wiki.archlinux.org/index.php/larch#Installation"&gt;wiki page&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Although I didn&amp;rsquo;t build a live environment with Arch, I booted one of their live ISO&amp;rsquo;s and found their live environment to be much like Fedora and CentOS. There was a device mapper snapshot available as an overlay and once it&amp;rsquo;s full, you&amp;rsquo;re in trouble.&lt;/p&gt;
&lt;h4 id="opensuse"&gt;OpenSUSE&lt;/h4&gt;
&lt;p&gt;The path to live booting an OpenSUSE image seems quite different. The live squashfs is mounted read only onto &lt;em&gt;/read-only&lt;/em&gt;. An ext3 filesystem is created in RAM and is mounted on &lt;em&gt;/read-write&lt;/em&gt;. From there, &lt;a href="https://kernel.googlesource.com/pub/scm/linux/kernel/git/mszeredi/vfs/+/overlayfs.current/Documentation/filesystems/overlayfs.txt"&gt;overlayfs&lt;/a&gt; is used to lay the writeable filesystem on top of the read-only squashfs. You can still fill up the overlay filesystem and cause some temporary problems, but you can back out those errant files and still have a useable live environment.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the problem: overlayfs was given the green light for &lt;em&gt;consideration&lt;/em&gt; in the Linux kernel &lt;a href="https://lwn.net/Articles/542709/"&gt;by Linus in 2013&lt;/a&gt;. It&amp;rsquo;s been proposed for several kernel releases and it didn&amp;rsquo;t make it into 3.16 (which will be released soon). OpenSUSE has wedged overlayfs into their kernel tree just as Debian and Ubuntu have wedged AUFS into theirs.&lt;/p&gt;
&lt;h4 id="wrap-up"&gt;Wrap-up&lt;/h4&gt;
&lt;p&gt;Building highly customized live images isn&amp;rsquo;t easy and running them in production makes it more challenging. Once the upstream kernel has a stable, solid, stackable filesystem, it should be much easier to operate a live environment for extended periods. There has been a parade of stackable filesystems over the years (remember funion-fs?) but I&amp;rsquo;ve been told that overlayfs seems to be a solid contender. I&amp;rsquo;ll keep an eye out for those kernel patches to land upstream but I&amp;rsquo;m not going to hold my breath quite yet.&lt;/p&gt;</description></item></channel></rss>