<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/hosting/</id>
  <link href="https://www.endpointdev.com/blog/tags/hosting/"/>
  <link href="https://www.endpointdev.com/blog/tags/hosting/" rel="self"/>
  <updated>2026-05-11T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Introducing EP Audit</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2026/05/introducing-ep-audit/"/>
      <id>https://www.endpointdev.com/blog/2026/05/introducing-ep-audit/</id>
      <published>2026-05-11T00:00:00+00:00</published>
      <author>
        <name>Dan Briones</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2026/05/introducing-ep-audit/cover.webp&#34; alt=&#34;A panoramic view from a mountain overlooks a vast valley stretching to the horizon under a stormy sky.&#34;&gt;&lt;br&gt;
Photo by Bimal Gharti Magar, 2026.&lt;/p&gt;
&lt;p&gt;In the complex landscape of cloud security, staying compliant and prepared for audits is important. Enter EP Audit, a compliance-focused audit process, AI-powered but led by senior engineers. It&amp;rsquo;s designed for Azure, AWS, and Google Cloud setups. EP Audit emerged from necessity: When a financial services client required an Azure security audit, we at End Point built a solution that not only met their immediate needs, but also evolved into an internal tool we continue to refine. Today, it serves as a key part of our multi-cloud security audit framework and is tested against our own cloud accounts before being used in client engagements.&lt;/p&gt;
&lt;h4 id=&#34;the-problem&#34;&gt;The Problem&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Cloud environments are dynamic&lt;/strong&gt;: New projects, personnel changes, and vendor updates can significantly alter configurations over time. As environments evolve, the security posture originally reviewed and approved by your engineers may no longer fully match what is running in production. Unused resources, overly permissive access, and orphaned infrastructure can also accumulate over time, increasing both risk and monthly costs. This often goes unnoticed until an audit, customer review, or security incident forces a closer look.&lt;/p&gt;
&lt;p&gt;Modern compliance frameworks—SOC 2, ISO 27001, HIPAA, PCI DSS—require regular, documented security reviews. Yet many organizations still struggle to provide consistent documentation with timestamps, severity tracking, and proof of remediation. EP Audit helps address this gap by generating a structured audit trail throughout the review process.&lt;/p&gt;
&lt;h4 id=&#34;what-ep-audit-looks-like&#34;&gt;What EP Audit Looks Like&lt;/h4&gt;
&lt;p&gt;An EP Audit engagement is structured as a scheduled review cycle with two phases: a Base scan to establish a security snapshot, and a Final scan performed after remediation work to verify fixes. Both phases use a command-line runner with a read-only audit identity, ensuring no changes are made during the audit itself. Each Base scan produces nine deliverables designed to provide both high-level summaries and detailed technical findings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Executive Summary:&lt;/strong&gt; Severity-ranked audit findings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client Report:&lt;/strong&gt; Full narrative with risk scorecard and roadmap.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured Findings Report:&lt;/strong&gt; Engineer-friendly findings by category.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-filled Hardening Checklist:&lt;/strong&gt; CIS-aligned checklist with auto-populated FAIL statuses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fillable Hardening Checklist:&lt;/strong&gt; A remediation tool for your team.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Diagram:&lt;/strong&gt; Auto-generated deployment topology.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Findings Workbook:&lt;/strong&gt; Excel file with color-coded severity tabs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remediation Plan:&lt;/strong&gt; Phased plan with affected resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partner Remediation Identity Setup:&lt;/strong&gt; Guide for temporary write scope during remediation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These deliverables are standardized across Azure, AWS, and GCP, helping simplify multi-cloud audit reviews and recurring engagements.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/05/introducing-ep-audit/epaudit-findings-category.webp&#34; alt=&#34;Findings by severity and category&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sample summary of findings by severity and category on EP Audit.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Every finding in EP Audit is mapped to controls from recognized security frameworks. For Azure, we reference the CIS Microsoft Azure Foundations Benchmark and the Microsoft Cloud Security Benchmark. AWS findings align with the CIS AWS Foundations Benchmark, AWS Foundational Security Best Practices, and related guidance. GCP findings follow the CIS GCP Foundation Benchmark and the Google Cloud Architecture Framework Security Pillar. This helps keep audit findings grounded in established industry standards rather than proprietary scoring systems or arbitrary recommendations.&lt;/p&gt;
&lt;h4 id=&#34;a-service-not-just-a-tool&#34;&gt;A Service, Not Just a Tool&lt;/h4&gt;
&lt;p&gt;There are already plenty of cloud configuration scanners available. What matters is how the findings are reviewed, prioritized, and applied in real environments.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Senior Engineering Review:&lt;/strong&gt; Our engineers provide context and actionable recommendations for each finding, bridging the gap between automated results and practical solutions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End Point-Specific Enhancements:&lt;/strong&gt; We include checks beyond published frameworks, such as billing data analysis for orphaned resources and third-party security tool integration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal Validation:&lt;/strong&gt; Every framework change is tested on End Point&amp;rsquo;s own cloud accounts before client deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A single audit provides a snapshot in time, but recurring audits make it easier to identify trends, validate remediation progress, and detect configuration drift over time. EP Audit includes year-over-year comparison reporting to help highlight both improvements and regressions. In practice, this helps support compliance reviews, procurement questionnaires, and ongoing security review processes while providing better visibility into how environments evolve over time.&lt;/p&gt;
&lt;h4 id=&#34;phased-remediation&#34;&gt;Phased Remediation&lt;/h4&gt;
&lt;p&gt;EP Audit generates remediation scripts and recommendations organized by severity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;P1 (0–7 days):&lt;/strong&gt; Critical issues like exposed management ports.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P2 (30 days):&lt;/strong&gt; High-priority issues such as encryption gaps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P3 (90 days):&lt;/strong&gt; Medium-priority defense-in-depth weaknesses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P4 (Maintenance):&lt;/strong&gt; Low-priority configuration hygiene.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Scripts default to dry-run mode, allowing proposed changes to be reviewed before execution. Our team can assist with remediation directly, or clients can implement the recommendations independently using the provided guidance.&lt;/p&gt;
&lt;p&gt;Over multiple engagements, organizations begin building a clearer picture of how their cloud environments evolve over time. Recurring audits make it easier to track remediation progress, identify recurring issues, and detect configuration drift before it becomes a larger problem. The resulting documentation can also help support compliance reviews, customer security questionnaires, cyber insurance requirements, internal security tracking, and reduce monthly costs.&lt;/p&gt;
&lt;h4 id=&#34;working-with-end-point&#34;&gt;Working with End Point&lt;/h4&gt;
&lt;p&gt;If your organization operates workloads in Azure, AWS, or Google Cloud and needs a structured, standards-aligned cloud security review process, feel free to &lt;a href=&#34;/contact/&#34;&gt;contact us&lt;/a&gt;. If you are working with us already, you can talk with your representative to find out more.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Rocky Linux 9 at Hetzner Robot Made Quick and Easy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/"/>
      <id>https://www.endpointdev.com/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/</id>
      <published>2023-07-01T00:00:00+00:00</published>
      <author>
        <name>Jeffry Johar</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/mangopickles.webp&#34; alt=&#34;Malaysian Mango Pickles&#34;&gt;&lt;br&gt;
Image &lt;a href=&#34;https://www.pexels.com/photo/mango-pickles-17315505/&#34;&gt;by Jeffry Johar&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;In &lt;a href=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/&#34;&gt;my last blog post&lt;/a&gt;, I shared my experience of installing Rocky Linux 8 on my Hetzner robot server and subsequently upgrading it to Rocky Linux 9.&lt;/p&gt;
&lt;p&gt;Rocky Linux project manager &lt;a href=&#34;https://github.com/brianclemens&#34;&gt;Brian Clemens&lt;/a&gt; said that method is not recommended and suggested using a boot kickstart for an automated installation. Thanks, Brian!&lt;/p&gt;
&lt;p&gt;Despite my attempts to utilize kickstart, I encountered difficulties in booting my NVMe disk. During this process, I discovered another workaround for installing Rocky 9 using the installimage script. This method is also experimental, just like the previous one.&lt;/p&gt;
&lt;h3 id=&#34;the-steps&#34;&gt;The Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Access the rescue mode (refer to &lt;a href=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/#enabling-rescue-mode&#34;&gt;my previous blog post&lt;/a&gt; if you need guidance).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the existing Rocky Linux 9 image to Rocky Linux 8 and place it in the root directory with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp /root/images/Rocky-91-amd64-base.tar.gz /root/Rocky-87-amd64-base.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The filename should adhere to the required naming convention for the installimage script to function correctly.&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Launch the &lt;code&gt;installimage&lt;/code&gt; and select the Custom Image option.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/installimage.webp&#34; alt=&#34;installimage&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the disk settings as required, and at the end of the script, select the image accordingly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IMAGE /root/Rocky-87-amd64-base.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To save the configuration file, simply press F10, allowing the installation process to resume uninterrupted. You may encounter a warning indicating the absence of an image signature, which is perfectly normal. Once the installation is finished, proceed to reboot the system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/complete.webp&#34; alt=&#34;installation completes with no error&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After the system restarts, you will have access to Rocky Linux 9. The installation will provide you with some fairly recent point-release of Rocky Linux, such as 9.1, but as always you need to update to the latest packages with &lt;code&gt;dnf update&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s all, folks! This second method is much easier compared to the first one, as it swiftly takes you to Rocky 9 without any complications.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Rocky Linux 9 via Hetzner Robot for the impatient</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/"/>
      <id>https://www.endpointdev.com/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/</id>
      <published>2023-06-12T00:00:00+00:00</published>
      <author>
        <name>Jeffry Johar</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/arrizqjeffry.webp&#34; alt=&#34;Arrizq Jeffry on a go-kart&#34;&gt;&lt;br&gt;
Image: &lt;a href=&#34;https://www.pexels.com/photo/go-kart-17122631/&#34;&gt;https://www.pexels.com/photo/go-kart-17122631/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;update-a-better-way-to-install-rocky-linux-9-at-hetzner-cloud&#34;&gt;Update: A Better Way to Install Rocky Linux 9 at Hetzner Cloud&lt;/h3&gt;
&lt;p&gt;Hey everyone, I wanted to share an update regarding the installation process of Rocky Linux 9 at Hetzner Cloud.&lt;/p&gt;
&lt;p&gt;After input from Brian Clemens of the Rocky Linux project and some further exploration and testing, I have a more efficient and straightforward method to get Rocky Linux up and running on the Hetzner platform. You can check out the new method in &lt;a href=&#34;/blog/2023/07/rocky-linux-9-at-hetzner-robot-made-quick-and-easy/&#34;&gt;my second blog post here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;about-rocky-linux&#34;&gt;About Rocky Linux&lt;/h3&gt;
&lt;p&gt;Rocky Linux is a free and open-source community-driven operating system designed to be a drop-in replacement for Red Hat Enterprise Linux (RHEL).&lt;/p&gt;
&lt;p&gt;Rocky fills the gap left by the end of CentOS, which was a popular Linux distribution based on the same source code as RHEL but offered as a free alternative with community support. CentOS Stream is their new offering, but it is just different enough to not be entirely compatible with RHEL.&lt;/p&gt;
&lt;p&gt;Another alternative is AlmaLinux, and everything mentioned here applies to Alma with some adaptation.&lt;/p&gt;
&lt;h3 id=&#34;rocky-9-on-hetzner&#34;&gt;Rocky 9 on Hetzner&lt;/h3&gt;
&lt;p&gt;Hetzner is a popular hosting company offering bare metal and virtual servers at very affordable prices. It is based in Germany and also has datacenters in Finland and the U.S.&lt;/p&gt;
&lt;p&gt;At the time of this writing (June 2023), Rocky Linux 9 is not supported by Hetzner Robot to install on its dedicated physical servers. Despite Hetzner&amp;rsquo;s the &lt;code&gt;installimage&lt;/code&gt; software indicating support, attempting to install it will result in the following error, at least on some of its servers:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/efi-error.webp&#34; alt=&#34;EFI error&#34;&gt;
“ERROR: We do not yet support rockylinux 91 on EFI systems”&lt;/p&gt;
&lt;p&gt;If you are looking for a workaround, consider installing Rocky Linux 8 and upgrading it to version 9.&lt;/p&gt;
&lt;p&gt;While it&amp;rsquo;s important to note that this installation approach hasn&amp;rsquo;t undergone comprehensive vendor testing, we have used it and I&amp;rsquo;ll provide you with the following step-by-step instructions to accomplish it.&lt;/p&gt;
&lt;h3 id=&#34;provisioning-the-server&#34;&gt;Provisioning the Server&lt;/h3&gt;
&lt;p&gt;To get started, follow &lt;a href=&#34;https://docs.hetzner.com/robot/dedicated-server/general-information/root-server-hardware&#34;&gt;Hetzner&amp;rsquo;s guide&lt;/a&gt; to order and provision a server from Hetzner Robot.&lt;/p&gt;
&lt;p&gt;Once the server has been provisioned, you may proceed to the next step.&lt;/p&gt;
&lt;h3 id=&#34;enabling-rescue-mode&#34;&gt;Enabling Rescue Mode&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Access the Hetzner Robot interface and navigate to the &amp;ldquo;Rescue&amp;rdquo; tab.&lt;/li&gt;
&lt;li&gt;Choose Linux as the rescue media and select the SSH key option to access the server. Alternatively, use the generated root password.&lt;/li&gt;
&lt;li&gt;Click the &amp;ldquo;Activate rescue system&amp;rdquo; button.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/robot-rescue.webp&#34; alt=&#34;Robot Menu&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;rebooting-the-server&#34;&gt;Rebooting the Server&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Switch to the &amp;ldquo;Reset&amp;rdquo; tab.&lt;/li&gt;
&lt;li&gt;Select the &amp;ldquo;CTRL+ALT+DEL&amp;rdquo; option.&lt;/li&gt;
&lt;li&gt;Click &amp;ldquo;Send&amp;rdquo; to reboot the server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/robot-reset.webp&#34; alt=&#34;Robot Menu&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;accessing-the-rescue-system&#34;&gt;Accessing the Rescue System&lt;/h3&gt;
&lt;p&gt;After a few minutes, SSH into the server using &lt;code&gt;root@[server IPv4 or server IPv6 address]&lt;/code&gt; to access the rescue system.&lt;/p&gt;
&lt;h3 id=&#34;installing-rocky-linux-8&#34;&gt;Installing Rocky Linux 8:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Once in the rescue system, proceed with the installation of Rocky Linux 8. For this installation, we&amp;rsquo;re going to configure the disk storage to use RAID 6 and LVM, with filesystems as follows:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;/boot/efi ESP: 256MB&lt;/li&gt;
&lt;li&gt;/boot ext4: 1GB&lt;/li&gt;
&lt;li&gt;LVM vg0 (rest of the disk)&lt;/li&gt;
&lt;li&gt;/dev/vg0/root ext4: 50GB&lt;/li&gt;
&lt;li&gt;/dev/vg0/home ext4: 100GB&lt;/li&gt;
&lt;li&gt;/dev/vg0/swap swap: 1GB&lt;/li&gt;
&lt;li&gt;Rest of vg0: unallocated, for future use&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Run the command: &lt;code&gt;imageinstall&lt;/code&gt; and you should get the following menu.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/06/rocky-linux-9-at-hetzner-robot-for-the-impatient/installimage.webp&#34; alt=&#34;Robot Menu&#34;&gt;&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Choose &amp;ldquo;Rocky Linux&amp;rdquo; → &amp;ldquo;Rocky Linux 8.2&amp;rdquo;. After confirming the selection, you will be brought to the configuration file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the configuration file, put these values that set up the planned filesystems and LVMs as specified.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PART /boot ext4 1G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PART /boot/efi esp 256M
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PART lvm vg0 all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV vg0 root / ext4 50G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV vg0 home /home ext4 100G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV vg0 swap swap swap 1G&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;Press F10 to exit the configuration file editor, and the OS installation will resume.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;completing-the-installation&#34;&gt;Completing the Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Once the installation is done, reboot the rescue system.
After a few minutes, SSH into the server again using &lt;code&gt;root@[server IPv4 or server IPv6 address]&lt;/code&gt;. The SSH key and root password will be the same as the rescue system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Execute the following to verify the OS is Rocky Linux 8:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /etc/os-release&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;upgrading-to-rocky-linux-9&#34;&gt;Upgrading to Rocky Linux 9:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Execute the following commands to upgrade the OS to Rocky Linux 9.2:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;REPO_URL&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/Packages/r&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;RELEASE_PKG&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;rocky-release-9.2-1.5.el9.noarch.rpm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;REPOS_PKG&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;rocky-repos-9.2-1.5.el9.noarch.rpm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;GPG_KEYS_PKG&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;rocky-gpg-keys-9.2-1.5.el9.noarch.rpm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dnf install &lt;span style=&#34;color:#369&#34;&gt;$REPO_URL&lt;/span&gt;/&lt;span style=&#34;color:#369&#34;&gt;$RELEASE_PKG&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;$REPO_URL&lt;/span&gt;/&lt;span style=&#34;color:#369&#34;&gt;$REPOS_PKG&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;$REPO_URL&lt;/span&gt;/&lt;span style=&#34;color:#369&#34;&gt;$GPG_KEYS_PKG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf /usr/share/redhat-logos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dnf --releasever=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9&lt;/span&gt; --allowerasing --setopt=&lt;span style=&#34;color:#369&#34;&gt;deltarpm&lt;/span&gt;=&lt;span style=&#34;color:#038&#34;&gt;false&lt;/span&gt; distro-sync -y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Execute the following to change the hostname to whatever you want it to be:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostnamectl set-hostname mynewhostname&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Reboot the system to complete the OS upgrade.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;accessing-the-rocky-linux-9-system&#34;&gt;Accessing the Rocky Linux 9 System:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;After a few minutes, SSH into the server again using &lt;code&gt;root@[server IPv4 or server IPv6 address]&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove dnf modules from Rocky Linux 8.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dnf module disable python36 virt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Execute the following to update the RPM database.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm --rebuilddb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;Execute the following to verify the OS is Rocky Linux 9.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /etc/os-release&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s all, folks.&lt;/p&gt;
&lt;p&gt;You can get past the EFI issue you encountered by installing Rocky Linux 8 on Hetzner Robot and upgrading it in-place to Rocky Linux 9.&lt;/p&gt;
&lt;p&gt;With these instructions, you can transition to the new and shiny Rocky Linux 9 without waiting for specific support by Hetzner Robot. Enjoy the enhanced features and capabilities of this updated version.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Bypassing a CDN to browse a website directly on your origin host</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/"/>
      <id>https://www.endpointdev.com/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/</id>
      <published>2023-01-20T00:00:00+00:00</published>
      <author>
        <name>Seth Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/winter-mountains.webp&#34; alt=&#34;A pale winter morning, looking out over a valley from a mountainside&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2023 --&gt;
