rubysecurity.org

Cloud Architect / DevOps Engineer / SRE / Developer | /root

Home About Books Blog Portfolio Archive

Tag Cloud


Currently Reading

Certified Kubernetes Administrator (CKA) Study Guide
Certified Kubernetes Administrator (CKA) Study Guide
38 / 155 Pages


Latest Book Reviews

Latest Posts


February 9, 2022

Goodbye CentOS 8, Hello Rocky Linux

by Alpha01

I’m over two months late, to the deadline as support for CentOS 8 stopped on December 31, 2021 and now the project is focusing on the CentOS 8 Stream rolling update distro.

Instead of converting my CentOS 8 to Stream, I opted to the popular approach of just dumping CentOS in favor of Rocky Linux. The migrating process itself was super easy. My original CentOS 8 system was NOT running the latest version of CentOS prior to its End-Of-Life.

[root@mail ~]# cat /etc/centos-release
CentOS Linux release 8.4.2105

[root@mail ~]# sudo dnf update
CentOS Linux 8 - AppStream                                                                                                                                                219  B/s |  38  B     00:00
Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist

Instead of opting to update the repos to point the CentOS archive vault repositories. I wanted to just try the migration from my 8.4.2105 running version. After all this particular system is just a Postfix mailserver, and if it botched completely, I’m easily able to recreate the mail server using my Ansible automation.

The update process is just a matter of running the migrate2rocky.sh migration shell script.

[root@mail migrate2rocky]# ./migrate2rocky.sh -r
migrate2rocky - Begin logging at Tue 08 Feb 2022 04:20:57 PM PST.


Removing dnf cache
Preparing to migrate CentOS Linux 8 to Rocky Linux 8.
[...]
Done, please reboot your system.
A log of this installation can be found at /var/log/migrate2rocky.log

After a few minutes where it applied the changes and them some package updates, the migration script ending without any errors. After rebooting the system, I was able to ssh in normally, verify that the system was in a working state, and verify Postfix still working. The migration worked!

[root@mail ~]# cat /etc/redhat-release
Rocky Linux release 8.5 (Green Obsidian)
[root@mail ~]# cat /etc/rocky-release
Rocky Linux release 8.5 (Green Obsidian)
[root@mail ~]# cat /etc/rocky-release-upstream
Derived from Red Hat Enterprise Linux 8.5

I even used Ansible to see what version it was reading after the migration:

[root@ansible ~]# ansible mail -m setup -a 'filter=ansible_distribution'
mail.rubyninja.org | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "Rocky",
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}
[root@ansible ~]# ansible mail -m setup -a 'filter=ansible_distribution_version'
mail.rubyninja.org | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution_version": "8.5",
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}

The beauty of binary compatible Linux distributions is that although updates are from new repackaged packages, when applied they work flawlessly.

Ironically, over a decade ago I had to do similar migration from White Box Enterprise Linux to CentOS 3. At the time, I simply had to update the repo URLs, refresh yum, and pull down the latest updates from the CentOS 3 repos. All of which worked beautifully.

Resources

Tags: [ centos rhel ]
January 1, 2022

#100DaysOfCode Go

by Alpha01

It’s been well over 10 years since I’ve learned a new programming language. While I’ve flirted with JavaScript to a certain point, I never truly did made an effort to learn it, given how horrifying that language is (there I said it). My programming journey began with simply Bash shell scripting, and Ruby in college. I won’t include Microsoft VisualBasic which I had a couple of courses in, because quite frankly I don’t remember much of it. As I got my second job as a Linux sysadmin in early 2008, that shifted towards me needing to learn PHP, and Perl; so I did. Then around that same time, seeing the popularity of Python, I’ve also decided to learn Python. So throughout all my tech career, I’ve extensively used Bash, Ruby, PHP, Perl, and Python in one way or another. So much, that I’m definitely comfortable using any of them, varying the problem I want to solve, hence I’ve have included them in my resumé.

Now in January 1, 2022, as stated in my New Year’s Resolution, I’ve made it an actual goal to learn Go in depth. It’s quite amazing to see how the tech industry has really embraced Go, as one of the defacto languages. My background is mostly all Linux DevOps, and the past two years I’ve been working extensively with Kubernetes. So being involved in the Kubernetes world, I feel somewhat constraint by the fact that I’m not well knowledge in the Go programming language. That’s why I want to learn this new powerful programming language.