&lt;p&gt;Using a content distribution network (CDN) has many advantages over serving a website directly, and for any reasonably large website, you should use one. Those advantages include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Caching at each of the CDN&amp;rsquo;s PoPs (points of presence).&lt;/li&gt;
&lt;li&gt;Often thousands of PoPs around the world, so traffic will be quick for everyone regardless of how far away they are from your origin server.&lt;/li&gt;
&lt;li&gt;Blocking of some Bad Guys automatically at the edge, including DDoS (distributed denial of service attacks) mitigation help.&lt;/li&gt;
&lt;li&gt;Origin IP address insulation. Hiding the origin IP address is useful to protect against DDoSes, since CDNs are generally well-defended against DDoS and your origin server probably is not as much.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should generally be cautious about revealing your websites&amp;rsquo; origin IP address. We serve other sites from our origin directly, so we don&amp;rsquo;t worry too much about sharing it here.&lt;/p&gt;
&lt;h3 id=&#34;straight-to-the-source&#34;&gt;Straight to the source&lt;/h3&gt;
&lt;p&gt;Sometimes, though, you need to bypass your CDN and test your website directly on its origin server. For example, if you need to test that your website would still work if the CDN goes down, or to sidestep CDN caching or content modification when troubleshooting a problem.&lt;/p&gt;
&lt;p&gt;It can be surprisingly confusing to bypass the CDN by yourself and not for the rest of your visitors, especially with newer features like Secure DNS in Chrome and Firefox muddying up traditional DNS resolution behaviors.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll use a browser extension called IPvFoo (available for Chrome and Firefox) to see which IP address our hostname resolves to. Install IPvFoo from the &lt;a href=&#34;https://chrome.google.com/webstore/detail/ipvfoo/ecanpcehffngcegjmadlcijfolapggal&#34;&gt;Chrome Web Store&lt;/a&gt; or Firefox&amp;rsquo;s &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/ipvfoo-pmarks/&#34;&gt;addons.mozilla.org&lt;/a&gt; and then click on its indicator next to the search bar.&lt;/p&gt;
&lt;p&gt;Before we change anything, www.endpointdev.com resolves to 104.21.30.147:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cloudflare.webp&#34; alt=&#34;IPvFoo showing Cloudflare&amp;rsquo;s IP address&#34;&gt;&lt;/p&gt;
&lt;p&gt;After a quick &lt;code&gt;whois&lt;/code&gt; search, we see that this IP address belongs to Cloudflare, our CDN:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ whois 104.21.30.147
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OrgName:        Cloudflare, Inc.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also check the certificate issuer by clicking on the padlock icon in our browser&amp;rsquo;s search bar, then clicking on &amp;ldquo;Connection is secure&amp;rdquo; or similar to see all the details about the certificate issuer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cert-issuer-chrome-before.webp&#34; alt=&#34;Chrome showing Cloudflare as the certificate-issuing authority, before sidestepping the CDN.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Before we change anything, we see the TLS/SSL certificate presented is issued by Cloudflare, as expected.&lt;/p&gt;
&lt;h3 id=&#34;make-the-hosts-file-point-directly-to-our-server&#34;&gt;Make the hosts file point directly to our server&lt;/h3&gt;
&lt;p&gt;Common desktop and server operating systems typically come with a &amp;ldquo;hosts file&amp;rdquo; that can be used to provide hostname to IP address translation that happens before your designated DNS servers are consulted.&lt;/p&gt;
&lt;p&gt;This is useful to test a hostname without ever adding it to DNS, or to override a DNS entry with your own IP address.&lt;/p&gt;
&lt;p&gt;We want to change our hosts file so that www.endpointdev.com points directly to our site&amp;rsquo;s origin server. How to do this depends on your operating system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux/macOS: Open /etc/hosts as root (using &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;su&lt;/code&gt;) in your favorite editor such as vim or nano.&lt;/li&gt;
&lt;li&gt;Windows: Open C:\Windows\System32\drivers\etc\hosts as administrator in a decent plain text editor, not a word processor — I used Notepad++.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you have your hosts file open, add a line to point your domain name directly to your origin server. For www.endpointdev.com:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;23.239.26.161 www.endpointdev.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;disable-dns-over-tls--dns-over-https&#34;&gt;Disable DNS-over-TLS &amp;amp; DNS-over-HTTPS&lt;/h3&gt;
&lt;p&gt;You may also need to disable any &amp;ldquo;secure DNS&amp;rdquo; in your browser, such as DNS-over-TLS or DNS-over-HTTPS.&lt;/p&gt;
&lt;h4 id=&#34;chrome&#34;&gt;Chrome&lt;/h4&gt;
&lt;p&gt;In Chrome, this is called Secure DNS, and you can disable it by going to Settings &amp;gt; Privacy and Security &amp;gt; Security &amp;gt; Use secure DNS, and disabling it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/secure-dns-chrome.webp&#34; alt=&#34;Chrome settings, navigated to Settings &amp;gt; Privacy and Security &amp;gt; Security &amp;gt; Use secure DNS with a radio button disabling Secure DNS&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;firefox&#34;&gt;Firefox&lt;/h4&gt;
&lt;p&gt;In Firefox, go to Network Settings, then disable DNS over HTTPS.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/dns-over-https-firefox.webp&#34; alt=&#34;Firefox preferences, navigated to Network Settings &amp;gt; Enable DNS over HTTPS, with a check box unchecked.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then close any open tabs in your browser and quit it completely. Then start it again.&lt;/p&gt;
&lt;h3 id=&#34;browse-the-website-directly&#34;&gt;Browse the website directly&lt;/h3&gt;
&lt;p&gt;Now go to www.endpointdev.com.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/origin.webp&#34; alt=&#34;IPvFoo showing the origin&amp;rsquo;s IP address&#34;&gt;&lt;/p&gt;
&lt;p&gt;IPvFoo is now showing the origin IP address we gave it, so we know that we&amp;rsquo;re being served data directly from that server.&lt;/p&gt;
&lt;p&gt;We can also run &lt;code&gt;whois&lt;/code&gt; on our origin server, for good measure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ whois 23.239.26.161
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OrgName:        Linode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we&amp;rsquo;re getting the Linode IP address, not Cloudflare&amp;rsquo;s. This is expected, since our origin site is hosted on a server at Linode.&lt;/p&gt;
&lt;h3 id=&#34;check-certificate-issuer&#34;&gt;Check certificate issuer&lt;/h3&gt;
&lt;p&gt;You can also check that the certificate issuer changed. Keep in mind that sometimes your certificate issuer might be the same when serving directly as when serving through a CDN, if you got a certificate signed by the CDN, or if you gave your CDN your TLS key &amp;amp; certificate to use.&lt;/p&gt;
&lt;p&gt;But if there &lt;em&gt;is&lt;/em&gt; a different certificate being served, we will likely see it was signed by a different certificate authority (CA):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cert-issuer-chrome-after.webp&#34; alt=&#34;Chrome showing Sectigo as the certificate-issuing authority, after sidestepping the CDN.&#34;&gt;&lt;/p&gt;
&lt;p&gt;After sidestepping Cloudflare our certificate is issued by Sectigo, so this is more proof our changes are working.&lt;/p&gt;
&lt;h3 id=&#34;clean-up&#34;&gt;Clean up&lt;/h3&gt;
&lt;p&gt;When you&amp;rsquo;re all done, open /etc/hosts again and either delete the line you added or comment it out by putting a # at the beginning of the line.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# 23.239.26.161 www.endpointdev.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save.&lt;/p&gt;
&lt;p&gt;Then close all browser windows, quit, and restart, and when you go to www.endpointdev.com, Cloudflare should be in the middle again.&lt;/p&gt;
&lt;h3 id=&#34;mobile&#34;&gt;Mobile&lt;/h3&gt;
&lt;p&gt;Note that there is no easy way to do something like this on iOS with an iPhone or iPad, as far as I can tell. And on Android, you either need a rooted phone, or a fancy VPN that lets you change your hostname mapping. I tried &lt;a href=&#34;https://play.google.com/store/apps/details?id=dns.hosts.server.change&amp;amp;hl=en_US&amp;amp;gl=US&#34;&gt;Hosts Go&lt;/a&gt; and it worked, despite some annoying ads which you don&amp;rsquo;t have to deal with in an /etc/hosts file 😁.&lt;/p&gt;
&lt;p&gt;If you need to test on mobile, or on multiple devices, you could also use a DNS server on your local network, and configure any device to point to your local DNS. &lt;a href=&#34;https://pi-hole.net/&#34;&gt;Pi-hole&lt;/a&gt; is a great option for this; see our &lt;a href=&#34;https://www.endpointdev.com/blog/2020/12/pihole-great-holiday-gift/&#34;&gt;blog post&lt;/a&gt; from a couple years ago for some of its other features.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Working around SPF problems delivering to Gmail</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/03/spf-problems-gmail-workaround/"/>
      <id>https://www.endpointdev.com/blog/2022/03/spf-problems-gmail-workaround/</id>
      <published>2022-03-30T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/03/spf-problems-gmail-workaround/20220321_194242-sm.webp&#34; alt=&#34;Hand-drawn signs reading &amp;ldquo;Someplace&amp;rdquo;, &amp;ldquo;Any pla…&amp;rdquo;, &amp;ldquo;No place&amp;rdquo;, with arrows pointing variously, attached to a leaning signpost in front of a high mountain desert scene with snow-topped peaks and sagebrush&#34;&gt;
Photo by Garrett Skinner&lt;/p&gt;
&lt;h3 id=&#34;email-deliverability&#34;&gt;Email deliverability&lt;/h3&gt;
&lt;p&gt;Legitimate email delivery keeps getting harder. Spammers and phishers never stop flooding everyone&amp;rsquo;s inboxes with unwanted and harmful email, so automated defenses against junk mail are necessary. But they are not perfect, and good email sometimes gets flagged as spam.&lt;/p&gt;
&lt;p&gt;When sending important &amp;ldquo;transactional&amp;rdquo; email such as for account confirmations, password resets, and ecommerce receipts, it is often worth using a paid email delivery service to increase deliverability. Those typically cost a flat amount per month for up to a certain quota of outgoing email, with overage charges for messages beyond that.&lt;/p&gt;
&lt;p&gt;Many of our clients use one of those services and generally they have all worked well and differ mostly in pricing and feature set. Popular choices include SendGrid, Mandrill, Postmark, Mailgun, and Amazon SES.&lt;/p&gt;
&lt;p&gt;We continue to have many cases where we want to be able to send potentially large amounts of automated email to ourselves, our clients, or our systems. This is usually for testing, notifications, or internal delivery to special mailboxes separate from our main mailboxes.&lt;/p&gt;
&lt;p&gt;These other uses for sending email keep us involved in the fight for good email deliverability from our own servers, which we have worked at over many years, long predating these paid email delivery services.&lt;/p&gt;
&lt;h3 id=&#34;sender-policy-framework&#34;&gt;Sender Policy Framework&lt;/h3&gt;
&lt;p&gt;One of the longest-running tools to fight spam is SPF, the Sender Policy Framework.&lt;/p&gt;
&lt;p&gt;SPF is an open standard that provides a way for a receiving mail server to verify that the sending server is authorized to send email for the message&amp;rsquo;s &amp;ldquo;envelope&amp;rdquo; sender domain. The envelope sender address or &amp;ldquo;return-path&amp;rdquo; is not normally seen by email recipients, but is used behind the scenes by servers. It may or may not be the same as the sender seen in the &amp;ldquo;From&amp;rdquo; header.&lt;/p&gt;
&lt;p&gt;The SPF policy for each domain is set in a special DNS TXT record for that domain.&lt;/p&gt;
&lt;p&gt;The important thing is that each sender&amp;rsquo;s email belongs to a domain with a valid SPF record showing that the sending servers are allowed to send for that domain, and that all other servers should &lt;em&gt;not&lt;/em&gt; be allowed to send email for that domain.&lt;/p&gt;
&lt;p&gt;For example, our endpointdev.com domain currently has this TXT record to define its SPF policy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v=spf1 a:maildrop.endpointdev.com include:_spf.google.com include:servers.mcsv.net -all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s look at each of those space-separated elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;v=spf1&lt;/code&gt; designates this TXT record as an SPF policy, version 1 (the only one so far).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a:maildrop.endpointdev.com&lt;/code&gt; means to allow the A (IPv4) and/or AAAA (IPv6) IP address(es) of hostname maildrop.endpointdev.com as a valid source.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;include:_spf.google.com&lt;/code&gt; means to look up another DNS TXT record at _spf.google.com (for Gmail, our main email provider here) and add its SPF policy to ours.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;include:servers.mcsv.net&lt;/code&gt; is the same thing, but for servers.mcsv.net (for Mailchimp, to allow it to deliver email newsletters for our domain).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-all&lt;/code&gt; means to disallow any other senders.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With such a policy, receiving mail servers can immediately reject any incoming email claiming to be sent by us for our domain if it didn&amp;rsquo;t come from one of our designated servers.&lt;/p&gt;
&lt;p&gt;This obviously doesn&amp;rsquo;t stop all spam, but it stops a whole class of forged senders, which is very helpful.&lt;/p&gt;
&lt;p&gt;The key point to note is that SPF applies to the sending email server at the moment it connects to the receiving email server. It doesn&amp;rsquo;t deal with anything else.&lt;/p&gt;
&lt;p&gt;One other point to note is that SPF policies are limited to a fairly small total number of DNS lookups via &lt;code&gt;include&lt;/code&gt; elements, so we can&amp;rsquo;t endlessly add new valid sending servers to our list.&lt;/p&gt;
&lt;h3 id=&#34;email-server-trails&#34;&gt;Email server trails&lt;/h3&gt;
&lt;p&gt;Based on the above SPF policy, if we want to send email from address &lt;code&gt;notifier@endpointdev.com&lt;/code&gt;, it will have to be sent through &lt;code&gt;maildrop.endpointdev.com&lt;/code&gt;, Gmail, or Mailchimp. Messages coming from any other sending server should be rejected by the receiving server. They don&amp;rsquo;t have to behave that way, but it is in their interest to do so if they don&amp;rsquo;t like spam.&lt;/p&gt;
&lt;p&gt;We have an internal server we&amp;rsquo;ll call &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt;, which sends email notifications from address &lt;code&gt;notifier@endpointdev.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since we don&amp;rsquo;t want to bloat our SPF policy, we&amp;rsquo;ll have our server &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; route its outgoing email through our mail forwarding service called maildrop, which lives on two or more servers behind the DNS name &lt;code&gt;maildrop.endpointdev.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is a good idea for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It keeps all our outgoing email flowing through a few places so we can easily monitor them for any problems.&lt;/li&gt;
&lt;li&gt;We don&amp;rsquo;t need to have SMTP daemons running on all our servers just to send outbound email.&lt;/li&gt;
&lt;li&gt;We don&amp;rsquo;t need to worry about the quotas or pricing of commercial emailing services when sending less-important or internal-only email.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since SPF is designed for a receiving email server to check that the server connecting to it to send email is authorized to do so for that email address&amp;rsquo;s domain, it shouldn&amp;rsquo;t matter what server the email originated on.&lt;/p&gt;
&lt;h3 id=&#34;gmail-misuses-header-information-in-spf-checks&#34;&gt;Gmail misuses header information in SPF checks&lt;/h3&gt;
&lt;p&gt;We recently discovered that Gmail has been misusing email header information in its SPF checks.&lt;/p&gt;
&lt;p&gt;When one of our outgoing emails originated from server &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; and was then forwarded to &lt;code&gt;maildrop.endpointdev.com&lt;/code&gt; which then delivered it to Gmail, Gmail looked at the earliest sender server it could find in the &lt;code&gt;Received&lt;/code&gt; headers of the email message, found &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt;, and flagged it as an SPF failure because our SPF policy didn&amp;rsquo;t include &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; [206.191.128.233].&lt;/p&gt;
&lt;p&gt;This can be seen in this excerpt of relevant email headers. (Some specific details here were changed to protect the innocent.) Note that email headers appear in reverse chronological order, so the most recent events are at the top:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Received: from maildrop14.epinfra.net (maildrop14.epinfra.net. [69.25.178.35])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        by mx.google.com with ESMTPS id l20si5561179oos.78.2022.01.25.10.52.05
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for &amp;lt;notifications@endpointdev.com&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Tue, 25 Jan 2022 10:52:05 -0800 (PST)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Received-SPF: fail (google.com: domain of notifier@endpointdev.com does not designate 206.191.128.233 as permitted
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sender) client-ip=206.191.128.233;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Authentication-Results: mx.google.com;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       dkim=pass header.i=@endpointdev.com header.s=maildrop header.b=hR445V77;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       spf=fail (google.com: domain of notifier@endpointdev.com does not designate 206.191.128.233 as permitted
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sender) smtp.mailfrom=notifier@endpointdev.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Received: from dashboard.endpointdev.com (dashboard.endpointdev.com [206.191.128.233])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    by maildrop14.epinfra.net (Postfix) with ESMTP id A2AA03E8A7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    for &amp;lt;notifications@endpointdev.com&amp;gt;; Tue, 25 Jan 2022 18:52:05 +0000 (UTC)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;To: &amp;lt;notifications@endpointdev.com&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is wrong! The SPF check should have been done against &lt;code&gt;maildrop14.epinfra.net&lt;/code&gt; [69.25.178.35] because that is the IP address that actually connected to Gmail to send the email. That server is one of our infrastructure hostnames allowed to send email as part of the &lt;code&gt;maildrop.endpointdev.com&lt;/code&gt; DNS record, so checking it would have led Gmail to give a passing SPF result.&lt;/p&gt;
&lt;p&gt;Why did Gmail do this? I don&amp;rsquo;t know, and at the time didn&amp;rsquo;t find any public discussion that would explain it. I suspect it has something to do with Gmail&amp;rsquo;s internal systems being comprised of many, many servers, and the SPF check being done long after the email was passed on from the initial receiving point through various other servers. Then Gmail parses the headers to find out who the sender was, and gets confused.&lt;/p&gt;
&lt;h3 id=&#34;dont-share-tmi&#34;&gt;Don&amp;rsquo;t share TMI&lt;/h3&gt;
&lt;p&gt;We can avoid this problem by not having maildrop mention our original sending server &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; at all.&lt;/p&gt;
&lt;p&gt;Why should it mention it in the first place? It&amp;rsquo;s helpful for tracing problems when debugging, but really is TMI (too much information) for normal email sending, and exposes internal infrastructure details that would be better omitted anyway.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; is running the very flexible and configurable Postfix email server, we can direct it to remove any &lt;code&gt;Received&lt;/code&gt; headers that mention our internal hostnames.&lt;/p&gt;
&lt;p&gt;By default Postfix in &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt; has the &lt;code&gt;header_checks&lt;/code&gt; directive set to look at a table to match regular expressions and take specified actions.&lt;/p&gt;
&lt;p&gt;So we added a regular expression to match and designated the action &lt;code&gt;IGNORE&lt;/code&gt;, to the file &lt;code&gt;/etc/postfix/header_checks&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/^Received:\ (from|by)\ .*(epinfra\.net|endpointdev\.com|localhost|localdomain)/  IGNORE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we update the map database file so that it takes immediate effect for new email flowing through Postfix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;postmap /etc/postfix/header_checks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When we sent another notification email from &lt;code&gt;dashboard.endpointdev.com&lt;/code&gt; and received it in Gmail we saw the email&amp;rsquo;s headers look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Received: from maildrop14.epinfra.net (maildrop14.epinfra.net. [69.25.178.35])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        by mx.google.com with ESMTPS id g72si1894187vke.271.2022.01.25.11.03.37
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for &amp;lt;notifications@endpointdev.com&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Tue, 25 Jan 2022 11:03:37 -0800 (PST)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Received-SPF: pass (google.com: domain endpointdev.com configured 69.25.178.35 as internal address)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Authentication-Results: mx.google.com;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       dkim=pass header.i=@endpointdev.com header.s=maildrop header.b=qkccUkkU;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       spf=pass (google.com: domain endpointdev.com configured 69.25.178.35 as internal address)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    smtp.mailfrom=notifier@endpointdev.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;To: &amp;lt;notifications@endpointdev.com&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is no more mention of &lt;code&gt;dashboard&lt;/code&gt; or its IP address, so Gmail runs its SPF check against the proper IP address 69.25.178.35 which belongs to server &lt;code&gt;maildrop14.epinfra.net&lt;/code&gt; which is part of the &lt;code&gt;maildrop.endpointdev.com&lt;/code&gt; DNS name. Gmail now validates that IP address is allowed to send for the endpointdev.com domain and gives a &amp;ldquo;pass&amp;rdquo; result for its SPF check.&lt;/p&gt;
&lt;p&gt;Perhaps this will help your legitimate email delivery too!&lt;/p&gt;
&lt;h3 id=&#34;reference&#34;&gt;Reference&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.open-spf.org/Introduction/&#34;&gt;SPF Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.postfix.org/&#34;&gt;Postfix mail server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>SRV DNS records in Terraform and Cloudflare</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/06/srv-dns-terraform-cloudflare/"/>
      <id>https://www.endpointdev.com/blog/2018/06/srv-dns-terraform-cloudflare/</id>
      <published>2018-06-26T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/06/srv-dns-terraform-cloudflare/2109300822_07103c8f1a_o-crop.jpg&#34; alt=&#34;woman walking across train tracks&#34; /&gt;&lt;br&gt;&lt;a href=&#34;https://www.flickr.com/photos/carbonnyc/2109300822/&#34;&gt;(Photo by David Goehring, CC BY 2.0, cropped)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At End Point we are using &lt;a href=&#34;https://www.terraform.io/&#34;&gt;Terraform&lt;/a&gt; for a few clients to manage their web hosting &lt;a href=&#34;https://en.wikipedia.org/wiki/Infrastructure_as_Code&#34;&gt;infrastructure as code (IaC)&lt;/a&gt;. Terraform is particularly helpful when working with multiple cloud or infrastructure providers and stitching together their services.&lt;/p&gt;