I love the idea of the #100DaysOfCode challenge, as well as its community aspect. So I’ve decided that for the next 100 days, I’ll be learning Go. I’m going to be using Twitter for daily assertions, as well a weekly post on this blog to keep myself accountable. All of my code will be on https://github.com/alpha01/100DaysOfCode-Go. I already have plans for some practical projects, such as writing a custom Kubernetes controller for a CRD using https://github.com/kubernetes/sample-controller.

For the study material, I’ll reading the book Go Programming Language and using the Udemy courses Learn How To Code: Google’s Go (golang) Programming Language and Go: The Complete Developer’s Guide (Golang).

Happy New Year, and happy Go hacking!

Tags: [ go ]
June 7, 2021

RIP Nagios

by Alpha01

It’s an end of an era, at least with me using Nagios or Nagios Core to be exact. Unless you’ve been living under a rock, Prometheus has become the defacto tool when it comes to system monitoring. While professionally, I stoped using Nagios a few years ago, but I still kept a Nagios server running in my HomeLab for internal monitoring along side Prometheus. What kept me from fully dumping Nagios, was having to migrate some of my custom alerts. However, this weekend I finally decided to give Nagios its final blow and migrate my custom alerts to Prometheus. With the help of the awesome Blackbox exporter, I was able to easily port over my custom http and dns alerts to Prometheus.

Like Nagios, I feel Prometheus also has a steep learning curve. However, overall I feel the benefits Prometheus brings like integration with cloud native system infrastructures, definitely outweigh the drawbacks of this awesome monitoring tool.

Prometheus

Tags: [ prometheus nagios ]
March 31, 2021

Updating BIND DNS records using Ansible

by Alpha01

This is a follow up to the post. Configure BIND to support DDNS updates Now, that I’m able to dynamically update DNS records, this is where Ansible comes in. Ansible is hands down my favorite orchestration/automation tool. So I choose to use it to update my local DNS records going forward.

I’ll be using the community.general.nsupdate module.

I constructed my DNS records on my nameserver’s corresponding Ansible group_vars using the following structure:

all_dns_records:
  - zone: DNS-NAME
    records:
      - record: (@ for $ORIGIN or normal record name )
        ttl: TTL-VALUE
        state: (present or absent)
        type: DNS-TYPE
        value: VALUE-OF-DNS-RECORD

Example

---
all_dns_records:
  - zone: "rubyninja.org"
    records:
      - record: "@"
        ttl: "10800"
        state: "present"
        type: "A"
        value: "192.168.1.63"
      - record: "shit"
        ttl: "10800"
        state: "present"
        type: "A"
        value: "192.168.1.64"
  - zone: "alpha.org"
    records:
      - record: "@"
        ttl: "10800"
        state: "present"
        type: "A"
        value: "192.168.1.63"
      - record: "test"
        ttl: "10800"
        state: "present"
        type: "A"
        value: "192.168.1.64"
[...]

Deployment Ansible playbook:

---
- hosts: ns1.rubyninja.org
  pre_tasks:
    - name: Get algorithm from vault
      ansible.builtin.set_fact:
        vault_algorithm: "{{ lookup('community.general.hashi_vault', 'secret/systems/bind:algorithm') }}"
      delegate_to: localhost

    - name: Get rndckey from vault
      ansible.builtin.set_fact:
        vault_rndckey: "{{ lookup('community.general.hashi_vault', 'secret/systems/bind:rndckey') }}"
      delegate_to: localhost

  tasks:
    - name: Sync $ORIGIN records"
      community.general.nsupdate:
        key_name: "rndckey"
        key_secret: "{{ vault_rndckey }}"
        key_algorithm: "{{ vault_algorithm }}"
        server: "ns1.rubyninja.org"
        port: "53"
        protocol: "tcp"
        ttl: "{{ item.1.ttl }}"
        record: "{{ item.0.zone }}."
        state: "{{ item.1.state }}"
        type: "{{ item.1.type }}"
        value: "{{ item.1.value }}"
      when: item.1.record == "@"
      with_subelements:
        - "{{ all_dns_records }}"
        - records
      notify: Sync zone files
      delegate_to: localhost

    - name: Sync DNS records"
      community.general.nsupdate:
        key_name: "rndckey"
        key_secret: "{{ vault_rndckey }}"
        key_algorithm: "{{ vault_algorithm }}"
        server: "ns1.rubyninja.org"
        port: "53"
        protocol: "tcp"
        zone: "{{ item.0.zone }}"
        ttl: "{{ item.1.ttl }}"
        record: "{{ item.1.record }}"
        state: "{{ item.1.state }}"
        type: "{{ item.1.type }}"
        value: "{{ item.1.value }}"
      when: item.1.record != "@"
      with_subelements:
        - "{{ all_dns_records }}"
        - records
      notify: Sync zone files
      delegate_to: localhost

  post_tasks:
    - name: Check master config
      command: named-checkconf /var/named/chroot/etc/named.conf
      delegate_to: ns1.rubyninja.org
      changed_when: false

    - name: Check zone config
      command: "named-checkzone {{ item }} /var/named/chroot/etc/zones/db.{{ item }}"
      with_items:
        - "{{ all_dns_records | map(attribute='zone') | list }}"
      delegate_to: ns1.rubyninja.org
      changed_when: false

  handlers:
    - name: Sync zone files
      command: rndc -c /var/named/chroot/etc/rndc.conf sync -clean
      delegate_to: ns1.rubyninja.org

My DNS deployment a playbook breakdown:

  1. Grabs the Dynamic DNS update keys from HashiCorp Vault
  2. Syncs all of @ $ORIGIN records for all zones.
  3. Syncs all of the records.
  4. For good measure, but not necessary: Checks named.conf file.
  5. For good measure, but not necessary: Checks each individual zone file.
  6. Force dynamic changes to be applied to disk.

Given that in my environment I have roughly a couple of dozen DNS records, the structured for DNS records works in my environment. Thus said, my group_vars file with all my DNS records is almost 600 lines long. The playbook executing run takes around 1-2 minutes to complete. If I were to be in an environment where I had thousands of DNS records, the approached that I described here might not be the most efficient.

Tags: [ ansible bind ]
March 29, 2021

PHP 7.4 with Remi's RPM Repository

by Alpha01

Containerizing all my web applications has been on my things to do list for some years now. Until then, I shall continue to run some of my apps in a traditional VM shared environment.

Remi’s RPM Repository is the best RPM based repository if you want to easily run the latest upstream version of PHP. One of the benefits of using this repository in a shared environment is the ability to easily run multiple versions of PHP. My sites have been on PHP 7.2 until a few minutes ago. This was because PHP 7.2 is officially deprecated and no longer maintained, so being a good internet citizen I needed to upgrade to the latest PHP 7.4.

Upgrading to PHP 7.4 is extremely easy (assuming your app is not using and legacy functionality that was removed or changed). Since I had PHP 7.2 already running, I simply query for all php72 packages installed on my system, then install their php74 counterpart.

for package in $(rpm -qa --queryformat "%{NAME}\n"|grep php72 |sed 's/php72/php74/g'); do yum install -y $package; done

All of the different PHP configurations can be found under /etc/opt/remi. Once all the packages have been installed, I ported over all my custom PHP ini and fpm settings. In addition I had to change the FPM node pool’s default listening node port. For example /etc/opt/remi/php74/php-fpm.d/www.conf

listen = 127.0.0.1:9002

This is to avoid a port collision with the already running PHP-FPM pool that is being used by 7.2

Afterwards, I’m able to start my new PHP 7.4 FPM node pool.

systemctl enable php74-php-fpm
systemctl start php74-php-fpm

The last step, is simply updating my site’s Apache configuration to point to the new PHP 7.4 FPM node port.

<VirtualHost *:80>
    DocumentRoot /www/shit.alpha01.org

    ServerName shit.alpha01.org
    ServerAlias www.shit.alpha01.org

    SetEnvIf Remote_Addr "192.168.1.150" is_proxied=1

    ErrorLog /var/log/httpd/shit.alpha01.org/error.log
    CustomLog /var/log/httpd/shit.alpha01.org/access.log cloudflare env=is_proxied
    CustomLog /var/log/httpd/shit.alpha01.org/access-local.log combined

    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9002/www/shit.alpha01.org/$1
    ProxyTimeout 120
</VirtualHost>
Tags: [ php ]