&lt;p&gt;For example, for one web application that involves failover from the primary production infrastructure to a secondary location at a different provider, we are using &lt;a href=&#34;https://www.cloudflare.com/&#34;&gt;Cloudflare&lt;/a&gt; as a CDN to provide caching, DDoS mitigation, and traffic routing in front of virtual servers at DigitalOcean and Amazon Web Services (AWS).&lt;/p&gt;
&lt;p&gt;We decided we wanted to store all of their infrastructure configuration in Terraform, not just what is required for the web application, so we can recreate their entire infrastructure from their Git repository.&lt;/p&gt;
&lt;p&gt;This all went fine until we got to their email DNS records. Our client is using Microsoft Office 365 for their email, which requires some SRV records. Terraform’s Cloudflare provider works fine with the universal MX records, but when we first wanted to do this, the Terraform provider for Cloudflare did not support SRV records at all.&lt;/p&gt;
&lt;p&gt;Luckily for us, Terraform recently (6 April 2018) gained support for DNS SRV records as mentioned in the &lt;a href=&#34;https://github.com/terraform-providers/terraform-provider-cloudflare/blob/master/CHANGELOG.md#100-april-06-2018&#34;&gt;release notes&lt;/a&gt; and described in more detail in the &lt;a href=&#34;https://github.com/terraform-providers/terraform-provider-cloudflare/pull/29&#34;&gt;pull request&lt;/a&gt; that added the feature.&lt;/p&gt;
&lt;p&gt;Great! So now we can get on with this.&lt;/p&gt;
&lt;p&gt;I began by naively assuming that the SRV record data should be given in space-separated form like many DNS interfaces use, including BIND and Cloudflare’s web interface itself. I tried setting it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resource &amp;#34;cloudflare_record&amp;#34; &amp;#34;_sipfederationtls_tcp&amp;#34; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  domain = &amp;#34;${var.domain}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name   = &amp;#34;_sip._tcp.${var.subdomain}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type   = &amp;#34;SRV&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  value  = &amp;#34;100 1 443 sipdir.online.lync.com.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But that resulted in an error. So when in doubt, consult the documentation, right? I did that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/docs/providers/cloudflare/r/record.html#data&#34;&gt;Terraform Cloudflare provider docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record&#34;&gt;Cloudflare API docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those make it clear that a &lt;code&gt;data&lt;/code&gt; element is required, but give no indication what format is needed.&lt;/p&gt;
&lt;p&gt;This is not currently documented for Cloudflare’s API, nor for Terraform’s Cloudflare provider. User &lt;a href=&#34;https://github.com/terraform-providers/terraform-provider-cloudflare/pull/29#issuecomment-374600386&#34;&gt;EpiqSty helpfully recorded&lt;/a&gt; asking Cloudflare’s support, who recommended reverse-engineering the format:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the meantime, what I would suggest is you can create a SRV record via our UI and then you can use the API to do a GET request on the DNS records, that should show you all the fields that are required.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Ok, then!&lt;/p&gt;
&lt;p&gt;It turns out that we must provide the component parts of the SRV record disassembled in key/​value pairs as the Cloudflare API expects, which looks like this in Terraform config:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resource &amp;#34;cloudflare_record&amp;#34; &amp;#34;_sip_tls&amp;#34; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  domain = &amp;#34;${var.domain}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name   = &amp;#34;_sip._tls.${var.subdomain}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type   = &amp;#34;SRV&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data   = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    service  = &amp;#34;_sip&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proto    = &amp;#34;_tls&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name     = &amp;#34;${var.subdomain}.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    priority = 100
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    weight   = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    port     = 443
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    target   = &amp;#34;sipdir.online.lync.com.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One unexpected aspect of this is that it requires duplicating the parts that make up the &lt;code&gt;name&lt;/code&gt; although the name doesn’t seem to be used by Cloudflare, which assembles the name from the &lt;code&gt;data&lt;/code&gt; components &lt;code&gt;service&lt;/code&gt;, &lt;code&gt;proto&lt;/code&gt;, and &lt;code&gt;name&lt;/code&gt;. The &lt;code&gt;name&lt;/code&gt; is apparently just there for Terraform, unlike other DNS records where the name is used as the DNS record value.&lt;/p&gt;
&lt;p&gt;The Terraform Cloudflare provider also gained support for the much more obscure &lt;a href=&#34;https://en.wikipedia.org/wiki/LOC_record&#34;&gt;DNS LOC record type&lt;/a&gt; at the same time, and it works similarly.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://github.com/benjvi&#34;&gt;Ben Vickers&lt;/a&gt; who contributed the new feature to Terraform!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>systemd: a primer from the trenches</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/06/systemd-primer-from-the-trenches/"/>
      <id>https://www.endpointdev.com/blog/2018/06/systemd-primer-from-the-trenches/</id>
      <published>2018-06-18T00:00:00+00:00</published>
      <author>
        <name>Ian Neilsen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/06/systemd-primer-from-the-trenches/6095265888_a27b664798_o-crop.jpg&#34; width=&#34;1540&#34; alt=&#34;gears&#34; /&gt;&lt;br&gt;&lt;a href=&#34;https://www.flickr.com/photos/guysie/6095265888/&#34;&gt;Gears image by Guy Sie, CC BY-SA 2.0, cropped &amp;amp; scaled&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;systemctl-lets-get-back-to-basics&#34;&gt;systemctl: Let’s get back to basics&lt;/h3&gt;
&lt;p&gt;&amp;lsquo;&amp;lsquo;Help me systemd, you are my only hope.&amp;rsquo;&amp;rsquo;&lt;/p&gt;
&lt;p&gt;Sometimes going back to day zero brings clarity to what seems like hopeless or frustrating situation for users from the Unix SysV init world. Caveat: I previously worked at Red Hat for many years before joining the excellent team at End Point and I have been using systemd for as long. I quite honestly have forgotten most of the SysV init days. Although at End Point we work daily on Debian, Ubuntu, CentOS, and BSD variants.&lt;/p&gt;
&lt;p&gt;Here is a short and sweet primer to get your fingers wet, before we dive into some of the heavier subjects with systemd.&lt;/p&gt;
&lt;p&gt;Did you know that systemd has many utilities you can run?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;systemctl&lt;/li&gt;
&lt;li&gt;timedatectl&lt;/li&gt;
&lt;li&gt;journalctl&lt;/li&gt;
&lt;li&gt;loginctl&lt;/li&gt;
&lt;li&gt;systemd-notify&lt;/li&gt;
&lt;li&gt;systemd-analyze - analyze system&lt;/li&gt;
&lt;li&gt;systemd-cgls - show cgroup tree&lt;/li&gt;
&lt;li&gt;systemd-cgtop&lt;/li&gt;
&lt;li&gt;systemd-nspawn&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And systemd consists of several daemons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;systemd&lt;/li&gt;
&lt;li&gt;journald&lt;/li&gt;
&lt;li&gt;networkd&lt;/li&gt;
&lt;li&gt;logind&lt;/li&gt;
&lt;li&gt;timedated&lt;/li&gt;
&lt;li&gt;udevd&lt;/li&gt;
&lt;li&gt;system-boot&lt;/li&gt;
&lt;li&gt;tmpfiles&lt;/li&gt;
&lt;li&gt;session&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s a long way from the old SysV init days. But in all essence it’s not that different. The one thing that stands out to me is we have more information with less typing then previously. That can only be a good thing, right?&lt;/p&gt;
&lt;p&gt;Well, let’s see! There are many many web pages out there that list systemd or systemctl switches/​flags. However in everyday use I want to speed up the work I do, I want information at my fingertips, and I find flags and switches which mean something sure do make it easier.&lt;/p&gt;
&lt;h3 id=&#34;pro-tip-1-tab-completion&#34;&gt;Pro Tip 1: Tab completion&lt;/h3&gt;
&lt;p&gt;Before you begin playing with the commands, you should install &lt;code&gt;bash-completion&lt;/code&gt;. Some distros don’t auto-complete with systemd until you install that, and without tab auto-completion you miss out on &lt;strong&gt;a lot&lt;/strong&gt; of systemctl.&lt;/p&gt;
&lt;p&gt;As an example when you tab for completion you will see many of the systemctl options:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemctl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;add-requires           enable                 is-system-running      preset                 show
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;add-wants              exit                   kexec                  preset-all             show-environment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cancel                 force-reload           kill                   reboot                 start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat                    get-default            link                   reenable               status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;condreload             halt                   list-dependencies      reload                 stop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;condrestart            help                   list-jobs              reload-or-restart      suspend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;condstop               hibernate              list-machines          rescue                 switch-root
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;daemon-reexec          hybrid-sleep           list-sockets           reset-failed           try-reload-or-restart
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;daemon-reload          import-environment     list-timers            restart                try-restart
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default                is-active              list-unit-files        revert                 unmask
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;disable                is-enabled             list-units             set-default            unset-environment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;edit                   is-failed              mask                   set-environment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;emergency              isolate                poweroff               set-property&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;systemctl-vs-old-school-commands&#34;&gt;systemctl vs. old school commands&lt;/h3&gt;
&lt;p&gt;Here we will list out new systemctl commands and the corresponding old SysV command, followed by systemctl flags and explanation.&lt;/p&gt;
&lt;p&gt;Go ahead and run each command to get a feel for what it displays. Remember each command usually has switches/​flags you can use.&lt;/p&gt;
&lt;p&gt;Let’s start at the top and work down:&lt;/p&gt;
&lt;h4 id=&#34;systemctl&#34;&gt;systemctl&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;service&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Used in conjunction with ABRT it can show you some great debug info and runtime metadata, categorized by their respective groupings of loaded, active, running and a description of the unit.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-status&#34;&gt;systemctl status&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;service --status-all&lt;/code&gt; or &lt;code&gt;initctl list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check all system services’ status. Normally during a server update I will run this and output it to a file. When the server reboots I can run it again and diff this file to ensure all things started.&lt;/p&gt;
&lt;p&gt;The output is great. It shows me the PID path and potentially the arguments which were run for the process or service. Saves me &lt;code&gt;ps&lt;/code&gt;ing the process.&lt;/p&gt;
&lt;p&gt;Note that each distro deals differently with &lt;code&gt;service --status-all&lt;/code&gt; output.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-status-servicename--l&#34;&gt;systemctl status serviceName -l&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;service serviceName status&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Good flags: &lt;code&gt;is-active&lt;/code&gt;, &lt;code&gt;-a&lt;/code&gt;, &lt;code&gt;-l&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As it suggests, show me the status and information related to the service unit file. Other good info included is whether the service is enabled or chkconfig is on, uptime, PID and cgroup info, and any other information associated with the service.&lt;/p&gt;
&lt;p&gt;Tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-l&lt;/code&gt; flag will usually output enough information to diagnose a service start or reload problem without having to go into the logs.&lt;/li&gt;
&lt;li&gt;You can view more than one service by separating them with spaces, e.g.: &lt;code&gt;systemctl status httpd mysql postfix&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl-enabledisable-nameofservice&#34;&gt;systemctl enable|disable NameofService&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;chkconfig ServiceName on|off&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You might find on some distros that &lt;code&gt;chkconfig&lt;/code&gt; is still present. It doesn’t do what you think it does with systemd systems.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-startstoprestart-httpd&#34;&gt;systemctl start|stop|restart httpd&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;service httpd start|stop|restart&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Good unit commands: reload-or-restart&lt;/p&gt;
&lt;p&gt;As it suggests, start, stop, or restart services/​processes/​units.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;reload-or-restart&lt;/code&gt; command tells the services to reload if it is able and if not then restart, similar to the old &lt;code&gt;service serviceName force-reload&lt;/code&gt;. Some services don’t allow a reload. Nagios is one example where a &lt;code&gt;reload-or-restart&lt;/code&gt; works because it doesn’t allow reloads.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-reload-httpd&#34;&gt;systemctl reload httpd&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;service httpd reload&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Perform a graceful reload of a configuration you may have just changed. Example: I’ve just made some changes to httpd conf and need to gracefully reload them without restarting the web service.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-daemon-reload&#34;&gt;systemctl daemon reload&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;chkconfig serviceName --add&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Graceful reloads configuration files on a running service/​process. See below for an explanation of “daemon reload”. Basically, if you have added in a new service and made many config changes, use &lt;code&gt;daemon-reload&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-list-unit-files&#34;&gt;systemctl list-unit-files&lt;/h4&gt;
&lt;p&gt;Good flags: &lt;code&gt;--type=service&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Formerly: &lt;code&gt;ls /etc/rc.d/init.d/ /etc/rc.d/rc.local&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Prints unit files from &lt;code&gt;/usr/lib/systemd/system/&lt;/code&gt; and &lt;code&gt;/etc/systemd/system/&lt;/code&gt;. Slightly different to &lt;code&gt;list-units&lt;/code&gt;; rarely used but has any interesting output. You may want to use this in monitoring scripts you write.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-list-units&#34;&gt;systemctl list-units&lt;/h4&gt;
&lt;p&gt;Good flags: &lt;code&gt;-a (--all)&lt;/code&gt;, &lt;code&gt;-t serviceName&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Formerly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chkconfig --list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ntsysv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /etc/rc.d/init.d/ /etc/rc.d/rc.local
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysv-rc-conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initctl list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I prefer to use &lt;code&gt;list-units&lt;/code&gt; over &lt;code&gt;list-unit-files&lt;/code&gt;. It shows more information and is shorter to type. Or you could install the &lt;code&gt;sysvinit-utils&lt;/code&gt; package, which by default is not installed on systemd distros.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-list-sockets&#34;&gt;systemctl list-sockets&lt;/h4&gt;
&lt;p&gt;Formerly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsof
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ss -s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /proc/net/*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sockets of all types can be viewed from one command. Although time to time I will still use &lt;code&gt;lsof&lt;/code&gt; or &lt;code&gt;ss&lt;/code&gt; depending on the socket type I want to look at.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-list-timers&#34;&gt;systemctl list-timers&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;crontab -e&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;systemd offers a way to schedule tasks like crontab. I’m going to go out on a limb here and say they both do the same thing, except systemd timers may be more readable by human eyes, are logged to the journal, easier to debug and enable or disable.&lt;/p&gt;
&lt;p&gt;My caveat is that I still use cron jobs in my daily work, because I’m familiar with them and emailing is still an issue from a timer.&lt;/p&gt;
&lt;p&gt;Tip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;set a systemd timer to a calendar day, month, year to trigger.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl-list-jobs&#34;&gt;systemctl list-jobs&lt;/h4&gt;
&lt;p&gt;Requires further explanation in another blog post.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-failed&#34;&gt;systemctl &amp;ndash;failed&lt;/h4&gt;
&lt;p&gt;Show me failed services. &lt;code&gt;systemctl status&lt;/code&gt; will highlight at the top if units have failed, especially useful after a reboot.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-get-default&#34;&gt;systemctl get-default&lt;/h4&gt;
&lt;p&gt;Formerly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;runlevel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chkconfig --list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To list targets run &lt;code&gt;systemctl list-units -t target&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Gets the run level default for the system. Not often used, but good to know when you start having boot issues or need to change to a different run level to fix things.&lt;/p&gt;
&lt;p&gt;Tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are many tables comparing the SysV runlevels to systemd. Get your Google on and search.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;systemctl set-default graphical.target&lt;/code&gt; will set a graphical user shell. For all those that like a good desktop.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl-set-default-multi-usertarget&#34;&gt;systemctl set-default multi-user.target&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;telinit runlevel&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The systemd &lt;code&gt;multi-user.target&lt;/code&gt; is equivalent to runlevels 2, 3, and 4.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-shutdown-or-reboot&#34;&gt;systemctl shutdown or reboot&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;shutdown -r|-h now&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Reboot/shutdown and poweroff the system. Personally I still use &lt;code&gt;shutdown&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-cat-servicename&#34;&gt;systemctl cat serviceName&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;cat /etc/init.d/$init_file&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Shows me the system service (unit) file contents and options. We will go more into these commands later as we work through building and maintaining our own unit files.&lt;/p&gt;
&lt;p&gt;Tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;systemctl cat&lt;/code&gt; shows all unit file information and snippets involved with the unit file.&lt;/li&gt;
&lt;li&gt;If you use Vim and Arch Linux, you can enable &lt;code&gt;vim-systemd&lt;/code&gt; to help with syntax highlighting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl-list-dependencies-servicename&#34;&gt;systemctl list-dependencies serviceName&lt;/h4&gt;
&lt;p&gt;What’s really depending on a given service. The &lt;code&gt;--all&lt;/code&gt; flag will show everything from &lt;code&gt;--before&lt;/code&gt;, &lt;code&gt;--after&lt;/code&gt;, &lt;code&gt;--reverse&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-show-servicename&#34;&gt;systemctl show serviceName&lt;/h4&gt;
&lt;p&gt;Flags: &lt;code&gt;-p&lt;/code&gt; shows a single property of a service.&lt;/p&gt;
&lt;p&gt;Shows more than using &lt;code&gt;systemctl cat servicename&lt;/code&gt;. Don’t forget tab completion is your friend. Running the &lt;code&gt;-p&lt;/code&gt; flag and using tab will help you.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-mask-servicename&#34;&gt;systemctl mask serviceName&lt;/h4&gt;
&lt;p&gt;Formerly: &lt;code&gt;update-rc.d serviceName disable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Never want someone starting a service &lt;strong&gt;ever&lt;/strong&gt;? &lt;code&gt;mask&lt;/code&gt; is your friend and a little sneaky. See if your system admins pick this one up. Good April Fool’s day trick on them. Use &lt;code&gt;unmask&lt;/code&gt; to return it to its normal state.&lt;/p&gt;
&lt;h4 id=&#34;systemctl-edit-servicename&#34;&gt;systemctl edit serviceName&lt;/h4&gt;
&lt;p&gt;Formerly: edit &lt;code&gt;/etc/init.d/scriptName&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Good options: &lt;code&gt;--full&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Yes, that’s right! Edit the service file without having to go find it on disk. That has saved me a bit of time.&lt;/p&gt;
&lt;p&gt;Tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Careful with this. The plain edit creates an override file in /etc/systemd/system to complement the original unit file.&lt;/li&gt;
&lt;li&gt;If you need to edit the original unit file use the &lt;code&gt;--full&lt;/code&gt; flag, which allows you to edit the unit file without creating a snippet.&lt;/li&gt;
&lt;li&gt;If you make a mistake in your unit file: &lt;code&gt;systemctl revert serviceName&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl--o&#34;&gt;systemctl -o&lt;/h4&gt;
&lt;p&gt;Formerly: Edit Apache config to set log level to warn or debug, &lt;code&gt;/etc/init.d/httpd reload&lt;/code&gt;, view logs&lt;/p&gt;
&lt;p&gt;Good options: &lt;code&gt;--output=verbose&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Particularly good if you have a service acting up. Outputs a short standard message or a very verbose message using different flags.&lt;/p&gt;
&lt;p&gt;Tip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;journalctl -u serviceName&lt;/code&gt; can help you here, but I often find it easier to include &lt;code&gt;--output=verbose&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;systemctl-isolate&#34;&gt;systemctl isolate&lt;/h4&gt;
&lt;p&gt;This deserves its own small blog post. Isolate can be used to rescue systems automagically following kernel reboot failures, but requires some special work.&lt;/p&gt;
&lt;h4 id=&#34;systemd-delta&#34;&gt;systemd-delta&lt;/h4&gt;
&lt;p&gt;Check your unit files to see if someone has been changing things on you. Especially useful if you are writing your own unit files.&lt;/p&gt;
&lt;p&gt;Tip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Used in conjunction with &lt;code&gt;systemctl cat&lt;/code&gt; or &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;delta&lt;/code&gt; can help you see what was what.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;gotchas&#34;&gt;Gotchas&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Sometimes you need to use the suffix such as ‘config_&lt;a href=&#34;mailto:file@openvpn.service&#34;&gt;file@openvpn.service&lt;/a&gt;’. systemd will always think services are services unless you use the suffix like .target or .socket, so make sure you tell the system so.&lt;/li&gt;
&lt;li&gt;If you want multiple services running use a prefix, such as; &lt;a href=&#34;mailto:ssh1@sshd.service&#34;&gt;ssh1@sshd.service&lt;/a&gt; &lt;a href=&#34;mailto:ssh2@sshd.service&#34;&gt;ssh2@sshd.service&lt;/a&gt; with different configs. Handy for multiple openvpn servers.&lt;/li&gt;
&lt;li&gt;Mount points will always be determined as mount points.&lt;/li&gt;
&lt;li&gt;If you have made a lot of configuration changes and want to gracefully load these without restarting everything try &lt;code&gt;systemctl daemon reload&lt;/code&gt;. This is not the same as the above &lt;code&gt;reload&lt;/code&gt; action. Daemon reload is for systemd and not the unit files it controls. This is a safe command to run since it keeps sockets open while it does its thing.&lt;/li&gt;
&lt;li&gt;Reboots on newer systems only really need to be done when new kernels are presented. Systemd is gracious and good at processing new packages and enabling these changes during a yum update.&lt;/li&gt;
&lt;li&gt;Autocomplete on CentOS is not present until you install &lt;code&gt;bash-completion&lt;/code&gt;. systemctl takes on a life of its own when you install this utility. Tabbing out will list all systemctl options. Very handy!&lt;/li&gt;
&lt;li&gt;Systemd does not use the /etc/inittab file even if you have it present.&lt;/li&gt;
&lt;li&gt;Converting your init scripts to systemd is easier than you think. Create a systemd unit file and add in 10 basic lines to call the bin or init script. You have basically created a systemd managed init script. Don’t forget to go back and one day convert it completely.&lt;/li&gt;
&lt;li&gt;Targets vs. runlevels: A target in systemd is a runlevel in sysV, names replace numbers; runlevel 3 = multi-user.target, runlevel 1 = rescue.target&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;whos-got-the-goods-on-speed&#34;&gt;Who’s got the goods on speed?&lt;/h3&gt;
&lt;p&gt;Is systemd faster than SysV init? Parallel processing says it is? You be the judge!&lt;/p&gt;
&lt;p&gt;One great test is to build a new machine which doesn’t have systemd installed. Reboot the machine and check your boot time. On an older SysV system you may have use “tuned”, “systemtap”, “numastat” etc. to gather performance information.&lt;/p&gt;
&lt;p&gt;Then install systemd. Better still, upgrade from a old version of Linux to a new version of linux from ‘init’ to ‘systemd’ and then run ‘systemd-analyze’.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemd-analyze&lt;/code&gt; will show you boot times. Notice that systemd starts fewer services at boot because it only starts what is necessary to get the server booting.&lt;/p&gt;
&lt;p&gt;Not a bad way to collect a baseline on a newly-built server. Add it to your Ansible facts for the server so you have a historical view and collection of boot times. In fact add it to your monitoring system and be proactive in your monitoring of server boot times while performing your maintenance cycles.&lt;/p&gt;
&lt;p&gt;How do you see what is taking its sweet time during boot or what is borking your beautiful server following an update/​upgrade? Wonder no more!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemd-analyze blame
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemd-analyze time&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example on my system, I can see that my top 10 culprits for a potentially slow boot are:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemd-analyze blame
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          7.346s dracut-initqueue.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          6.787s systemd-cryptsetup@luks.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          5.378s NetworkManager-wait-online.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          2.308s abrtd.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          1.444s docker.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          1.395s plymouth-quit-wait.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          1.358s lvm2-pvscan@8:1.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          1.145s lvm2-pvscan@253:0.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          1.072s fwupd.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           609ms docker-storage-setup.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I might disable the Docker service by &lt;code&gt;systemctl disable docker&lt;/code&gt; and start it when I need it.&lt;/p&gt;
&lt;p&gt;What else can &lt;code&gt;systemd-analyze&lt;/code&gt; show me?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemd-analyze critical-chain
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The time after the unit is active or started is printed after the &amp;#34;@&amp;#34; character.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The time the unit takes to start is printed after the &amp;#34;+&amp;#34; character.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;graphical.target @5.209s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└─multi-user.target @5.209s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  └─abrt-journal-core.service @5.209s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └─abrtd.service @2.897s +2.308s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      └─livesys.service @2.881s +13ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └─basic.target @2.804s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          └─sockets.target @2.804s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            └─dbus.socket @2.804s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              └─sysinit.target @2.797s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                └─systemd-update-utmp.service @2.782s +14ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  └─auditd.service @2.634s +145ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    └─systemd-tmpfiles-setup.service @2.590s +41ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      └─fedora-import-state.service @2.566s +22ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        └─local-fs.target @2.562s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          └─run-user-42.mount @4.614s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            └─local-fs-pre.target @964ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              └─lvm2-monitor.service @321ms +442ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                └─dm-event.socket @320ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  └─-.slice&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s look at how long our network targets take to start:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemd-analyze critical-chain network.target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The time after the unit is active or started is printed after the &amp;#34;@&amp;#34; character.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The time the unit takes to start is printed after the &amp;#34;+&amp;#34; character.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network.target @2.618s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└─network.service @2.403s +214ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  └─NetworkManager-wait-online.service @1.458s +941ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └─NetworkManager.service @1.417s +40ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      └─network-pre.target @1.415s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └─firewalld.service @976ms +438ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          └─polkit.service @891ms +83ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            └─basic.target @885ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              └─paths.target @885ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                └─brandbot.path @885ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  └─sysinit.target @881ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    └─systemd-update-utmp.service @872ms +7ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      └─auditd.service @702ms +168ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        └─systemd-tmpfiles-setup.service @676ms +24ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          └─rhel-import-state.service @653ms +22ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            └─local-fs.target @652ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              └─boot.mount @523ms +128ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                └─local-fs-pre.target @522ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                  └─lvm2-monitor.service @369ms +152ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                    └─lvm2-lvmetad.service @397ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                      └─lvm2-lvmetad.socket @368ms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                        └─-.slice&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s go one step further and output the entire system hierarchy. With this one you get a nice image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemd-analyze dot | dot -Tpng -o system-stuff.png&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;pro-tip-2-remote-commands&#34;&gt;Pro Tip 2: Remote commands&lt;/h3&gt;
&lt;p&gt;I have a server which needs a service restarted or checked constantly. Running systemctl remotely will show me or allow me to do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemctl status sshd -H root@server.domain.tld&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemctl -H root@server.domain.tld status httpd&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I might make an alias for it. Obviously this is a pretty useless example, if you’re having to manually do this for a service/​process you should fix the problem on the server. However for edge cases it can be quite handy. Use your imagination: We could use this for monitoring which takes a local ssh user found on all machines and pass this for some returned output to a monitoring server.&lt;/p&gt;
&lt;h3 id=&#34;pro-tip-3-what-relies-on-my-service&#34;&gt;Pro Tip 3: What relies on my service&lt;/h3&gt;
&lt;p&gt;Figure out what targets/​runlevel a target runs at:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemctl show httpd -p wants multi-user.target&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;pro-tip-4-monitoring&#34;&gt;Pro Tip 4: Monitoring&lt;/h4&gt;
&lt;p&gt;Check processes, service association, and busiest processes. You can still grep/​awk the output if you wish.&lt;/p&gt;
&lt;p&gt;Instead of using &lt;code&gt;top&lt;/code&gt; or something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps xawf -eo pid,user,cgroup,args&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;use the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemd-cgls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# systemd-cgtop&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;summing-up&#34;&gt;Summing up&lt;/h3&gt;
&lt;p&gt;I know this is only touching the surface of systemctl or systemd as whole but from a day-to-day context this should help you play in the systemd world. I think the biggest part that people struggle with is workable, usable examples.&lt;/p&gt;
&lt;p&gt;Stay tuned for future posts on unit files, unit targets, systemctl isolate and slices, journalctl, timedatectl, and loginctl.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Instant TLS Upgrades Through Proxy Magic!</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/06/tls-proxy-magic/"/>
      <id>https://www.endpointdev.com/blog/2018/06/tls-proxy-magic/</id>
      <published>2018-06-14T00:00:00+00:00</published>
      <author>
        <name>David Christensen</name>
      </author>
      <content type="html">
        &lt;img alt=&#34;cards&#34; src=&#34;/blog/2018/06/tls-proxy-magic/cards.jpg&#34; /&gt;
&lt;h3 id=&#34;tls-shutdowns-are-real&#34;&gt;TLS shutdowns are real&lt;/h3&gt;
&lt;p&gt;The payment gateways have been warning for years about the impending and required TLS
updates. Authorize.net and PayPal—to name a few—have stopped accepting transaction requests from
servers using TLS 1.0. Despite the many warnings about this (and many delays in the final
enforcement date), some projects are affected by this and payments are coming to a stop, customers
cannot checkout, and e-commerce is at a standstill.&lt;/p&gt;
&lt;p&gt;Ideally, getting to security compliance would include a larger migration to update your underlying
operating system and your application. But a migration and software update can be an expensive
project and in some cases, the business can’t wait weeks while this is done.&lt;/p&gt;
&lt;p&gt;End Point has worked with several clients recently to try to remedy the situation by using a reverse
proxy to fix this and we’ve had good success on getting payments flowing again.&lt;/p&gt;
&lt;h3 id=&#34;what-is-a-proxy&#34;&gt;What is a proxy?&lt;/h3&gt;
&lt;p&gt;A proxy is a mid-point, essentially a digital middleman, moving your data from one place to another.
In two recent client instances, we ended up using nginx (the stack’s webserver) as
the reverse proxy, basically running a separate server for just shuttling requests to/​from the
payment gateway. Since we want to be able to run the gateway in both live and test modes, we use
two separate server definitions in our nginx include, one for each.&lt;/p&gt;
&lt;p&gt;Since the proxy is talking to the gateway in TLS 1.2 the payment gateway is happy. Since the
application can talk http to the proxy running on the same machine, your application is happy.
Since payments are now flowing, the business is happy.&lt;/p&gt;
&lt;h3 id=&#34;why-use-a-proxy&#34;&gt;Why use a proxy?&lt;/h3&gt;
&lt;p&gt;While we always impress on clients the importance of staying up-to-date with their entire stack (operating system,
language, application frameworks), this is not always practical for some sites, whether for cost
reasons or some technical limitations which keep them on a specific library or framework version.
In our case, these clients had been migrated to CentOS 7 already (which supports TLS 1.2), but the
versions of Ruby and Ruby on Rails they were on were too old to be able to use the TLS 1.2 libraries
built-in.&lt;/p&gt;
&lt;p&gt;This can then be a fast way to get payments flowing again, ideally the first step on updating the
site to work with a modern stack. This can also minimize development costs compared to doing a full
migration or complete stack upgrade.&lt;/p&gt;
&lt;h3 id=&#34;steps&#34;&gt;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Run on an operating system version that supports TLS 1.2 natively. In practice for us, this is CentOS 7, but modern Debian, Ubuntu, and other Linux distributions would work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Locate the existing payment gateway URLs for live and test modes. For Authorize.net, this differs depending on if you are connecting to their legacy systems or their modern systems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set up and configure the proxy. We used nginx for this; a later section covers the sample configs with explanations. We created a config file that we can just drop in an &lt;code&gt;/etc/nginx/sites/&lt;/code&gt; directory to be able to quickly set up and deploy the reverse proxies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adjust the configuration of the software to point to alternate payment gateway URLs. If you are using Rails’ ActiveMerchant, this can be accomplished via an application-level configuration override. We provide an example of the overriding of the live/test mode URLs for a Rails application later.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;nginx-sample-config&#34;&gt;nginx sample config&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# apitest.authorize.net
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen 127.0.0.1:1337 default_server;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    resolver 8.8.8.8;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    access_log /var/log/nginx/sites/authnet-proxies/access_log;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_log /var/log/nginx/sites/authnet-proxies/error_log warn;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location / {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_pass_header Authorization;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_pass https://apitest.authorize.net$request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_set_header Host apitest.authorize.net;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_redirect off;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# api.authorize.net
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen 127.0.0.1:1338 default_server;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    resolver 8.8.8.8;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    access_log /var/log/nginx/sites/authnet-proxies/access_log;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_log /var/log/nginx/sites/authnet-proxies/error_log warn;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location / {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_pass_header Authorization;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_pass https://api.authorize.net$request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_set_header Host api.authorize.net;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_redirect off;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this file, we are defining a separate server block for each service (test mode and production),
choosing an arbitrarily defined TCP port. Because nginx is speaking TLS 1.2 to the upstream gateway
and we are speaking plain HTTP only to &lt;code&gt;localhost&lt;/code&gt; and not storing any information regarding the request, we
are able to fulfill the PCI DSS requirements.&lt;/p&gt;
&lt;p&gt;A few notes about this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We needed the &lt;code&gt;resolver&lt;/code&gt; line for this to work given our configuration/​setup because we are
referring to the upstream servers by domain name instead of IP addresses; we just used the
easily-memorable Google public DNS resolver servers for this purpose.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We need the &lt;code&gt;Authorization&lt;/code&gt; header passed through the proxy, as this is what contains the site
credentials when making a request from ActiveMerchant.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We need the &lt;code&gt;Host&lt;/code&gt; header defined explicitly in the server block, as we want to override the
&lt;code&gt;localhost&lt;/code&gt; value that will be sent by the application due to application configuration.
Authorize.net was (understandably) very picky about this being provided and correct.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The port numbers here are arbitrary and just need to match what we configure the application to
connect to; one for the test server and one for production.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This setup will work for multiple development environments running on the same server as long as
they are configured to point to the correct test/​live server. There is nothing inherently
insecure about doing this, as no authorization is shared, it just bounces the connection.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;rails-sample-application-config&#34;&gt;Rails sample application config&lt;/h3&gt;
&lt;p&gt;A configuration file for the Authorize.net CIM gateway, for clients using ActiveMerchant as the base for payment gateway integration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rb&#34; data-lang=&#34;rb&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;File&lt;/span&gt;.expand_path(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;../boot&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#038&#34;&gt;__FILE__&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rails/all&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;MyApp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Application&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Rails&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveMerchant&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Billing&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;AuthorizeNetCimGateway&lt;/span&gt;.test_url = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;http://localhost:1337/xml/v1/request.api&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveMerchant&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Billing&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;AuthorizeNetCimGateway&lt;/span&gt;.live_url = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;http://localhost:1338/xml/v1/request.api&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And another one for the legacy Authorize.net gateway:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rb&#34; data-lang=&#34;rb&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;File&lt;/span&gt;.expand_path(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;../boot&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#038&#34;&gt;__FILE__&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rails/all&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;MyApp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Application&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Rails&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveMerchant&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Billing&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;AuthorizeNetGateway&lt;/span&gt;.test_url = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;http://localhost:1337/gateway/transaction.dll&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveMerchant&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Billing&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;AuthorizeNetGateway&lt;/span&gt;.live_url = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;http://localhost:1338/gateway/transaction.dll&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ensure that you override the URLs depending on the gateway setup that your merchant account is set up for. Also make sure that your &lt;code&gt;localhost&lt;/code&gt; URLs are using the ports corresponding to the &lt;code&gt;server&lt;/code&gt; blocks set up in nginx to make sure these are proxying to the correct server.&lt;/p&gt;
&lt;p&gt;While this example is using Authorize.net, you could use a similar setup for any payment gateway which allows you to set the URLs.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Hopefully this gives you some ideas about how you can use reverse proxies to upgrade the outgoing
connection strength. If you need assistance getting something like this set up, feel free to &lt;a href=&#34;/contact/&#34;&gt;contact us&lt;/a&gt; for help.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;(Co-authored by &lt;a href=&#34;/blog/authors/elizabeth-garrett-christensen/&#34;&gt;Elizabeth Garrett Christensen&lt;/a&gt;.)&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Logstash: Removing fields with empty values</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/11/logstash-remove-fields-empty-values/"/>
      <id>https://www.endpointdev.com/blog/2017/11/logstash-remove-fields-empty-values/</id>
      <published>2017-11-22T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;The &lt;a href=&#34;https://www.elastic.co/products&#34;&gt;Elastic stack&lt;/a&gt; is a nice toolkit for collecting, transporting, transforming, aggregating, searching, and reporting on log data from many sources. It was formerly known as the ELK stack, after its main components Elasticsearch, Logstash, and Kibana, but with the addition of Beats and other tools, the company now calls it simply the Elastic stack.&lt;/p&gt;
&lt;p&gt;We are using it in a common configuration, on a central log server that receives logs via rsyslog over TLS, which are then stored in local files and processed further by Logstash.&lt;/p&gt;
&lt;h3 id=&#34;when-conservation-is-recommended&#34;&gt;When conservation is recommended&lt;/h3&gt;
&lt;p&gt;When forwarding logs on to SaaS log services such as Logentries, SumoLogic, etc., we have a limited amount of data transfer and storage allotted to us. So we need to either economize on what we send them, pay for a more expensive plan, or retain a shorter period of history.&lt;/p&gt;
&lt;p&gt;For some very busy logs (nginx logs in JSON format) we decided to delete fields with empty values from the log event during the filter phase in Logstash. This removes a lot of data from the log message we send to the log service over the wire, and reduces the size of each log event stored in their system.&lt;/p&gt;
&lt;p&gt;I expected this to be simple, but that expectation sometimes proves to be false. :)&lt;/p&gt;
&lt;h3 id=&#34;trying-the-prune-filter&#34;&gt;Trying the prune filter&lt;/h3&gt;
&lt;p&gt;The most obvious way would be to use the Logstash &lt;code&gt;prune&lt;/code&gt; filter, which is designed for just such a use case. However, the &lt;code&gt;prune&lt;/code&gt; filter doesn’t handle nested keys, as explained in the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: This filter currently only support operations on top-level fields, i.e. whitelisting and blacklisting of subfields based on name or value does not work.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That is too bad.&lt;/p&gt;
&lt;h3 id=&#34;pruning-with-custom-ruby-code&#34;&gt;Pruning with custom Ruby code&lt;/h3&gt;
&lt;p&gt;Several people have posted alternative solutions to this in the past. A representative recipe to have &lt;a href=&#34;https://manwhoami.wordpress.com/2014/11/25/logstash-delete-empty-fields/&#34;&gt;Logstash delete empty fields&lt;/a&gt; looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# This doesn’t work in Logstash 5 and newer ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;filter {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ruby {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    code =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;event.to_hash.delete_if {|field, value| value == &amp;#39;&amp;#39; }&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And sadly, it doesn’t work.&lt;/p&gt;
&lt;h3 id=&#34;logstash-5-event-api-changes&#34;&gt;Logstash 5 event API changes&lt;/h3&gt;
&lt;p&gt;It used to work with older versions of Logstash, but no longer. Logstash was originally written in Ruby, specifically JRuby for running on the JVM. But for Logstash 5 it was rewritten in Java, and though JRuby extensions are still possible, the &lt;a href=&#34;https://www.elastic.co/guide/en/logstash/5.0/breaking-changes.html#_ruby_filter_and_custom_plugin_developers&#34;&gt;Ruby event API has changed&lt;/a&gt; so that the log data is no longer provided as a mutable hash that the above code expects. (See also &lt;a href=&#34;https://www.elastic.co/guide/en/logstash/current/event-api.html&#34;&gt;the Logstash event API documentation&lt;/a&gt;.)&lt;/p&gt;
&lt;h3 id=&#34;custom-ruby-code-to-prune-in-logstash-5&#34;&gt;Custom Ruby code to prune in Logstash 5+&lt;/h3&gt;
&lt;p&gt;So I came up with Ruby code that works using the new Logstash event API. It is more complicated , but it is still pretty straightforward:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;filter {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# remove fields with empty values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ruby {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    code =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      def walk_hash(parent, path, hash)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        path &amp;lt;&amp;lt; parent if parent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        hash.each do |key, value|
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;          walk_hash(key, path, value) if value.is_a?(Hash)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;          @paths &amp;lt;&amp;lt; (path + [key]).map {|p| &amp;#39;[&amp;#39; + p + &amp;#39;]&amp;#39; }.join(&amp;#39;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        path.pop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      @paths = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      walk_hash(nil, [], event.to_hash)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      @paths.each do |path|
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        value = event.get(path)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        event.remove(path) if value.nil? || (value.respond_to?(:empty?) &amp;amp;&amp;amp; value.empty?)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;      end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We first recursively walk through the whole data structure that the API converts to a Ruby hash for us. We get all nested field names and store in an array their Logstash-style paths like &lt;code&gt;&amp;quot;[nginx][access][upstream_addr]&amp;quot;&lt;/code&gt; that the API expects. Then we walk through the paths and use the API to check for empty values, and remove them. This way we also avoid changing the hash while still walking through it.&lt;/p&gt;
&lt;p&gt;With that configuration and code in a file in &lt;code&gt;/etc/logstash/conf.d/&lt;/code&gt; (this is on CentOS 7 using the logstash RPM from Elastic) all the fields with empty values are removed.&lt;/p&gt;
&lt;h3 id=&#34;some-other-log-event-trimming&#34;&gt;Some other log event trimming&lt;/h3&gt;
&lt;p&gt;In addition we added a few other filters to remove or limit the size of fields that we are happy to have on our own central log server for archival or forensic purposes, but that we don’t need to send to our paid log service for the kinds of reporting we are doing there:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mutate {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  remove_field =&amp;gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;@version&amp;#34;, &amp;#34;beat&amp;#34;, &amp;#34;host&amp;#34;, &amp;#34;input_type&amp;#34;, &amp;#34;offset&amp;#34;, &amp;#34;source&amp;#34;, &amp;#34;type&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[geoip][location]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][pipe]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][remote_port]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][ssl_session_id]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][ssl_session_reused]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][upstream_bytes_received]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][upstream_connect_time]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][upstream_response_length]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;[nginx][access][upstream_status]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;if &amp;#34;beats_input_codec_plain_applied&amp;#34; in [tags] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mutate {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    remove_tag =&amp;gt; [&amp;#34;beats_input_codec_plain_applied&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;truncate {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  length_bytes =&amp;gt; 1024
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, sometimes the client sends an absurdly long HTTP &lt;code&gt;Referer&lt;/code&gt; request header, or the URI requested is very long—​we see plenty longer than 5000 characters. We are happy to truncate those to save space.&lt;/p&gt;
&lt;p&gt;We also do not need to waste space in our paid log service with the repetitive tag &lt;code&gt;beats_input_codec_plain_applied&lt;/code&gt; or the same Filebeat version in every single log event.&lt;/p&gt;
&lt;h3 id=&#34;finis&#34;&gt;Finis&lt;/h3&gt;
&lt;p&gt;This is working for us on Logstash 5.6.3, but should work on Logstash 5.0 and newer.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>From Zero to HTTPS in an afternoon</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/11/from-zero-to-https-in-an-afternoon/"/>
      <id>https://www.endpointdev.com/blog/2017/11/from-zero-to-https-in-an-afternoon/</id>
      <published>2017-11-20T00:00:00+00:00</published>
      <author>
        <name>Matt Vollrath</name>
      </author>
      <content type="html">
        &lt;p&gt;I’ve been hosting my own &lt;a href=&#34;https://mvollrath.net&#34;&gt;humble personal web site&lt;/a&gt; since 2012. I had never bothered setting up HTTPS for my domain, but after hearing about the &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let’s Encrypt&lt;/a&gt; project, I was completely out of excuses.&lt;/p&gt;
&lt;p&gt;For the unfamiliar, Let’s Encrypt offers free and fully automatic HTTPS certificates. The web cares about HTTPS now more than ever. Deeply interactive interfaces like geolocation and user media (camera, microphone) are too sensitive to trust an insecure transport. By leveraging the security features present in modern browsers, users can expect a reasonable safety from attacks that would exploit the weaknesses of HTTP.&lt;/p&gt;
&lt;p&gt;To take the security mission even further, I decided to completely containerize my server and expose only a couple of ports. Using a Docker composition made it very easy to deploy up-to-date nginx and keep it isolated from the rest of my host shard.&lt;/p&gt;
&lt;p&gt;The first mission was to set up certificates with &lt;code&gt;certbot&lt;/code&gt;, the EFF’s free certificate tool. &lt;code&gt;certbot&lt;/code&gt; has a plugin that writes nginx configuration for you, but in this case I didn’t want nginx installed on my host at all. Instead of following the nginx-specific instructions for my platform, I opted for the &lt;a href=&#34;https://certbot.eff.org/docs/using.html#webroot&#34;&gt;webroot plugin&lt;/a&gt; to just give me a certificate and let me figure out how to set it up. A &lt;code&gt;certbot&lt;/code&gt; invocation and a few seconds later I have certificates for my site in &lt;code&gt;/etc/letsencrypt/live/www.mvollrath.net&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next I went shopping for nginx Docker images. The &lt;a href=&#34;https://store.docker.com/images/nginx&#34;&gt;official nginx image&lt;/a&gt; has everything I want: the latest and greatest mainline nginx based on stable Debian. I considered the Alpine variant, but felt like Debian was a better choice for me; familiarity outweighs a few tens of MB of image size.&lt;/p&gt;
&lt;p&gt;The nginx image ships with a default configuration serving a single root directory over HTTP. Since HTTPS was the point of this experiment, I set out to correct this. I started by creating a project directory on the host to house all the configuration needed to build out my server. Then I started up a container with the vanilla configuration and copied config files &lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt; and &lt;code&gt;/etc/nginx/conf.d/default.conf&lt;/code&gt; out of the container to the project directory. With those config files now in my possession, I created a simple Dockerfile to inject them into a new image based on the library nginx image.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;nginx:latest&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;COPY&lt;/span&gt; nginx.conf /etc/nginx/nginx.conf&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;COPY&lt;/span&gt; default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that out of the way, I started hacking config to create my ideal HTTPS server. First I set up a redirect to force all traffic to the HTTPS site.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;listen&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;80&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;server_name&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;mvollrath.net&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;www.mvollrath.net&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;301&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;https://&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$server_name$request_uri&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now I would need a good way to get my certificates into the container. Docker compose has a handy &lt;code&gt;secrets&lt;/code&gt; directive to make this really painless.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;version&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;3.1&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#888&#34;&gt;# must be at least 3.1 for secrets feature&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;secrets&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ssl_privkey&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;file&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/etc/letsencrypt/live/www.mvollrath.net/privkey.pem&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ssl_fullchain&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;file&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/etc/letsencrypt/live/www.mvollrath.net/fullchain.pem&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;services&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nginx&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;container_name&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;build&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ports&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;80:80&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;443:443&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;volumes&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/home/matt/htdocs:/usr/share/nginx/html:ro&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;restart&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;on-failure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;secrets&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ssl_privkey&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ssl_fullchain&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This mounts the provided secrets in &lt;code&gt;/run/secrets&lt;/code&gt; to be scooped up by the site config.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;listen&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;443&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;ssl&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;http2&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;default_server&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;server_name&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;mvollrath.net&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;www.mvollrath.net&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;ssl_certificate&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;/run/secrets/ssl_fullchain&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;ssl_certificate_key&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;/run/secrets/ssl_privkey&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;[...]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now I can update my server by running &lt;code&gt;docker-compose build --pull&lt;/code&gt; and then &lt;code&gt;docker-compose up -d&lt;/code&gt;. This may cause a momentary outage while the containers are being swapped, but for a personal site this is nothing to sweat over. I dropped these commands in a cron script since I like updates but would rather not have to think about updates.&lt;/p&gt;
&lt;p&gt;With my new HTTPS site now exposed to the world, I found some free HTTPS validation tools to check my work and optimize the configuration a few notches beyond the “pretty good” nginx defaults. If you’ve deployed an HTTPS site for work or pleasure, check out the &lt;a href=&#34;/blog/2017/09/web-security-services-roundup/&#34;&gt;collection of web security tools&lt;/a&gt; rounded up by Phin in September.&lt;/p&gt;
&lt;p&gt;I was really happy with the Let’s Encrypt tools and user experience. If you’re still hosting HTTP with no HTTPS option, consider using the free tools to get your free certificate and help your users protect their privacy. If you’re interested in using HTTPS wherever available, consider using the &lt;a href=&#34;https://www.eff.org/https-everywhere&#34;&gt;HTTPS Everywhere&lt;/a&gt; extension offered by the EFF.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Web Security Services Roundup</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/09/web-security-services-roundup/"/>
      <id>https://www.endpointdev.com/blog/2017/09/web-security-services-roundup/</id>
      <published>2017-09-19T00:00:00+00:00</published>
      <author>
        <name>Phineas Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Security is often a very difficult thing to get right, especially when it’s not easy to find reliable or up-to-date information or the process of testing can be confusing and complicated. We have a lot of history and experience working on the security of websites and servers, and we’ve found many tools and websites to be very helpful. Here is a collection of those.&lt;/p&gt;
&lt;h3 id=&#34;server-side-security&#34;&gt;Server-side security&lt;/h3&gt;
&lt;p&gt;There are a number of tools available that can scan your website to check for common vulnerabilities and the quality of SSL/TLS configuration, as well as give great tips on how to improve security for your website.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ssllabs.com/ssltest/&#34;&gt;Qualys SSL Labs Server Test&lt;/a&gt; takes a simple domain name, performs a series of tests from a variety of clients, and returns a simple letter grade (from A+ down to F) indicating the quality of your SSL/TLS configuration, as well as a detailed summary for a host of configuration options. It covers certificates key and algorithms; TLS and SSL configurations; cipher suites; handshakes on a wide variety of platforms including Android, iOS, Chrome, Firefox, Internet Explorer and Edge, Safari, and others; common protocols and vulnerabilities; and other details.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://httpsecurityreport.com/&#34;&gt;HTTP Security Report&lt;/a&gt; does a similar scan, but provides a much more simplified summary of a website, with a numeric score from 0 to 100. It gives a simple, easy to understand list of results, with a green check mark or a red X to indicate whether something is configured for security or not. It also provides short paragraphs explaining settings and recommended configurations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.htbridge.com/ssl/&#34;&gt;HT-Bridge SSL/TLS Server Test&lt;/a&gt; is very similar to Qualys SSL Labs Server Test, but provides some valuable extra information, such as PCI-DSS, HIPAA, and NIST guidelines compliance, as well as industry best practices and basic analysis of third-party content.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://securityheaders.io/&#34;&gt;securityheaders.io&lt;/a&gt; is another letter-grade scan, but focuses on server headers only. It provides simple explanations for each recommended server header and links to guides on how to configure them correctly.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://observatory.mozilla.org/&#34;&gt;Observatory by Mozilla&lt;/a&gt; scans and gives information on HTTP, TLS, and SSH configuration, as well as simple summaries from other websites, including Qualys, HT-Bridge, and securityheaders.io as covered above.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ssl-tools.net/&#34;&gt;SSL-Tools&lt;/a&gt; is focused on SSL and TLS configuration and certificates, with tools to scan websites and mail servers, check for common vulnerabilities, and decode certificates.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.windows.com/en-us/microsoft-edge/tools/staticscan/&#34;&gt;Microsoft Site Scan&lt;/a&gt; performs a series of simple tests, focused more on general website guidelines and best practices, including tests for outdated libraries and plugins which can be a security issue.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://testssl.sh/&#34;&gt;testssl.sh&lt;/a&gt;, the final website scanning tool I’ll cover, is a more advanced bash script that covers many of the same things these other websites do, but provides lots of options for fine-tuning test methods, returned information, and testing abnormal configurations. It’s also open source and doesn’t rely on any third parties.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These websites provide valuable information on SSL/TLS which can be used to create a secure, fast, and functional server configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.mozilla.org/Security/Server_Side_TLS&#34;&gt;Security/Server Side TLS&lt;/a&gt; on the Mozilla wiki is a fantastic page which provides great summaries, recommendations, and reference information on many TLS topics, including handshakes, OCSP Stapling, HSTS, HPKP, certificate ciphers, and common attacks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mozilla.github.io/server-side-tls/ssl-config-generator/&#34;&gt;Mozilla SSL Configuration Generator&lt;/a&gt; is a simple tool that generates boilerplate server configuration files for common servers, including Apache and Nginx, and specific server and OpenSSL versions. It also allows you to target “modern”, “intermediate”, or “old” clients and servers, which will give the best configuration possible for each level.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://istlsfastyet.com/&#34;&gt;Is TLS Fast Yet?&lt;/a&gt; is a great, simple, and to-the-point informational website which explains why TLS is so important and how to improve its performance so it has the smallest impact possible on your website’s speed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;client-side-security&#34;&gt;Client-side security&lt;/h3&gt;
&lt;p&gt;These websites provide information and diagnostic tools to ensure that you are using a secure browser.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://badssl.com/&#34;&gt;badssl.com&lt;/a&gt; gives a list of links to subdomains with various SSL configurations, including badly configured SSL, so you can have a good idea of what a well-configured website looks like versus one with errors in configuration, weak ciphers or key exchange protocols, or insecure HTTP forms.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ipv6-test.com/&#34;&gt;IPv6 Test&lt;/a&gt; checks your network and browser for IPv6 support, showing you your ISP, reverse DNS pointers, both your IPv4 and IPv6 addresses, and giving an idea of when your computer or network may have problems with dual-stack IPv4 + IPv6 remote hosts or DNS.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.howsmyssl.com/&#34;&gt;How’s My SSL?&lt;/a&gt; and &lt;a href=&#34;https://www.ssllabs.com/ssltest/viewMyClient.html&#34;&gt;Qualys Labs SSL Client Test&lt;/a&gt; both check your browser for support of SSL/TLS versions, protocols, ciphers, and features, as well as susceptibility to common vulnerabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;general-tools&#34;&gt;General Tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://neverssl.com/&#34;&gt;NeverSSL&lt;/a&gt; is a simple website that promises to never use SSL. Many public wifi networks require you to go through a payment or login page, which can be blocked when trying to access a well-secured website such as Google, Facebook, Twitter, or Amazon, which can cause trouble connecting to that website. NeverSSL provides an easy and simple way to access that login website.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://crt.sh/&#34;&gt;crt.sh&lt;/a&gt; is a search engine for public TLS certificate information. It provides a history of certificates for a given domain name, with information including issuer and issue date, as well as an advanced search.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.digitalattackmap.com/&#34;&gt;Digital Attack Map&lt;/a&gt; is an interactive map showing DDoS attacks across the world.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://scans.io/&#34;&gt;The Internet-Wide Scan Data Repository&lt;/a&gt; is a public archive of scans across the internet, intended for research and provided by the University of Michigan Censys Team.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.take-a-screenshot.org/&#34;&gt;take-a-screenshot.org&lt;/a&gt; is a simple website that shows how to take a screenshot on a variety of operating systems and desktop environments. It’s a fantastic tool to help less technically-minded people share their screens or issues they’re having.&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Linode IPv6 issues with NetworkManager on CentOS 7</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/04/linode-ipv6-issues-with-networkmanager/"/>
      <id>https://www.endpointdev.com/blog/2017/04/linode-ipv6-issues-with-networkmanager/</id>
      <published>2017-04-04T00:00:00+00:00</published>
      <author>
        <name>Marco Matarazzo</name>
      </author>
      <content type="html">
        &lt;p&gt;In End Point, we use different hosting providers based on the specific task needs. One provider we use extensively with good results is &lt;a href=&#34;https://www.linode.com&#34;&gt;Linode&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During a routine CentOS 7 system update, we noticed a very strange behavior where our IPv6 assigned server address was wrong after restarting the server.&lt;/p&gt;
&lt;h3 id=&#34;ipv6-on-linode-and-slaac&#34;&gt;IPv6 on Linode and SLAAC&lt;/h3&gt;
&lt;p&gt;Linode is offering IPv6 on all their VPS, and IPv6 dynamic addresses are assigned to servers using &lt;a href=&#34;https://en.wikipedia.org/wiki/IPv6#Stateless_address_autoconfiguration_.28SLAAC.29&#34;&gt;SLAAC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the provided CentOS 7 server image, this is managed by NetworkManager by default. After some troubleshooting, we noticed that during the update the NetworkManager package was upgraded from 1.0.6 to 1.4.0.&lt;/p&gt;
&lt;p&gt;This was a major update, and it turned out that the problem was a change in the configuration defaults between the two version.&lt;/p&gt;
&lt;h3 id=&#34;privacy-stable-addressing&#34;&gt;Privacy stable addressing&lt;/h3&gt;
&lt;p&gt;Since 1.2, NetworkManager added the Stable Privacy Addressing feature. This allows for some form of tracking prevention, with the IPv6 address to be stable on a network but changing when entering another network, and still remain unique.&lt;/p&gt;
&lt;p&gt;This new interesting feature has apparently become the default after the update, with the ipv6.addr-gen-mode property set to “stable-privacy”. Setting it to “eui64” maintains the old default behavior.&lt;/p&gt;
&lt;h3 id=&#34;privacy-extension&#34;&gt;Privacy Extension&lt;/h3&gt;
&lt;p&gt;Another feature apparently also caused some problems on our VPS: the Privacy Extension. This is a simple mechanism that somewhat randomizes the network hardware’s (MAC) address, to add another layer of privacy. Alas, this is used in address generation, and that randomization seemed to be part of the problem we were seeing.&lt;/p&gt;
&lt;p&gt;This too has become the default, with the ipv6.ip6-privacy property set to 1. Setting it to 0 turns off the feature.&lt;/p&gt;
&lt;h3 id=&#34;to-sum-it-up&#34;&gt;To sum it up&lt;/h3&gt;
&lt;p&gt;In the end, after the update, we could restore the old behavior and resolve our issues by running, in a root shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nmcli connection modify &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Wired connection 1&amp;#34;&lt;/span&gt; ipv6.ip6-privacy &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nmcli connection modify &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Wired connection 1&amp;#34;&lt;/span&gt; ipv6.addr-gen-mode eui64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a reboot, the IPv6 address finally matched the one actually assigned by Linode, and everything was working ok again.&lt;/p&gt;
&lt;p&gt;If you want to know more on Privacy Extensions and Privacy Stable Addressing, &lt;a href=&#34;https://blogs.gnome.org/lkundrak/2015/12/03/networkmanager-and-privacy-in-the-ipv6-internet/&#34;&gt;this great blog post&lt;/a&gt; by Lubomir Rintel helped us a lot understanding what was going on.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>TriSano Case Study</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/01/trisano-case-study/"/>
      <id>https://www.endpointdev.com/blog/2017/01/trisano-case-study/</id>
      <published>2017-01-24T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;overview&#34;&gt;Overview&lt;/h3&gt;
&lt;p&gt;End Point has been working with state and local health agencies since 2008. We host disease outbreak surveillance and management systems and have expertise providing clients with the sophisticated case management tools they need to deliver in-house analysis, visualization, and reporting—​combined with the flexibility to comply with changing state and federal requirements. End Point provides the hosting infrastructure, database, reporting systems, and customizations that agencies need in order to service to their populations.&lt;/p&gt;
&lt;p&gt;Our work with health agencies is a great example of End Point’s ability to use our experience in open source technology, Ruby on Rails, manage and back up large secure datasets, and integrate reporting systems to build and support a full-stack application. We will discuss one such client in this case study.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-0.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;376&#34; src=&#34;/blog/2017/01/trisano-case-study/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;why-end-point&#34;&gt;Why End Point?&lt;/h3&gt;
&lt;p&gt;End Point is a good fit for this project because of our expertise in several areas including reporting and our hosting capabilities. End Point has had a long history of consultant experts in PostgreSQL and Ruby on Rails, which are the core software behind this application.&lt;/p&gt;
&lt;p&gt;Also, End Point specializes in customizing open-source software, which can save not-for-profit and state agencies valuable budget dollars they can invest in other social programs.&lt;/p&gt;
&lt;p&gt;Due to the secure nature of the medical data in these database, we and our clients must adhere to all HIPAA and CDC policies regarding hosting of data handling, server hosting, and staff authorization and access auditing.&lt;/p&gt;
&lt;h3 id=&#34;team&#34;&gt;Team&lt;/h3&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-1-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-1.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;steve-yoman&#34;&gt;Steve Yoman&lt;/h4&gt;
&lt;p&gt;Steve serves as the project manager for both communication and internal development for End Point’s relationship with the client. Steve brings many years in project management to the table for this job and does a great job keeping track of every last detail, quote, and contract item.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-2-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-2.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;selvakumar-arumugam&#34;&gt;Selvakumar Arumugam&lt;/h4&gt;
&lt;p&gt;Selva is one of those rare engineers who is gifted with both development and DevOps expertise. He is the main developer on daily tasks related to the disease tracking system. He also does a great job navigating a complex hosting environment and has helped the client make strides towards their future goals.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: left; text-align: center; padding:10px;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-3-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;100&#34; src=&#34;/blog/2017/01/trisano-case-study/image-3.jpeg&#34; width=&#34;100&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;josh-tolley&#34;&gt;Josh Tolley&lt;/h4&gt;
&lt;p&gt;Josh is one of End Point’s most knowledgeable database and reporting experts. Josh’s knowledge of PostgreSQL is extremely helpful to make sure that the data is secure and stable. He built and maintains a standalone reporting application based on Pentaho.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/01/trisano-case-study/image-4-big.jpeg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2017/01/trisano-case-study/image-4.jpeg&#34; width=&#34;500&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;application&#34;&gt;Application&lt;/h3&gt;
&lt;p&gt;The disease tracking system consists of several applications including a web application, reporting application, two messaging areas, and SOAP services that relay data between internal and external systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TriSano&lt;/strong&gt;: The disease tracking web app is an open source Ruby on Rails application based on the TriSano product, originally built at the Collaborative Software Initiative. This is a role-based web application where large amounts of epidemiological data can be entered manually or by data transfer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pentaho&lt;/strong&gt;: Pentaho is a PostgreSQL reporting application that allows you to run a separate reporting service or embed reports into your website. Pentaho has a community version and an enterprise version, which is what is used on this particular project. This reporting application provides OLAP services, dashboarding, and generates ad hoc and static reports. Josh Tolley customized Pentaho so that the client can download or create custom reports depending on their needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two Messaging Area applications&lt;/strong&gt;: The TriSano system also serves as the central repository for messaging feeds used to collect data from local health care providers, laboratories throughout the state, and the CDC.&lt;/p&gt;
&lt;p&gt;SOAP services run between the TriSano web app, the Pentaho reporting application, and the client’s data systems translate messages into the correct formats and relay the information to each application.&lt;/p&gt;
&lt;h3 id=&#34;into-the-future&#34;&gt;Into the Future&lt;/h3&gt;
&lt;p&gt;Based on the success over 9+ years working on this project, the client continues to work with their End Point team to manage their few non open-source software licenses, create long term security strategies, and plan and implement all of their needs related to the continuous improvement and changes in epidemiology tracking. We partner with the client so they can focus their efforts on reading results and planning for the future health of their citizens. This ongoing partnership is something End Point is very proud to be a part of and we hope to continue our work in this field well into the future.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>A Beginner’s Guide to PCI DSS Compliance and TLS Versions</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/"/>
      <id>https://www.endpointdev.com/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/</id>
      <published>2016-03-29T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently did some research for one of End Point’s ecommerce clients on their PCI compliance and wanted to share some basic information for those of you who are new to this topic.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;tls&#34;&gt;TLS&lt;/h3&gt;
&lt;p&gt;TLS (Transport Layer Security) is a standard for secure communications between applications. TLS is the current version of what used to be called SSL, the secure sockets layer. In the case of a financial transaction, this is the communication between the website selling a product and the end user. TLS works by encrypting data between two endpoints to ensure any sensitive data (such as financial details and private customer information) is exchanged securely. As security measures increase, new versions of TLS are released. To date, TLS 1.2 is the most up-to-date, with TLS 1.1 being considered safe, and TLS 1.0 being phased out. For details about OS versions supporting the latest TLS standards, please see &lt;a href=&#34;/blog/2015/07/e-commerce-website-encryption-changes/&#34;&gt;Jon Jensen’s write-up here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;compliance-with-pci-dss&#34;&gt;Compliance with PCI DSS&lt;/h3&gt;
&lt;p&gt;As all online retailers know, becoming and staying compliant with PCI DSS (Payment Card Industry Data Security Standard) is a big job. PCI is &lt;em&gt;THE&lt;/em&gt; ecommerce security standard and in order to accept payment with Visa, MasterCard, American Express, and Discover, you must comply with their security standards.&lt;/p&gt;
&lt;p&gt;As the Internet security landscape changes, PCI DSS standards are updated and reflect new risks and adjustments in security protections. As of today, PCI is requiring vendors to upgrade TLS 1.1 or above by June of 2016, with an optional extension until June 2018.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-1-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-1.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;compliance-assessors&#34;&gt;Compliance Assessors&lt;/h3&gt;
&lt;p&gt;Here’s where things get tricky. PCI does not actually do their own compliance, instead each merchant must have a neutral third party help them fulfill their PCI requirements. These are called ‘assessors’ and there are a large number of companies that offer this service along with help for other security-related tasks.&lt;/p&gt;
&lt;p&gt;In preparation for the new requirements, many of the assessor companies are including the new TLS standards in their current compliance protocols.&lt;/p&gt;
&lt;p&gt;What does that mean? Well, it means that even though PCI might not be requiring you to have TLS 1.1 until June of 2018, your compliance assessor might be require you to do it right &lt;strong&gt;now&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;bite-the-bullet&#34;&gt;Bite the Bullet&lt;/h3&gt;
&lt;p&gt;So, now, given that you know you this change is coming AND you need it to get your compliance done, you might as well get your site updated. So where’s the catch?&lt;/p&gt;
&lt;h3 id=&#34;unsupported-browsers&#34;&gt;Unsupported browsers&lt;/h3&gt;
&lt;p&gt;The big catch is that some browsers do not support TLS 1.1 or 1.2. In those cases, some of your users will not be able to complete a payment transaction and will instead hit an error screen and cannot continue. They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internet Explorer on Windows XP&lt;/li&gt;
&lt;li&gt;Internet Explorer older than version 11 on any version of Windows&lt;/li&gt;
&lt;li&gt;the stock Android browser on versions of Android before 5.0&lt;/li&gt;
&lt;li&gt;Safari 6 or older on Mac OS X 10.8 (Mountain Lion) or older&lt;/li&gt;
&lt;li&gt;Safari on iOS 4 or older&lt;/li&gt;
&lt;li&gt;very, very old versions of Firefox or Chrome that have been set not to auto-update&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay, so how many people still use those old browsers? We’ll take a look at some of the breakdowns here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.w3schools.com/browsers/browsers_explorer.asp&#34;&gt;http://www.w3schools.com/browsers/browsers_explorer.asp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might be thinking, ‘That doesn’t seem like very many people’. And that’s true. However, every site has a different customer base and browsers use varies widely by demographics. So where can you go to find out what kinds of browser’s your customers use?&lt;/p&gt;
&lt;h3 id=&#34;google-analytics-your-old-friend&#34;&gt;Google Analytics, your old friend&lt;/h3&gt;
&lt;p&gt;If you have Google Analytics setup, you can go through the Audience/Technology/Browser&amp;amp;OS screens to find out what kind of impact this might have.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-2-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/a-beginners-guide-to-pci-dss-compliance/image-2.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;plan-for-the-worst&#34;&gt;Plan for the Worst&lt;/h3&gt;
&lt;p&gt;Now armed with your information, you will probably want to go ahead and get your website on the newest TLS version. The change is coming anyways but help your staff and web team plan for the worst by making sure everyone knows about the browser limitations and can help your customers through the process.&lt;/p&gt;
&lt;h3 id=&#34;server-compatibility-notes&#34;&gt;Server Compatibility Notes&lt;/h3&gt;
&lt;p&gt;For many ecommerce sites, enabling TLS 1.1 and 1.2 is easy, just changing a configuration setting and restarting the web server. But on older operating systems, such as the still supported and very popular Red Hat Enterprise Linux 5 and CentOS Linux 5, TLS 1.0 is the newest supported version. Various workarounds might be possible, but the only real solution is to migrate to a newer version of the operating system. There can be cost and time factors to consider, so it’s best to plan ahead. Ask us or your in-house developers whether a migration will be necessary!&lt;/p&gt;
&lt;h3 id=&#34;need-help&#34;&gt;Need Help?&lt;/h3&gt;
&lt;p&gt;As End Point’s client liaison, I’m happy to chat with anyone who needs answers or advice about PCI DSS and your ecommerce site.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>E-commerce website encryption changes</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/07/e-commerce-website-encryption-changes/"/>
      <id>https://www.endpointdev.com/blog/2015/07/e-commerce-website-encryption-changes/</id>
      <published>2015-07-24T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;the-big-picture&#34;&gt;The big picture&lt;/h3&gt;
&lt;p&gt;Computer security is a moving target, and during the past few years it’s been moving faster than ever.&lt;/p&gt;
&lt;p&gt;In the e-commerce world, the &lt;a href=&#34;https://www.pcisecuritystandards.org/&#34;&gt;PCI Security Standards Council&lt;/a&gt; sets the rules for what merchants and vendors must do to have what they consider to be a sufficiently secure environment to handle cardholder data such as credit card numbers, expiration dates, and card security codes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.pcisecuritystandards.org/pdfs/15_04_15%20PCI%20DSS%203%201%20Press%20Release.pdf&#34;&gt;PCI DSS 3.1, released on 15 April 2015&lt;/a&gt; puts us all on notice that TLS 1.0 is considered unfit to use for e-commerce website encryption (HTTPS), and will be disallowed soon. The new rules specify that new software implementations must not use TLS versions prior to 1.1. Existing implementations must require TLS 1.1 or 1.2 no later than 30 June 2016.&lt;/p&gt;
&lt;p&gt;They provide some guidance on &lt;a href=&#34;https://www.pcisecuritystandards.org/documents/Migrating_from_SSL_Early_TLS_Information%20Supplement_v1.pdf&#34;&gt;Migrating from SSL and early TLS&lt;/a&gt; and explain what is expected in more detail.&lt;/p&gt;
&lt;p&gt;Long ago we were required to disable SSL 2, and last year we were expected to disable SSL 3, the predecessor to TLS 1.0. That turned out to not be particularly hard or cause too many problems, because almost all systems that supported SSL 3 also supported TLS 1.0.&lt;/p&gt;
&lt;p&gt;This time we are not so lucky. Many clients (such as browsers) and servers did not support TLS beyond version 1.0 until fairly recently. That means much more work is involved in meeting these new requirements than just changing some settings and restarting servers.&lt;/p&gt;
&lt;p&gt;Almost every client (browser) and server that supports TLS 1.1 also supports TLS 1.2, and almost everything that doesn’t support TLS 1.2 doesn’t support TLS 1.1 either. So to keep things simpler here I’ll just talk about TLS 1.0 vs. TLS 1.2 below, and TLS 1.1 can be assumed to apply as well where TLS 1.2 is mentioned.&lt;/p&gt;
&lt;p&gt;At End Point we deploy, support, and host e-commerce sites for many customers, so I’ll talk about the server side of this first. Note that servers can act as both server and client in TLS connections, since servers often make outgoing HTTPS connections as well as accepting incoming requests. Let’s review the situation with each of the major Linux server operating systems.&lt;/p&gt;
&lt;h3 id=&#34;debian&#34;&gt;Debian&lt;/h3&gt;
&lt;p&gt;Debian 8 is the current version, and supports TLS 1.2. It is scheduled to be supported until April 2020.&lt;/p&gt;
&lt;p&gt;Debian 7 supports TLS 1.2, and has planned support until May 2018.&lt;/p&gt;
&lt;p&gt;Debian’s support lifetime has historically depended on how quickly future releases come, but recently the project began to offer long-term support (LTS) for Debian 6, which was supposed to be at end of life, so it will be supported until February 2016. It also only supports TLS 1.0.&lt;/p&gt;
&lt;h3 id=&#34;ubuntu&#34;&gt;Ubuntu&lt;/h3&gt;
&lt;p&gt;Ubuntu’s long-term support (LTS) server versions are supported for 5 years. Currently supported versions 12.04 and 14.04 both handle TLS 1.2.&lt;/p&gt;
&lt;p&gt;Some sites are still using Ubuntu 10.04, which supports only TLS 1.0,  but its support ended in April 2015, so it should not be used any longer in any case.&lt;/p&gt;
&lt;h3 id=&#34;red-hat-enterprise-linux-rhel-and-centos&#34;&gt;Red Hat Enterprise Linux (RHEL) and CentOS&lt;/h3&gt;
&lt;p&gt;Red Hat and CentOS are “enterprise” operating systems with a very long support lifetime of 10 years. Because that is so long, the oldest supported versions may become practically unusable due to changes in the world such as the deprecation of TLS 1.0.&lt;/p&gt;
&lt;p&gt;RHEL/CentOS 7 is the current version, supported until June 2024. It supports TLS 1.2.&lt;/p&gt;
&lt;p&gt;RHEL/CentOS 6 is supported until November 2020. It is mostly ok for TLS 1.2. One exception is that the bundled version of curl doesn’t support TLS &amp;gt; 1.0 for some reason, so if you have applications making curl client calls to other systems, they may break without workarounds.&lt;/p&gt;
&lt;p&gt;RHEL/CentOS 5 is the oldest version still supported, until March 2017, and it is very widely used, but it does not supprt TLS &amp;gt; 1.0.&lt;/p&gt;
&lt;h3 id=&#34;old-server-remediation&#34;&gt;Old server remediation&lt;/h3&gt;
&lt;p&gt;If you’re on an older server that doesn’t support TLS 1.2, the best thing to do is upgrade or migrate to a newer operating system, as soon as possible.&lt;/p&gt;
&lt;p&gt;The common versions of OpenSSL that don’t support TLS 1.2 also do not support &lt;a href=&#34;https://en.wikipedia.org/wiki/Server_Name_Indication&#34;&gt;Server Name Indication&lt;/a&gt; used for hosting multiple HTTPS sites on the same IP address. That is now becoming more commonly used since the thing holding back acceptance was old versions of Windows XP that didn’t support it, and they are now are mostly dead. You can control whether you need SNI on the server side, avoiding it by continuing to get a separate IP address for each HTTPS site you host. But when you are a client of someone else’s service that requires SNI, you’ll wish you had it.&lt;/p&gt;
&lt;p&gt;So migrate. That’s easier said than done, of course. Moving to a new OS version involves a lot of new system library versions, language versions, web server version, etc. Some things aren’t compatible. It takes work and time. That’s life, so accept it and move ahead. Advocate it, schedule it, do it. But in the meantime, if you must cope with old servers, there are some not entirely terrible options.&lt;/p&gt;
&lt;p&gt;You could use plain HTTP on a local private network to talk to a newer server running &lt;a href=&#34;https://www.stunnel.org&#34;&gt;stunnel&lt;/a&gt; or an nginx proxy to do the TLS layer, or use a VPN if you have no private network.&lt;/p&gt;
&lt;p&gt;You can use CDN in front of your site, which will certainly support TLS 1.2, and covers the path between the end user and the CDN, at least.&lt;/p&gt;
&lt;p&gt;You can build your own versions of OpenSSL, any libraries that link to OpenSSL such as curl or wget, Apache or nginx, etc. This is tempting but is a terrible option, because you are almost certain to not update this hand-crafted stack often enough in the future to protect against new vulnerabilities in it. Sidestepping the operating system’s native package management for core infrastructure software like this is usually a mistake.&lt;/p&gt;
&lt;p&gt;You could avoid that problem by using someone else’s backported parallel-install packages of all that, if you can find some, and if you think they’re trustworthy, and if they’re going to maintain them so you can get later updates. I’m not familiar with anyone doing this, but it may be out there and could be hired for the right ongoing price.&lt;/p&gt;
&lt;p&gt;But the best bet is to start planning your upgrade or migration as soon as possible.&lt;/p&gt;
&lt;h3 id=&#34;browser-support-for-tls-12&#34;&gt;Browser support for TLS 1.2&lt;/h3&gt;
&lt;p&gt;Of course the other half of the connection is the client, primarily end-users’ web browsers. On Wikipedia is a very detailed table showing various browsers’ support of various features, broken down by version, here: &lt;a href=&#34;https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers&#34;&gt;TLS support history of web browsers&lt;/a&gt;. My summary follows:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Chrome and Mozilla Firefox&lt;/strong&gt; have been automatically updating themselves for a long time, so unless you or your system administrator have disabled the auto-update, they will work with TLS 1.2.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Internet Explorer&lt;/strong&gt; 8, 9, and 10 support TLS 1.2, but it is disabled by default. Not until IE 11 can TLS 1.2 be counted on to work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apple Safari&lt;/strong&gt; 7, 8, and 9 for Mac OS X support TLS 1.2.&lt;/p&gt;
&lt;p&gt;The built-in browser on &lt;strong&gt;Android&lt;/strong&gt; &amp;lt; 4.4 doesn’t support TLS &amp;gt; 1.0, and Android 4.4 has TLS &amp;gt; 1.0 disabled by default, which is the same thing for most users. So anyone with Android &amp;lt; 5.0 will not be able to connect to your site unless they’re using a separate and newer mobile browser such as Chrome and Firefox.&lt;/p&gt;
&lt;h3 id=&#34;browser-support-for-tls-10&#34;&gt;Browser support for TLS 1.0&lt;/h3&gt;
&lt;p&gt;I have not heard of any timelines being announced for browsers to disable TLS 1.0 yet. I suspect that’s because there are still so many servers that only support TLS 1.0. But before too long we may start to see servers catch up and then I expect browsers will eventually disable TLS 1.0.&lt;/p&gt;
&lt;h3 id=&#34;other-clients&#34;&gt;Other clients&lt;/h3&gt;
&lt;p&gt;There are too many non-browser clients to list here. We’ve already mentioned curl; there is also wget, and the web client libraries in Perl, Python, Ruby, and Java. PHP uses libcurl. NodeJS and Go are likely not from the operating system and newer than it, so may be more current. At any rate, some of those clients will be old and won’t support TLS 1.2, so when other sites stop allowing TLS 1.0 connections, whatever you were talking to them for will stop working.&lt;/p&gt;
&lt;p&gt;PCI DSS will require client applications to stop using TLS 1.0 also, which may mean that applications need to be configured to require TLS 1.2 for outgoing HTTPS connections.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Your systems need to stop supporting TLS 1.0 by June 2016 at the latest.&lt;/strong&gt; Start planning the migration now! &lt;a href=&#34;/contact/&#34;&gt;We are available to help&lt;/a&gt; our current and new clients test, assess needs, and plan upgrades and migrations.&lt;/p&gt;
&lt;h3 id=&#34;reference&#34;&gt;Reference&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;“SSL and early TLS are no longer considered to be strong cryptography and cannot be used as a security control after June 30, 2016. Prior to this date, existing implementations that use SSL and/or early TLS must have a formal Risk Mitigation and Migration Plan in place. Effective immediately, new implementations must not use SSL or early TLS.” ―Sections 2.2.3, 2.3, 4.1 of &lt;a href=&#34;https://www.pcisecuritystandards.org/documents/PCI_DSS_v3-1.pdf&#34;&gt;PCI DSS 3.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.howsmyssl.com/&#34;&gt;How’s My SSL?&lt;/a&gt; — tells you how secure your TLS client is&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ssllabs.com/ssltest/viewMyClient.html&#34;&gt;Qualys SSL Labs client test&lt;/a&gt; — a different client test&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ssllabs.com/ssltest/index.html&#34;&gt;Qualys SSL Labs server test&lt;/a&gt; — very useful, and shows client compatibility with a server’s configuration&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://linuxlifecycle.com/&#34;&gt;linuxlifecycle.com — Support Life Cycles for Enterprise Linux Distributions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Cron Wrapper: Keep your cron jobs environment sane</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/02/cron-wrapper-keep-your-cron-jobs/"/>
      <id>https://www.endpointdev.com/blog/2015/02/cron-wrapper-keep-your-cron-jobs/</id>
      <published>2015-02-06T00:00:00+00:00</published>
      <author>
        <name>Richard Templet</name>
      </author>
      <content type="html">
        &lt;p&gt;It is becoming more common for developers to not use the operating system packages for programming languages. Perl, Python, Ruby, and PHP are all making releases of new versions faster than the operating systems can keep up (at least without causing compatibility problems).
There are now plenty of tools to help with this problem. For Perl we have &lt;a href=&#34;https://perlbrew.pl/&#34;&gt;Perlbrew&lt;/a&gt; and &lt;a href=&#34;https://github.com/tokuhirom/plenv&#34;&gt;plenv&lt;/a&gt;. For Ruby there is &lt;a href=&#34;https://github.com/sstephenson/rbenv&#34;&gt;rbenv&lt;/a&gt; and &lt;a href=&#34;https://rvm.io/&#34;&gt;RVM&lt;/a&gt;. For Python there is &lt;a href=&#34;https://virtualenv.pypa.io/en/latest/&#34;&gt;Virtualenv&lt;/a&gt;. For PHP there is &lt;a href=&#34;https://github.com/wilmoore/php-version&#34;&gt;PHP version&lt;/a&gt;.
These tools are all great for many different reasons but they all have issues when being used with cron jobs. The cron environment is very minimal on purpose. It has a very restrictive path, very few environment variables and other issues. As far as I know, all of these tools would prefer using the env command to get the right version of the language you are using. This works great while you are logged in but tends to fail bad as a cron job. The cron wrapper script is a super simple script that you put before whatever you want to run in your crontab which will ensure you have the right environment variables set.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;#!/bin/bash -l
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;exec&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$@&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The crontab entry would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;34&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;12&lt;/span&gt; * * * bin/cron-wrapper bin/blog-update.pl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The -l on the executing of bash makes it act like it is logging in. Therefore it picks up anything in the ~/.bash_profile and has that available to the env command. This means the cron job runs in the same environment that is setup when you run it from the command line, helping to stop those annoying times where it works fine from the command line but breaks in cron. Jon Jensen went into much greater detail on the benefits of using the -l &lt;a href=&#34;/blog/2013/05/login-shells-in-scripts-called-from-cron/&#34;&gt;here&lt;/a&gt;.
Hope this helps!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>CentOS 7 on Hetzner server with more than 2 TB disk</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/01/centos-7-on-hetzner-server-with-more/"/>
      <id>https://www.endpointdev.com/blog/2015/01/centos-7-on-hetzner-server-with-more/</id>
      <published>2015-01-22T00:00:00+00:00</published>
      <author>
        <name>Spencer Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;We use a variety of hosting providers for ourselves and our clients, including &lt;a href=&#34;https://www.hetzner.de/&#34;&gt;Hetzner&lt;/a&gt;.  They provide good servers for a great price, have decent support, and we’ve been happy with them for our needs.&lt;/p&gt;
&lt;p&gt;Recently I was given the task of building out a new development server for one of our clients, and we wanted it to be set up identically to another one of their servers but with CentOS 7. I placed the order for the hardware with Hetzner and then began the procedure for installing the OS.&lt;/p&gt;
&lt;p&gt;Hetzner provides a scripted install process that you can kick off after booting the machine into rescue mode. I followed this process and selected CentOS 7 and proceeded through the whole process without a problem. After rebooting the server and logging in to verify everything, I noticed that the disk space was capped at 2 TB, even though the machine had two 3 TB drives in it (in hardware RAID 1). I looked at the partitions and found the partition table was “msdos”. Ah ha!&lt;/p&gt;
&lt;p&gt;At this point &lt;a href=&#34;/blog/2013/11/installing-centos-5-on-3tb-drive/&#34;&gt;painful memories of running into this problem before&lt;/a&gt; hit me. I reviewed our notes of what we had done last time, and felt like it was worth a shot even though this time I’m dealing with CentOS 7. I went through the steps up to patching anaconda and then found that anaconda for CentOS 7 is newer and the files are different. I couldn’t find any files that care about the partition table type, so I didn’t patch anything.&lt;/p&gt;
&lt;p&gt;I then tried to run the CentOS 7 install as-is. This only got me so far because I then ran into trouble with NetworkManager timing out and not starting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2015/01/centos-7-on-hetzner-server-with-more/image-0.png&#34;&gt;&lt;img alt=&#34;screen shot of CentOS 7 installer failing&#34; height=&#34;300&#34; src=&#34;/blog/2015/01/centos-7-on-hetzner-server-with-more/image-0.png&#34; width=&#34;400&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;font-size:11px; font-style:italic; clear: both; margin-bottom:15px;&#34;&gt;A screenshot of the CentOS 7 installer failing (anaconda) similar to what I was seeing.&lt;/div&gt;&lt;/a&gt;
&lt;p&gt;Baffled, I looked into what may have been causing the trouble and discovered that the network was not set up at all and it looked as if no network interfaces existed. WHAT?? At this point I dug through dmesg and found that the network interfaces did indeed exist but udevd had renamed them. Ugh!&lt;/p&gt;
&lt;p&gt;Many new Linux distributions are naming network interfaces based on their physical connection to the system: those embedded on the motherboard get named em1, em2, etc. Apparently I missed the memo on this one, as I was still expecting eth0, eth1, etc. And from all indications, so was NetworkManager because it could not find the network interfaces!&lt;/p&gt;
&lt;p&gt;Rather than spend more time going down this route, I decided to change gears and look to see if there was any way to patch the Hetzner install scripts to use a GPT partition table with my install instead of msdos. I found and read through the source code for their scripts and soon stumbled on something that just might solve my problem. In the file /root/.oldroot/nfs/install/functions.sh I found mention of a config variable &lt;strong&gt;FORCE_GPT&lt;/strong&gt;.  If this is set to “1” then it will try to use a GPT partition table unless it thinks the OS won’t like it, and it thinks that CentOS won’t like it (no matter the version). But if you set &lt;strong&gt;FORCE_GPT&lt;/strong&gt; to “2” it will use a GPT partition table no matter what. This config setting just needs to be added to the file you edit where you list out your partitions and LVM volumes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FORCE_GPT 2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PART /boot ext3 512M
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PART lvm   vg0  all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV  vg0  swap swap   swap  32G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV  vg0  root  /     ext4 100G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LV  vg0  home  /home ext4 400G&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I then ran the installer script and added the secret config option and&amp;hellip; Bingo! It worked perfectly! No need to manually patch anything or install manually. And now we have a CentOS 7 server with full 3 TB of disk space usable.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(parted) print
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Model: DELL PERC H710 (scsi)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disk /dev/sda: 3000GB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Sector size (logical/physical): 512B/512B
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Partition Table: gpt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disk Flags: pmbr_boot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Number  Start   End     Size    File system  Name  Flags
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 3      1049kB  2097kB  1049kB                     bios_grub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 1      2097kB  539MB   537MB   ext3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 2      539MB   3000GB  2999GB                     lvm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


      </content>
    </entry>
  
    <entry>
      <title>Adventures in Downgrading my Linode Plan</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/09/adventures-downgrading-linode-plan/"/>
      <id>https://www.endpointdev.com/blog/2014/09/adventures-downgrading-linode-plan/</id>
      <published>2014-09-09T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently went through the process of downgrading and downsizing my &lt;a href=&#34;https://www.linode.com/&#34;&gt;Linode&lt;/a&gt; plan and I wanted to share a few of the [small] hoops that I had to jump through to get there, with the help of the Linode Support team.&lt;/p&gt;
&lt;h3 id=&#34;background&#34;&gt;Background&lt;/h3&gt;
&lt;p&gt;I’ve had a small personal &lt;a href=&#34;https://wordpress.org/&#34;&gt;WordPress&lt;/a&gt; site running for more than a few years now. I also use this server for personal Ruby on Rails development. When I began work on that site, I tried out a few shared hosting providers such as Bluehost and GoDaddy because of the low cost (Bluehost was ~$6/mo) at the time. However, I quickly encountered common limitations of shared server hosting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shared hosting providers typically make it very difficult to run Ruby on Rails, especially edge versions of Ruby on Rails. It’s possible this has improved over the last few years, but when you are a developer and want to experiment (not locally), shared hosting providers are not going to give you the freedom to do so.&lt;/li&gt;
&lt;li&gt;Shared hosting providers do not give you control of specific performance settings (e.g. use of &lt;a href=&#34;https://en.wikipedia.org/wiki/Mod_gzip&#34;&gt;mod_gzip&lt;/a&gt;, &lt;a href=&#34;https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html&#34;&gt;expires headers&lt;/a&gt;), so I was suffering from lack of control for my little WordPress site as well as my Rails sites. While this is another limitation that may have improved over the last few years, ultimately you are limited by non-root access as a shared server user.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;enter-linode&#34;&gt;Enter Linode&lt;/h3&gt;
&lt;p&gt;I looked to virtual server providers such as Linode, Slicehost, and Rackspace after experiencing these common limitations. At the time of my transition, Linode and Slicehost were comparatively priced, but because End Point had successful experiences with Linode for several clients up to that point, I decided to make the jump to Linode. I can’t remember what my initial Linode size was (I think 512MB), but I chose the smallest available option at $20/mo, plus $5/mo for backups. I am not a sysadmin expert like my fellow coworkers (&lt;a href=&#34;/team/richard-templet/&#34;&gt;Richard&lt;/a&gt;, &lt;a href=&#34;/team/jon-jensen/&#34;&gt;Jon&lt;/a&gt;, the list goes on &amp;hellip;), but I managed to get PHP and Ruby on Rails running on Apache with MySQL, and several of the &lt;a href=&#34;https://developer.yahoo.com/performance/rules.html&#34;&gt;best practices for speeding up your web site&lt;/a&gt; in place.&lt;/p&gt;
&lt;p&gt;Fast forward about 2 years, and I’ve been very happy with Linode. I can only remember one specific instance where my server has gone down, and the support team has always been very responsive. They also release occasionally free upgrades at the $20/mo price point, and the current offering at that price point is the Linode 2GB (&lt;a href=&#34;https://www.linode.com/pricing&#34;&gt;see more here&lt;/a&gt;). But lately, I’ve been hearing that &lt;a href=&#34;https://www.digitalocean.com/&#34;&gt;Digital Ocean&lt;/a&gt; has been gaining momentum with a few cheaper options, and I considered making the jump. But I missed the &lt;a href=&#34;https://blog.linode.com/2014/06/16/11th-linode-birthday-10-linode-plan/&#34;&gt;recent announcement&lt;/a&gt; that Linode introduced a new $10/mo. plan back in June (hooray!), so I’m happy to stay with Linode at this lower price point that is suitable for my small, but optimized WordPress site and small Ruby on Rails experiments.&lt;/p&gt;
&lt;h3 id=&#34;how-to-downsize&#34;&gt;How to Downsize&lt;/h3&gt;
&lt;p&gt;In a perfect world, it would seem that to quickly downsize your Linode instance, you would first click on the “Resize” tab upon logging in to the Linode dashboard, click on the lower plan that you want, and then click “Resize this Linode now!”, as shown in the screenshot below:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;padding-bottom:15px;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/09/adventures-downgrading-linode-plan/image-0.png&#34; style=&#34;width:750px;padding-bottom:2px;&#34;/&gt;The Linode resize options.&lt;/div&gt;
&lt;p&gt;Things went a little differently for me. First, I received this message when I tried to resize:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Pending free upgrades must be performed before you are able to resize. Please visit the dashboard to upgrade.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So I headed to my dashboard and clicked on the free upgrade link on the bottom right in the dashboard. I then encountered this message:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Linodes with configuration profiles referencing a 32 bit kernel are currently not eligible for this upgrade. For more information please see our switching kernels guide, or redeploy this Linode using a 64 bit distro.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My main Linode Configuration Profile was 64 bit, but my Restore Configuration Profile was running the 32 bit kernel. So, I first had to update that by clicking on the “Edit” link, selecting the right kernel, and saving those changes. That took a few minutes to take effect.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;padding-bottom:15px;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/09/adventures-downgrading-linode-plan/image-1.png&#34; style=&#34;width:750px;padding-bottom:2px;&#34;/&gt;&lt;br/&gt;
My two configuration profiles needed to be on 64 bit kernel to allow for the Linode upgrade.&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Then&lt;/em&gt;, I was ready for the free upgrade, which took another few minutes after the server booted down, migrated, and booted back up. Next, I headed back to the &amp;ldquo;Resize&amp;rdquo; tab on the dashboard and tried to proceed on the downgrade. I immediately received an error message notifying me that my disk images exceeded the resized option I wanted to switch to (24GB). Upon examining my dashboard, my disk images showed ~28GB allocated to the various disk images:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;padding-bottom:15px;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/09/adventures-downgrading-linode-plan/image-2.png&#34; style=&#34;width:750px;padding-bottom:2px;&#34;/&gt;&lt;br/&gt;
My disk image space exceeded the 24GB allotted for the Linode 1024 plan.&lt;/div&gt;
&lt;p&gt;I was directed by the Linode support team to edit the disk image to get under that 24GB allowed amount. They also explained that I must verify my current app(s) didn’t exceed what I was going to downsize to, using &amp;ldquo;df -h&amp;rdquo; while logged into my server. I had already verified previously where disk space was going on my server and cleaned out some cached files and old log files, so I knew the space used was well under 24GB. The only additional step here was that I had to shut down my server first from the dashboard before reducing the disk image space. So I went through all that, and the disk image adjustment took another few minutes. After the disk image size was adjusted, I booted up the server again and verified it was still running.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;padding-bottom:15px;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/09/adventures-downgrading-linode-plan/image-3.png&#34; style=&#34;width:750px;padding-bottom:2px;&#34;/&gt;&lt;br/&gt;
Editing my Disk Image&lt;/div&gt;
&lt;p&gt;Finally, after all that, I went to the “Resize” tab again and selected the Linode 1024 plan and proceeded. The new plan was implemented within a few minutes, automagically booting down my server and restarting it after completion. My billing information was also updated almost immediately, showing that I will now pay $12.50/mo for the Linode 1024 plan with backups.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In list form, here are the steps I went through to reach my final destination:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Updated kernels to 64 bit for all configuration profiles.&lt;/li&gt;
&lt;li&gt;Applied pending, free upgrades.&lt;/li&gt;
&lt;li&gt;Manually shut down server.&lt;/li&gt;
&lt;li&gt;Applied change to reduce disk image space.&lt;/li&gt;
&lt;li&gt;Rebooted server (not necessary, but I verified at this point things were still running).&lt;/li&gt;
&lt;li&gt;Resized to Linode 1024 plan.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this process wasn’t as trivial as I had hoped, the support folks were super responsive, often responding within a minute or two when I had questions. I’m happy to stay with Linode at this offering and it allows them to remain competitive with both virtual private hosting providers and as an appealing alternative to shared hosting providers. The Linode 1024 plan is also a great starting point for a proof-of-concept or staging server that may be scaled up later as applications move to production and increase in traffic. Linode has plans ranging from the $10/mo plan I have (1GB of RAM, 24GB SSD storage, etc.) all the way up to a 96GB RAM, 1920 GB SSD storage plan at $960/mo.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>The Beauty of IPMI</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/08/the-beauty-of-ipmi/"/>
      <id>https://www.endpointdev.com/blog/2014/08/the-beauty-of-ipmi/</id>
      <published>2014-08-01T00:00:00+00:00</published>
      <author>
        <name>Josh Ausborne</name>
      </author>
      <content type="html">
        &lt;p&gt;For our &lt;a href=&#34;https://www.visionport.com/&#34;&gt;Liquid Galaxy&lt;/a&gt; installations, we use a master computer known as a “head node” and a set of slave computers known as “display nodes.” The slave computers all PXE-boot from the head node, which directs them to boot from a specific ISO disk image.&lt;/p&gt;
&lt;p&gt;In general, this system works great. We connect to the head node and from there can communicate with the display nodes. We can boot them, change their ISO, and do all sorts of other maintenance tasks.&lt;/p&gt;
&lt;p&gt;There are two main settings that we change in the BIOS to make things run smoothly. First is that we set the machine to power on when AC power is restored. Second, we set the machine’s boot priority to use the network.&lt;/p&gt;
&lt;p&gt;Occasionally, though, the CMOS battery has an issue, and the BIOS settings get lost.  How do we get in and boot the machine up? This is where ipmitool has really become quite handy.&lt;/p&gt;
&lt;p&gt;Today we had a problem with one display node at one of our sites. It seems that all of the machines in the Liquid Galaxy were rebooted, or otherwise powered off and then back on. One of them just didn’t come up, and it was causing me much grief.  We have used &lt;a href=&#34;https://sourceforge.net/projects/ipmitool/&#34;&gt;ipmitool&lt;/a&gt; in the past to be able to help us administer the machines.&lt;/p&gt;
&lt;p&gt;IPMI stands for &lt;a href=&#34;https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface&#34;&gt;Intelligent Platform Media Interface&lt;/a&gt;, and it gives the administrator some non-operating system level access to the machine.  Most vendors have some sort of management interface (&lt;a href=&#34;https://en.wikipedia.org/wiki/HP_Integrated_Lights-Out&#34;&gt;HP’s iLO&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Dell_DRAC&#34;&gt;Dell’s DRAC&lt;/a&gt;), including our Asus motherboards.  The open source ipmitool is the tool we use on our Linux systems to be able to interface with the &lt;a href=&#34;https://web.archive.org/web/20171206120929/https://www.asus.com/Commercial-Servers-Workstations/ASMB5iKVM/&#34;&gt;IPMI module on the motherboard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I connected to the head node and ran the following command and got the following output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin@headnode:~ ipmitool -H 10.42.41.33 -I lanplus -P &amp;#39;xxxxxx&amp;#39; chassis status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;System Power         : off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Power Overload       : false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Power Interlock      : inactive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Main Power Fault     : false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Power Control Fault  : false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Power Restore Policy : always-off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Last Power Event     : ac-failed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Chassis Intrusion    : inactive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Front-Panel Lockout  : inactive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Drive Fault          : false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cooling/Fan Fault    : true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While Asus’s Linux support is pretty lacking, and most of the options we find here don’t work with with the open source ipmitool, we did find “System Power : off” in the output, which is a pretty good indicator of our problem.  This tells me that the BIOS settings have been lost for some reason, as we had previously set the system to power on when AC power was restored.  I ran the following to tell it to boot into the BIOS, then powered on the machine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin@headnode:~ ipmitool -H 10.42.41.33 -I lanplus -P &amp;#39;xxxxxx&amp;#39; chassis bootdev bios
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin@headnode:~ ipmitool -H 10.42.41.33 -I lanplus -P &amp;#39;xxxxxx&amp;#39; chassis power on&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At this point, the machine is ready for me to be able to access the BIOS through a terminal window. I opened a new terminal window and typed the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin@headnode:~ ipmitool -H ipmi-lg2-3 -U admin -I lanplus sol activate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Password:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After typing in the password, I get the ever-helpful dialog below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[SOL Session operational.  Use ~? for help]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I didn’t bother with the ~? because I knew that the BIOS would eventually just show up in my terminal. There are, however, other commands that pressing ~? would show.&lt;/p&gt;
&lt;p&gt;See, look at this terminal version of the BIOS that we all know and love!&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/08/the-beauty-of-ipmi/image-0.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;433&#34; src=&#34;/blog/2014/08/the-beauty-of-ipmi/image-0.png&#34; width=&#34;640&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Now that the BIOS was up, it’s as if I was really right in front of the computer typing on a keyboard attached to it. I was able to get in and change the settings for the APM, so that the system will power on upon restoration of AC power. I also verified that the machine is set to boot from the network port before saving changes and exiting. The next thing I knew, the system was booting up PXE, which then pointed it to the proper ISO, and then it was all the way up and running.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/08/the-beauty-of-ipmi/image-1.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;449&#34; src=&#34;/blog/2014/08/the-beauty-of-ipmi/image-1.png&#34; width=&#34;640&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/08/the-beauty-of-ipmi/image-2.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;450&#34; src=&#34;/blog/2014/08/the-beauty-of-ipmi/image-2.png&#34; width=&#34;640&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/08/the-beauty-of-ipmi/image-3.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;450&#34; src=&#34;/blog/2014/08/the-beauty-of-ipmi/image-3.png&#34; width=&#34;640&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;And this, my friends, is why systems should have IPMI. I state the obvious here when I say that life as a system administrator is so much easier when one can get into the BIOS on a remote system.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Managing Multiple Hosts and SSH Identities with OpenSSH</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/12/managing-multiple-hosts-and-ssh/"/>
      <id>https://www.endpointdev.com/blog/2013/12/managing-multiple-hosts-and-ssh/</id>
      <published>2013-12-12T00:00:00+00:00</published>
      <author>
        <name>Patrick Lewis</name>
      </author>
      <content type="html">
        &lt;p&gt;When I started working at End Point I was faced with the prospect of having multiple SSH identities for the first time. I had historically used an RSA SSH key with the default length of 2048 bits, but for my work at End Point I needed to generate a new key that was 4096 bits long.&lt;/p&gt;
&lt;p&gt;Although I could have used &lt;a href=&#34;https://linux.die.net/man/1/ssh-copy-id&#34;&gt;ssh-copy-id&lt;/a&gt; to copy my new SSH public key to all of my old servers, I liked the idea of maintaining separate “personal” and “work” identities and decided to look for a way to automatically use the right key based on the server I was trying to connect to.&lt;/p&gt;
&lt;p&gt;For the first few days I was specifying my new identity on the command line using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh -i .ssh/endpoint_rsa patrick@server.example.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That worked, but I often forgot to specify my new SSH identity when connecting to a server, only realizing my mistake when I was prompted for a password instead of being authenticated automatically.&lt;/p&gt;
&lt;h3 id=&#34;host-definitions&#34;&gt;Host Definitions&lt;/h3&gt;
&lt;p&gt;I had previously learned the value of creating an &lt;a href=&#34;https://linux.die.net/man/5/ssh_config&#34;&gt;ssh_config&lt;/a&gt; file when I replaced a series of command-line aliases with equivalent entries in the SSH config file.&lt;/p&gt;
&lt;p&gt;Instead of creating aliases in my shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;alias server1=&amp;#39;ssh -p 2222 -L 3389:192.168.1.99:3389 patrick@server1.example.com&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I learned that I could add an equivalent entry to my ~/.ssh/config file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host server1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  HostName server1.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Port 2222
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  User patrick
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  LocalForward 3389 192.168.1.99:3389&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, to connect to that server, all I needed to do was run &lt;strong&gt;ssh server1&lt;/strong&gt; and all of the configuration details would be pulled in from the SSH config file. Replacing my series of shell aliases with Host definitions had the added benefit of automatically carrying over to other tools like &lt;a href=&#34;https://git-scm.com/&#34;&gt;git&lt;/a&gt; and &lt;a href=&#34;https://mosh.mit.edu/&#34;&gt;mosh&lt;/a&gt; which read the same configuration.&lt;/p&gt;
&lt;h3 id=&#34;switching-identities-automatically&#34;&gt;Switching Identities Automatically&lt;/h3&gt;
&lt;p&gt;There’s an easy solution to managing multiple SSH identities if you only use one identity per server; use &lt;a href=&#34;https://linux.die.net/man/1/ssh-add&#34;&gt;ssh-add&lt;/a&gt; to store all of your keys in the SSH authentication agent. For example, I used &lt;strong&gt;ssh-add ~/.ssh/endpoint_rsa&lt;/strong&gt; to add my new key, and &lt;strong&gt;ssh-add -l&lt;/strong&gt; to verify that it was showing up in the list of known keys. After adding all of your keys to the agent, it will automatically try them in order for SSH connections until it finds one that authenticates successfully.&lt;/p&gt;
&lt;h3 id=&#34;manually-defining-identities&#34;&gt;Manually Defining Identities&lt;/h3&gt;
&lt;p&gt;If you need more control over which identity an SSH session is using, the &lt;strong&gt;IdentityFile&lt;/strong&gt; option in &lt;a href=&#34;https://linux.die.net/man/5/ssh_config&#34;&gt;ssh_config&lt;/a&gt; lets you specify which key will be used to authenticate. Here’s an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host server2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  HostName server2.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  User patrick
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  IdentityFile ~/.ssh/endpoint_rsa&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This usage is particularly helpful when you have a server that accepts more than one of your identities and you need to control which one should be used.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Comparing installed RPMs on two servers</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/09/comparing-installed-rpms-on-two-servers/"/>
      <id>https://www.endpointdev.com/blog/2013/09/comparing-installed-rpms-on-two-servers/</id>
      <published>2013-09-27T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Sometimes I’m called on to deal with a problem that shows up only on one of two or more servers that are supposed to be configured identically, or nearly identically. One of the first things I do is run &lt;code&gt;rpm -qa | sort&lt;/code&gt; on each machine and diff the output to see which RPM packages may be missing on one or the other server. I’ve never bothered to package this functionality up into a script because it’s so simple.&lt;/p&gt;
&lt;p&gt;To exclude minor version differences, you need to specify a custom &lt;code&gt;rpm --queryformat&lt;/code&gt; that leaves the version number off.&lt;/p&gt;
&lt;p&gt;To understand what you’re seeing when it appears that some package is different but seems the same, you’re often looking at multiple architectures of packages (e.g. i386 and x86_64) which RPM doesn’t show in its default query format.&lt;/p&gt;
&lt;p&gt;Finally, to turn the diff output into a list of RPMs to install via yum, I usually do some combination of grep and sed to pick out the RPMs I need.&lt;/p&gt;
&lt;p&gt;After all that the process isn’t entirely simple anymore, and I recently decided it was easier to script it than explain it all to someone else. I first looked around to see what scripts others have come up with, since this is certainly not a new need. I found the &lt;a href=&#34;https://major.io/2009/03/10/compare-the-rpm-packages-installed-on-two-different-servers/&#34;&gt;blog post “Compare the RPM Packages Installed on Two Different Servers”&lt;/a&gt; which gives a very simple example of the manual labor version I’ve long done.&lt;/p&gt;
&lt;p&gt;In that blog post’s comments, people link to various scripts others have done. I checked them out and found that they are all &lt;em&gt;way&lt;/em&gt; overcomplicated for my needs, and the simple approach I want just needed to be scripted after all. So here is my script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;test&lt;/span&gt; -n &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$TMPDIR&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt; || &lt;span style=&#34;color:#369&#34;&gt;TMPDIR&lt;/span&gt;=/tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;tmpfilebase&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$TMPDIR&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;/rpmdb-compare.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$$&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;test&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;$#&lt;/span&gt; -ne &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Usage: &lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$0&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; [user@]server1 [user@]server2&amp;#34;&lt;/span&gt; &amp;gt;&amp;amp;&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Special name localhost means this server, without ssh&amp;#34;&lt;/span&gt; &amp;gt;&amp;amp;&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;exit&lt;/span&gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$@&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#369&#34;&gt;tmpfile&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$i&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;test&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;$i&lt;/span&gt; = localhost
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rpm -qa --qf &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;%{NAME}.%{ARCH}\n&amp;#39;&lt;/span&gt; | sort &amp;gt; &lt;span style=&#34;color:#369&#34;&gt;$tmpfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ssh &lt;span style=&#34;color:#369&#34;&gt;$i&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;rpm -qa --qf &amp;#39;%{NAME}.%{ARCH}\n&amp;#39;&amp;#34;&lt;/span&gt; | sort &amp;gt; &lt;span style=&#34;color:#369&#34;&gt;$tmpfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;RPMs in &lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; only:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;comm -23 &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$2&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;echo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;RPMs in &lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$2&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; only:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;comm -13 &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$2&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -f &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$tmpfilebase&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$2&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I noticed one of those commenters mentioned using comm instead of diff/grep/sed, and so I used that too. Now the script is easier for me too, and helps avoid copying and leaving temporary files sitting around.&lt;/p&gt;
&lt;p&gt;To run it, just do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./rpmdb-compare host1 host2 &amp;gt; mylist&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the output redirected to file mylist, you can edit it to result in a list of RPMs that need to be installed on one server, then do this on that server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt; mylist yum -y install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It’s a good idea to test it first without the -y option, which will cause yum to abort the installation and gives you a chance to see if any unexpected dependencies will be dragged in.&lt;/p&gt;
&lt;p&gt;Also, don’t blindly install every package you don’t know the purpose of. Watch out for RPMs that may not belong everywhere due to hardware differences such as Ethernet firmware, RAID controller, IPMI, etc.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Apache accidental DNS hostname lookups</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/09/apache-accidental-dns-hostname-lookups/"/>
      <id>https://www.endpointdev.com/blog/2013/09/apache-accidental-dns-hostname-lookups/</id>
      <published>2013-09-18T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Logging website visitor traffic is an interesting thing: Which details should be logged? How long and in what form should you keep log data afterward? That includes questions of log rotation frequency, file naming, and compression. And how do you analyze the data later, if at all?&lt;/p&gt;
&lt;p&gt;Allow me to tell a little story that illustrates a few limited areas around these questions.&lt;/p&gt;
&lt;h3 id=&#34;reverse-dns-ptr-records&#34;&gt;Reverse DNS PTR records&lt;/h3&gt;
&lt;p&gt;System administrators may want to make more sense of visitor IP addresses they see in the logs, and one way to do that is with a reverse DNS lookup on the IP address. The network administrators for the netblock that the IP address is part of have the ability to set up a PTR (pointer) record, or not. You can find out what it is, if anything.&lt;/p&gt;
&lt;p&gt;For example, let’s look at DNS for End Point’s main website at www.endpoint.com using the standard Unix tool “host”:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host www.endpoint.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;www.endpoint.com has address 208.43.132.31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;www.endpoint.com has IPv6 address 2607:f0d0:2001:103::31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 208.43.132.31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;31.132.43.208.in-addr.arpa domain name pointer 208.43.132.31-static.reverse.softlayer.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 2607:f0d0:2001:103::31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3.0.1.0.1.0.0.2.0.d.0.f.7.0.6.2.ip6.arpa domain name pointer 2607.f0d0.2001.0103.0000.0000.0000.0031-static.v6reverse.softlayer.com.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The www.endpoint.com name points to both an IPv4 and an IPv6 address, so there are two answers. When each of those IP addresses is looked up, each shows a PTR record pointing to a subdomain of softlayer.com, which gives a clue about where our site is hosted.&lt;/p&gt;
&lt;p&gt;(As an aside: Why don’t we use a prettier or more specific PTR record? We could set it to almost whatever we want. Well, there are dozens of websites hosted on those IP addresses, so which one should be in the PTR record? There’s no obvious choice, and it doesn’t matter for normal network functioning, so we just left it the way it was.)&lt;/p&gt;
&lt;p&gt;So, is a PTR record like these useful to know about visitors to your website? Sometimes. Let’s take a look at a random sample of visitors to a different website we manage. How much can you tell about each of the visitors based on their reverse DNS PTR records? Is it a bot, someone at home or the office, in which country, and who is their Internet provider? How common is it for a visitor’s IP address to have no PTR record? And keep in mind that most of the visitors have no idea what their IP address or its PTR record is.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 93.137.189.55
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;55.189.137.93.in-addr.arpa domain name pointer 93-137-189-55.adsl.net.t-com.hr.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 66.249.73.121
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;121.73.249.66.in-addr.arpa domain name pointer crawl-66-249-73-121.googlebot.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 88.134.68.31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;31.68.134.88.in-addr.arpa domain name pointer 88-134-68-31-dynip.superkabel.de.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 67.49.156.20
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;20.156.49.67.in-addr.arpa domain name pointer cpe-67-49-156-20.hawaii.res.rr.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 123.211.36.234
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;234.36.211.123.in-addr.arpa domain name pointer CPE-123-211-36-234.lnse3.cha.bigpond.net.au.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 91.75.70.162 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host 162.70.75.91.in-addr.arpa. not found: 3(NXDOMAIN)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 209.82.97.10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;10.97.82.209.in-addr.arpa domain name pointer mail02.westjet.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 76.70.117.223
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;223.117.70.76.in-addr.arpa domain name pointer bas1-toronto26-1279686111.dsl.bell.ca.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 101.160.207.115 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host 115.207.160.101.in-addr.arpa. not found: 3(NXDOMAIN)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 184.198.177.214
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;214.177.198.184.in-addr.arpa domain name pointer 184-198-177-214.pools.spcsdns.net.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 84.199.97.130
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;130.97.199.84.in-addr.arpa domain name pointer 84-199-97-130.iFiber.telenet-ops.be.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 182.19.87.24 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host 24.87.19.182.in-addr.arpa. not found: 3(NXDOMAIN)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 62.34.219.216
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;216.219.34.62.in-addr.arpa domain name pointer i01v-62-34-219-216.d4.club-internet.fr.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;216.219.34.62.in-addr.arpa domain name pointer lns-c10k01-v-62-34-219-216.dsl.sta.abo.bbox.fr.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 187.86.213.190
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host 190.213.86.187.in-addr.arpa. not found: 3(NXDOMAIN)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 15.211.201.84
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;84.201.211.15.in-addr.arpa domain name pointer zccy01cs104.houston.hp.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 161.69.46.150
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;150.46.69.161.in-addr.arpa domain name pointer miv-scan015.scanalert.com.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 77.182.146.99
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;99.146.182.77.in-addr.arpa domain name pointer essn-4db69263.pool.mediaWays.net.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% host 107.0.160.152 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;152.160.0.107.in-addr.arpa domain name pointer 107-0-160-152-ip-static.hfc.comcastbusiness.net.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Did you notice that one IP address returned two different PTR records? That is allowed, though uncommon, as I mentioned in my blog post &lt;a href=&#34;/blog/2008/11/multiple-reverse-dns-pointers-per-ip/&#34;&gt;Multiple reverse DNS pointers per IP address&lt;/a&gt; a few years back. Many reverse DNS control panels provided by commodity hosting providers won’t allow you to assign multiple PTR records, but if you get your reverse DNS delegated to a real nameserver you control, you can do it.&lt;/p&gt;
&lt;h3 id=&#34;finding-the-ip-address-owner-whois&#34;&gt;Finding the IP address owner: whois&lt;/h3&gt;
&lt;p&gt;The reverse DNS PTR can be set misleadingly, such that a forward lookup on the name does not point back to the same IP address. In the end the way to really know who controls that IP address (or at least a network provider who supplies the ultimately responsible person) is with a “whois” lookup. We can check that the 208.43.132.31 IP address really is hosted at SoftLayer, and for which customer, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% whois 208.43.132.31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Querying whois.arin.net]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Redirected to rwhois.softlayer.com:4321]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Querying rwhois.softlayer.com]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[rwhois.softlayer.com]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;%rwhois V-1.5:003fff:00 rwhois.softlayer.com (by Network Solutions, Inc. V-1.5.9.5)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Class-Name:network
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:ID:NETBLK-SOFTLAYER.208.43.128.0/19
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Auth-Area:208.43.128.0/19
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Network-Name:SOFTLAYER-208.43.128.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:IP-Network:208.43.132.0/27
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:IP-Network-Block:208.43.132.0-208.43.132.31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Organization;I:End Point Corporation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Street-Address:920 Broadway, Suite 701
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:City:New York
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:State:NY
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Postal-Code:10010
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Country-Code:US
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Tech-Contact;I:sysadmins@softlayer.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Abuse-Contact;I:abuse@endpoint.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Admin-Contact;I:IPADM258-ARIN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Created:2007-06-18 12:15:54
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Updated:2010-11-21 18:59:43
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network:Updated-By:ipadmin@softlayer.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;%referral rwhois://root.rwhois.net:4321/auth-area=.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;%ok&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So you can see that’s really End Point’s IP address, at SoftLayer.&lt;/p&gt;
&lt;p&gt;Use your local whois tool or search for a web-based one and look up a few of the IP addresses that didn’t have reverse DNS PTR records in our log cross-section above. The results are interesting.&lt;/p&gt;
&lt;h3 id=&#34;reverse-lookups-in-apache-httpd&#34;&gt;Reverse lookups in Apache httpd&lt;/h3&gt;
&lt;p&gt;Now let’s say that as a system administrator you would like to see the PTR records for visitor IP addresses on your Apache httpd website. It may be tempting to use the &lt;a href=&#34;http://httpd.apache.org/docs/2.2/mod/core.html#hostnamelookups&#34;&gt;HostnameLookups&lt;/a&gt; configuration directive to do real-time lookups and put them in the log alongside the IP address. It’s easy but not wise to put the PTR record &lt;em&gt;instead&lt;/em&gt; of the IP address, because it may not point back to the IP address, and even if it does, it can change over time, and will not provide a complete picture of the connection later on.&lt;/p&gt;
&lt;p&gt;However, if you read the &lt;a href=&#34;http://httpd.apache.org/docs/2.2/mod/core.html#hostnamelookups&#34;&gt;HostnameLookups documentation&lt;/a&gt;, you’ll see the authors recommend it not be enabled on busy production servers because of the extra network traffic and delay for visitors, especially for any netblocks with slow DNS servers (and there are many out there). This is important! It really should almost never be enabled for any public site.&lt;/p&gt;
&lt;p&gt;Most web server administrators learn this early on and wouldn’t dream of enabling HostnameLookups.&lt;/p&gt;
&lt;p&gt;However, I recently came across a situation where we inadvertently were doing the equivalent without explicitly enabling HostnameLookups. How? By limiting access based on the remote hostname! Read the documentation on the &lt;a href=&#34;http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#allow&#34;&gt;Allow directive&lt;/a&gt;, under the section “A (partial) domain-name”:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This configuration will cause Apache to perform a double reverse DNS lookup on the client IP address, regardless of the setting of the HostnameLookups directive. It will do a reverse DNS lookup on the IP address to find the associated hostname, and then do a forward lookup on the hostname to assure that it matches the original IP address. Only if the forward and reverse DNS are consistent and the hostname matches will access be allowed.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This makes perfect sense, but it is a pretty big likely unexpected side effect to using something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Allow from .example.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In our case it was an even less obvious case that didn’t make us think of hostnames at all:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Allow from localhost&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here localhost was written, perhaps to save some effort or maybe increase clarity vs. writing out 127.0.0.1 (IPv4) and ::1 (IPv6). Mentally it’s so easy to view “localhost” is a direct alias for 127.0.0.1 and ::1 that we can forget that the name “localhost” is just a convention, and requires a lookup like any other name. Those familiar with the MySQL database may know that it actually assigns special confusing meaning to the word “localhost” to make a UNIX socket connection instead of a TCP connection to 127.0.0.1 or whatever “localhost” is defined as on the system!&lt;/p&gt;
&lt;p&gt;You may also be thinking that looking up 127.0.0.1 is fast because that is usually mapped to “localhost” in /etc/hosts. True, but every other visitor who is not in /etc/hosts gets the slow DNS PTR lookup instead! And depending on the operating system, you may see “ip6-localhost” or “ip6-loopback” (Debian 7, Ubuntu 12.04), “localhost6” (RHEL 5/6, Fedora 19) in /etc/hosts, or something else. So it’s important to spell out the addresses:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Allow from 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Allow from ::1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Doing so immediately stops the implicit HostnameLookups behavior and speeds up the website. In this case it wasn’t a problem, since it was for a private, internal website that couldn’t be visited at all by anyone not first allowed through a firewall, so traffic levels were relatively low. That access control is part of why localhost needed to be allowed in the first place. But it would have been very bad on a public production system due to the slowdown in serving traffic.&lt;/p&gt;
&lt;h3 id=&#34;the-right-way&#34;&gt;The right way&lt;/h3&gt;
&lt;p&gt;If you really want to see PTR records for every visitor IP address, you can use Apache’s &lt;a href=&#34;http://httpd.apache.org/docs/2.2/programs/logresolve.html&#34;&gt;logresolve&lt;/a&gt; log post-processing program. Or you can let an analytics package do it for you.&lt;/p&gt;
&lt;p&gt;So, lesson learned: It’s not just HostnameLookups you need to keep turned off. Also watch out for the Apache Allow directive and don’t use it with anything other than numeric IP addresses!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>GNU Screen logtstamp string</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/07/gnu-screen-logtstamp-string/"/>
      <id>https://www.endpointdev.com/blog/2013/07/gnu-screen-logtstamp-string/</id>
      <published>2013-07-24T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;A short note on &lt;a href=&#34;https://www.gnu.org/software/screen/&#34;&gt;GNU Screen&lt;/a&gt; configuration:&lt;/p&gt;
&lt;p&gt;You can add configuration to &lt;code&gt;~/.screenrc&lt;/code&gt; or another configuration file named by &lt;code&gt;-c $filename&lt;/code&gt; upon invocation, and among the many options are some to enable logging what happens in the screen windows. This is useful when using screen as a reattachable daemonizer.&lt;/p&gt;
&lt;p&gt;Consider this configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logfile path/to/screen-output.%Y%m%d.log
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logfile flush 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logtstamp on
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logtstamp after 5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log on&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That works nicely. With &lt;code&gt;logfile&lt;/code&gt; we specify the name of the log file, using some &lt;code&gt;%&lt;/code&gt; escapes as per “STRING ESCAPES” in the manpage to put the date in the logfile name.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;logfile flush 1&lt;/code&gt; we request that every 1 second the output be flushed to the log, making it easier to follow with &lt;code&gt;tail -f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;logtstamp on&lt;/code&gt; option writes a timestamp to the log after a default 2 minutes of inactivity. We shorten that to 5 seconds with &lt;code&gt;logtstamp after 5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;log on&lt;/code&gt; turns on the logging.&lt;/p&gt;
&lt;p&gt;Now, what if we want to customize the timestamp? The default looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- 0:process-name -- time-stamp -- Jul/24/13  9:09:56 --&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The manpage says that can be customized with &lt;code&gt;logtstampt string ...&lt;/code&gt;, where the default is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The manpage earlier says that arguments may be separated by single or double quotes. Doing so with the default shown doesn’t work, because a literal \n shows up in the logfile.&lt;/p&gt;
&lt;p&gt;The solution I worked out by trial and error is that you must double-quote the string and use octal escape value &lt;code&gt;\012&lt;/code&gt;. Single-quoting that will output a literal backslash 0 1 2, and &lt;code&gt;\n&lt;/code&gt; simply is not a recognized escape. Thus our final configuration directive is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logtstamp string &amp;#34;-- time-stamp -- %Y-%m-%d %0c:%s --\012&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which results in output like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- time-stamp -- 2013-07-24 09:59:35 --&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you use more than one screen window with this configuration, all windows’ output will go into the same logfile. Use the &lt;code&gt;%n&lt;/code&gt; escape string to include a window number in the logfile name if you’d like them kept separate.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Converting root filesystem from ext3 to ext4 on CentOS and RHEL 5.9</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/06/converting-root-filesystem-from-ext3-to/"/>
      <id>https://www.endpointdev.com/blog/2013/06/converting-root-filesystem-from-ext3-to/</id>
      <published>2013-06-12T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Here’s a quick explanation of the procedure to convert the root / filesystem on RHEL and CentOS 5.9 from ext3 to &lt;a href=&#34;https://en.wikipedia.org/wiki/Ext4&#34;&gt;ext4&lt;/a&gt;, because ext3 wasn’t available during install time.&lt;/p&gt;
&lt;p&gt;Note that this is not a configuration Red Hat supports, but it works fine. (I believe you cannot convert the /boot filesystem to ext4 on standard RHEL/CentOS 5 because its GRUB can’t handle it, but you can convert all the other filesystems.)&lt;/p&gt;
&lt;p&gt;Ideally do this only on a fairly freshly-installed system you don’t mind losing. Back everything up first unless this is a system you don’t mind destroying! This is a risky operation and (ahem) things can go wrong.&lt;/p&gt;
&lt;p&gt;You’ll need direct console or KVM access to the server. You can do without that if you can remount -o ro / but that usually won’t work with sshd or other daemons that keep files open on the / filesystem.&lt;/p&gt;
&lt;p&gt;You will of course need to adapt the current kernel version and root filesystem block device path in the examples below.&lt;/p&gt;
&lt;p&gt;Now, to live dangerously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;yum -y install e4fsprogs&lt;/li&gt;
&lt;li&gt;Edit /etc/fstab so that the / filesystem is mounted as ext4 (which works with the existing ext3 filesystem as well). If you’re using a battery-backed RAID controller you may want to add the nobarrier mount option. See man mount to read about what that choice entails.&lt;/li&gt;
&lt;li&gt;mkinitrd &amp;ndash;with=ext4 &amp;ndash;with=ext3 -f /boot/initrd-2.6.18-348.el5.img 2.6.18-348.el5&lt;/li&gt;
&lt;li&gt;shutdown -r now&lt;/li&gt;
&lt;li&gt;Boot into single-user mode: use GRUB to edit the linux arguments adding “single” to the end&lt;/li&gt;
&lt;li&gt;fsck.ext3 -pf /dev/vg0/lv_root&lt;/li&gt;
&lt;li&gt;tune4fs -O extents,uninit_bg,dir_index /dev/vg0/lv_root&lt;/li&gt;
&lt;li&gt;fsck.ext4 -yfD /dev/vg0/lv_root&lt;/li&gt;
&lt;li&gt;shutdown -r now&lt;/li&gt;
&lt;li&gt;Allow it to boot normally into multi-user mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are lots of articles out there about converting from ext3 to ext4, but none I found that covered RHEL/CentOS 5 specifically and contained all the needed steps and actually worked. This is based on info from &lt;a href=&#34;https://www.debian-administration.org/article/Migrating_a_live_system_from_ext3_to_ext4_filesystem&#34;&gt;here for Debian&lt;/a&gt; and &lt;a href=&#34;https://web.archive.org/web/20100610195928/http://www.centos.org/modules/newbb/viewtopic.php?topic_id=26309&amp;amp;forum=37&#34;&gt;here for CentOS&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Converting RHEL 5.9 and 6.4 to CentOS</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/04/converting-rhel-59-and-64-to-centos/"/>
      <id>https://www.endpointdev.com/blog/2013/04/converting-rhel-59-and-64-to-centos/</id>
      <published>2013-04-04T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;CentOS is, by design, an almost identical rebuild of Red Hat Enterprise Linux (RHEL). Any given version of each OS should behave the same as the other and packages and yum repositories built for one should work for the other unchanged. Any exception I would call a bug.&lt;/p&gt;
&lt;p&gt;Because Red Hat is the source or origin of packages that ultimately end up in CentOS, there is an inherent delay between when Red Hat releases new packages and when they appear in CentOS. CentOS is financed by optional donations of work, hosting, and money, while Red Hat Enterprise Linux is financed by requiring customers to purchase entitlements to use the software and get various levels of support from Red Hat.&lt;/p&gt;
&lt;p&gt;Thanks to this close similarity and the tradeoff between rapidity of updates vs. cost and entitlement tracking, we find reasons to use both RHEL and CentOS, depending on the situation.&lt;/p&gt;
&lt;p&gt;Sometimes we want to convert RHEL to CentOS or vice versa, on a running machine, without the expense and destabilizing effect of having to reinstall the operating system. In the past I’ve written on this blog about &lt;a href=&#34;/blog/2011/12/converting-centos-6-to-rhel-6/&#34;&gt;converting from CentOS 6 to RHEL 6&lt;/a&gt;, and earlier about &lt;a href=&#34;/blog/2009/10/upgrading-from-rhel-52-to-centos-54/&#34;&gt;converting from RHEL 5 to CentOS 5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I recently needed to migrate several servers from RHEL to CentOS, and found an update of the procedure was in order because some URLs and package versions had changed. Here are current instructions on how to migrate from RHEL 5.9 to CentOS 5.9, and RHEL 6.4 to CentOS 6.4.&lt;/p&gt;
&lt;p&gt;These commands should of course be run as root, and observed carefully by a human eye to look for any errors or warnings and adapt accordingly.&lt;/p&gt;
&lt;h3 id=&#34;rhel-59-to-centos-59-conversion-64-bit-x86_64&#34;&gt;RHEL 5.9 to CentOS 5.9 conversion, 64-bit (x86_64)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/RPM-GPG-KEY-CentOS-5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/centos-release-5-9.el5.centos.1.x86_64.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/centos-release-notes-5.9-0.x86_64.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/yum-3.2.22-40.el5.centos.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/yum-updatesd-0.9-5.el5.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/yum-fastestmirror-1.1.16-21.el5.centos.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/x86_64/CentOS/gamin-python-0.1.7-10.el5.x86_64.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum erase yum-rhn-plugin rhn-client-tools rhn-virtualization-common rhn-setup rhn-check rhnsd yum-updatesd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum clean all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm --import RPM-GPG-KEY-CentOS-5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm -e --nodeps redhat-release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum localinstall *.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shutdown -r now&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;rhel-59-to-centos-59-conversion-32-bit-i386&#34;&gt;RHEL 5.9 to CentOS 5.9 conversion, 32-bit (i386)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/RPM-GPG-KEY-CentOS-5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/centos-release-5-9.el5.centos.1.i386.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/centos-release-notes-5.9-0.i386.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/yum-3.2.22-40.el5.centos.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/yum-updatesd-0.9-5.el5.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/yum-fastestmirror-1.1.16-21.el5.centos.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/5.9/os/i386/CentOS/gamin-python-0.1.7-10.el5.i386.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum erase yum-rhn-plugin rhn-client-tools rhn-virtualization-common rhn-setup rhn-check rhnsd yum-updatesd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum clean all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm --import RPM-GPG-KEY-CentOS-5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm -e --nodeps redhat-release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum localinstall *.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shutdown -r now&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;rhel-64-to-centos-64-conversion-64-bit-x86_64&#34;&gt;RHEL 6.4 to CentOS 6.4 conversion, 64-bit (x86_64)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; centos
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/6.4/os/x86_64/RPM-GPG-KEY-CentOS-6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/6.4/os/x86_64/Packages/centos-release-6-4.el6.centos.10.x86_64.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/6.4/os/x86_64/Packages/yum-3.2.29-40.el6.centos.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/6.4/os/x86_64/Packages/yum-utils-1.1.30-14.el6.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://mirror.centos.org/centos/6.4/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.30-14.el6.noarch.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum erase yum-rhn-plugin rhn-client-tools rhn-virtualization-common rhn-setup rhn-check rhnsd yum-updatesd subscription-manager
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum clean all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm --import RPM-GPG-KEY-CentOS-6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpm -e --nodeps redhat-release-server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum localinstall *.rpm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shutdown -r now&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We don’t use 32-bit (i386) RHEL or CentOS 6, so you’re on your own with that, but it should be very straightforward to adapt the x86_64 instructions.&lt;/p&gt;
&lt;p&gt;If during the yum localinstall you get an error like this that references a URL containing %24releasever:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Errno 14] PYCURL ERROR 22 - &amp;#34;The requested URL returned error: 404 Not Found&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Error: Cannot retrieve repository metadata (repomd.xml) for repository&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then you need to temporarily disable that add-on yum repository until after the conversion is complete by editing /etc/yum.repos.d/&lt;em&gt;name&lt;/em&gt;.repo to change enabled=1 to enabled=0. The problem here is caused by the repo configuration using the releasever yum variable which is undefined mid-conversion because we forcibly removed the redhat-release* package that defines it. We can’t expect the OS to know what kind it is in the middle of its identity crisis and change!&lt;/p&gt;
&lt;p&gt;If all goes well, nothing will look any different at all, except you’ll now see:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# cat /etc/redhat-release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CentOS release 5.9 (Final)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# cat /etc/redhat-release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CentOS release 6.4 (Final)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


      </content>
    </entry>
  
</feed>
