aboutsummaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2025-11-11 22:49:13 -0600
committerChristian Cleberg <[email protected]>2025-11-11 22:49:13 -0600
commit51a7a02f0c96d49b68fbcc155414c218207fa270 (patch)
tree845af8aad0e8769352efc02fcd1044eed9cc1ec1 /content
parent7d3e80ebf1dc770eac0e21890b74f18ba2d15a6b (diff)
downloadcleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.tar.gz
cleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.tar.bz2
cleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.zip
fix grammar in 2022 posts
Diffstat (limited to 'content')
-rw-r--r--content/blog/2022-02-10-leaving-the-office.org282
-rw-r--r--content/blog/2022-02-10-njalla-dns-api.org96
-rw-r--r--content/blog/2022-02-16-debian-and-nginx.org121
-rw-r--r--content/blog/2022-02-17-exiftool.org38
-rw-r--r--content/blog/2022-02-20-nginx-caching.org68
-rw-r--r--content/blog/2022-02-22-tuesday.org47
-rw-r--r--content/blog/2022-03-02-reliable-notes.org185
-rw-r--r--content/blog/2022-03-03-financial-database.org159
-rw-r--r--content/blog/2022-03-08-plex-migration.org238
-rw-r--r--content/blog/2022-03-23-cloudflare-dns-api.org42
-rw-r--r--content/blog/2022-03-23-nextcloud-on-ubuntu.org61
-rw-r--r--content/blog/2022-03-24-server-hardening.org119
-rw-r--r--content/blog/2022-03-26-ssh-mfa.org69
-rw-r--r--content/blog/2022-04-02-nginx-reverse-proxy.org135
-rw-r--r--content/blog/2022-04-09-pinetime.org122
-rw-r--r--content/blog/2022-06-01-ditching-cloudflare.org105
-rw-r--r--content/blog/2022-06-07-self-hosting-freshrss.org152
-rw-r--r--content/blog/2022-06-16-terminal-lifestyle.org212
-rw-r--r--content/blog/2022-06-22-daily-poetry.org74
-rw-r--r--content/blog/2022-06-24-fedora-i3.org110
-rw-r--r--content/blog/2022-07-01-git-server.org295
-rw-r--r--content/blog/2022-07-14-gnupg.org238
-rw-r--r--content/blog/2022-07-25-curseradio.org52
-rw-r--r--content/blog/2022-07-30-flac-to-opus.org73
-rw-r--r--content/blog/2022-07-31-bash-it.org123
-rw-r--r--content/blog/2022-08-31-privacy-com-changes.org105
-rw-r--r--content/blog/2022-09-17-serenity-os.org76
-rw-r--r--content/blog/2022-09-21-graphene-os.org109
-rw-r--r--content/blog/2022-10-04-mtp-linux.org47
-rw-r--r--content/blog/2022-10-04-syncthing.org171
-rw-r--r--content/blog/2022-10-22-alpine-linux.org194
-rw-r--r--content/blog/2022-10-30-linux-display-manager.org45
-rw-r--r--content/blog/2022-11-07-self-hosting-matrix.org89
-rw-r--r--content/blog/2022-11-11-nginx-tmp-errors.org33
-rw-r--r--content/blog/2022-11-27-server-build.org127
-rw-r--r--content/blog/2022-11-29-nginx-referrer-ban-list.org47
-rw-r--r--content/blog/2022-12-01-nginx-compression.org67
-rw-r--r--content/blog/2022-12-07-nginx-wildcard-redirect.org60
-rw-r--r--content/blog/2022-12-17-st.org46
-rw-r--r--content/blog/2022-12-23-alpine-desktop.org88
40 files changed, 2099 insertions, 2421 deletions
diff --git a/content/blog/2022-02-10-leaving-the-office.org b/content/blog/2022-02-10-leaving-the-office.org
index 88a879c..720d04d 100644
--- a/content/blog/2022-02-10-leaving-the-office.org
+++ b/content/blog/2022-02-10-leaving-the-office.org
@@ -5,126 +5,114 @@
* The Working World is Changing
-There has been a trend for the past few years of companies slowly
-realizing that the pandemic is not just a temporary state that will go
-away eventually and let everything return to the way it was before. In
-terms of business and employment, this means that more and more jobs are
-being offered as permanently remote roles.
+There has been a trend for the past few years of companies slowly realizing that
+the pandemic is not just a temporary state that will go away eventually and let
+everything return to the way it was before. In terms of business and employment,
+this means that more and more jobs are being offered as permanently remote
+roles.
I had always dreamt of working from home but thought of it as a fantasy,
-especially since I did not want to move over into the software
-development field. However, I have found that almost all roles being
-sent to me via recruiters are permanently remote (although most are
-limited to US citizens or even region-locked for companies who only
-operate in select states).
+especially since I did not want to move over into the software development
+field. However, I have found that almost all roles being sent to me via
+recruiters are permanently remote (although most are limited to US citizens or
+even region-locked for companies who only operate in select states).
-I decided to take a look back at my relatively short career so far and
-compare the positive and negative effects of the different work
-environments I've been in.
+I decided to take a look back at my relatively short career so far and compare
+the positive and negative effects of the different work environments I've been
+in.
* In-Person Offices
** Retail Internship
-I started my first job as a management intern at a busy retail pharmacy,
-working my 40-hour weeks on my feet. As these retail stores don't
-believe in resting or sitting down, you can guarantee that you will
-spend entire shifts standing, walking, or running around the store.
-Unfortunately, I worked at a time when our store didn't have enough
-managers, so I spent the majority of my tenure at the store running and
-breaking a sweat.
-
-Now, things aren't all bad in retail stores like this. It is definitely
-tiring and inefficient to force employees to work constantly, or pretend
-to work if there's nothing to do, and not allow anyone to sit down.
-However, if you are able to operate a retail store with a limited crew
-and provide enough comfort and support, I believe these jobs could be
-both comfortable and efficient.
+I started my first job as a management intern at a busy retail pharmacy, working
+my 40-hour weeks on my feet. As these retail stores don't believe in resting or
+sitting down, you can guarantee that you will spend entire shifts standing,
+walking, or running around the store. Unfortunately, I worked at a time when our
+store didn't have enough managers, so I spent the majority of my tenure at the
+store running and breaking a sweat.
+
+Now, things aren't all bad in retail stores like this. It is definitely tiring
+and inefficient to force employees to work constantly, or pretend to work if
+there's nothing to do, and not allow anyone to sit down. However, if you are
+able to operate a retail store with a limited crew and provide enough comfort
+and support, I believe these jobs could be both comfortable and efficient.
** Semi-Private Cubicles
-After about a year, I was able to find another internship - this time,
-it was in my field of interest: internal auditing. This was for a life
-insurance company that was well over 100 years old. The age of the
-company shows if you work there, as most people in management are well
-into their 40s-60s with little to no youthful leadership in the company.
-Likewise, they owned a large headquarters in a nice area of town with
-plenty of space, parking, etc.
-
-One upside is that each person gets their own large L-shaped desk,
-formed into cubicles that house 4 desks/employees. These "pods" of
-4-person cubicles are linked throughout each floor of the headquarters
-(except the sales people, who had that open-floor concept going on). The
-walls of the cubicle were tall and provided a lot of privacy and
-sound-proofing, except when I used the standing desk feature (I'm over 6
-feet tall, so probably not an issue for most people).
+After about a year, I was able to find another internship - this time, it was in
+my field of interest: internal auditing. This was for a life insurance company
+that was well over 100 years old. The age of the company shows if you work
+there, as most people in management are well into their 40s-60s with little to
+no youthful leadership in the company. Likewise, they owned a large headquarters
+in a nice area of town with plenty of space, parking, etc.
+
+One upside is that each person gets their own large L-shaped desk, formed into
+cubicles that house 4 desks/employees. These "pods" of 4-person cubicles are
+linked throughout each floor of the headquarters (except the sales people, who
+had that open-floor concept going on). The walls of the cubicle were tall and
+provided a lot of privacy and sound-proofing, except when I used the standing
+desk feature (I'm over 6 feet tall, so probably not an issue for most people).
I loved this environment, it allowed me to focus on my work with minimal
-distractions, but also allowed easy access, so I could spin around in my
-chair and chat with my friends without leaving my chair. This is the
-closest I've been to a home office environment (which is my personal
-favorite, as I'll get to later in this post).
+distractions, but also allowed easy access, so I could spin around in my chair
+and chat with my friends without leaving my chair. This is the closest I've been
+to a home office environment (which is my personal favorite, as I'll get to
+later in this post).
** Semi-Open Floor Concept
-When I shifted to my first full-time internal audit job out of college,
-I was working at a company that was headquartered on a floor in a
-downtown high-rise building. The company was only about 20 years old
-when I worked there and were trying a lot of new things to attract young
-talent, one of which was a semi-open floor concept for the office. My
-department worked just around the hallway corner from the executive
-offices and used that "modern" layout young tech companies started using
-in the 2000s/2010s.
-
-Each desk was brief, and you could look most coworkers in the face
-without moving from your chair, I hated this so much. Directly to my
-left was the Chief Audit Executive (our department's leading boss), and
-his desk was pointed so that his face would stare straight at my desk
-all day. I spent more time thinking about who was looking at me or
-checking on me than actually working.
-
-The other annoying part of the open concept they used was that the
-kitchen area and pathways were too close to everyone's desks (since the
-desks were spread out, to provide space or something), so noise and
-conversation would be constant throughout the day while you try to work.
-For someone like me, who needs silence to get work done, that was a
-non-starter.
+When I shifted to my first full-time internal audit job out of college, I was
+working at a company that was headquartered on a floor in a downtown high-rise
+building. The company was only about 20 years old when I worked there and were
+trying a lot of new things to attract young talent, one of which was a semi-open
+floor concept for the office. My department worked just around the hallway
+corner from the executive offices and used that "modern" layout young tech
+companies started using in the 2000s/2010s.
+
+Each desk was brief, and you could look most coworkers in the face without
+moving from your chair, I hated this so much. Directly to my left was the Chief
+Audit Executive (our department's leading boss), and his desk was pointed so
+that his face would stare straight at my desk all day. I spent more time
+thinking about who was looking at me or checking on me than actually working.
+
+The other annoying part of the open concept they used was that the kitchen area
+and pathways were too close to everyone's desks (since the desks were spread
+out, to provide space or something), so noise and conversation would be constant
+throughout the day while you try to work. For someone like me, who needs silence
+to get work done, that was a non-starter.
** Hotel Office Concept
-I currently work for a company remotely (for now) and travel to the
-office every once in a while for events and to help coach the staff
-underneath me. The office I visit uses the hotel desk concept, where you
-need to check in at a touch screen when you enter the office and "rent"
-a desk for the day. The same goes for offices and meeting rooms.
+I currently work for a company remotely (for now) and travel to the office every
+once in a while for events and to help coach the staff underneath me. The office
+I visit uses the hotel desk concept, where you need to check in at a touch
+screen when you enter the office and "rent" a desk for the day. The same goes
+for offices and meeting rooms.
-These desks are flat-top only and do not have any walls at all. In
-addition, they're stacked with one row of 4 desks facing another row of
-4 desks. These pairs of desk rows are repeated through the office.
+These desks are flat-top only and do not have any walls at all. In addition,
+they're stacked with one row of 4 desks facing another row of 4 desks. These
+pairs of desk rows are repeated through the office.
-This means that when I go, I need to rent a random desk or try to
-remember the unique ID numbers on desks I like. Once I rent it, I have
-to make sure no one sat down in that desk without renting it. Then, I
-can sit down and work, but will probably need to adjust the monitors so
-that I'm not staring in the face of the person across from me all day.
-Finally, I need to wear headphones as this environment does nothing to
-provide you with peace or quiet.
+This means that when I go, I need to rent a random desk or try to remember the
+unique identification (ID) numbers on desks I like. Once I rent it, I have to
+make sure no one sat down in that desk without renting it. Then, I can sit down
+and work, but will probably need to adjust the monitors so that I'm not staring
+in the face of the person across from me all day. Finally, I need to wear
+headphones as this environment does nothing to provide you with peace or quiet.
-Luckily, you can rent offices with doors that offer quiet and privacy,
-which can be very nice if you have a lot of meetings or webinars on a
-certain day.
+Luckily, you can rent offices with doors that offer quiet and privacy, which can
+be very nice if you have a lot of meetings or webinars on a certain day.
* Home Office
-Okay, now let's finally get to the home office concept. I have worked
-from home for a little over two years at this point, across three
-different jobs/employers. Over this time, I have experimented with a
-plethora of different organizational ideas, desks, and room layouts to
-find what works best for me.
+Okay, now let's finally get to the home office concept. I have worked from home
+for a little over two years at this point, across three different
+jobs/employers. Over this time, I have experimented with a plethora of different
+organizational ideas, desks, and room layouts to find what works best for me.
-These things might not apply to you, and that's fine. Everyone has a
-different situation, and I really don't think you'll know what works
-until you try.
+These things might not apply to you, and that's fine. Everyone has a different
+situation, and I really don't think you'll know what works until you try.
** Tip #1
@@ -134,16 +122,15 @@ Let's start with my top rule for a home office:
If you live with others, working in a shared space is not effective.
#+end_quote
-It just does not work. If you have another person sleeping in your
-bedroom, it is difficult to manage your work schedule with their
-sleeping/work/school schedule. If they wake up after you need to start
-work, you might wake them up or have to suffer the agony of staring at
-bright screens in a dark room.
+It just does not work. If you have another person sleeping in your bedroom, it
+is difficult to manage your work schedule with their sleeping/work/school
+schedule. If they wake up after you need to start work, you might wake them up
+or have to suffer the agony of staring at bright screens in a dark room.
-In a similar vein, working from a location such as the living room
-likely won't work either. Distractions will come far more frequently:
-televisions, cooking, cleaning, deliveries, etc. If you're like me,
-you'll end up playing a game instead of actually doing any work.
+In a similar vein, working from a location such as the living room likely won't
+work either. Distractions will come far more frequently: televisions, cooking,
+cleaning, deliveries, etc. If you're like me, you'll end up playing a game
+instead of actually doing any work.
** Tip #2
@@ -154,39 +141,38 @@ Use the pomodoro method (or something similar) to balance work tasks
with personal tasks.
#+end_quote
-I use a very casual version of the pomodoro method where I will work for
-1-2 hours (usually set in strict intervals like 1, 1.5, 2 hours) and
-then will allow myself 30-60 minutes for personal tasks. This schedule
-works for me, since my work schedule really only comes to 3-6 hours of
-work per day.
+I use a very casual version of the pomodoro method where I will work for 1-2
+hours (usually set in strict intervals like 1, 1.5, 2 hours) and then will allow
+myself 30-60 minutes for personal tasks. This schedule works for me, since my
+work schedule really only comes to 3-6 hours of work per day.
-In this case, I'll work through my list of tasks for an hour or two and
-then give myself personal time to get drinks and food, wash dishes, put
-clothes in the washer, get the mail, etc. If you're in a convenient
-location, this usually gives time for things like getting groceries (as
-long as you're not a slow shopper).
+In this case, I'll work through my list of tasks for an hour or two and then
+give myself personal time to get drinks and food, wash dishes, put clothes in
+the washer, get the mail, etc. If you're in a convenient location, this usually
+gives time for things like getting groceries (as long as you're not a slow
+shopper).
** Tip #3
-While I listed this one as number three, I don't think I'd accomplish
-anything without it:
+While I listed this one as number three, I don't think I'd accomplish anything
+without it:
#+begin_quote
Document everything: even things you didn't before - such as task lists
and notes from casual calls or meetings.
#+end_quote
-I've noticed that staying in an office gave me more constant reminders
-of outstanding tasks or facts I had learned in a conversation.
-Translating everything to a digital world has made me lose a bit of that
-focus (perhaps since I don't have visual reminders?).
+I've noticed that staying in an office gave me more constant reminders of
+outstanding tasks or facts I had learned in a conversation. Translating
+everything to a digital world has made me lose a bit of that focus (perhaps
+since I don't have visual reminders?).
-Keeping a running task list of all things I have to do - even potential
-tasks! - has helped me keep up without missing anything small. Likewise,
-keeping notes for ALL meetings and calls, no matter how casual/quick,
-has improved my retention immensely. Beyond helping my mental
-recollection, it has saved me numerous times when I need to do a keyword
-search for some topic that was discussed 6+ months ago.
+Keeping a running task list of all things I have to do - even potential tasks! -
+has helped me keep up without missing anything small. Likewise, keeping notes
+for ALL meetings and calls, no matter how casual/quick, has improved my
+retention immensely. Beyond helping my mental recollection, it has saved me
+numerous times when I need to do a keyword search for some topic that was
+discussed 6+ months ago.
** Tip #4
@@ -196,36 +182,32 @@ Okay, last one for now.
Keep your work area clean.
#+end_quote
-This one is straightforward, but I know some people struggle with
-cleanliness or may not believe it makes a difference. Trust me, keeping
-your desk area clean and organized makes a huge difference, both
-mentally and emotionally.
+This one is straightforward, but I know some people struggle with cleanliness or
+may not believe it makes a difference. Trust me, keeping your desk area clean
+and organized makes a huge difference, both mentally and emotionally.
-Just think about it, you walk into your home office and see a clean desk
-with a laptop, dock, monitors, keyboard, mouse, and a notepad with a pen
-on top.
+Just think about it, you walk into your home office and see a clean desk with a
+laptop, dock, monitors, keyboard, mouse, and a notepad with a pen on top.
-Now imagine the opposite, there's an office with the same equipment, but
-there are clothes hanging on the chair, empty drink bottles, candy
-wrappers and dirty plates. This can take both a mental and emotional
-toll by bringing constant disarray and stress into your working
-environment.
+Now imagine the opposite, there's an office with the same equipment, but there
+are clothes hanging on the chair, empty drink bottles, candy wrappers and dirty
+plates. This can take both a mental and emotional toll by bringing constant
+disarray and stress into your working environment.
-Just keep things clean each day, and you won't need to do any big
-cleaning days to recover.
+Just keep things clean each day, and you won't need to do any big cleaning days
+to recover.
* My Preferences
-I've talked about the different environments I've worked in and
-expressed some honest thoughts on pros or cons to each, but what do I
-prefer? Well, if you're reading along, you should be able to tell that I
-much prefer a home office above all else.
+I've talked about the different environments I've worked in and expressed some
+honest thoughts on pros or cons to each, but what do I prefer? Well, if you're
+reading along, you should be able to tell that I much prefer a home office above
+all else.
-Being able to control my own day and allot my time as needed has brought
-a calmness to my life and has allowed me to maximize each day. I feel
-far more effective and efficient in a home office than any other office,
-especially open-office layouts.
+Being able to control my own day and allot my time as needed has brought a
+calmness to my life and has allowed me to maximize each day. I feel far more
+effective and efficient in a home office than any other office, especially
+open-office layouts.
-If I do need to return to an office part-time in the future, I really
-hope the office will have privacy and quietness in order for me to get
-my work done.
+If I do need to return to an office part-time in the future, I really hope the
+office will have privacy and quietness in order for me to get my work done.
diff --git a/content/blog/2022-02-10-njalla-dns-api.org b/content/blog/2022-02-10-njalla-dns-api.org
index 7511368..ab233c9 100644
--- a/content/blog/2022-02-10-njalla-dns-api.org
+++ b/content/blog/2022-02-10-njalla-dns-api.org
@@ -5,47 +5,43 @@
* Njalla's API
-As noted in my recent post about
-[[https://cleberg.net/blog/ditching-cloudflare/][switching to Njalla from
-Cloudflare]], I was searching for a way to replace my very easy-to-use
-bash script to [[https://cleberg.net/blog/cloudflare-dns-api/][update Cloudflare's
-DNS via their API]].
+As noted in my recent post about [[https://cleberg.net/blog/ditching-cloudflare/][switching to Njalla from Cloudflare]], I was
+searching for a way to replace my [[https://cleberg.net/blog/cloudflare-dns-api.html][bash script]] to update my domain's =A= record
+with my home's internet protocol (IP) address dynamically.
-To reiterate what I said in those posts, this is a common necessity for
-those of us who have non-static IP addresses that can change at any
-moment due to ISP policy.
+To reiterate what I said in those posts, this is a common necessity for those of
+us who have non-static IP addresses that can change at any moment due to
+internet service provider (ISP) policy.
-In order to keep a home server running smoothly, the server admin needs
-to have a process to constantly monitor their public IP address and
-update their domain's DNS records if it changes.
+In order to keep a home server running smoothly, the server admin needs to have
+a process to constantly monitor their public IP address and update their
+domain's DNS records if it changes.
-This post explains how to use Python to update Njalla's DNS records
-whenever a machine's public IP address changes.
+This post explains how to use Python to update Njalla's DNS (domain name system)
+records whenever a machine's public IP address changes.
** Creating a Token
-To use Njalla's API, you will first need to create a token that will be
-used to authenticate you every time you call the API. Luckily, this is
-very easy to do if you have an account with Njalla.
+To use Njalla's API, you will first need to create a token that will be used to
+authenticate you every time you call the API (application programming
+interface). Luckily, this is very easy to do if you have an account with Njalla.
-Simply go the [[https://njal.la/settings/api/][API Settings]] page and
-click the =Add Token= button. Next, enter a name for the token and click
-=Add=.
+Simply go the [[https://njal.la/settings/api/][API Settings]] page and click the =Add Token= button. Next, enter a
+name for the token and click =Add=.
-Finally, click the =Manage= button next to your newly created token and
-copy the =API Token= field.
+Finally, click the =Manage= button next to your newly created token and copy the
+=API Token= field.
** Finding the Correct API Request
-Once you have a token, you're ready to call the Njalla API for any
-number of requests. For a full listing of available requests, see the
-[[https://njal.la/api/][Njalla API Documentation]].
+Once you have a token, you're ready to call the Njalla API for any number of
+requests. For a full listing of available requests, see the [[https://njal.la/api/][Njalla API
+Documentation]].
-For this demo, we are using the =list-records= and =edit-record=
-requests.
+For this demo, we are using the =list-records= and =edit-record= requests.
-The =list-records= request requires the following payload to be sent
-when calling the API:
+The =list-records= request requires the following payload to be sent when
+calling the API:
#+begin_src txt
params: {
@@ -53,8 +49,8 @@ params: {
}
#+end_src
-The =edit-record= request requires the following payload to be sent when
-calling the API:
+The =edit-record= request requires the following payload to be sent when calling
+the API:
#+begin_src txt
params: {
@@ -66,14 +62,14 @@ params: {
* Server Set-Up
-To create this script, we will be using Python. By default, I use Python
-3 on my servers, so please note that I did not test this in Python 2,
-and I do not know if Python 2 will work for this.
+To create this script, we will be using Python. By default, I use Python 3 on my
+servers, so please note that I did not test this in Python 2, and I do not know
+if Python 2 will work for this.
** Creating the Script
-First, find a suitable place to create your script. Personally, I just
-create a directory called =ddns= in my home directory:
+First, find a suitable place to create your script. Personally, I just create a
+directory called =ddns= in my home directory:
#+begin_src sh
mkdir ~/ddns
@@ -85,20 +81,18 @@ Next, create a Python script file:
nano ~/ddns/ddns.py
#+end_src
-The following code snippet is quite long, so I won't go into depth on
-each part. However, I suggest you read through the entire script before
-running it; it is quite simple and contains comments to help explain
-each code block.
+The following code snippet is quite long, so I won't go into depth on each part.
+However, I suggest you read through the entire script before running it; it is
+quite simple and contains comments to help explain each code block.
-:warning: *Note*: You will need to update the following variables for
-this to work:
+*Note*: You will need to update the following variables for this to work:
- =token=: This is the Njalla API token you created earlier.
- =user_domain=: This is the top-level domain you want to modify.
-- =include_subdomains=: Set this to =True= if you also want to modify
- subdomains found under the TLD.
-- =subdomains=: If =include_subdomains= = =True=, you can include your
- list of subdomains to be modified here.
+- =include_subdomains=: Set this to =True= if you also want to modify subdomains
+ found under the TLD (top-level domain).
+- =subdomains=: If =include_subdomains= = =True=, you can include your list of
+ subdomains to be modified here.
#+begin_src python
#!/usr/bin/python
@@ -183,8 +177,8 @@ for record in data['records']:
** Running the Script
-Once you've created the script and are ready to test it, run the
-following command:
+Once you've created the script and are ready to test it, run the following
+command:
#+begin_src sh
python3 ~/ddns/ddns.py
@@ -192,15 +186,15 @@ python3 ~/ddns/ddns.py
** Setting the Script to Run Automatically
-To make sure the scripts run automatically, add it to the =cron= file so
-that it will run on a schedule. To do this, open the =cron= file:
+To make sure the scripts run automatically, add it to the =cron= file so that it
+will run on a schedule. To do this, open the =cron= file:
#+begin_src sh
crontab -e
#+end_src
-In the cron file, paste the following at the bottom of the editor in
-order to check the IP every five minutes:
+In the cron file, paste the following at the bottom of the editor in order to
+check the IP every five minutes:
#+begin_src sh
*/5 * * * * python3 /home/<your_username>/ddns/ddns.py
diff --git a/content/blog/2022-02-16-debian-and-nginx.org b/content/blog/2022-02-16-debian-and-nginx.org
index 575ede5..bec0712 100644
--- a/content/blog/2022-02-16-debian-and-nginx.org
+++ b/content/blog/2022-02-16-debian-and-nginx.org
@@ -3,34 +3,31 @@
#+description: Step-by-step protocol for transitioning web server infrastructure to Debian operating system, including installation, configuration, and security hardening of Nginx and Agate services.
#+slug: debian-and-nginx
-* Server OS: Debian
+* Server Operating System (OS): Debian
-I've used various Linux distributions throughout the years, but I've
-never used anything except Ubuntu for my servers. Why? I really have no
-idea, mostly just comfort around the commands and software availability.
+I've used various Linux distributions throughout the years, but I've never used
+anything except Ubuntu for my servers. Why? I really have no idea, mostly just
+comfort around the commands and software availability.
-However, I have always wanted to try Debian as a server OS after testing
-it out in a VM a few years ago (side-note: I'd love to try Alpine too,
-but I always struggle with compatibility). So, I decided to launch a new
-VPS and use [[https://www.debian.org][Debian]] 11 as the OS. Spoiler
-alert: it feels identical to Ubuntu for my purposes.
+However, I have always wanted to try Debian as a server OS after testing it out
+in a VM a few years ago (side-note: I'd love to try Alpine too, but I always
+struggle with compatibility). So, I decided to launch a new VPS and use [[https://www.debian.org][Debian]]
+11 as the operating system (OS). Spoiler alert: it feels identical to Ubuntu for my purposes.
-I did the normal things when first launching the VPS, such as adding a
-new user, locking down SSH, etc. If you want to see that level of
-detail, read my other post about
-[[https://cleberg.net/blog/how-to-set-up-a-vps-web-server/][How to Set
-Up a VPS Web Server]].
+I did the normal things when first launching the VPS (virtual private server),
+such as adding a new user, locking down SSH (secure shell protocol), etc. If you
+want to see that level of detail, read my other post about [[https://cleberg.net/blog/how-to-set-up-a-vps-web-server/][How to Set Up a VPS
+Web Server]].
-All of this has been similar, apart from small things such as the
-location of users' home folders. No complaints at all from me - Debian
-seems great.
+All of this has been similar, apart from small things such as the location of
+users' home folders. No complaints at all from me - Debian seems great.
* Web Server: Nginx
-Once I had the baseline server configuration set-up for Debian, I moved
-on to trying out [[https://nginx.org][Nginx]] as my web server software.
-This required me to install the =nginx= and =ufw= packages, as well as
-setting up the initial UFW config:
+Once I had the baseline server configuration set-up for Debian, I moved on to
+trying out [[https://nginx.org][Nginx]] as my web server software. This required me to install the
+=nginx= and =ufw= packages, as well as setting up the initial UFW (Uncomplicated
+Firewall) config:
#+begin_src sh
sudo apt install nginx ufw
@@ -41,9 +38,9 @@ sudo ufw status
sudo systemctl status nginx
#+end_src
-Once I had the firewall set, I moved on to creating the directories and
-files for my website. This is very easy and is basically the same as
-setting up an Apache server, so no struggles here.
+Once I had the firewall set, I moved on to creating the directories and files
+for my website. This is very easy and is basically the same as setting up an
+Apache server, so no struggles here.
#+begin_src sh
sudo mkdir -p /var/www/your_domain/html
@@ -52,17 +49,17 @@ sudo chmod -R 755 /var/www/your_domain
nano /var/www/your_domain/html/index.html
#+end_src
-The next part, creating the Nginx configuration files, is quite a bit
-different from Apache. First, you need to create the files in the
-=sites-available= folder and symlink it the =sites-enabled= folder.
+The next part, creating the Nginx configuration files, is quite a bit different
+from Apache. First, you need to create the files in the =sites-available= folder
+and symlink it the =sites-enabled= folder.
-Creating the config file for your domain:
+Creating the configuration file for your domain:
#+begin_src sh
sudo nano /etc/nginx/sites-available/your_domain
#+end_src
-Default content for an Nginx config file:
+Default content for an Nginx configuration file:
#+begin_src sh
server {
@@ -87,9 +84,9 @@ sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
#+end_src
This will make your site available to the public (as long as you have
-=your_domain= DNS records pointed at the server's IP address)!
+=your_domain= DNS (Domain Name System) records pointed at the server's IP address)!
-Next, I used [[https://certbot.eff.org/][certbot]] to issue an HTTPS
+Next, I used [[https://certbot.eff.org/][certbot]] to issue an HTTPS (Hypertext Transfer Protocol Secure)
certificate for my domains using the following commands:
#+begin_src sh
@@ -99,16 +96,15 @@ sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
#+end_src
-Now that certbot ran successfully and updated my Nginx config files to
+Now that =certbot= ran successfully and updated my Nginx configuration files to
include a =443= server block of code, I went back in and edited the
-config file to include security HTTP headers. This part is optional, but
-is recommended for security purposes; you can even test a website's HTTP
-header security at [[https://securityheaders.com/][Security Headers]].
+configuration file to include security HTTP headers. This part is optional, but
+is recommended for security purposes; you can even test a website's HTTP header
+security at [[https://securityheaders.com/][Security Headers]].
-The configuration below shows a set-up where you only want your website
-to serve content from its own domain, except for images and scripts,
-which may come from =nullitics.com=. All other content would be blocked
-from loading in a browser.
+The configuration below shows a set-up where you only want your website to serve
+content from its own domain, except for images and scripts, which may come from
+=nullitics.com=. All other content would be blocked from loading in a browser.
#+begin_src sh
sudo nano /etc/nginx/sites-available/your_domain
@@ -133,35 +129,32 @@ sudo systemctl restart nginx
** Nginx vs. Apache
-As I stated at the beginning, my historical hesitation with trying Nginx
-was that the differences in configuration formats scared me away from
-leaving Apache. However, I prefer Nginx to Apache for a few reasons:
+As I stated at the beginning, my historical hesitation with trying Nginx was
+that the differences in configuration formats scared me away from leaving
+Apache. However, I prefer Nginx to Apache for a few reasons:
-1. Nginx uses only one config file (=your_domain=) vs. Apache's two-file
+1. Nginx uses only one configuration file (=your_domain=) vs. Apache's two-file
approach for HTTP vs. HTTPS (=your_domain.conf= and
=your_domain-le-ssl.conf=).
-2. Symlinking new configurations files and reloading Nginx are way
- easier than Apache's process of having to enable headers with
- =a2enmod mod_headers=, enable PHP with =a2enmod php= (plus any other
- mods you need), and then enabling sites with =a2ensite=, and THEN
- reloading Apache.
-3. The contents of the Nginx config files seem more organized and
- logical with the curly-bracket approach. This is a minor reason, but
- everything just felt cleaner while I was installing my sites and that
- had a big quality of life impact on the installation for me.
-
-They're both great software packages, but Nginx just seems more
-organized and easier to use these days. I will certainly be exploring
-the Nginx docs to see what other fun things I can do with all of this.
+2. Symlinking new configurations files and reloading Nginx are way easier than
+ Apache's process of having to enable headers with =a2enmod mod_headers=,
+ enable PHP with =a2enmod php= (plus any other mods you need), and then
+ enabling sites with =a2ensite=, and THEN reloading Apache.
+3. The contents of the Nginx configuration files seem more organized and logical
+ with the curly-bracket approach. This is a minor reason, but everything just
+ felt cleaner while I was installing my sites and that had a big quality of
+ life impact on the installation for me.
+
+They're both great software packages, but Nginx just seems more organized and
+easier to use these days. I will certainly be exploring the Nginx docs to see
+what other fun things I can do with all of this.
* Gemini Server: Agate
-Finally, I set up the Agate software on this server again to host my
-Gemini server content, using Rust as I have before. You can read my
-other post for more information on installing Agate:
-[[https://cleberg.net/blog/hosting-a-gemini-server/][Hosting a Gemini
-Server]].
+Finally, I set up the Agate software on this server again to host my Gemini
+server content, using Rust as I have before. You can read my other post for more
+information on installing Agate: [[https://cleberg.net/blog/hosting-a-gemini-server/][Hosting a Gemini Server]].
-All in all, Debian + Nginx is very slick and I prefer it over my old
-combination of Ubuntu + Apache (although it's really just Nginx > Apache
-for me, since Debian seems mostly the same as Ubuntu is so far).
+All in all, Debian + Nginx is very slick and I prefer it over my old combination
+of Ubuntu + Apache (although it's really just Nginx > Apache for me, since
+Debian seems mostly the same as Ubuntu is so far).
diff --git a/content/blog/2022-02-17-exiftool.org b/content/blog/2022-02-17-exiftool.org
index 8383ddd..45308ef 100644
--- a/content/blog/2022-02-17-exiftool.org
+++ b/content/blog/2022-02-17-exiftool.org
@@ -5,14 +5,14 @@
** Why Strip Metadata?
-Okay, so you want to strip metadata from your photos. Perhaps you take
-pictures of very rare birds, and the location metadata is a gold mine
-for poachers, or perhaps you're just privacy-oriented like me and prefer
-to strip metadata from publicly-available images.
+Okay, so you want to strip metadata from your photos. Perhaps you take pictures
+of very rare birds, and the location metadata is a gold mine for poachers, or
+perhaps you're just privacy-oriented like me and prefer to strip metadata from
+publicly-available images.
-There are various components of image metadata that you may want to
-delete before releasing a photo to the public. Here's an incomplete list
-of things I could easily see just by inspecting a photo on my laptop:
+There are various components of image metadata that you may want to delete
+before releasing a photo to the public. Here's an incomplete list of things I
+could easily see just by inspecting a photo on my laptop:
- Location (Latitude & Longitude)
- Dimensions
@@ -25,15 +25,14 @@ of things I could easily see just by inspecting a photo on my laptop:
- Metering Mode
- F Number
-Regardless of your reasoning, I'm going to explain how I used the
-=exiftool= package in Linux to automatically strip metadata from all
-images in a directory (+ subdirectories).
+Regardless of your reasoning, I'm going to explain how I used the =exiftool=
+package in Linux to automatically strip metadata from all images in a directory
+(+ subdirectories).
** Installing =exiftool=
-First things first: we need to install the tool. I'm running Debian 11
-on my server (Ubuntu will work the same), so the command is as simple
-as:
+First things first: we need to install the tool. I'm running Debian 11 on my
+server (Ubuntu will work the same), so the command is as simple as:
#+begin_src sh
sudo apt install exiftool
@@ -44,16 +43,15 @@ distributions, but I really only care to test out this one package.
** Recursively Strip Data
-I actually use this tool extensively to strip any photos uploaded to the
-website that serves all the images for my blog (=img.cleberg.net=).
+I actually use this tool extensively to strip any photos uploaded to the website
+that serves all the images for my blog (=img.cleberg.net=).
-The following command is incredibly useful and can be modified to
-include any image extensions that =exiftool= supports:
+The following command is incredibly useful and can be modified to include any
+image extensions that =exiftool= supports:
#+begin_src sh
exiftool -r -all= -ext jpg -ext png /path/to/directory/
#+end_src
-The output of the command will let you know how many directories were
-scanned, how many images were updated, and how many images were
-unchanged.
+The output of the command will let you know how many directories were scanned,
+how many images were updated, and how many images were unchanged.
diff --git a/content/blog/2022-02-20-nginx-caching.org b/content/blog/2022-02-20-nginx-caching.org
index a075951..d74aed9 100644
--- a/content/blog/2022-02-20-nginx-caching.org
+++ b/content/blog/2022-02-20-nginx-caching.org
@@ -5,16 +5,15 @@
* Update Your Nginx Config to Cache Static Files
-If you run a website on Nginx that serves static content (i.e., content
-that is not dynamic and changing with interactions from the user), you
-would likely benefit from caching that content on the client-side. If
-you're used to Apache and looking for the Nginx equivalent, this post
-should help.
+If you run a website on Nginx that serves static content (i.e., content that is
+not dynamic and changing with interactions from the user), you would likely
+benefit from caching that content on the client-side. If you're used to Apache
+and looking for the Nginx equivalent, this post should help.
-Luckily, setting up the cache is as easy as identifying the file types
-you want to cache and determining the expiration length. To include more
-file types, simply use the bar separator (=|=) and type the new file
-extension you want to include.
+Luckily, setting up the cache is as easy as identifying the file types you want
+to cache and determining the expiration length. To include more file types,
+simply use the bar separator (=|=) and type the new file extension you want to
+include.
#+begin_src config
server {
@@ -28,41 +27,36 @@ server {
}
#+end_src
-I have seen some people who prefer to set =expires= as =365d= or even
-=max=, but that is only for stable, infrequently changing websites. As
-my site often changes (i.e., I'm never content with my website), I need
-to know that my readers are seeing the new content without waiting too
-long.
+I have seen some people who prefer to set =expires= as =365d= or even =max=, but
+that is only for stable, infrequently changing websites. As my site often
+changes (i.e., I'm never content with my website), I need to know that my
+readers are seeing the new content without waiting too long.
-So, I went ahead and set the expiration date at =30d=, which is short
-enough to refresh for readers but long enough that clients/browsers
-won't be re-requesting the static files too often, hopefully resulting
-in faster loading times, as images should be the only thing slowing down
-my site.
+So, I went ahead and set the expiration date at =30d=, which is short enough to
+refresh for readers but long enough that clients/browsers won't be re-requesting
+the static files too often, hopefully resulting in faster loading times, as
+images should be the only thing slowing down my site.
* Testing Results
-To test my changes to the Nginx configuration, I used the
-[[https://addons.mozilla.org/en-US/firefox/addon/http-header-live/][HTTP
-Header Live]] extension on my Gecko browser and used the sidebar to
-inspect the headers of a recent image from my blog.
+To test my changes to the Nginx configuration, I used the [[https://addons.mozilla.org/en-US/firefox/addon/http-header-live/][HTTP Header Live]]
+extension on my Gecko browser and used the sidebar to inspect the headers of a
+recent image from my blog.
-In the image below, you can see that the =Cache-Control= header is now
-present and set to 2592000, which is 30 days represented in seconds (30
-days _ 24 hours/day _ 60 minutes/hour ** 60 seconds/minute = 2,592,000
-seconds).
+In the image below, you can see that the =Cache-Control= header is now present
+and set to 2592000, which is 30 days represented in seconds (30 days _ 24
+hours/day _ 60 minutes/hour ** 60 seconds/minute = 2,592,000 seconds).
-The =Expires= field is now showing 22 March 2022, which is 30 days from
-the day of this post, 20 February 2022.
+The =Expires= field is now showing 22 March 2022, which is 30 days from the day
+of this post, 20 February 2022.
* Caveats
-Remember that this caching system is *client-side*, which means that
-content is only cached for as long as a client allows it. For example,
-my browser purges all caches, data, etc. upon exit, so this caching
-policy will only work as long as my browser remains open and running.
+Remember that this caching system is *client-side*, which means that content is
+only cached for as long as a client allows it. For example, my browser purges
+all caches, data, etc. upon exit, so this caching policy will only work as long
+as my browser remains open and running.
-If you need to test updates to your site, you'll need to clear the cache
-to see updates for any file extension you configured. This can often be
-done with the =Shift + F5= or =Ctrl + F5= key combinations in most
-browsers.
+If you need to test updates to your site, you'll need to clear the cache to see
+updates for any file extension you configured. This can often be done with the
+=Shift + F5= or =Ctrl + F5= key combinations in most browsers.
diff --git a/content/blog/2022-02-22-tuesday.org b/content/blog/2022-02-22-tuesday.org
index 2b27054..9c1fc52 100644
--- a/content/blog/2022-02-22-tuesday.org
+++ b/content/blog/2022-02-22-tuesday.org
@@ -5,34 +5,27 @@
* Tuesday, Twosday
-I'm taking a break from my usual technology-related posts and writing
-about something a little more enjoyable today.
+I'm taking a break from my usual technology-related posts and writing about
+something a little more enjoyable today.
-Today is Tuesday, February 22nd, 2022. Today is 02-22-2022. Today is
-Twosday.
+Today is Tuesday, February 22nd, 2022. Today is 02-22-2022. Today is Twosday.
Let's look at everything that fell in place today:
-1. Written in the =m-dd-yy= or =dd-m-yy= formats, today is 2-22-22 or
- 22-2-22, which is a neat little palindrome in either format. (The
- last ubiquitous six-digit palindrome was 1-11-11.)
-2. Today is Tuesday, which is why everyone is using the nickname Twosday
- to call out these similarities.
-3. Falling on Tuesday means today is the 2nd day of the week (for most
- cultures. For the US, it's the 3rd day of the week since we start on
- Sunday).
-4. The only culture I could find with a connection to a =2= is that some
- Slavic languages derived their version of Tuesday from the Old Church
- Slavonic word =въторъ=, meaning "the second."
-5. Written in the classic monospaced, digital font (think of digital
- clocks from the 80s/90s), there is nice symmetry to the numbers
- ([[https://img.cleberg.net/blog/20220222-tuesday/digital_font.webp][view
- the image here]]!).
-6. This one isn't naturally-occurring, but it seems people around the
- world are celebrating the day. For example, a group is putting
- together
- [[https://www.eventbrite.com/e/2-22-22-a-collective-wedding-ceremony-at-the-state-capitol-tickets-211434605597][a
- wedding of 222 couples at the California State Capitol in
- Sacramento]], concluding at exactly 2:22 PM. These couples will
- record their marriage dates as 2-22-22 2:22 PM. Tickets were on sale
- for $222.22.
+1. Written in the =m-dd-yy= or =dd-m-yy= formats, today is 2-22-22 or 22-2-22,
+ which is a neat little palindrome in either format. (The last ubiquitous
+ six-digit palindrome was 1-11-11.)
+2. Today is Tuesday, which is why everyone is using the nickname Twosday to call
+ out these similarities.
+3. Falling on Tuesday means today is the 2nd day of the week (for most cultures.
+ For the US, it's the 3rd day of the week since we start on Sunday).
+4. The only culture I could find with a connection to a =2= is that some Slavic
+ languages derived their version of Tuesday from the Old Church Slavonic word
+ =въторъ=, meaning "the second."
+5. Written in the classic monospaced, digital font (think of digital clocks from
+ the 80s/90s), there is nice symmetry to the numbers ([[https://img.cleberg.net/blog/20220222-tuesday/digital_font.webp][view the image here]]!).
+6. This one isn't naturally-occurring, but it seems people around the world are
+ celebrating the day. For example, a group is putting together [[https://www.eventbrite.com/e/2-22-22-a-collective-wedding-ceremony-at-the-state-capitol-tickets-211434605597][a wedding of
+ 222 couples at the California State Capitol in Sacramento]], concluding at
+ exactly 2:22 PM. These couples will record their marriage dates as 2-22-22
+ 2:22 PM. Tickets were on sale for $222.22.
diff --git a/content/blog/2022-03-02-reliable-notes.org b/content/blog/2022-03-02-reliable-notes.org
index 42628a9..47c09e3 100644
--- a/content/blog/2022-03-02-reliable-notes.org
+++ b/content/blog/2022-03-02-reliable-notes.org
@@ -4,154 +4,129 @@
#+slug: reliable-notes
* Choosing Durable File Formats
-:PROPERTIES:
-:CUSTOM_ID: choosing-durable-file-formats
-:END:
#+begin_quote
-TL;DR: Write in a format that can be easily rendered and read in
-plain-text mode (e.g., =.txt=, =.md=, etc.).
+TL;DR (Too Long; Didn't Read): Write in a format that can be easily rendered and
+read in plain-text mode (e.g., =.txt=, =.md=, etc.).
#+end_quote
As I've written more and more over the years, I've found that my love of
-note-taking is always growing. Everything I learn or need to remember
-can be written down in a note and saved digitally, with no cost to
-myself. Unlike paper copies that need physical storage space, digital
-files simply need space on your local disk or cloud storage, which is
-fairly abundant these days.
-
-However, I had a historical struggle with migration of notes between
-different apps that require different formats and applied proprietary
-styling. This meant that I had to go through each note during migration
-and edit the file to look presentable again.
-
-For the last year or two, I have written everything exclusively in
-[[https://en.wikipedia.org/wiki/Markdown][Markdown]] format. Small
-notes, long-form writings, and even these blog posts are all written in
-Markdown.
-
-Why Markdown? While I do appreciate the simplicity of plain-text files
-without any formatting, I often need visual cues such as heading and
-code blocks to keep my thoughts straight. Markdown provides a minimal
-set of styling indicators for me to style my notes without adding any
-proprietary, embedded data into the files. If I want a top-level
-heading, I simply add a hash (=#=) before the line. An added bonus is
-that even if a system doesn't understand Markdown, it will render it as
-plain-text and I can read it just as easily.
-
-For example, here's how TextEdit on macOS will open and display a
-Markdown file in plain-text, since it does contain any features to
-preview Markdown as HTML:
+note-taking is always growing. Everything I learn or need to remember can be
+written down in a note and saved digitally, with no cost to myself. Unlike paper
+copies that need physical storage space, digital files simply need space on your
+local disk or cloud storage, which is fairly abundant these days.
+
+However, I had a historical struggle with migration of notes between different
+apps that require different formats and applied proprietary styling. This meant
+that I had to go through each note during migration and edit the file to look
+presentable again.
+
+For the last year or two, I have written everything exclusively in [[https://en.wikipedia.org/wiki/Markdown][Markdown]]
+format. Small notes, long-form writings, and even these blog posts are all
+written in Markdown.
+
+Why Markdown? While I do appreciate the simplicity of plain-text files without
+any formatting, I often need visual cues such as heading and code blocks to keep
+my thoughts straight. Markdown provides a minimal set of styling indicators for
+me to style my notes without adding any proprietary, embedded data into the
+files. If I want a top-level heading, I simply add a hash (=#=) before the line.
+An added bonus is that even if a system doesn't understand Markdown, it will
+render it as plain-text and I can read it just as easily.
+
+For example, here's how TextEdit on macOS will open and display a Markdown file
+in plain-text, since it does contain any features to preview Markdown as HTML:
#+caption: Plain Text Markdown
[[https://img.cleberg.net/blog/20220302-easy-reliable-note-taking/plain_markdown.webp]]
** Saving & Syncing Files
-:PROPERTIES:
-:CUSTOM_ID: saving-syncing-files
-:END:
-In order to read and edit my notes across platforms, I use my personal
-cloud storage through Tresorit due to its native integration with macOS
-and iOS file managers. In addition, Tresorit works well on Debian-based
-Linux distros, which I used before macOS (and will likely switch back to
-in a few years).
-You can use whatever sync software you want - syncing plain-text or
-markdown files is incredibly easy and fast, since the files are
-generally tiny.
+In order to read and edit my notes across platforms, I use my personal cloud
+storage through Tresorit due to its native integration with macOS and iOS file
+managers. In addition, Tresorit works well on Debian-based Linux distributions,
+which I used before macOS (and will likely switch back to in a few years).
-Since the cloud storage syncs files automatically, there is no need for
-me to sync anything manually or kick-off a sync job to update my files.
-This means that I can edit on mobile, and it takes about 5-10 seconds to
-see the changes on desktop.
+You can use whatever sync software you want - syncing plain-text or markdown
+files is incredibly easy and fast, since the files are generally tiny.
+
+Since the cloud storage syncs files automatically, there is no need for me to
+sync anything manually or kick-off a sync job to update my files. This means
+that I can edit on mobile, and it takes about 5-10 seconds to see the changes on
+desktop.
*** Version Control with Git
:PROPERTIES:
:CUSTOM_ID: version-control-with-git
:END:
-A different approach I've contemplated is storing my notes and
-attachments is using a hosted Git repository to track changes to the
-files. However, I don't want to rely on an external service that could
-potentially see into my data, even if the repository is private.
+A different approach I've contemplated is storing my notes and attachments is
+using a hosted Git repository to track changes to the files. However, I don't
+want to rely on an external service that could potentially see into my data,
+even if the repository is private.
-I might just do =git init= locally and then commit my changes each time
-I write or update a note, but that seems to be a lot of work just for
-tracking changes - which I don't necessarily care to know.
+I might just do =git init= locally and then commit my changes each time I write
+or update a note, but that seems to be a lot of work just for tracking changes -
+which I don't necessarily care to know.
*** Backups!
:PROPERTIES:
:CUSTOM_ID: backups
:END:
-One small addition to the storage/sync conversation is the idea of
-backups. Personally, I manually create periodic backups of my entire
-cloud storage, compress it into an archive, and store it on my home
-server.
+One small addition to the storage/sync conversation is the idea of backups.
+Personally, I manually create periodic backups of my entire cloud storage,
+compress it into an archive, and store it on my home server.
-To improve my workflow, I am going to be exploring options to
-automatically compress the mounted cloud directory and send it over to
-my server on a set schedule.
+To improve my workflow, I am going to be exploring options to automatically
+compress the mounted cloud directory and send it over to my server on a set
+schedule.
** Writing on Desktop
-:PROPERTIES:
-:CUSTOM_ID: writing-on-desktop
-:END:
#+begin_quote
-*Update (06.14.22)*: Since writing this post, I have reverted to simply
-keeping my =notes= folder open and opening notes individually in
-TextEdit for a more minimal and relaxing writing experience on the
-desktop.
+*Update (06.14.22)*: Since writing this post, I have reverted to simply keeping
+my =notes= folder open and opening notes individually in TextEdit for a more
+minimal and relaxing writing experience on the desktop.
#+end_quote
-The bulk of my writing occurs in a desktop environment, with a full
-keyboard layout and wide screen. I don't illustrate with a smart pen, I
-rarely use embedded images, and I love being able to see all of my
-notes/directories in a sidebar.
+The bulk of my writing occurs in a desktop environment, with a full keyboard
+layout and wide screen. I don't illustrate with a smart pen, I rarely use
+embedded images, and I love being able to see all of my notes/directories in a
+sidebar.
-With this simple set of requirements, I chose
-[[https://obsidian.md][Obsidian]] as my desktop text editor. Obsidian
-has some in-depth tools like a graph view, command palette, mentions,
-etc., but I've found that using it as a simple Markdown editor is
+With this simple set of requirements, I chose [[https://obsidian.md][Obsidian]] as my desktop text
+editor. Obsidian has some in-depth tools like a graph view, command palette,
+mentions, etc., but I've found that using it as a simple Markdown editor is
incredibly easy and straightforward.
-Here's an example of how my Markdown notes look when opened in
-plain-text mode:
+Here's an example of how my Markdown notes look when opened in plain-text mode:
#+caption: Obsidian Markdown Source Mode
[[https://img.cleberg.net/blog/20220302-easy-reliable-note-taking/obsidian_source_mode.webp]]
-Here's the "live preview" version, where the Markdown is rendered into
-its HTML format:
+Here's the "live preview" version, where the Markdown is rendered into its HTML
+format:
#+caption: Obsidian Markdown Live Preview
[[https://img.cleberg.net/blog/20220302-easy-reliable-note-taking/obsidian_live_preview.webp]]
*** Programming on Desktop
-:PROPERTIES:
-:CUSTOM_ID: programming-on-desktop
-:END:
-While I was writing this, I realized I should specify that I don't use
-the same editor for writing notes and for writing code. For programming
-purposes, I use [[https://vscodium.com][VSCodium]] as my development
-IDE.
+
+While I was writing this, I realized I should specify that I don't use the same
+editor for writing notes and for writing code. For programming purposes, I use
+[[https://vscodium.com][VSCodium]] as my development IDE.
** Writing on Mobile
-:PROPERTIES:
-:CUSTOM_ID: writing-on-mobile
-:END:
-Personally, I write very little on mobile, except when needing to take
-important notes on-the-go. Any long-form writing, journals, etc. are
-done at home, where I always have my laptop available.
-
-I wanted a simple and foolproof editor for iOS, preferably open-source.
-After a long journey of testing the few (& terrible) open-source iOS
-note-taking apps, I finally found a phenomenal one:
-[[https://github.com/simonbs/runestone][Runestone]]. This app is
-fantastic for note-taking, has plenty of optional features, and
-integrates natively with the iOS file manager.
-
-This app opens the iOS file manager and allows you to click any file you
-want, opens it up in an editor, and lets me save and close out of that
-note.
+
+Personally, I write very little on mobile, except when needing to take important
+notes on-the-go. Any long-form writing, journals, etc. are done at home, where I
+always have my laptop available.
+
+I wanted a simple and foolproof editor for iOS, preferably open-source. After a
+long journey of testing the few (& terrible) open-source iOS note-taking apps, I
+finally found a phenomenal one: [[https://github.com/simonbs/runestone][Runestone]]. This app is fantastic for
+note-taking, has plenty of optional features, and integrates natively with the
+iOS file manager.
+
+This app opens the iOS file manager and allows you to click any file you want,
+opens it up in an editor, and lets me save and close out of that note.
Quite simple but effective.
diff --git a/content/blog/2022-03-03-financial-database.org b/content/blog/2022-03-03-financial-database.org
index 40612b5..b82fccf 100644
--- a/content/blog/2022-03-03-financial-database.org
+++ b/content/blog/2022-03-03-financial-database.org
@@ -4,60 +4,49 @@
#+slug: financial-database
* Personal Financial Tracking
-:PROPERTIES:
-:CUSTOM_ID: personal-financial-tracking
-:END:
-For the last 6-ish years, I've tracked my finances in a spreadsheet.
-This is common practice in the business world, but any good dev will
-cringe at the thought of storing long-term data in a spreadsheet. A
-spreadsheet is not for long-term storage or as a source of data to pull
-data/reports.
-
-As I wanted to expand the functionality of my financial data (e.g.,
-adding more reports), I decided to migrate the data into a database. To
-run reports, I would query the database and use a language like Python
-or Javascript to process the data, perform calculations, and visualize
-the data.
+
+For the last 6-ish years, I've tracked my finances in a spreadsheet. This is
+common practice in the business world, but any good dev will cringe at the
+thought of storing long-term data in a spreadsheet. A spreadsheet is not for
+long-term storage or as a source of data to pull data/reports.
+
+As I wanted to expand the functionality of my financial data (e.g., adding more
+reports), I decided to migrate the data into a database. To run reports, I would
+query the database and use a language like Python or Javascript to process the
+data, perform calculations, and visualize the data.
* SQLite
-:PROPERTIES:
-:CUSTOM_ID: sqlite
-:END:
-When choosing the type of database I wanted to use for this project, I
-was split between three options:
-
-1. MySQL: The database I have the most experience with and have used for
- years.
+
+When choosing the type of database I wanted to use for this project, I was split
+between three options:
+
+1. MySQL: The database I have the most experience with and have used for years.
2. PostgreSQL: A database I'm new to, but want to learn.
-3. SQLite: A database that I've used for a couple projects and have
- moderate experience.
-
-I ended up choosing SQLite since it can be maintained within a single
-=.sqlite= file, which allows me more flexibility for storage and backup.
-I keep this file in my cloud storage and pull it up whenever needed.
-
-** GUI Editing
-:PROPERTIES:
-:CUSTOM_ID: gui-editing
-:END:
-Since I didn't want to try and import 1000--1500 records into my new
-database via the command line, I opted to use
-[[https://sqlitebrowser.org/][DB Browser for SQLite (DB4S)]] as a GUI
-tool. This application is excellent, and I don't see myself going back
-to the CLI when working in this database.
+3. SQLite: A database that I've used for a couple projects and have moderate
+ experience.
+
+I ended up choosing SQLite since it can be maintained within a single =.sqlite=
+file, which allows me more flexibility for storage and backup. I keep this file
+in my cloud storage and pull it up whenever needed.
+
+** Visual Editing
+
+Since I didn't want to try and import 1000--1500 records into my new database
+via the command line, I opted to use [[https://sqlitebrowser.org/][DB Browser for SQLite (DB4S)]] as a GUI
+(graphical user interface) tool. This application is excellent, and I don't see
+myself going back to the CLI (command line interface) when working in this
+database.
DB4S allows you to copy a range of cells from a spreadsheet and paste it
-straight into the SQL table. I used this process for all 36 accounts,
-1290 account statements, and 126 pay statements. Overall, I'm guessing
-this took anywhere between 4--8 hours. In comparison, it probably took
-me 2-3 days to initially create the spreadsheet.
+straight into the SQL table. I used this process for all 36 accounts, 1290
+account statements, and 126 pay statements. Overall, I'm guessing this took
+anywhere between 4--8 hours. In comparison, it probably took me 2-3 days to
+initially create the spreadsheet.
** Schema
-:PROPERTIES:
-:CUSTOM_ID: schema
-:END:
-The schema for this database is actually extremely simple and involves
-only three tables (for now):
+
+The schema for this database is actually extremely simple and involves only
+three tables (for now):
1. Accounts
2. Statements
@@ -65,9 +54,9 @@ only three tables (for now):
*Accounts*
-The Accounts table contains summary information about an account, such
-as a car loan or a credit card. By viewing this table, you can find
-high-level data, such as interest rate, credit line, or owner.
+The Accounts table contains summary information about an account, such as a car
+loan or a credit card. By viewing this table, you can find high-level data, such
+as interest rate, credit line, or owner.
#+begin_src sql
CREATE TABLE "Accounts" (
@@ -85,10 +74,10 @@ CREATE TABLE "Accounts" (
*Statements*
-The Statements table uses the same unique identifier as the Accounts
-table, meaning you can join the tables to find a monthly statement for
-any of the accounts listed in the Accounts table. Each statement has an
-account ID, statement date, and total balance.
+The Statements table uses the same unique identifier as the Accounts table,
+meaning you can join the tables to find a monthly statement for any of the
+accounts listed in the Accounts table. Each statement has an account identified
+(ID), statement date, and total balance.
#+begin_src sql
CREATE TABLE "Statements" (
@@ -103,10 +92,10 @@ CREATE TABLE "Statements" (
*Payroll*
-The Payroll table is a separate entity, unrelated to the Accounts or
-Statements tables. This table contains all information you would find on
-a pay statement from an employer. As you change employers or obtain new
-perks/benefits, just add new columns to adapt to the new data.
+The Payroll table is a separate entity, unrelated to the Accounts or Statements
+tables. This table contains all information you would find on a pay statement
+from an employer. As you change employers or obtain new perks/benefits, just add
+new columns to adapt to the new data.
#+begin_src sql
CREATE TABLE "Payroll" (
@@ -141,23 +130,18 @@ CREATE TABLE "Payroll" (
#+end_src
** Python Reporting
-:PROPERTIES:
-:CUSTOM_ID: python-reporting
-:END:
-Once I created the database tables and imported all my data, the only
-step left was to create a process to report and visualize on various
-aspects of the data.
-In order to explore and create the reports I'm interested in, I utilized
-a two-part process involving Jupyter Notebooks and Python scripts.
+Once I created the database tables and imported all my data, the only step left
+was to create a process to report and visualize on various aspects of the data.
+
+In order to explore and create the reports I'm interested in, I utilized a
+two-part process involving Jupyter Notebooks and Python scripts.
*** Step 1: Jupyter Notebooks
-:PROPERTIES:
-:CUSTOM_ID: step-1-jupyter-notebooks
-:END:
+
When I need to explore data, try different things, and re-run my code
-cell-by-cell, I use Jupyter Notebooks. For example, I explored the
-=Accounts= table until I found the following useful information:
+cell-by-cell, I use Jupyter Notebooks. For example, I explored the =Accounts=
+table until I found the following useful information:
#+begin_src python
import sqlite3
@@ -182,12 +166,9 @@ df.groupby(['AccountType']).sum().plot.pie(title='Credit Line by Account Type',
#+end_src
*** Step 2: Python Scripts
-:PROPERTIES:
-:CUSTOM_ID: step-2-python-scripts
-:END:
-Once I explored enough through the notebooks and had a list of reports I
-wanted, I moved on to create a Python project with the following
-structure:
+
+Once I explored enough through the notebooks and had a list of reports I wanted,
+I moved on to create a Python project with the following structure:
#+begin_src txt
finance/
@@ -212,16 +193,15 @@ This structure allows me to:
1. Compile all required python packages into =requirements.txt= for easy
installation if I move to a new machine.
-2. Activate a virtual environment in =venv/= so I don't need to maintain
- a system-wide Python environment just for this project.
-3. Keep my =notebooks/= folder to continuously explore the data as I see
- fit.
+2. Activate a virtual environment in =venv/= so I don't need to maintain a
+ system-wide Python environment just for this project.
+3. Keep my =notebooks/= folder to continuously explore the data as I see fit.
4. Maintain a local copy of the database in =src/= for easy access.
5. Export reports, images, HTML files, etc. to =public/=.
-Now, onto the differences between the code in a Jupyter Notebook and the
-actual Python files. To create the report in the Notebook snippet above,
-I created the following function inside =process.py=:
+Now, onto the differences between the code in a Jupyter Notebook and the actual
+Python files. To create the report in the Notebook snippet above, I created the
+following function inside =process.py=:
#+begin_src python
# Create summary pie chart
@@ -258,11 +238,10 @@ Other charts generated by this project include:
- Charts of account balances over time.
- Line chart of effective tax rate (taxes divided by taxable income).
-- Salary projections and error limits using past income and inflation
- rates.
+- Salary projections and error limits using past income and inflation rates.
- Multi-line chart of gross income, taxable income, and net income.
-The best thing about this project? I can improve it at any given time,
-shaping it into whatever helps me the most for that time. I imagine that
-I will be introducing an asset tracking table soon to track the
-depreciating value of cars, houses, etc. Who knows what's next?
+The best thing about this project? I can improve it at any given time, shaping
+it into whatever helps me the most for that time. I imagine that I will be
+introducing an asset tracking table soon to track the depreciating value of
+cars, houses, etc. Who knows what's next?
diff --git a/content/blog/2022-03-08-plex-migration.org b/content/blog/2022-03-08-plex-migration.org
index 23ae0a3..f6da160 100644
--- a/content/blog/2022-03-08-plex-migration.org
+++ b/content/blog/2022-03-08-plex-migration.org
@@ -4,18 +4,15 @@
#+slug: plex-migration
* Migration Phases
-:PROPERTIES:
-:CUSTOM_ID: migration-phases
-:END:
-I recently decided to migrate my server from an old OptiPlex desktop
-machine to a custom-built tower with better hardware in every category.
-In order to do this, I would need to properly migrate a full Plex
-installation.
-
-The second part of this migration is that the new server uses an Nvidia
-GPU and does not have any integrated graphics, which requires extra work
-for installation, but provides much better hardware transcoding options
-for Plex.
+
+I recently decided to migrate my server from an old OptiPlex desktop machine to
+a custom-built tower with better hardware in every category. In order to do
+this, I would need to properly migrate a full Plex installation.
+
+The second part of this migration is that the new server uses an Nvidia GPU
+(graphics processing unit) and does not have any integrated graphics, which
+requires extra work for installation, but provides much better hardware
+transcoding options for Plex.
Therefore, I have broken this migration down into three phases:
@@ -24,50 +21,41 @@ Therefore, I have broken this migration down into three phases:
3. Configure GPU Transcoding
* Phase 1: Configure the New Server
-:PROPERTIES:
-:CUSTOM_ID: phase-1-configure-the-new-server
-:END:
-** Choosing an OS
-:PROPERTIES:
-:CUSTOM_ID: choosing-an-os
-:END:
+
+** Choosing an Operating System (OS)
+
In order to migrate Plex to my new server, I first needed to choose an
-appropriate operating system (OS) and install it on the machine. Given
-that I have encountered numerous issues installing other Linux
-distributions properly with Nvidia graphics, I chose
-[[https://ubuntu.com/download/server][Ubuntu Server]].
+appropriate OS and install it on the machine. Given that I have encountered
+numerous issues installing other Linux distributions properly with Nvidia
+graphics, I chose [[https://ubuntu.com/download/server][Ubuntu Server]].
-The first step is to create a bootable USB with Ubuntu Server. This is
-easy with [[https://www.balena.io/etcher/][Etcher]], an app that runs on
-many different platforms. Just download the Ubuntu Server =.iso= image,
-launch Etcher, and install the =.iso= on the USB.
+The first step is to create a bootable USB (universal serial bus) with Ubuntu
+Server. This is easy with [[https://www.balena.io/etcher/][Etcher]], an app that runs on many different platforms.
+Just download the Ubuntu Server =.iso= image, launch Etcher, and install the
+=.iso= on the USB.
-Once the USB is created, insert it into my server, reboot, and click
-=Esc= (or any of the =F1-12= keys) until the BIOS menu appears. Finally,
-launch the USB boot drive.
+Once the USB is created, insert it into my server, reboot, and click =Esc= (or
+any of the =F1-12= keys) until the BIOS (Basic Input/Output System) menu
+appears. Finally, launch the USB boot drive.
** Booting with Nvidia
-:PROPERTIES:
-:CUSTOM_ID: booting-with-nvidia
-:END:
+
In order to install Ubuntu Server with an Nvidia Graphics card (and no
-integrated graphics on this device for some reason), you'll have to
-configure the boot menu to allow different graphics drivers to be
-loaded.
+integrated graphics on this device for some reason), you'll have to configure
+the boot menu to allow different graphics drivers to be loaded.
-When booting from the USB, the machine will launch the initial
-installation menu. From this menu, type =e= to view the default command
-options that come with the device - it's a good idea to take a photo of
-this screen, so you can enter these commands on the next screen (along
-with adding support for Nvidia).
+When booting from the USB, the machine will launch the initial installation
+menu. From this menu, type =e= to view the default command options that come
+with the device - it's a good idea to take a photo of this screen, so you can
+enter these commands on the next screen (along with adding support for Nvidia).
-Finally, type =Ctrl + C= to enter the command line. From this command
-line, enter the commands found on the =e= screen. /Remember to add
-=nomodeset= to the =linux ...= line so that your Nvidia device will
-display the installation screens properly!/
+Finally, type =Ctrl + C= to enter the command line. From this command line,
+enter the commands found on the =e= screen. Remember to add =nomodeset= to the
+=linux ...= line so that your Nvidia device will display the installation
+screens properly!
-Here's an example of the commands I pulled from the =e= screen and
-entered on the command line.
+Here's an example of the commands I pulled from the =e= screen and entered on
+the command line.
#+begin_src sh
setparams 'Install Ubuntu Server'
@@ -77,12 +65,11 @@ initrd /casper/initrd
boot
#+end_src
-Once the machine is rebooted, enter the =e= screen again and add
-=nomodeset= to the =linux ...= line again and press =Ctrl + X= to save
-the boot options.
+Once the machine is rebooted, enter the =e= screen again and add =nomodeset= to
+the =linux ...= line again and press =Ctrl + X= to save the boot options.
-The machine is now fully installed and can properly display on an
-external display using the Nvidia GPU.
+The machine is now fully installed and can properly display on an external
+display using the Nvidia GPU.
Always remember to update and upgrade on a new installation:
@@ -91,40 +78,29 @@ sudo apt update; sudo apt upgrade -y; sudo apt autoremove -y
#+end_src
* Phase 2: Migrate Plex Data & Devices
-:PROPERTIES:
-:CUSTOM_ID: phase-2-migrate-plex-data-devices
-:END:
-This phase uses the great Plex article on migrations
-([[https://support.plex.tv/articles/201370363-move-an-install-to-another-system/][Move
-an Installation to Another System]]) and adds a bit more information to
-help with commands and context.
+
+This phase uses the great Plex article on migrations ([[https://support.plex.tv/articles/201370363-move-an-install-to-another-system/][Move an Installation to
+Another System]]) and adds a bit more information to help with commands and
+context.
** Terminology
-:PROPERTIES:
-:CUSTOM_ID: terminology
-:END:
-*Source:* The original server that is being replaced.\\
-*Destination:* The new server.\\
-*Client:* Any application that can be used to modify settings for both
-source/destination.
+
+- *Source:* The original server that is being replaced.
+- *Destination:* The new server.
+- *Client:* Any application that can be used to modify settings for both
+ source/destination.
** Step 01: [Client] Update Settings
-:PROPERTIES:
-:CUSTOM_ID: step-01-client-update-settings
-:END:
-Open up a Plex app and /disable/ the =Account= > =Library= >
-=Empty trash automatically after every scan= preference for the source
-server.
+
+Open up a Plex app and /disable/ the =Account= > =Library= > =Empty trash
+automatically after every scan= preference for the source server.
** Step 02: [Destination] Install Plex
-:PROPERTIES:
-:CUSTOM_ID: step-02-destination-install-plex
-:END:
-Open up the [[https://www.plex.tv/media-server-downloads/][Plex Media
-Server download page]] and copy the link for the appropriate platform.
-Execute the following commands on the destination server to install
-Plex:
+Open up the [[https://www.plex.tv/media-server-downloads/][Plex Media Server download page]] and copy the link for the
+appropriate platform.
+
+Execute the following commands on the destination server to install Plex:
#+begin_src sh
wget <url>
@@ -133,50 +109,44 @@ sudo systemctl stop plexmediaserver.service
#+end_src
** Step 03: [Source] Stop Plex & Migrate Data
-:PROPERTIES:
-:CUSTOM_ID: step-03-source-stop-plex-migrate-data
-:END:
-First, stop the Plex service so that no data is created or modified
-during the migration.
+
+First, stop the Plex service so that no data is created or modified during the
+migration.
#+begin_src sh
sudo systemctl stop plexmediaserver.service
#+end_src
-Next, copy the data to the new server. To find where the Plex data
-directory is located, Plex has another excellent article available:
-[[https://support.plex.tv/articles/202915258-where-is-the-plex-media-server-data-directory-located/][Where
-is the Plex Media Server data directory located?]].
+Next, copy the data to the new server. To find where the Plex data directory is
+located, Plex has another excellent article available: [[https://support.plex.tv/articles/202915258-where-is-the-plex-media-server-data-directory-located/][Where is the Plex Media
+Server data directory located?]].
-There are many ways to copy the data to the new server and will largely
-depend on the size of the folder being copied. Personally, my data
-folder was ~23GB and I opted to simply use the =scp= command to copy the
-files over SSH.
+There are many ways to copy the data to the new server and will largely depend
+on the size of the folder being copied. Personally, my data folder was ~23GB and
+I opted to simply use the =scp= command to copy the files over SSH (Secure Shell
+Protocol).
-This process was throttled by the old server's slow HDD and ports and
-took approximately 90 minutes to complete. In comparison, moving the
-data from the new server's =home/user/= directory to the
-=/var/.../Plex Media Server= directory took 2-3 minutes.
+This process was throttled by the old server's slow hard disk and ports and took
+approximately 90 minutes to complete. In comparison, moving the data from the
+new server's =home/user/= directory to the =/var/.../Plex Media Server=
+directory took 2-3 minutes.
#+begin_src sh
scp -r "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server" [email protected]:"'/path/to/destination/'"
#+end_src
** Step 04: [Destination] Update File Permissions
-:PROPERTIES:
-:CUSTOM_ID: step-04-destination-update-file-permissions
-:END:
-In case you move the data directory to a common area on the new server,
-it will have to be moved to the proper location before Plex can function
-properly:
+
+In case you move the data directory to a common area on the new server, it will
+have to be moved to the proper location before Plex can function properly:
#+begin_src sh
mv "Plex Media Server" /var/lib/plexmediaserver/Library/Application Support/
#+end_src
-To ensure permissions were retained properly, the server will need to
-show that all files and folders in the data directory are owned by
-=plex:plex= (or whichever user is running the Plex application).
+To ensure permissions were retained properly, the server will need to show that
+all files and folders in the data directory are owned by =plex:plex= (or
+whichever user is running the Plex application).
#+begin_src sh
sudo chown -R plex:plex "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server"
@@ -190,43 +160,37 @@ sudo systemctl status plexmediaserver.service
#+end_src
** Step 05: [Client] Update Libraries & Metadata
-:PROPERTIES:
-:CUSTOM_ID: step-05-client-update-libraries-metadata
-:END:
-The first step - now that the new server is up and running - is to sign
-out of the client and sign back in. Once this is done, update any
-library locations, if necessary. This was unnecessary in my case since I
-simply moved my storage drives from the source server to the destination
-server.
+
+The first step - now that the new server is up and running - is to sign out of
+the client and sign back in. Once this is done, update any library locations, if
+necessary. This was unnecessary in my case since I simply moved my storage
+drives from the source server to the destination server.
Next, perform the following actions in the client:
-1. On the left sidebar, click =More= > Three-Dot Menu >
- =Scan Library Files=
-2. /Enable/ the =Account= > =Library= >
- =Empty trash automatically after every scan= preference for the
- source server.
-3. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server=
- > =Empty Trash=
-4. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server=
- > =Clean Bundles=
-5. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server=
- > =Optimize Database=
+1. On the left sidebar, click =More= > Three-Dot Menu > =Scan Library Files=
+2. /Enable/ the =Account= > =Library= > =Empty trash automatically after every
+ scan= preference for the source server.
+3. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server= > =Empty
+ Trash=
+4. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server= > =Clean
+ Bundles=
+5. On the left sidebar, click =More= > Three-Dot Menu > =Manage Server= >
+ =Optimize Database=
-Finally, double-check the Remote Access settings to make sure no changes
-have caused issues with accessing the server from outside the network.
+Finally, double-check the Remote Access settings to make sure no changes have
+caused issues with accessing the server from outside the network.
-In my case, I use a single port forwarding rule in my router and needed
-to update the Local LAN IP Address to the new server IP address.
+In my case, I use a single port forwarding rule in my router and needed to
+update the Local LAN (local area network) IP (internet protocol) Address to the
+new server IP address.
* Phase 3: Configure GPU Transcoding
-:PROPERTIES:
-:CUSTOM_ID: phase-3-configure-gpu-transcoding
-:END:
-The final piece to the migration is enabling hardware transcoding so
-that Plex can fully utilize the new Nvidia GPU available in the server.
-The first step is to install Nvidia graphics drivers. This process may
-take a few minutes, but the commands are pretty simple:
+
+The final piece to the migration is enabling hardware transcoding so that Plex
+can fully utilize the new Nvidia GPU available in the server. The first step is
+to install Nvidia graphics drivers. This process may take a few minutes, but the
+commands are pretty simple:
#+begin_src sh
sudo add-apt-repository ppa:graphics-drivers/ppa
@@ -248,5 +212,5 @@ following command to view the available GPUs, statistics, and processes:
sudo nvidia-smi
#+end_src
-Finally, enable hardware transcoding settings in the Plex application to
-finish the process.
+Finally, enable hardware transcoding settings in the Plex application to finish
+the process.
diff --git a/content/blog/2022-03-23-cloudflare-dns-api.org b/content/blog/2022-03-23-cloudflare-dns-api.org
index af0e5e8..cc722aa 100644
--- a/content/blog/2022-03-23-cloudflare-dns-api.org
+++ b/content/blog/2022-03-23-cloudflare-dns-api.org
@@ -7,15 +7,15 @@
:PROPERTIES:
:CUSTOM_ID: ddns-dynamic-dns
:END:
-If you're hosting a service from a location with dynamic DNS (where your
-IP may change at any time), you must have a solution to update the DNS
-so that you can access your service even when the IP of the server
-changes.
+If you're hosting a service from a location with DDNS (Dynamic Domain Name
+System), where your internet protocol (IP)address may change at any time, you
+must have a solution to update the DNS (Domain Name System) so that you can
+access your service even when the IP of the server changes.
-The process below uses the [[https://api.cloudflare.com/][Cloudflare
-API]] to update DNS =A= and =AAAA= records with the server's current IP.
-If you use another DNS provider, you will have to find a way to update
-your DNS (or find a way to get a static IP).
+The process below uses the [[https://api.cloudflare.com/][Cloudflare API]] (application programming interface) to
+update DNS =A= and =AAAA= records with the server's current IP. If you use
+another DNS provider, you will have to find a way to update your DNS (or find a
+way to get a static IP).
First, install =jq= since we will use it in the next script:
@@ -23,18 +23,16 @@ First, install =jq= since we will use it in the next script:
sudo apt install jq
#+end_src
-Next, create a location for your DDNS update scripts and open the first
-script:
+Next, create a location for your DDNS update scripts and open the first script:
#+begin_src sh
mkdir ~/ddns
nano ~/ddns/update.sh
#+end_src
-The following =update.sh= script will take all of your domains and
-subdomains and check Cloudflare to see if the current =A= and =AAAA=
-records match your server's IP address. If not, it will update the
-records.
+The following =update.sh= script will take all of your domains and subdomains
+and check Cloudflare to see if the current =A= and =AAAA= records match your
+server's IP address. If not, it will update the records.
#+begin_src sh
# file: update.sh
@@ -60,16 +58,16 @@ do
done
#+end_src
-Next, open up the =ddns.sh= script. Paste the following into the script
-and update the =api_token= and =email= variables.
+Next, open up the =ddns.sh= script. Paste the following into the script and
+update the =api_token= and =email= variables.
#+begin_src sh
nano ~/ddns/ddns.sh
#+end_src
-*Note*: If you want your DNS records to be proxied through Cloudflare,
-find and update the following snippet: ="proxied":false}"= to say =true=
-instead of =false=.
+*Note*: If you want your DNS records to be proxied through Cloudflare, find and
+update the following snippet: ="proxied":false}"= to say =true= instead of
+=false=.
#+begin_src sh
# file: ddns.sh
@@ -179,14 +177,14 @@ You can test the script by running it manually:
./update.sh
#+end_src
-To make sure the scripts run automatically, add it to the =cron= file so
-that it will run on a schedule. To do this, open the cron file:
+To make sure the scripts run automatically, add it to the =cron= file so that it
+will run on a schedule. To do this, open the cron file:
#+begin_src sh
crontab -e
#+end_src
-In the cron file, paste the following at the bottom of the editor:
+In the =cron= file, paste the following at the bottom of the editor:
#+begin_src sh
,*/5 ** ** ** ** bash /home/<your_username>/ddns/update.sh
diff --git a/content/blog/2022-03-23-nextcloud-on-ubuntu.org b/content/blog/2022-03-23-nextcloud-on-ubuntu.org
index 2d85c23..0409f12 100644
--- a/content/blog/2022-03-23-nextcloud-on-ubuntu.org
+++ b/content/blog/2022-03-23-nextcloud-on-ubuntu.org
@@ -7,8 +7,8 @@
:PROPERTIES:
:CUSTOM_ID: what-is-nextcloud
:END:
-[[https://nextcloud.com/][Nextcloud]] is a self-hosted solution for
-storage, communications, editing, calendar, contacts, and more.
+[[https://nextcloud.com/][Nextcloud]] is a self-hosted solution for storage, communications, editing,
+calendar, contacts, and more.
This tutorial assumes that you have an Ubuntu server and a domain name
configured to point toward the server.
@@ -29,16 +29,14 @@ sudo apt install php7.4-gmp php7.4-bcmath php-imagick php7.4-xml php7.4-zip
:PROPERTIES:
:CUSTOM_ID: set-up-mysql
:END:
-Next, you will need to log in to MySQL as the =root= user of the
-machine.
+Next, you will need to log in to MySQL as the =root= user of the machine.
#+begin_src sh
sudo mysql -uroot -p
#+end_src
-Once you've logged in, you must create a new user so that Nextcloud can
-manage the database. You will also create a =nextcloud= database and
-assign privileges:
+Once you've logged in, you must create a new user so that Nextcloud can manage
+the database. You will also create a =nextcloud= database and assign privileges:
#+begin_src sql
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
@@ -52,15 +50,12 @@ quit;
:PROPERTIES:
:CUSTOM_ID: download-install-nextcloud
:END:
-To download Nextcloud, go the
-[[https://nextcloud.com/install/#instructions-server][Nextcloud
-downloads page]], click on =Archive File= and right-click the big blue
-button to copy the link.
+To download Nextcloud, go the [[https://nextcloud.com/install/#instructions-server][Nextcloud downloads page]], click on =Archive File=
+and right-click the big blue button to copy the link.
-Then, go to your server and enter the following commands to download,
-unzip, and move the files to your destination directory. This example
-uses =example.com= as the destination, but you can put it wherever you
-want to server your files from.
+Then, go to your server and enter the following commands to download, unzip, and
+move the files to your destination directory. This example uses =example.com= as
+the destination, but you can put it wherever you want to server your files from.
#+begin_src sh
wget https://download.nextcloud.com/server/releases/nextcloud-23.0.3.zip
@@ -73,9 +68,9 @@ sudo cp -r nextcloud /var/www/example.com
:PROPERTIES:
:CUSTOM_ID: configure-the-apache-web-server
:END:
-Now that the database is set up and Nextcloud is installed, you need to
-set up the Apache configuration files to tell the server how to handle
-requests for =example.com/nextcloud=.
+Now that the database is set up and Nextcloud is installed, you need to set up
+the Apache configuration files to tell the server how to handle requests for
+=example.com/nextcloud=.
First, open the following file in the editor:
@@ -83,8 +78,8 @@ First, open the following file in the editor:
sudo nano /etc/apache2/sites-available/nextcloud.conf
#+end_src
-Once the editor is open, paste the following information in. Then, save
-and close the file.
+Once the editor is open, paste the following information in. Then, save and
+close the file.
#+begin_src config
<VirtualHost *:80>
@@ -113,14 +108,14 @@ Once the file is saved, enable it with Apache:
sudo a2ensite nextcloud.conf
#+end_src
-Next, enable the Apache mods required by Nextcloud:
+Next, enable the Apache modules required by Nextcloud:
#+begin_src sh
sudo a2enmod rewrite headers env dir mime
#+end_src
-Finally, restart Apache. If any errors arise, you must solve those
-before continuing.
+Finally, restart Apache. If any errors arise, you must solve those before
+continuing.
#+begin_src sh
sudo systemctl restart apache2
@@ -137,20 +132,20 @@ sudo chown -R www-data:www-data /var/www/example.com/nextcloud/
:PROPERTIES:
:CUSTOM_ID: dns
:END:
-If you do not have a static IP address, you will need to update your DNS
-settings (at your DNS provider) whenever your dynamic IP address
-changes.
+If you do not have a static internet protocol (IP) address, you will need to
+update your DNS (Domain Name System) settings (at your DNS provider) whenever
+your dynamic IP address changes.
-For an example on how I do that with Cloudflare, see my other post:
-[[../updating-dynamic-dns-with-cloudflare-api/][Updating Dynamic DNS
-with Cloudflare API]]
+For an example on how I do that with Cloudflare, see my other post: [[https://cleberg.net/blog/cloudflare-dns-api.html][Dynamic DNS
+Record Updates via Cloudflare API]].
* Certbot
:PROPERTIES:
:CUSTOM_ID: certbot
:END:
-If you want to serve Nextcloud from HTTPS rather than plain HTTP, use
-the following commands to issue Let's Encrypt SSL certificates:
+If you want to serve Nextcloud from HTTPS (Hypertext Transfer Protocol Secure)
+rather than plain HTTP (Hypertext Transfer Protocol), use the following commands
+to issue Let's Encrypt SSL (Secure Socket Layer) certificates:
#+begin_src sh
sudo apt install snapd
@@ -165,5 +160,5 @@ sudo certbot --apache
:PROPERTIES:
:CUSTOM_ID: results
:END:
-Voilà! You're all done and should be able to access Nextcloud from your
-domain or IP address.
+Voilà! You're all done and should be able to access Nextcloud from your domain
+or IP address.
diff --git a/content/blog/2022-03-24-server-hardening.org b/content/blog/2022-03-24-server-hardening.org
index 2ac897c..c79cf44 100644
--- a/content/blog/2022-03-24-server-hardening.org
+++ b/content/blog/2022-03-24-server-hardening.org
@@ -27,8 +27,9 @@ have to think about the transport of data from =server= to =client=.
Let's start with the actual server itself. Think about the following:
- Do I have a firewall enabled? Do I need to update this to allow new ports or
- IPs?
-- Do I have an IPS/IDS that may prevent outside traffic?
+ internet protocol (IP) addresses?
+- Do I have an intrusion prevention system (IPS) or intrusion detection system
+ (IDS) that may prevent outside traffic?
- Do I have any other security software installed?
- Are the services hosted inside Docker containers, behind a reverse proxy, or
virtualized? If so, are they configured to allow outside traffic?
@@ -37,7 +38,7 @@ Once the data leaves the server, where does it go? In my case, it goes to a
managed switch. In this case, I asked the following:
- What configurations is the switch using?
-- Am I using VLANs?
+- Am I using VLANs (virtual local area networks)?
- Yes, I am using 802.1Q VLANs.
- Are the VLANs configured properly?
- Yes, as shown in the Switch section below, I have a separate VLAN to allow
@@ -47,7 +48,7 @@ managed switch. In this case, I asked the following:
At this point, the data has been processed through the switch. Where does it go
next? In my case, it's pretty simple: it goes to the router/modem device.
-- Does my ISP block any ports that I need?
+- Does my internet service provider (ISP) block any ports that I need?
- This is an important step that a lot of people run into when self-hosting at
home. Use an online port-checker tool for your IP or call your ISP if you
think ports are blocked.
@@ -59,9 +60,9 @@ next? In my case, it's pretty simple: it goes to the router/modem device.
- Are there any other settings affecting inbound/outbound traffic?
- Schedules or access blocks
- Static Routing
- - QoS
+ - QoS (Quality of Service)
- Port Forwarding
- - DMZ Hosting
+ - DMZ (demilitarized zone) hosting
- Remote Management (this can sometimes mess with services that also require
the use of ports 80 and 443)
@@ -70,27 +71,31 @@ publicly.
*** Server
-The services I run on my server are installed straight into the OS, without any
-use of Docker or VMs, so I don't need any extra application configuration to
-make them accessible to the outside world.+
+The services I run on my server are installed straight into the operating system
+(OS), without any use of Docker or virtual machines (VMs), so I don't need any
+extra application configuration to make them accessible to the outside world.
+#+BEGIN_QUOTE
As of 2022-10-04, the paragraph above is no longer true as I now run a reverse
proxy with Nginx and host many services inside Docker. However, it doesn't
change anything regarding this post as I still just need to open ports 80 & 443
and create the necessary website configuration files.
+#+END_QUOTE
When creating new services - either installed directly on bare metal or within
something like Docker - I ensure that I read through the documentation
-thoroughly to understand a few key things: - What network activities should this
-app perform (if any)? Using which ports and protocols? - Does this app require
-any commands/services to be run as =root=? - Does this app log errors,
-authentication failures/successes, or anything else that would be useful for an
-investigation?
+thoroughly to understand a few key things:
+
+- What network activities should this app perform (if any)? Using which ports
+ and protocols?
+- Does this app require any commands/services to be run as =root=?
+- Does this app log errors, authentication failures/successes, or anything else
+ that would be useful for an investigation?
For extra security, I use limit all incoming connections to SSH connections
-through my server firewall (=ufw=) and disable common SSH settings. After all of
-that, I use =fail2ban= as a preventative measure against brute-force login
-attempts.
+through my server firewall [=ufw= (Uncomplicated Firewall)] and disable common
+SSH (Secure Shell Protocol) settings. After all of that, I use =fail2ban= as a
+preventative measure against brute-force login attempts.
As another piece of security, you can randomize your SSH port to ensure that
random scanners or attackers can't easily try to force their way into your
@@ -101,8 +106,8 @@ via your randomized port.
** =ufw=
-To see how to configure =ufw=, see my other post: [[https://cleberg.net/blog/ufw.html][Secure Your
-Network with the Uncomplicated Firewall]].
+To see how to configure =ufw=, see my other post: [[https://cleberg.net/blog/ufw.html][Secure Your Network with the
+Uncomplicated Firewall]].
The general notion with an on-device firewall is that you want to deny all
incoming connections by default and then selectively open certain ports for
@@ -178,7 +183,7 @@ sudo ufw enable
lock yourself out at some point and will need to use a recovery method (e.g.,
hooking monitor up to home server) to get yourself back in.
-3. Enable MFA for =ssh=
+3. Enable Multi-Factor Authentication (MFA) for =ssh=
This part is optional, but I highly recommend it. So far, we've ensured that
no one can log into our user on the server without using our secret key, and
@@ -187,8 +192,7 @@ sudo ufw enable
This process involves editing a couple files and installing an MFA package,
so I will not include all the details in this post. To see how to configure
- MFA for =ssh=, see my other post: [[https://cleberg.net/blog/ssh-mfa.html][Enabling MFA for
- SSH]].
+ MFA for =ssh=, see my other post: [[https://cleberg.net/blog/ssh-mfa.html][Enabling MFA for SSH]].
** =fail2ban=
@@ -224,8 +228,8 @@ the server to manage it.
| VLAN ID | VLAN Name | Member Ports | Tagged Ports | Untagged Ports |
|---------+-----------+--------------+--------------+----------------|
-| 1 | Default | 1-24 | 1-24 | |
-| 2 | Server | 1,8,23 | 1,8,23 | |
+| 1 | Default | 1-24 | 1-24 | |
+| 2 | Server | 1,8,23 | 1,8,23 | |
** 802.1Q VLAN PVID Setting
@@ -235,30 +239,30 @@ any related ports (in this case, see that ports =8= and =23= have a PVID of
| Port | PVID |
|------+------|
-| 1 | 1 |
-| 2 | 1 |
-| 3 | 1 |
-| 4 | 1 |
-| 5 | 1 |
-| 6 | 1 |
-| 7 | 1 |
-| 8 | 2 |
-| 9 | 1 |
-| 10 | 1 |
-| 11 | 1 |
-| 12 | 1 |
-| 13 | 1 |
-| 14 | 1 |
-| 15 | 1 |
-| 16 | 1 |
-| 17 | 1 |
-| 18 | 1 |
-| 19 | 1 |
-| 20 | 1 |
-| 21 | 1 |
-| 22 | 1 |
-| 23 | 2 |
-| 24 | 1 |
+| 1 | 1 |
+| 2 | 1 |
+| 3 | 1 |
+| 4 | 1 |
+| 5 | 1 |
+| 6 | 1 |
+| 7 | 1 |
+| 8 | 2 |
+| 9 | 1 |
+| 10 | 1 |
+| 11 | 1 |
+| 12 | 1 |
+| 13 | 1 |
+| 14 | 1 |
+| 15 | 1 |
+| 16 | 1 |
+| 17 | 1 |
+| 18 | 1 |
+| 19 | 1 |
+| 20 | 1 |
+| 21 | 1 |
+| 22 | 1 |
+| 23 | 2 |
+| 24 | 1 |
* Router
@@ -266,9 +270,9 @@ On my router, the configuration was as easy as opening the firewall settings and
unblocking the ports I needed for my services (e.g., HTTP/S, Plex, SSH, MySQL,
etc.).
-Since I'm relying on an ISP-provided modem/router combo for now (not by
-choice), I do not use any other advanced settings on my router that would
-inhibit any valid traffic to these services.
+Since I'm relying on an ISP-provided modem/router combo for now (not by choice),
+I do not use any other advanced settings on my router that would inhibit any
+valid traffic to these services.
The paragraph above regarding the ISP-owned router is no longer accurate as I
now use the Ubiquiti Unifi Dream Machine Pro as my router. Within this router, I
@@ -287,10 +291,10 @@ physical security. However, physical security is very important for everyone who
hosts a server like this. Exactly /how/ important it is depends on the server
use/purpose.
-If you self-host customer applications that hold protected data (HIPAA, GDPR,
-COPPA, etc.), then physical security is extremely important and cannot be
-ignored. If you simply host a blog and some hobby sites, then it's a relatively
-minor consideration, but one you still need to think about.
+If you self-host customer applications that hold protected data, then physical
+security is extremely important and cannot be ignored. If you simply host a blog
+and some hobby sites, then it's a relatively minor consideration, but one you
+still need to think about.
** Location
@@ -312,8 +316,9 @@ Secondly, consider the hardware itself:
- Are any other users able to access the server, even if your data/space is
segregated?
- If you're utilizing a third party, do they have any documentation to show
- responsibility? This could be a SOC 1/2/3 report, ISO compliance report,
- internal security/safety documentation.
+ responsibility? This could be a Service Organization Controls (SOC) 1/2/3
+ report, International Organization for Standardization (ISO) compliance
+ report, internal security/safety documentation.
** Physical Controls
diff --git a/content/blog/2022-03-26-ssh-mfa.org b/content/blog/2022-03-26-ssh-mfa.org
index dd9a5ac..0236aa4 100644
--- a/content/blog/2022-03-26-ssh-mfa.org
+++ b/content/blog/2022-03-26-ssh-mfa.org
@@ -3,31 +3,29 @@
#+description: Step-by-step deployment guide for enabling TOTP multi-factor authentication on SSH services using Google Authenticator and Pluggable Authentication Module (PAM) integration.
#+slug: ssh-mfa
-* Why Do I Need MFA for SSH?
+* Why Do I Need Multi-Factor Authentication (MFA) for SSH (Secure Shell Protocol)?
-If you are a sysadmin of a server anywhere (that includes at home!), you
-may want an added layer of protection against intruders. This is not a
-replacement for other security measures, such as:
+If you are a sysadmin of a server anywhere (that includes at home!), you may
+want an added layer of protection against intruders. This is not a replacement
+for other security measures, such as:
- Disable root SSH
- Disable SSH password authentication
- Allow only certain users to login via SSH
-- Allow SSH only from certain IPs
+- Allow SSH only from certain internet protocol (IP) addressess
-However, MFA can be added as an additional security measure to ensure
-that your server is protected. This is especially important if you need
-to allow password authentication for SSH.
+However, MFA can be added as an additional security measure to ensure that your
+server is protected. This is especially important if you need to allow password
+authentication for SSH.
-For more guidance on server security measures, see my other post:
-[[../hardening-a-public-facing-home-server/][Hardening a Public-Facing
-Home Server]].
+For more guidance on server security measures, see my other post: [[https://cleberg.net/blog/server-hardening.html][Step-by-Step
+Guide to Securing Your Home Server with Firewalls, SSH, and VLANs]].
* Install MFA PAM Module
-PAM, which stands for Pluggable Authentication Module, is an
-authentication infrastructure used on Linux systems to authenticate a
-user. In order to use this technology, let's install the
-=libpam-google-authenticator= package:
+PAM (Pluggable Authentication Module) is an authentication infrastructure used
+on Linux systems to authenticate a user. In order to use this technology, let's
+install the =libpam-google-authenticator= package:
#+begin_src sh
sudo apt-get update
@@ -41,16 +39,17 @@ sudo apt-get install libpam-google-authenticator
** Interactive Method
-Once the package is installed, initialize it and following the
-interactive prompts to generate your OTP or TOTP:
+Once the package is installed, initialize it and following the interactive
+prompts to generate your OTP (One-Time Password) or TOTP (Time-based One-Time
+Password):
#+begin_src sh
google-authenticator
#+end_src
-If you are not sure how to answer, read the prompts carefully and think
-about having to how each situation would affect your normal login
-attempts. If you are still not sure, use my default responses below.
+If you are not sure how to answer, read the prompts carefully and think about
+having to how each situation would affect your normal login attempts. If you are
+still not sure, use my default responses below.
#+begin_src txt
OUTPUT
@@ -58,8 +57,8 @@ OUTPUT
Do you want authentication tokens to be time-based (y/n) y
#+end_src
-At this point, use an authenticator app somewhere one of your devices to
-scan the QR code. Any future login attempts after our upcoming
+At this point, use an authenticator app somewhere one of your devices to scan
+the QR (quick-response) code. Any future login attempts after our upcoming
configuration changes will require that TOTP.
#+begin_src txt
@@ -134,23 +133,23 @@ google-authenticator [<options>]
-e, --emergency-codes=N Number of emergency codes to generate
#+end_src
-This fully configures the authenticator, saves it to a file, and then
-outputs the secret key, QR code, and recovery codes. (If you add the
-flag =-q=, then there won't be any output). If you use this command in
-an automated fashion, make sure your script captures the secret key
-and/or recovery codes and makes them available to the user.
+This fully configures the authenticator, saves it to a file, and then outputs
+the secret key, QR code, and recovery codes. (If you add the flag =-q=, then
+there won't be any output). If you use this command in an automated fashion,
+make sure your script captures the secret key and/or recovery codes and makes
+them available to the user.
* PAM Configuration Settings
-Once you've enabled the T/OTP and have it saved to an MFA app on your
-phone or other device, open the PAM =sshd= file:
+Once you've enabled MFA and have it saved to an MFA app on your phone or other
+device, open the PAM =sshd= file:
#+begin_src sh
sudo nano /etc/pam.d/sshd
#+end_src
-You need to do two things in this file. First, add the following lines
-to the bottom of the file:
+You need to do two things in this file. First, add the following lines to the
+bottom of the file:
#+begin_src config
auth required pam_google_authenticator.so nullok
@@ -159,8 +158,8 @@ auth required pam_permit.so
Second, comment-out the following line near the top of the file.
-If you leave this line uncommented, every SSH login attempt will ask for
-the following three authentication factors:
+If you leave this line uncommented, every SSH login attempt will ask for the
+following three authentication factors:
1. Publickey
2. Password
@@ -178,8 +177,8 @@ Finally, edit the =sshd_config= file again:
sudo nano /etc/ssh/sshd_config
#+end_src
-You'll need to change =ChallengeResponseAuthentication= to yes and add
-the =AuthenticationMethods= line to the bottom of the file.
+You'll need to change =ChallengeResponseAuthentication= to yes and add the
+=AuthenticationMethods= line to the bottom of the file.
#+begin_src config
ChallengeResponseAuthentication yes
diff --git a/content/blog/2022-04-02-nginx-reverse-proxy.org b/content/blog/2022-04-02-nginx-reverse-proxy.org
index d6fa8b0..c7d2602 100644
--- a/content/blog/2022-04-02-nginx-reverse-proxy.org
+++ b/content/blog/2022-04-02-nginx-reverse-proxy.org
@@ -5,10 +5,10 @@
* What is a Reverse Proxy?
-A reverse proxy is a server that is placed between local servers or
-services and clients/users (e.g., the internet). The reverse proxy
-intercepts all requests from clients at the network edge and uses its
-configuration files to determine where each request should be sent.
+A reverse proxy is a server that is placed between local servers or services and
+clients/users (e.g., the internet). The reverse proxy intercepts all requests
+from clients at the network edge and uses its configuration files to determine
+where each request should be sent.
** A Brief Example
@@ -18,23 +18,21 @@ For example, let's say that I run three servers in my home:
- Server02 (=service01.example.com=)
- Server03 (=service02.example.com=)
-I also run a reverse proxy in my home that intercepts all public
-traffic:
+I also run a reverse proxy in my home that intercepts all public traffic:
- Reverse Proxy
-Assume that I have a domain name (=example.com=) that allows clients to
-request websites or services from my home servers.
+Assume that I have a domain name (=example.com=) that allows clients to request
+websites or services from my home servers.
-In this case, the reverse proxy will intercept all traffic from
-=example.com= that enters my network and determine if the client is
-requesting valid data, based on my configuration.
+In this case, the reverse proxy will intercept all traffic from =example.com=
+that enters my network and determine if the client is requesting valid data,
+based on my configuration.
-If the user is requesting =example.com= and my configuration files say
-that Server_{01} holds that data, Nginx will send the user to
-Server_{01}. If I were to change the configuration so that =example.com=
-is routed to Server_{02}, that same user would be sent to Server_{02}
-instead.
+If the user is requesting =example.com= and my configuration files say that
+Server_{01} holds that data, Nginx will send the user to Server_{01}. If I were
+to change the configuration so that =example.com= is routed to Server_{02}, that
+same user would be sent to Server_{02} instead.
#+begin_src txt
┌──────┐ ┌───────────┐
@@ -50,9 +48,9 @@ instead.
* Reverse Proxy Options
-There are a lot of options when it comes to reverse proxy servers, so
-I'm just going to list a few of the options I've heard recommended over
-the last few years:
+There are a lot of options when it comes to reverse proxy servers, so I'm just
+going to list a few of the options I've heard recommended over the last few
+years:
- [[https://nginx.com][Nginx]]
- [[https://caddyserver.com][Caddy]]
@@ -60,42 +58,41 @@ the last few years:
- [[https://www.haproxy.org/][HAProxy]]
- [[https://ubuntu.com/server/docs/proxy-servers-squid][Squid]]
-In this post, we will be using Nginx as our reverse proxy, running on
-Ubuntu Server 20.04.4 LTS.
+In this post, we will be using Nginx as our reverse proxy, running on Ubuntu
+Server 20.04.4 LTS.
* Nginx Reverse Proxy Example
** Local Applications
-You may be like me and have a lot of applications running on your local
-network that you'd like to expose publicly with a domain.
+You may be like me and have a lot of applications running on your local network
+that you'd like to expose publicly with a domain.
-In my case, I have services running in multiple Docker containers within
-a single server and want a way to visit those services from anywhere
-with a URL. For example, on my local network,
-[[https://dashy.to][Dashy]] runs through port 4000 (=localhost:4000=)
-and [[https://github.com/louislam/uptime-kuma][Uptime Kuma]] runs
-through port 3001 (=localhost:3001=).
+In my case, I have services running in multiple Docker containers within a
+single server and want a way to visit those services from anywhere with a URL.
+For example, on my local network, [[https://dashy.to][Dashy]] runs through port 4000
+(=localhost:4000=) and [[https://github.com/louislam/uptime-kuma][Uptime Kuma]] runs through port 3001 (=localhost:3001=).
In order to expose these services to the public, I will need to do the
following:
-1. Set up DNS records for a domain or subdomain (one per service) to
- point toward the IP address of the server.
-2. Open up the server network's HTTP and HTTPS ports (80 & 443) so that
- the reverse proxy can accept traffic and determine where to send it.
+1. Set up DNS (Domain Name System) records for a domain or subdomain (one per
+ service) to point toward the internet protocol (IP) address of the server.
+2. Open up the server network's HTTP (Hypertext Transfer Protocol) and HTTPS
+ (Hypertext Transfer Protocol Secure) ports (80 & 443) so that the reverse
+ proxy can accept traffic and determine where to send it.
3. Install the reverse proxy software.
-4. Configure the reverse proxy to recognize which service should get
- traffic from any of the domains or subdomains.
+4. Configure the reverse proxy to recognize which service should get traffic
+ from any of the domains or subdomains.
** Step 1: DNS Configuration
-To start, update your DNS configuration so that you have an =A= record
-for each domain or subdomain.
+To start, update your DNS configuration so that you have an =A= record for each
+domain or subdomain.
-The =A= records should point toward the public IP address of the server.
-If you don't know the public IP address, log in to the server and run
-the following command:
+The =A= records should point toward the public IP address of the server. If you
+don't know the public IP address, log in to the server and run the following
+command:
#+begin_src sh
curl ifconfig.co
@@ -111,34 +108,30 @@ dashy.example.com A xxx.xxx.xxx.xxx
www CNAME example.com
#+end_src
-Finally, ensure the DNS has propagated correctly with
-[[https://dnschecker.org][DNS Checker]] by entering your domains or
-subdomains in the search box and ensuring the results are showing the
-correct IP address.
+Finally, ensure the DNS has propagated correctly with [[https://dnschecker.org][DNS Checker]] by entering
+your domains or subdomains in the search box and ensuring the results are
+showing the correct IP address.
** Step 2: Open Network Ports
-This step will be different depending on which router you have in your
-home. If you're not sure, try to visit
-[[http://192.168.1.1][192.168.1.1]] in your browser. Login credentials
-are usually written on a sticker somewhere on your modem/router.
+This step will be different depending on which router you have in your home. If
+you're not sure, try to visit [[http://192.168.1.1][192.168.1.1]] in your browser. Login credentials are
+usually written on a sticker somewhere on your modem/router.
-Once you're able to log in to your router, find the Port Forwarding
-settings. You will need to forward ports =80= and =443= to whichever
-machine is running the reverse proxy.
+Once you're able to log in to your router, find the Port Forwarding settings.
+You will need to forward ports =80= and =443= to whichever machine is running
+the reverse proxy.
-In my case, the table below shows the port-forwarding rules I've
-created. In this table, =xxx.xxx.xxx.xxx= is the local device IP of the
-reverse proxy server, it will probably be an IP between =192.168.1.1=
-and =192.168.1.255=.
+In my case, the table below shows the port-forwarding rules I've created. In
+this table, =xxx.xxx.xxx.xxx= is the local device IP of the reverse proxy
+server, it will probably be an IP between =192.168.1.1= and =192.168.1.255=.
| NAME | FROM PORT | DEST PORT/IP | ENABLED |
|-------+-----------+-----------------+---------|
| HTTP | 80 | xxx.xxx.xxx.xxx | TRUE |
| HTTPS | 443 | xxx.xxx.xxx.xxx | TRUE |
-Once configured, these rules will direct all web traffic to your reverse
-proxy.
+Once configured, these rules will direct all web traffic to your reverse proxy.
** Step 3: Nginx Installation
@@ -148,11 +141,11 @@ To install Nginx, simply run the following command:
sudo apt install nginx
#+end_src
-If you have a firewall enabled, open up ports =80= and =443= on your
-server so that Nginx can accept web traffic from the router.
+If you have a firewall enabled, open up ports =80= and =443= on your server so
+that Nginx can accept web traffic from the router.
-For example, if you want to use =ufw= for web traffic and SSH, run the
-following commands:
+For example, if you want to use =ufw= for web traffic and SSH, run the following
+commands:
#+begin_src sh
sudo ufw allow 'Nginx Full'
@@ -162,9 +155,8 @@ sudo ufw enable
** Step 4: Nginx Configuration
-Now that we have domains pointing toward the server, the only step left
-is to configure the reverse proxy to direct traffic from domains to
-local services.
+Now that we have domains pointing toward the server, the only step left is to
+configure the reverse proxy to direct traffic from domains to local services.
To start, you'll need to create a configuration file for each domain in
=/etc/nginx/sites-available/=. They will look identical except for the
@@ -204,22 +196,23 @@ server {
}
#+end_src
-Once the configuration files are created, you will need to enable them
-with the =symlink= command:
+Once the configuration files are created, you will need to enable them with the
+=symlink= command:
#+begin_src sh
sudo ln -s /etc/nginx/sites-available/dashy.example.com /etc/nginx/sites-enabled/
#+end_src
-Voilà! Your local services should now be available through their URLs.
+Voilà! Your local services should now be available through their URLs (uniform
+resource locators).
* HTTPS with Certbot
-If you've followed along, you'll notice that your services are only
-available via HTTP (not HTTPS).
+If you've followed along, you'll notice that your services are only available
+via HTTP (not HTTPS).
-If you want to enable HTTPS for your new domains, you will need to
-generate SSL/TLS certificates for them. The easiest way to generate
+If you want to enable HTTPS for your new domains, you will need to generate TLS
+(Transport Layer Security) certificates for them. The easiest way to generate
certificates on Nginx is [[https://certbot.eff.org][Certbot]]:
#+begin_src sh
diff --git a/content/blog/2022-04-09-pinetime.org b/content/blog/2022-04-09-pinetime.org
index d2347e5..24301b9 100644
--- a/content/blog/2022-04-09-pinetime.org
+++ b/content/blog/2022-04-09-pinetime.org
@@ -7,17 +7,15 @@
** Overview
-The [[https://www.pine64.org/pinetime/][PineTime]] is an open-source
-smartwatch, created by [[https://www.pine64.org][PINE64]]. Originally
-announced in September 2019, this ARM-based watch is a fantastic option
-for users who want the benefits of a modern smartwatch with the backing
-of open-source components and software.
+The [[https://www.pine64.org/pinetime/][PineTime]] is an open-source smartwatch, created by [[https://www.pine64.org][PINE64]]. Originally
+announced in September 2019, this ARM-based watch is a fantastic option for
+users who want the benefits of a modern smartwatch with the backing of
+open-source components and software.
** Product Specifications
-I won't dive into too many details that you can find on
-[[https://www.pine64.org/pinetime/][the product page]], but I wanted to
-point out the prices for each watch and the primary functions:
+I won't dive into too many details that you can find on [[https://www.pine64.org/pinetime/][the product page]], but I
+wanted to point out the prices for each watch and the primary functions:
1. Price:
@@ -38,52 +36,48 @@ point out the prices for each watch and the primary functions:
* Unboxing
-Now, my PineTime was ordered on 2022-02-17, shipped on 2022-02-22, and
-was delivered on 2022-03-23. With the current delays on shipping times
-around the world (and the semiconductor shortage), a month for delivery
-from China seems reasonable to me.
+Now, my PineTime was ordered on 2022-02-17, shipped on 2022-02-22, and was
+delivered on 2022-03-23. With the current delays on shipping times around the
+world (and the semiconductor shortage), a month for delivery from China seems
+reasonable to me.
-The packaging is simple, and the watch comes with instructions,
-technical information, the watch, and a charger (it does not include a
-USB wall adapter).
+The packaging is simple, and the watch comes with instructions, technical
+information, the watch, and a charger (it does not include a USB wall adapter).
-The watch itself was able to turn on immediately when I pulled it out of
-the box, but the battery was depleted and required charging right away.
+The watch itself was able to turn on immediately when I pulled it out of the
+box, but the battery was depleted and required charging right away.
* Software
-** Watch OS: InfiniTime
+** Watch Operating System (OS): InfiniTime
-While turning on the watch for the first time, some of the main design
-choices you can see in the watch OS,
-[[https://wiki.pine64.org/wiki/InfiniTime][InfiniTime]], are:
+While turning on the watch for the first time, some of the main design choices
+you can see in the watch OS, [[https://wiki.pine64.org/wiki/InfiniTime][InfiniTime]], are:
- A square bezel, not too thin against the sides of the watch.
- A simple, rubber band.
- Basic font and screen pixel design.
- Swipe gestures to access other screens.
-The OS itself is fantastic in terms of functionality for me. It does
-exactly what a smartwatch should do - track time, steps, heart rates,
-and connect to another smart device, without being overly burdensome to
-the user.
+The OS itself is fantastic in terms of functionality for me. It does exactly
+what a smartwatch should do - track time, steps, heart rates, and connect to
+another smart device, without being overly burdensome to the user.
-My only gripe so far is that it's /really/ difficult to swipe to
-different screens, such as pulling down the notification tray. I'm not
-sure if this is an OS or hardware issue, but it makes it quite hard to
-quickly move around the screens.
+My only gripe so far is that it's /really/ difficult to swipe to different
+screens, such as pulling down the notification tray. I'm not sure if this is an
+OS or hardware issue, but it makes it quite hard to quickly move around the
+screens.
-However, my absolute favorite design choice is that the button the side
-turns the screen on and off and tilting/waving my wrist doesn't
-accidentally turn on the screen. With other watches, I absolutely hated
-not being able to turn off the raise-to-wake or wave features (i.e.,
-blinding myself while wearing a watch at night because I moved my arm).
+However, my absolute favorite design choice is that the button the side turns
+the screen on and off and tilting/waving my wrist doesn't accidentally turn on
+the screen. With other watches, I absolutely hated not being able to turn off
+the raise-to-wake or wave features (i.e., blinding myself while wearing a watch
+at night because I moved my arm).
** iOS App: InfiniLink
-Since I am using iOS as my primary mobile device OS, I am using the
-[[https://github.com/xan-m/InfiniLink][InfiniLink]] app to connect my
-watch.
+Since I am using iOS as my primary mobile device OS, I am using the [[https://github.com/xan-m/InfiniLink][InfiniLink]]
+app to connect my watch.
This app provides the following for PineTime owners:
@@ -92,47 +86,45 @@ This app provides the following for PineTime owners:
- Charts
- Notifications
-Another big feature of InfiniLink is the ability to track pedometer
-steps in a collection of beautiful graphs, with the option to change
-your step goal and add in manual steps.
+Another big feature of InfiniLink is the ability to track pedometer steps in a
+collection of beautiful graphs, with the option to change your step goal and add
+in manual steps.
-Finally, there are charts to display the battery percentage and heart
-rates over time. This area also comes with an option to clear data.
+Finally, there are charts to display the battery percentage and heart rates over
+time. This area also comes with an option to clear data.
* Final Thoughts
** Pros
-After wearing my watch for a few weeks, I have mostly positive thoughts
-about the watch so far. In the past, I have owned smartwatches by
-FitBit, Fossil, Apple, etc. - *but I prefer the PineTime over all of
-those watches*.
+After wearing my watch for a few weeks, I have mostly positive thoughts about
+the watch so far. In the past, I have owned smartwatches by FitBit, Fossil,
+Apple, etc. - *but I prefer the PineTime over all of those watches*.
-The PineTime strips out all the unnecessary features and performs the
-functions that it provides effectively and efficiently.
+The PineTime strips out all the unnecessary features and performs the functions
+that it provides effectively and efficiently.
-The battery life is amazing on this device. By default, the watch seems
-to last anywhere from a few days to a week before dying.
+The battery life is amazing on this device. By default, the watch seems to last
+anywhere from a few days to a week before dying.
And of course, it's open source and backed by some of the most dedicated
-enthusiasts and developers I've seen. Watching the Matrix channel,
-forums, and website have been exciting to see.
+enthusiasts and developers I've seen. Watching the Matrix channel, forums, and
+website have been exciting to see.
** Cons
-If I had to complain about anything, it would simply be the small bugs
-in some features that can be contributed to the companion apps more than
-the watch itself.
+If I had to complain about anything, it would simply be the small bugs in some
+features that can be contributed to the companion apps more than the watch
+itself.
-A regular user would want native notification support out-of-the-box,
-which is the biggest item not working for me at the moment.
+A regular user would want native notification support out-of-the-box, which is
+the biggest item not working for me at the moment.
-My only other complaint is that the battery indicator on the watch
-doesn't seem accurate when it's nearing depletion - it seems that
-there's a bit of battery life left and then my watch is dead very
-suddenly after. This could just be me misinterpreting the battery level
-icons, but it has fooled me a few times into thinking I had more battery
-left than I actually did.
+My only other complaint is that the battery indicator on the watch doesn't seem
+accurate when it's nearing depletion - it seems that there's a bit of battery
+life left and then my watch is dead very suddenly after. This could just be me
+misinterpreting the battery level icons, but it has fooled me a few times into
+thinking I had more battery left than I actually did.
-Other than those small items, I really do love this watch and am glad I
-replaced my Apple Watch with the PineTime.
+Other than those small items, I really do love this watch and am glad I replaced
+my Apple Watch with the PineTime.
diff --git a/content/blog/2022-06-01-ditching-cloudflare.org b/content/blog/2022-06-01-ditching-cloudflare.org
index 755681c..8b02e29 100644
--- a/content/blog/2022-06-01-ditching-cloudflare.org
+++ b/content/blog/2022-06-01-ditching-cloudflare.org
@@ -5,91 +5,84 @@
* Registrar
-After spending a year or so using Cloudflare for DNS only - no proxying
-or applications - I spent the last few months using Cloudflare Tunnels
-and Cloudflare Access to protect my self-hosted websites and
+After spending a year or so using Cloudflare for DNS (Domain Name System) only -
+no proxying or applications - I spent the last few months using Cloudflare
+Tunnels and Cloudflare Access to protect my self-hosted websites and
applications via their proxy traffic model.
-However, I have never liked using Cloudflare due to their increasingly
-large share of control over web traffic, as well as their business model
-of being a MITM for all of your traffic.
+However, I have never liked using Cloudflare due to their increasingly large
+share of control over web traffic, as well as their business model of being a
+MITM (man-in-the-middle) for all of your traffic.
-So, as of today, I have switched over to [[https://njal.la][Njalla]] as
-my registrar and DNS manager. I was able to easily transfer my domains
-over rapidly, with only one domain taking more than 15-30 minutes to
-propagate.
+So, as of today, I have switched over to [[https://njal.la][Njalla]] as my registrar and DNS manager.
+I was able to easily transfer my domains over rapidly, with only one domain
+taking more than 15-30 minutes to propagate.
-+I do still have two domains sitting at Cloudflare for the moment while
-I decide if they're worth the higher rates (one domain is 30€ and the
-other is 45€).+
++I do still have two domains sitting at Cloudflare for the moment while I decide
+if they're worth the higher rates (one domain is 30€ and the other is 45€).+
#+begin_quote
-*Update (2022.06.03)*: I ended up transferring my final two domains over
-to Njalla, clearing my Cloudflare account of personal data, and deleting
-the Cloudflare account entirely. /I actually feel relieved to have moved
-on to a provider I trust./
+*Update (2022.06.03)*: I ended up transferring my final two domains over to
+Njalla, clearing my Cloudflare account of personal data, and deleting the
+Cloudflare account entirely. /I actually feel relieved to have moved on to a
+provider I trust./
#+end_quote
* DNS
-As noted above, I'm using Njalla exclusively for DNS configurations on
-my domains.
+As noted above, I'm using Njalla exclusively for DNS configurations on my
+domains.
-However, the transfer process was not ideal. As soon as the domains
-transferred over, I switched the nameservers from Cloudflare to Njalla
-and lost most of the associated DNS records. So, the majority of the
-time spent during the migration was simply re-typing all the DNS records
-back in one-by-one.
+However, the transfer process was not ideal. As soon as the domains transferred
+over, I switched the nameservers from Cloudflare to Njalla and lost most of the
+associated DNS records. So, the majority of the time spent during the migration
+was simply re-typing all the DNS records back in one-by-one.
-This would be much simpler if I were able to edit the plain-text format
-of the DNS configuration. I was able to do that at a past registrar
-(perhaps it was [[https://gandi.net/][Gandi.net]]?) and it made life a
-lot easier.
+This would be much simpler if I were able to edit the plain-text format of the
+DNS configuration. I was able to do that at a past registrar (perhaps it was
+[[https://gandi.net/][Gandi.net]]?) and it made life a lot easier.
** Dynamic DNS Updates
I have built an easy Python script to run (or set-up in =cron= to run
-automatically) that will check my server's IPv4 and IPv6, compare it to
-Njalla, and update the DNS records if they don't match. You can see the
-full script and process in my other post: [[../njalla-dns-api/][Updating
-Dynamic DNS with Njalla API]].
+automatically) that will check my server's IPv4 (Internet Protocol version 4)and
+IPv6 (Internet Protocol version 6), compare it to Njalla, and update the DNS
+records if they don't match. You can see the full script and process in my other
+post: [[https://cleberg.net/blog/njalla-dns-api.html][Automating Dynamic DNS Record Updates via Njalla API]].
-I haven't used this other method, but I do know that you can create
-=Dynamic= DNS records with Njalla that
-[[https://njal.la/docs/ddns/][work for updating dynamic subdomains]].
+I haven't used this other method, but I do know that you can create =Dynamic=
+DNS records with Njalla that [[https://njal.la/docs/ddns/][work for updating dynamic subdomains]].
** Njalla's DNS Tool
-One neat upside to Njalla is that they have a
-[[https://check.njal.la/dns/][DNS lookup tool]] that provides a lot of
-great information for those of you (AKA: me) who hate using the =dig=
+One neat upside to Njalla is that they have a [[https://check.njal.la/dns/][DNS lookup tool]] that provides a
+lot of great information for those of you (AKA: me) who hate using the =dig=
command.
-This was very useful for monitoring a couple of my transferred domains
-to see when the changes in nameservers, records, and DNSSEC went into
-effect.
+This was very useful for monitoring a couple of my transferred domains to see
+when the changes in nameservers, records, and DNSSEC (Domain Name System
+Security Extensions) went into effect.
* Tunnel
Cloudflare Tunnel is a service that acts as a reverse-proxy (hosted on
-Cloudflare's servers) and allowed me to mask the private IP address of
-the server hosting my various websites and apps.
-
-However, as I was moving away from Cloudflare, I was not able to find a
-suitable replacement that was both inexpensive and simple. So, I simply
-went back to hosting [[https://cleberg.net/blog/set-up-nginx-reverse-proxy/][my own
-reverse proxy with Nginx]]. With the recent additions of Unifi hardware
-in my server/network rack, I am much more protected against spam and
+Cloudflare's servers) and allowed me to mask the private internet protocol (IP)
+address of the server hosting my various websites and apps.
+
+However, as I was moving away from Cloudflare, I was not able to find a suitable
+replacement that was both inexpensive and simple. So, I simply went back to
+hosting [[https://cleberg.net/blog/set-up-nginx-reverse-proxy/][my own reverse proxy with Nginx]]. With the recent additions of Unifi
+hardware in my server/network rack, I am much more protected against spam and
malicious attacks at the network edge than I was before I switched to
Cloudflare.
* Access
-Cloudflare Access, another app I used in combination with Cloudflare
-Tunnel, provided an authentication screen that required you to enter
-valid credentials before Cloudflare would forward you to the actual
-website or app (if the website/app has their own authentication, you'd
-then have to authenticate a second time).
+Cloudflare Access, another app I used in combination with Cloudflare Tunnel,
+provided an authentication screen that required you to enter valid credentials
+before Cloudflare would forward you to the actual website or app (if the
+website/app has their own authentication, you'd then have to authenticate a
+second time).
-I did not replace this service with anything since I only host a handful
-of non-sensitive apps that don't require duplicate authentication.
+I did not replace this service with anything since I only host a handful of
+non-sensitive apps that don't require duplicate authentication.
diff --git a/content/blog/2022-06-07-self-hosting-freshrss.org b/content/blog/2022-06-07-self-hosting-freshrss.org
index 4b54cd9..b356f44 100644
--- a/content/blog/2022-06-07-self-hosting-freshrss.org
+++ b/content/blog/2022-06-07-self-hosting-freshrss.org
@@ -3,47 +3,43 @@
#+description: Stepwise instructions for installing FreshRSS using Docker and configuring Nginx as a reverse proxy to enable secure and synchronized RSS feed access.
#+slug: self-hosting-freshrss
-* Why RSS?
+* Why Use Really Simple Syndication (RSS)?
-After noticing that I have collected 50+ blogs as bookmarks, I decided
-to migrate back to using RSS feeds to stay up-to-date with my favorite
-websites. Using RSS allows me to read all of these posts in a single app
-(on both mobile & desktop) and allows me to be notified when new posts
-are available.
+After noticing that I have collected 50+ blogs as bookmarks, I decided to
+migrate back to using RSS feeds to stay up-to-date with my favorite websites.
+Using RSS allows me to read all of these posts in a single app (on both mobile &
+desktop) and allows me to be notified when new posts are available.
-However, I ran into one issue: syncing subscriptions and read/unread
-posts across devices. Since I want to be able to easily read on both
-mobile and desktop, I decided to look for a self-hosted RSS solution.
+However, I ran into one issue: syncing subscriptions and read/unread posts
+across devices. Since I want to be able to easily read on both mobile and
+desktop, I decided to look for a self-hosted RSS solution.
-Thus, I found [[https://www.freshrss.org/][FreshRSS]] and was able to
-successfully install it on my server in about 30 minutes.
+Thus, I found [[https://www.freshrss.org/][FreshRSS]] and was able to successfully install it on my server in
+about 30 minutes.
* Documentation
-While it's certainly not robust, the
-[[https://freshrss.github.io/FreshRSS/][FreshRSS documentation]] is
-helpful for figuring out basic information about the service.
+While it's certainly not robust, the [[https://freshrss.github.io/FreshRSS/][FreshRSS documentation]] is helpful for
+figuring out basic information about the service.
-However, I wanted to install this service as a Docker container and
-stumbled across the
-[[https://github.com/FreshRSS/FreshRSS/tree/edge/Docker][Docker README]]
-within the GitHub repository.
+However, I wanted to install this service as a Docker container and stumbled
+across the [[https://github.com/FreshRSS/FreshRSS/tree/edge/Docker][Docker README]] within the GitHub repository.
-This README was the documentation I actually needed. However, as you'll
-see below, I still had to manually edit one file (=config.php=) to
-access the API externally via my RSS apps.
+This README was the documentation I actually needed. However, as you'll see
+below, I still had to manually edit one file (=config.php=) to access the API
+externally via my RSS apps.
* Installation
** DNS
-The first step, as required by any external web service, was assigning a
-domain name to use. I chose to use a subdomain, like =rss.example.com=.
+The first step, as required by any external web service, was assigning a domain
+name to use. I chose to use a subdomain, like =rss.example.com=.
To assign this, I created an =A= record in my DNS settings with the IPv4
-address of the server and an =AAAA= record with the IPv6 address of the
-server. Note: assigning an IPv6 (=AAAA=) record is optional, but I like
-to enable IPV6 for my services.
+(Internet Protocol version 4) address of the server and an =AAAA= record with
+the IPv6 (Internet Protocol version 6) address of the server. Note: assigning an
+IPv6 (=AAAA=) record is optional, but I like to enable IPV6 for my services.
#+begin_src config
rss.example.com A xxx.xxx.xxx.xxx
@@ -52,11 +48,10 @@ rss.example.com AAAA xxxx:xxxx: ... :xxxx
** Docker
-I initially tried to set up a =docker-compose.yml= file with a =.env=
-file because I prefer to have a file I can look back at later to see how
-I initially started the container, but it simply wouldn't work for me.
-I'm not sure why, but I assume I wasn't telling =docker-compose= where
-the =.env= file was.
+I initially tried to set up a =docker-compose.yml= file with a =.env= file
+because I prefer to have a file I can look back at later to see how I initially
+started the container, but it simply wouldn't work for me. I'm not sure why, but
+I assume I wasn't telling =docker-compose= where the =.env= file was.
Regardless, I chose to simply run the service with =docker run=. See the
following command for my =docker run= configuration:
@@ -72,25 +67,24 @@ sudo docker run -d --restart unless-stopped --log-opt max-size=10m \
freshrss/freshrss
#+end_src
-This started the container successfully and allowed me to visit the
-FreshRSS instance at =localhost:8080=.
+This started the container successfully and allowed me to visit the FreshRSS
+instance at =localhost:8080=.
** Fresh RSS Set-Up
-I *HIGHLY* suggest that you set up your user account prior to exposing
-this service to the public. It's unlikely that someone is trying to
-access the exact domain or IP/port you're assigning here, but as soon as
-you expose this service, the first person to open the URL will be able
-to create the admin user.
+I *HIGHLY* suggest that you set up your user account prior to exposing this
+service to the public. It's unlikely that someone is trying to access the exact
+domain or IP/port you're assigning here, but as soon as you expose this service,
+the first person to open the URL will be able to create the administrative user.
-In order to set up your FreshRSS service, open the =localhost:8080= URL
-in your browser (you may need to use a local IP instead of =localhost=
-if you're accessing the page from a different machine on the network -
-e.g., =192.168.1.20:8080=).
+In order to set up your FreshRSS service, open the =localhost:8080= URL in your
+browser (you may need to use a local internet protocol (IP) instead of
+=localhost= if you're accessing the page from a different machine on the
+network - e.g., =192.168.1.20:8080=).
Once the page loads, set up your default user with a strong username and
-password. You may also choose to configure other settings prior to
-exposing this service.
+password. You may also choose to configure other settings prior to exposing this
+service.
** Nginx Reverse-Proxy
@@ -103,7 +97,7 @@ First, I created a new Nginx configuration file:
sudo nano /etc/nginx/sites-available/rss.example.com
#+end_src
-Within the config file, I pasted the following code:
+Within the configuration file, I pasted the following code:
#+begin_src config
upstream freshrss {
@@ -136,8 +130,7 @@ server {
}
#+end_src
-Finally, restart Nginx and you will be able to access your service via
-HTTP:
+Finally, restart Nginx and you will be able to access your service via HTTP (Hypertext Transfer Protocol):
#+begin_src sh
sudo systemctl restart nginx.service
@@ -145,49 +138,46 @@ sudo systemctl restart nginx.service
** HTTPS
-However, I don't want to access my RSS feeds via HTTP. I want it
-available only via HTTPS. In order to do this, I ran the
-[[https://certbot.eff.org/][certbot]] program to generate SSL
-certificates for me:
+However, I don't want to access my RSS feeds via HTTP. I want it available only
+via HTTPS (Hypertext Transfer Protocol Secure). In order to do this, I ran the
+[[https://certbot.eff.org/][certbot]] program to generate SSL (Secure Socket Layer) certificates for me:
#+begin_src sh
sudo certbot --nginx
#+end_src
-This process will automatically generate an SSL certificate for you and
-modify the Nginx configuration file to include a redirect from HTTP to
-HTTPS.
+This process will automatically generate an SSL certificate for you and modify
+the Nginx configuration file to include a redirect from HTTP to HTTPS.
* Post-Installation Fixes
-At this point, we have a functional FreshRSS website, available from
-anywhere and secured with HTTPS. However, attempting to connect this
-service to an RSS app resulted in many errors regarding unavailable URLs
-and incorrect credentials.
+At this point, we have a functional FreshRSS website, available from anywhere
+and secured with HTTPS. However, attempting to connect this service to an RSS
+app resulted in many errors regarding unavailable URLs and incorrect
+credentials.
** API Set-Up
-First, you need to open your user profile in FreshRSS (=Settings= >
-=Profile=) and set an API password in the field at the bottom. This is
-the password you will need to provide to your RSS apps.
+First, you need to open your user profile in FreshRSS (=Settings= > =Profile=)
+and set an API password in the field at the bottom. This is the password you
+will need to provide to your RSS apps.
-Once that is set and saved, click the link below the API password field
-to open the API check tool. It should look something like
-=https://localhost:8080/api/= or =https://rss.example.com/api/=.
+Once that is set and saved, click the link below the API password field to open
+the API (application programming interface) check tool. It should look something
+like =https://localhost:8080/api/= or =https://rss.example.com/api/=.
-Within this page, you /should/ see your correct external URL and "PASS"
-at the bottom of each API type. This would mean everything is set up
-correctly, and you can now move on and login to any RSS apps that
-support self-hosted options.
+Within this page, you /should/ see your correct external URL and "PASS" at the
+bottom of each API type. This would mean everything is set up correctly, and you
+can now move on and login to any RSS apps that support self-hosted options.
In my case, the URL showed an internal URL and I had a warning that the
-=base_url= variable may be misconfigured. If this is the case, see the
-next section for a fix.
+=base_url= variable may be misconfigured. If this is the case, see the next
+section for a fix.
** Base URL Fix
-In order to fix the =base_url= for the API, I opened up my docker
-container with the following command:
+In order to fix the =base_url= for the API, I opened up my docker container with
+the following command:
#+begin_src sh
sudo docker exec -it freshrss bash
@@ -206,9 +196,10 @@ Finally, open up =config.php= in the =data= directory:
nano data/config.php
#+end_src
-Within =config.php=, you will need to update the =base_url= variable and
-update it to match your external URL. In my case, I simply commented-out
-the incorrect URL with =//= and added the correct one on a new line:
+Within =config.php=, you will need to update the =base_url= variable and update
+it to match your external URL (uniform resource locator). In my case, I simply
+commented-out the incorrect URL with =//= and added the correct one on a new
+line:
#+begin_src php
<?php
@@ -221,8 +212,8 @@ the incorrect URL with =//= and added the correct one on a new line:
>
#+end_src
-You can now exit the file with =Ctrl + x=, press =y= to save the file,
-and then click =Enter= to keep the same file name.
+You can now exit the file with =Ctrl + x=, press =y= to save the file, and then
+click =Enter= to keep the same file name.
Finally, just exit out of the docker container:
@@ -236,8 +227,7 @@ Next, just restart the container:
sudo docker restart freshrss
#+end_src
-Voilà! Your API check should now "PASS" and you should be able to use
-one of the API URLs in your RSS apps.
+Voilà! Your API check should now "PASS" and you should be able to use one of the
+API URLs in your RSS apps.
-In my case, I use [[https://netnewswire.com][NetNewsWire]] on my desktop
-and phone.
+In my case, I use [[https://netnewswire.com][NetNewsWire]] on my desktop and phone.
diff --git a/content/blog/2022-06-16-terminal-lifestyle.org b/content/blog/2022-06-16-terminal-lifestyle.org
index 09c4398..b602875 100644
--- a/content/blog/2022-06-16-terminal-lifestyle.org
+++ b/content/blog/2022-06-16-terminal-lifestyle.org
@@ -5,29 +5,27 @@
* Text-Based Simplicity
-I've detailed my views on web-based minimalism and related topics in
-other posts throughout the years; e.g., JavaScript/CSS bloat slowing
-down websites that are essentially a text document. However, I have
-never really expanded beyond talking about the web and describing how I
-focus on minimizing distractions in other digital environments.
-
-This post is going to set the baseline for how I /try/ to live my
-digital life. It does not necessarily get into my physical life, which
-is often harder to control and contain all the noise in our modern
-world.
-
-While there are new things to do every day in our digital world, I find
-that keeping a core set of values and interests can ground you and keep
-you mindful of /why/ you are participating in the digital world. For
-example, if - at your core - you have no interest in what strangers
-think about random topics, it would be unwise to start participating in
-social media. However, I am someone who has been dragged in by effective
-advertising to participate in communities that I realize I do not care
-for.
-
-I won't dive much further into explaining the philosophy of all this,
-but I will link a few helpful articles that may pique your interest if
-you're in search of more meaningful experiences:
+I've detailed my views on web-based minimalism and related topics in other posts
+throughout the years; e.g., JavaScript/CSS (Cascading Style Sheets) bloat
+slowing down websites that are essentially a text document. However, I have
+never really expanded beyond talking about the web and describing how I focus on
+minimizing distractions in other digital environments.
+
+This post is going to set the baseline for how I /try/ to live my digital life.
+It does not necessarily get into my physical life, which is often harder to
+control and contain all the noise in our modern world.
+
+While there are new things to do every day in our digital world, I find that
+keeping a core set of values and interests can ground you and keep you mindful
+of /why/ you are participating in the digital world. For example, if - at your
+core - you have no interest in what strangers think about random topics, it
+would be unwise to start participating in social media. However, I am someone
+who has been dragged in by effective advertising to participate in communities
+that I realize I do not care for.
+
+I won't dive much further into explaining the philosophy of all this, but I will
+link a few helpful articles that may pique your interest if you're in search of
+more meaningful experiences:
- [[https://en.wikipedia.org/wiki/Mindfulness][Mindfulness]]
- [[https://en.wikipedia.org/wiki/Minimalism][Minimalism]]
@@ -35,125 +33,111 @@ you're in search of more meaningful experiences:
* Living Life in the Terminal
-My personal approach to reducing digital distractions and increasing my
-focus on the task at hand is to use a terminal for as much as I possibly
-can.
+My personal approach to reducing digital distractions and increasing my focus on
+the task at hand is to use a terminal for as much as I possibly can.
-Most days, this means that I have a few tabs open constantly in my
-terminal:
+Most days, this means that I have a few tabs open constantly in my terminal:
1. A web browser
2. A chat client
3. An email client
-4. An RSS feed reader
+4. An RSS (Really Simple Syndication) feed reader
5. A local shell for navigating my computer's files
6. A remote shell for managing servers and other machines
-Beyond this, I rarely open other tabs or GUI applications, unless
-absolutely necessary. If you look, you may be surprised what can be
-accomplished in the terminal.
+Beyond this, I rarely open other tabs or graphical applications, unless
+absolutely necessary. If you look, you may be surprised what can be accomplished
+in the terminal.
-For example, I have moved my music and entertainment downloads to the
-terminal, along with my device VPN connections. I am exploring options
-for moving my RSS subscriptions to something like
-[[https://newsboat.org/][Newsboat]], so that I can read my daily
-articles without all the fuss.
+For example, I have moved my music and entertainment downloads to the terminal,
+along with my device virtual private network (VPN) connections. I am exploring
+options for moving my RSS subscriptions to something like [[https://newsboat.org/][Newsboat]], so that I
+can read my daily articles without all the fuss.
-Now that we have some examples out of the way, let's dive into the
-specifics.
+Now that we have some examples out of the way, let's dive into the specifics.
** Browsing the Web
-I'm going to start off with a hard topic for those who prefer to live in
-the terminal: web browsing. This task is made hard mostly by websites
-and web apps that require JavaScript to run. The other difficult part is
-that if you're using a text-based browser, that means images won't load
-(hopefully that's obvious).
+I'm going to start off with a hard topic for those who prefer to live in the
+terminal: web browsing. This task is made hard mostly by websites and web apps
+that require JavaScript to run. The other difficult part is that if you're using
+a text-based browser, that means images won't load (hopefully that's obvious).
-I am using [[https://lynx.invisible-island.net][Lynx]], a text-based
-browser that runs quickly and easily in the terminal. Lynx allows me to
-browser most websites by simply typing =g= and then typing in the URL I
-want.
+I am using [[https://lynx.invisible-island.net][Lynx]], a text-based browser that runs quickly and easily in the
+terminal. Lynx allows me to browser most websites by simply typing =g= and then
+typing in the URL I want.
-If you need a search engine while in Lynx, I recommend
-[[https://lite.duckduckgo.com/lite/][DuckDuckGo (Lite)]], which allows
-you to search the web using their text-only interface.
+If you need a search engine while in Lynx, I recommend [[https://lite.duckduckgo.com/lite/][DuckDuckGo (Lite)]], which
+allows you to search the web using their text-only interface.
-Eventually, you will run into websites that don't work (or are just too
-ugly and messy) in a text-only mode, and you'll be forced to switch over
-to a GUI browser to look at that site. Personally, I don't mind this as
-it doesn't happen as often as I thought it would.
+Eventually, you will run into websites that don't work (or are just too ugly and
+messy) in a text-only mode, and you'll be forced to switch over to a GUI browser
+to look at that site. Personally, I don't mind this as it doesn't happen as
+often as I thought it would.
-The only time I need to do this is when I want to browse an
-image/video-focused webpage or if I need to log in to a site, and it
-doesn't support a text-only login page. For example, I am able to easily
-log in to [[https://sr.ht][Sourcehut]] in lynx.
+The only time I need to do this is when I want to browse an image/video-focused
+webpage or if I need to log in to a site, and it doesn't support a text-only
+login page. For example, I am able to easily log in to [[https://sr.ht][Sourcehut]] in lynx.
** Chatting with Friends
-After web browsing activities, my main form of terminal communication is
-Matrix. I use the [[https://docs.mau.fi/gomuks/][gomuks]] client
-currently.
+After web browsing activities, my main form of terminal communication is Matrix.
+I use the [[https://docs.mau.fi/gomuks/][gomuks]] client currently.
-This was incredibly easy to install on macOS (but I will need to see if
-it'll be just as easy on Linux when my new laptop arrives):
+This was incredibly easy to install on macOS (but I will need to see if it'll be
+just as easy on Linux when my new laptop arrives):
#+begin_src sh
brew install gomuks
#+end_src
-Once you launch gomuks, it will sync and require your username and
-password to login. After doing so, the only problem I ran into was
-verifying my gomuks client so that I could participate in rooms with
-E2EE.
+Once you launch gomuks, it will sync and require your username and password to
+login. After doing so, the only problem I ran into was verifying my gomuks
+client so that I could participate in rooms with E2EE (end-to-end encryption).
-Finally, I was able to verify the session by opening the Element desktop
-app (I assume you can do this in the browser and mobile app too, but I'm
-not sure) and manually verifying myself with this process:
+Finally, I was able to verify the session by opening the Element desktop app (I
+assume you can do this in the browser and mobile app too, but I'm not sure) and
+manually verifying myself with this process:
1. Open the Element desktop app
2. Open a room I was a member of
3. Open the =Room Info= pane
4. Open the =People= menu and search for myself
5. Click on my profile name
-6. Click on the session link under the =Security= section and follow the
- prompts to manually verify the session
+6. Click on the session link under the =Security= section and follow the prompts
+ to manually verify the session
-Overall, I like gomuks and am able to enjoy all the features I was using
-in Element. The only hiccup I have occurred is manually downloading
-images to view them, which can be annoying.
+Overall, I like gomuks and am able to enjoy all the features I was using in
+Element. The only hiccup I have occurred is manually downloading images to view
+them, which can be annoying.
** Email
-Moving email to the terminal has been the hardest of the tasks for me.
-Unlike web browsing, where I can simply decide to not look at a website
-that does not work in the terminal, I cannot simply ignore emails sent
-to me.
+Moving email to the terminal has been the hardest of the tasks for me. Unlike
+web browsing, where I can simply decide to not look at a website that does not
+work in the terminal, I cannot simply ignore emails sent to me.
-Personally, I am experimenting with [[https://neomutt.org/][neomutt]] as
-a potential email client.
+Personally, I am experimenting with [[https://neomutt.org/][neomutt]] as a potential email client.
-However, this requires a *TON* of configuration and tweaking to get
-right. Even when I was able to set up neomutt, configure my email
-account, and customize a few personal preferences, a lot of emails still
-do not display correctly (mostly due to HTML and images).
+However, this requires a *TON* of configuration and tweaking to get right. Even
+when I was able to set up neomutt, configure my email account, and customize a
+few personal preferences, a lot of emails still do not display correctly (mostly
+due to HTML (Hypertext Markup Language) and images).
-I won't get into the details of configuring =neomutt=; I mostly followed
-this blog post:
-[[https://gideonwolfe.com/posts/workflow/neomutt/intro/][Email in the
-Terminal: Configuring Neomutt]].
+I won't get into the details of configuring =neomutt=; I mostly followed this
+blog post: [[https://gideonwolfe.com/posts/workflow/neomutt/intro/][Email in the Terminal: Configuring Neomutt]].
-Finally, I have yet to figure out how to connect my GPG keys to
-=neomutt=, but that's a problem for another day.
+Finally, I have yet to figure out how to connect my PGP (Pretty Good Privacy)
+keys to =neomutt=, but that's a problem for another day.
** RSS Feed Reader
-I have just started using [[https://newsboat.org/][Newsboat]] to read
-articles in my terminal and have found quick success with it.
+I have just started using [[https://newsboat.org/][Newsboat]] to read articles in my terminal and have
+found quick success with it.
-The configuration was super easy for this app; I simply installed the
-app, created a file for URLs, and imported my OPML subscriptions that I
-had exported out of my old feed reader:
+The configuration was super easy for this app; I simply installed the app,
+created a file for URLs, and imported my OPML (Outline Processor Markup
+Language) subscriptions that I had exported out of my old feed reader:
#+begin_src sh
brew install newsboat
@@ -169,13 +153,12 @@ newsboat -i=my_subscriptions.opml
** Writing & Programming
-Unfortunately, the weak link in my terminal-based environment right now
-is my grasp of the possibilities of editing files within a shell.
+Unfortunately, the weak link in my terminal-based environment right now is my
+grasp of the possibilities of editing files within a shell.
-I am used to the easy extensions found in VSCodium and Kate, so I am
-slowly learning how to mold the default editing tools to my needs.
-Currently, this means I am using =nano= with the following
-configuration:
+I am used to the easy extensions found in VSCodium and Kate, so I am slowly
+learning how to mold the default editing tools to my needs. Currently, this
+means I am using =nano= with the following configuration:
#+begin_src config
set breaklonglines
@@ -187,15 +170,14 @@ set fill 80
#+end_src
This configuration allows nano to automatically hard-wrap lines at 80
-characters, autoindent the wrapped lines (if the previous line was
-indented), use 2 spaces per tab, and display line numbers within each
-file I open.
-
-I am currently looking to see if =vim= or =emacs= would be more useful
-for my current needs, but I'm not in any rush, so I don't expect to find
-an answer anytime soon.
-
-With my current life demands, I am not programming at the moment and
-have not explored the best terminal set-up for programming. However, I
-have seen many peers find success configuring =vim= and =emacs=, so
-that's where I will start when I pick my projects back up.
+characters, autoindent the wrapped lines (if the previous line was indented),
+use 2 spaces per tab, and display line numbers within each file I open.
+
+I am currently looking to see if =vim= or =emacs= would be more useful for my
+current needs, but I'm not in any rush, so I don't expect to find an answer
+anytime soon.
+
+With my current life demands, I am not programming at the moment and have not
+explored the best terminal set-up for programming. However, I have seen many
+peers find success configuring =vim= and =emacs=, so that's where I will start
+when I pick my projects back up.
diff --git a/content/blog/2022-06-22-daily-poetry.org b/content/blog/2022-06-22-daily-poetry.org
index cb0a73f..a51db06 100644
--- a/content/blog/2022-06-22-daily-poetry.org
+++ b/content/blog/2022-06-22-daily-poetry.org
@@ -14,8 +14,8 @@ I use to email myself plaintext poems daily, visit the repository:
Most of my programming projects are small, random projects that are made
strictly to fix some small problem I have or enhance my quality of life.
-In this case, I was looking for a simply and easy way to get a daily
-dose of literature or poetry to read in the mornings.
+In this case, I was looking for a simply and easy way to get a daily dose of
+literature or poetry to read in the mornings.
However, I don't want to sign up for a random mailing list on just any
website. I also don't want to have to work to find the reading content
@@ -29,21 +29,20 @@ a daily basis, and scheduled to deliver automatically.
This solution uses Python and email, so the following process requires
the following to be installed:
-1. An SMTP server, which can be as easy as installing =mailutils= if
- you're on a Debian-based distro.
+1. A Simple Mail Transfer Protocol (SMTP) server, which can be as easy as
+ installing =mailutils= if you're on a Debian-based distribution.
2. Python (& pip!)
-3. The following Python packages: =email=, =smtplib=, =json=, and
- =requests=
+3. The following Python packages: =email=, =smtplib=, =json=, and =requests=
* Breaking Down the Logic
-I want to break down the logic for this program, as it's quite simple
-and informational.
+I want to break down the logic for this program, as it's quite simple and
+informational.
** Required Packages
-This program starts with a simple import of the required packages, so I
-wanted to explain why each package is used:
+This program starts with a simple import of the required packages, so I wanted
+to explain why each package is used:
#+begin_src python
from email.mime.text import MIMEText # Required for translating MIMEText
@@ -54,15 +53,15 @@ import requests # Required to send out a request to the API
** Sending the API Request
-Next, we need to actually send the API request. In my case, I'm calling
-a random poem from the entire API. If you want, you can call specific
-poems or authors from this API.
+Next, we need to actually send the application programming interface (API)
+request. In my case, I'm calling a random poem from the entire API. If you want,
+you can call specific poems or authors from this API.
#+begin_src python
json_data = requests.get('https://poetrydb.org/random').json()
#+end_src
-This gives us the following result in JSON:
+This gives us the following result in JSON (JavaScript Object Notation):
#+begin_src json
[
@@ -94,12 +93,12 @@ This gives us the following result in JSON:
** Parsing the API Results
-In order to parse this into a readable format, we need to use the =json=
-package and extract the fields we want. In the example below, I am
-grabbing every field presented by the API.
+In order to parse this into a readable format, we need to use the =json= package
+and extract the fields we want. In the example below, I am grabbing every field
+presented by the API.
-For the actual poem content, we need to loop over each line in the
-=lines= variable since each line is a separate string by default.
+For the actual poem content, we need to loop over each line in the =lines=
+variable since each line is a separate string by default.
#+begin_quote
You /could/ also extract the title or author and make another call out
@@ -125,21 +124,20 @@ for line in json_data[0]['lines']:
** Composing the Email
-Now that I have all the data I need, I just need to compose it into a
-message and prepare the message metadata.
+Now that I have all the data I need, I just need to compose it into a message
+and prepare the message metadata.
-For my daily email, I want to see the title of the poem first, followed
-by the author, then a blank line, and finally the full poem. This code
-snippet combines that data and packages it into a MIMEText container,
-ready to be emailed.
+For my daily email, I want to see the title of the poem first, followed by the
+author, then a blank line, and finally the full poem. This code snippet combines
+that data and packages it into a MIMEText container, ready to be emailed.
#+begin_src python
msg_body = title + "\n" + author + "\n\n" + lines
msg = MIMEText(msg_body)
#+end_src
-Before we send the email, we need to prepare the metadata (subject,
-from, to, etc.):
+Before we send the email, we need to prepare the metadata (subject, from, to,
+etc.):
#+begin_src python
sender_email = '[email protected]'
@@ -151,10 +149,9 @@ msg['To'] = recipient_email
** Sending the Email
-Now that I have everything ready to be emailed, the last step is to
-simply connect to an SMTP server and send the email out to the
-recipients. In my case, I installed =mailutils= on Ubuntu and let my
-SMTP server be =localhost=.
+Now that I have everything ready to be emailed, the last step is to simply
+connect to an SMTP server and send the email out to the recipients. In my case,
+I installed =mailutils= on Ubuntu and let my SMTP server be =localhost=.
#+begin_src python
smtp_server = 'localhost'
@@ -165,9 +162,8 @@ s.quit()
* The Result!
-Instead of including a screenshot, I've copied the contents of the email
-that was delivered to my inbox below since I set this process up in
-plaintext format.
+Instead of including a screenshot, I've copied the contents of the email that
+was delivered to my inbox below since I set this process up in plaintext format.
#+begin_src txt
Date: Wed, 22 Jun 2022 14:37:19 +0000 (UTC)
@@ -200,16 +196,16 @@ Some, wise in show, more fools indeed than they.
* Scheduling the Daily Email
Last, but not least, is scheduling this Python script with =crontab=. To
-schedule a script to run daily, you can add it to the =crontab= file. To
-do this, open =crontab= in editing mode:
+schedule a script to run daily, you can add it to the =crontab= file. To do
+this, open =crontab= in editing mode:
#+begin_src sh
crontab -e
#+end_src
-In the file, simply paste the following snippet at the bottom of the
-file and ensure that the file path is correctly pointing to wherever you
-saved your Python script:
+In the file, simply paste the following snippet at the bottom of the file and
+ensure that the file path is correctly pointing to wherever you saved your
+Python script:
#+begin_src config
0 8 ** ** ** python3 /home/<your_user>/dailypoem/main.py
diff --git a/content/blog/2022-06-24-fedora-i3.org b/content/blog/2022-06-24-fedora-i3.org
index 304f87c..12c93c7 100644
--- a/content/blog/2022-06-24-fedora-i3.org
+++ b/content/blog/2022-06-24-fedora-i3.org
@@ -5,61 +5,57 @@
* Leaving macOS
-As I noted [[../foss-macos-apps][in a recent post]], I have been
-planning on migrating from macOS back to a Linux-based OS. I am happy to
-say that I have finally completed my migration and am now stuck in the
-wonderful world of Linux again.
+As I noted in a recent post, I have been planning on migrating from macOS back
+to a Linux-based operating system (OS). I am happy to say that I have finally
+completed my migration and am now stuck in the wonderful world of Linux again.
My decision to leave macOS really came down to just a few important
things:
-- Apple Security (Gatekeeper) restricting me from running any software I
- want. Even if you disable Gatekeeper and allow software to bypass the
- rest of the device installation security, you still have to repeat
- that process every time the allowed software is updated.
-- macOS sends out nearly constant connections, pings, telemetry, etc. to
- a myriad of mysterious Apple services. I'm not even going to dive into
- how many macOS apps have constant telemetry on, as well.
-- Lastly, I just /really/ missed the customization and freedom that
- comes with Linux. Being able to switch to entirely new kernel, OS, or
- desktop within minutes is a freedom I took for granted when I switched
- to macOS.
-
-Now that I've covered macOS, I'm going to move on to more exciting
-topics: my personal choice of OS, DE, and various customizations I'm
+- Apple Security (Gatekeeper) restricting me from running any software I want.
+ Even if you disable Gatekeeper and allow software to bypass the rest of the
+ device installation security, you still have to repeat that process every time
+ the allowed software is updated.
+- macOS sends out nearly constant connections, pings, telemetry, etc. to a
+ myriad of mysterious Apple services. I'm not even going to dive into how many
+ macOS apps have constant telemetry on, as well.
+- Lastly, I just /really/ missed the customization and freedom that comes with
+ Linux. Being able to switch to entirely new kernel, OS, or desktop within
+ minutes is a freedom I took for granted when I switched to macOS.
+
+Now that I've covered macOS, I'm going to move on to more exciting topics: my
+personal choice of OS, desktop environment (DE), and various customizations I'm
using.
* Fedora
-After trying a ton of distros (I think I booted and tested around 20-25
-distros), I finally landed on [[https://getfedora.org/][Fedora Linux]].
-I have quite a bit of experience with Fedora and enjoy the =dnf= package
-manager. Fedora allows me to keep up-to-date with recent software (I'm
-looking at you, Debian), but still provides a level of stability you
-don't find in every distro.
-
-In a very close second place was Arch Linux, as well as its spin-off:
-Garuda Linux (Garuda w/ sway is /beautiful/). Arch is great for
-compatibility and the massive community it has, but I have just never
-had the time to properly sit down and learn the methodology behind their
-packaging systems.
-
-Basically, everything else I tested was unacceptable in at least one way
-or another. Void (=glibc=) was great, but doesn't support all the
-software I need. Slackware worked well as a tui, but I wasn't skilled
+After trying a ton of distributions (I think I booted and tested around 20-25
+distributions), I finally landed on [[https://getfedora.org/][Fedora Linux]]. I have quite a bit of experience
+with Fedora and enjoy the =dnf= package manager. Fedora allows me to keep
+up-to-date with recent software (I'm looking at you, Debian), but still provides
+a level of stability you don't find in every distribution.
+
+In a very close second place was Arch Linux, as well as its spin-off: Garuda
+Linux (Garuda w/ sway is /beautiful/). Arch is great for compatibility and the
+massive community it has, but I have just never had the time to properly sit
+down and learn the methodology behind their packaging systems.
+
+Basically, everything else I tested was unacceptable in at least one way or
+another. Void (=glibc=) was great, but doesn't support all the software I need.
+Slackware worked well as a text-based user interface (TUI), but I wasn't skilled
enough to get a tiling window manager (WM) working on it.
** i3
-One of the reasons I settled on Fedora is that it comes with an official
-i3 spin. Being able to use a tiling WM, such as i3 or sway, is one of
-the biggest things I wanted to do as soon as I adopted Linux again.
+One of the reasons I settled on Fedora is that it comes with an official i3
+spin. Being able to use a tiling WM, such as i3 or sway, is one of the biggest
+things I wanted to do as soon as I adopted Linux again.
-I will probably set up a dotfile repository soon, so that I don't lose
-any of my configurations, but nothing big has been configured thus far.
+I will probably set up a dotfile repository soon, so that I don't lose any of my
+configurations, but nothing big has been configured thus far.
-The two main things I have updated in i3wm are natural scrolling and
-binding my brightness keys to the =brightnessctl= program.
+The two main things I have updated in i3wm are natural scrolling and binding my
+brightness keys to the =brightnessctl= program.
1. Natural Scrolling
@@ -69,8 +65,8 @@ binding my brightness keys to the =brightnessctl= program.
sudo nano /usr/share/X11/xorg.conf.d/40-libinput.conf
#+end_src
- Within the =40-libinput.conf= file, find the following input sections
- and enable the natural scrolling option.
+ Within the =40-libinput.conf= file, find the following input sections and
+ enable the natural scrolling option.
This is the =pointer= section:
@@ -98,10 +94,10 @@ binding my brightness keys to the =brightnessctl= program.
2. Enabling Brightness Keys
- Likewise, enabling brightness key functionality is as simple as
- binding the keys to the =brightnessctl= program.
+ Likewise, enabling brightness key functionality is as simple as binding the
+ keys to the =brightnessctl= program.
- To do this, open up your i3 config file. Mine is located here:
+ To do this, open up your i3 configuration file. Mine is located here:
#+begin_src sh
nano /home/<my-user>/.config/i3/config
@@ -115,24 +111,24 @@ binding my brightness keys to the =brightnessctl= program.
3. =polybar=
- Instead of using the default =i3status= bar, I have opted to use
- =polybar= instead (as you can also see in the screenshot above).
+ Instead of using the default =i3status= bar, I have opted to use =polybar=
+ instead (as you can also see in the screenshot above).
- My config for this menu bar is basically just the default settings
- with modified colors and an added battery block to quickly show me
- the machine's battery info.
+ My configuration for this menu bar is basically just the default settings
+ with modified colors and an added battery block to quickly show me the
+ machine's battery info.
4. =alacritty=
- Not much to say on this part yet, as I haven't configured it much,
- but I installed =alacritty= as my default terminal, and I am using
- =zsh= and the shell.
+ Not much to say on this part yet, as I haven't configured it much, but I
+ installed =alacritty= as my default terminal, and I am using =zsh= and the
+ shell.
* Software Choices
-Again, I'm not going to say much that I haven't said yet in other blog
-posts, so I'll just do a quick rundown of the apps I installed
-immediately after I set up the environment.
+Again, I'm not going to say much that I haven't said yet in other blog posts, so
+I'll just do a quick rundown of the apps I installed immediately after I set up
+the environment.
Flatpak Apps:
diff --git a/content/blog/2022-07-01-git-server.org b/content/blog/2022-07-01-git-server.org
index 9bb36ce..bde0d0b 100644
--- a/content/blog/2022-07-01-git-server.org
+++ b/content/blog/2022-07-01-git-server.org
@@ -5,56 +5,55 @@
* My Approach to Self-Hosting Git
-I have often tried to self-host my Git repositories, but have always
-fallen short when I tried to find a suitable web interface to show on
-the front-end.
+I have often tried to self-host my Git repositories, but have always fallen
+short when I tried to find a suitable web interface to show on the front-end.
-After a few years, I have finally found a combination of methods that
-allow me to easily self-host my projects, view them on the web, and
-access them from anywhere.
+After a few years, I have finally found a combination of methods that allow me
+to easily self-host my projects, view them on the web, and access them from
+anywhere.
-Before I dive into the details, I want to state a high-level summary of
-my self-hosted Git approach:
+Before I dive into the details, I want to state a high-level summary of my
+self-hosted Git approach:
- This method uses the =ssh://= (read & write) and =git://= (read-only)
protocols for push and pull access.
- - For the =git://= protocol, I create a =git-daemon-export-ok= file in
- any repository that I want to be cloneable by anyone.
- - The web interface I am using (=cgit=) allows simple HTTP cloning by
- default. I do not disable this setting as I want beginners to be
- able to clone one of my repositories even if they don't know the
- proper method.
-- I am not enabling Smart HTTPS for any repositories. Updates to
- repositories must be pushed via SSH.
-- Beyond the actual repository management, I am using =cgit= for the
- front-end web interface.
+ - For the =git://= protocol, I create a =git-daemon-export-ok= file in any
+ repository that I want to be cloneable by anyone.
+ - The web interface I am using (=cgit=) allows simple HTTP cloning by default.
+ I do not disable this setting as I want beginners to be able to clone one of
+ my repositories even if they don't know the proper method.
+- I am not enabling Smart HTTPS (Hypertext Transfer Protocol Secure) for any
+ repositories. Updates to repositories must be pushed via SSH (Secure Shell
+ Protocol).
+- Beyond the actual repository management, I am using =cgit= for the front-end
+ web interface.
- If you use the =scan-path=<path>= configuration in the =cgitrc=
- configuration file to automatically find repositories, you can't
- exclude a repository from =cgit= if it's stored within the path that
- =cgit= reads. To host private repositories, you'd need to set up
- another directory that =cgit= can't read.
+ configuration file to automatically find repositories, you can't exclude a
+ repository from =cgit= if it's stored within the path that =cgit= reads. To
+ host private repositories, you'd need to set up another directory that
+ =cgit= can't read.
* Assumptions
For the purposes of this walkthrough, I am assuming you have a URL
-(=git.example.com=) or IP address (=207.84.26.991=) addressed to the
-server that you will be using to host your git repositories.
+(=git.example.com=) or internet protocol (IP) address (=207.84.26.991=)
+addressed to the server that you will be using to host your git repositories.
* Adding a Git User
-In order to use the SSH method associated with git, we will need to add
-a user named =git=. If you have used the SSH method for other git
-hosting sites, you are probably used to the following syntax:
+In order to use the SSH method associated with Git, we will need to add a user
+named =git=. If you have used the SSH method for other git hosting sites, you
+are probably used to the following syntax:
#+begin_src sh
git clone [user@]server:project.git
#+end_src
-The syntax above is an =scp=-like syntax for using SSH on the =git= user
-on the server to access your repository.
+The syntax above is an =scp=-like syntax for using SSH on the =git= user on the
+server to access your repository.
-Let's delete any remnants of an old =git= user, if any, and create the
-new user account:
+Let's delete any remnants of an old =git= user, if any, and create the new user
+account:
#+begin_src sh
sudo deluser --remove-home git
@@ -63,8 +62,8 @@ sudo adduser git
** Import Your SSH Keys to the Git User
-Once the =git= user is created, you will need to copy your public SSH
-key on your local development machine to the =git= user on the server.
+Once the =git= user is created, you will need to copy your public SSH key on
+your local development machine to the =git= user on the server.
If you don't have an SSH key yet, create one with this command:
@@ -72,11 +71,10 @@ If you don't have an SSH key yet, create one with this command:
ssh-keygen
#+end_src
-Once you create the key pair, the public should be saved to
-=~/.ssh/id_rsa.pub=.
+Once you create the key pair, the public should be saved to =~/.ssh/id_rsa.pub=.
-If your server still has password-based authentication available, you
-can copy it over to your user's home directory like this:
+If your server still has password-based authentication available, you can copy
+it over to your user's home directory like this:
#+begin_src sh
ssh-copy-id git@server
@@ -88,8 +86,8 @@ Otherwise, copy it over to any user that you can access.
scp ~/.ssh/id_rsa.pub your_user@your_server:
#+end_src
-Once on the server, you will need to copy the contents into the =git=
-user's =authorized_keys= file:
+Once on the server, you will need to copy the contents into the =git= user's
+=authorized_keys= file:
#+begin_src sh
cat id_rsa.pub > /home/git/.ssh/authorized_keys
@@ -97,16 +95,15 @@ cat id_rsa.pub > /home/git/.ssh/authorized_keys
** (Optional) Disable Password-Based SSH
-If you want to lock down your server and ensure that no one can
-authenticate in via SSH with a password, you will need to edit your SSH
-configuration.
+If you want to lock down your server and ensure that no one can authenticate in
+via SSH with a password, you will need to edit your SSH configuration.
#+begin_src sh
sudo nano /etc/ssh/sshd_config
#+end_src
-Within this file, find the following settings and set them to the values
-I am showing below:
+Within this file, find the following settings and set them to the values I am
+showing below:
#+begin_src conf
PermitRootLogin no
@@ -114,18 +111,17 @@ PasswordAuthentication no
AuthenticationMethods publickey
#+end_src
-You may have other Authentication Methods required in your personal
-set-up, so the key here is just to ensure that =AuthenticationMethods=
-does not allow passwords.
+You may have other Authentication Methods required in your personal set-up, so
+the key here is just to ensure that =AuthenticationMethods= does not allow
+passwords.
*** Setting up the Base Directory
-Now that we have set up a =git= user to handle all transport methods, we
-need to set up the directory that we will be using as our base of all
-repositories.
+Now that we have set up a =git= user to handle all transport methods, we need to
+set up the directory that we will be using as our base of all repositories.
-In my case, I am using =/git= as my source folder. To create this folder
-and assign it to the user we created, execute the following commands:
+In my case, I am using =/git= as my source folder. To create this folder and
+assign it to the user we created, execute the following commands:
#+begin_src sh
sudo mkdir /git
@@ -134,15 +130,15 @@ sudo chown -R git:git /git
*** Creating a Test Repository
-On your server, switch over to the =git= user in order to start managing
-git files.
+On your server, switch over to the =git= user in order to start managing git
+files.
#+begin_src sh
su git
#+end_src
-Once logged-in as the =git= user, go to your base directory and create a
-test repository.
+Once logged-in as the =git= user, go to your base directory and create a test
+repository.
#+begin_src sh
cd /git
@@ -150,9 +146,9 @@ mkdir test.git && cd test.git
git init --bare
#+end_src
-If you want to make this repo viewable/cloneable to the public via the
-=git://= protocol, you need to create a =git-daemon-export-ok= file
-inside the repository.
+If you want to make this repo viewable/cloneable to the public via the =git://=
+protocol, you need to create a =git-daemon-export-ok= file inside the
+repository.
#+begin_src sh
touch git-daemon-export-ok
@@ -160,34 +156,33 @@ touch git-daemon-export-ok
* Change the Login Shell for =git=
-To make sure that the =git= user is only used for git operations and
-nothing else, you need to change the user's login shell. To do this,
-simply use the =chsh= command:
+To make sure that the =git= user is only used for git operations and nothing
+else, you need to change the user's login shell. To do this, simply use the
+=chsh= command:
#+begin_src sh
sudo chsh git
#+end_src
-The interactive prompt will ask which shell you want the =git= user to
-use. You must use the following value:
+The interactive prompt will ask which shell you want the =git= user to use. You
+must use the following value:
#+begin_src sh
/usr/bin/git-shell
#+end_src
-Once done, no one will be able to SSH to the =git= user or execute
-commands other than the standard git commands.
+Once done, no one will be able to SSH to the =git= user or execute commands
+other than the standard git commands.
* Opening the Firewall
-Don't forget to open up ports on the device firewall and network
-firewall if you want to access these repositories publicly. If you're
-using default ports, forward ports =22= (ssh) and =9418= (git) from your
-router to your server's IP address.
+Don't forget to open up ports on the device firewall and network firewall if you
+want to access these repositories publicly. If you're using default ports,
+forward ports =22= (ssh) and =9418= (git) from your router to your server's IP
+address.
-If your server also has a firewall, ensure that the firewall allows the
-same ports that are forwarded from the router. For example, if you use
-=ufw=:
+If your server also has a firewall, ensure that the firewall allows the same
+ports that are forwarded from the router. For example, if you use =ufw=:
#+begin_src sh
sudo ufw allow 22
@@ -196,12 +191,12 @@ sudo ufw allow 9418
** Non-Standard SSH Ports
-If you use a non-standard port for SSH, such as =9876=, you will need to
-create an SSH configuration file on your local development machine in
-order to connect to your server's git repositories.
+If you use a non-standard port for SSH, such as =9876=, you will need to create
+an SSH configuration file on your local development machine in order to connect
+to your server's git repositories.
-To do this, you'll need to define your custom port on your client
-machine in your =~/.ssh/config= file:
+To do this, you'll need to define your custom port on your client machine in
+your =~/.ssh/config= file:
#+begin_src sh
nano ~/.ssh/config
@@ -222,8 +217,8 @@ There are two main syntaxes you can use to manage git over SSH:
- =git clone [user@]server:project.git=
- =git clone ssh://[user@]server/project.git=
-I prefer the first, which is an =scp=-like syntax. To test it, try to
-clone the test repository you set up on the server:
+I prefer the first, which is an =scp=-like syntax. To test it, try to clone the
+test repository you set up on the server:
#+begin_src sh
git clone [email protected]:/git/test.git
@@ -231,9 +226,8 @@ git clone [email protected]:/git/test.git
* Enabling Read-Only Access
-If you want people to be able to clone any repository where you've
-placed a =git-daemon-export-ok= file, you will need to start the git
-daemon.
+If you want people to be able to clone any repository where you've placed a
+=git-daemon-export-ok= file, you will need to start the git daemon.
To do this on a system with =systemd=, create a service file:
@@ -271,8 +265,7 @@ sudo systemctl enable git-daemon.service
sudo systemctl start git-daemon.service
#+end_src
-To clone read-only via the =git://= protocol, you can use the following
-syntax:
+To clone read-only via the =git://= protocol, you can use the following syntax:
#+begin_src sh
git clone git://git.example.com/test.git
@@ -283,9 +276,9 @@ git clone git://git.example.com/test.git
At this point, we have a working git server that works with both SSH and
read-only access.
-For each of the repositories I had hosted a different provider, I
-executed the following commands in order to place a copy on my server as
-my new source of truth:
+For each of the repositories I had hosted a different provider, I executed the
+following commands in order to place a copy on my server as my new source of
+truth:
Server:
@@ -308,20 +301,20 @@ git push
* Optional Web View: =cgit=
-If you want a web viewer for your repositories, you can use various
-tools, such as =gitweb=, =cgit=, or =klaus=. I chose =cgit= due to its
-simple interface and fairly easy set-up (compared to others). Not to
-mention that the [[https://git.kernel.org/][Linux kernel uses =cgit=]].
+If you want a web viewer for your repositories, you can use various tools, such
+as =gitweb=, =cgit=, or =klaus=. I chose =cgit= due to its simple interface and
+fairly easy set-up (compared to others). Not to mention that the [[https://git.kernel.org/][Linux kernel
+uses =cgit=]].
** Docker Compose
-Instead of using my previous method of using a =docker run= command,
-I've updated this section to use =docker-compose= instead for an easier
-installation and simpler management and configuration.
+Instead of using my previous method of using a =docker run= command, I've
+updated this section to use =docker-compose= instead for an easier installation
+and simpler management and configuration.
-In order to use Docker Compose, you will set up a =docker-compose.yml=
-file to automatically connect resources like the repositories, =cgitrc=,
-and various files or folders to the =cgit= container you're creating:
+In order to use Docker Compose, you will set up a =docker-compose.yml= file to
+automatically connect resources like the repositories, =cgitrc=, and various
+files or folders to the =cgit= container you're creating:
#+begin_src sh
mkdir ~/cgit && cd ~/cgit
@@ -352,16 +345,16 @@ Then, just start the container:
sudo docker-compose up -d
#+end_src
-Once it's finished installing, you can access the site at
-=<SERVER_IP>:8763= or use a reverse-proxy service to forward =cgit= to a
-URL, such as =git.example.com=. See the next section for more details on
-reverse proxying a URL to a local port.
+Once it's finished installing, you can access the site at =<SERVER_IP>:8763= or
+use a reverse-proxy service to forward =cgit= to a URL, such as
+=git.example.com=. See the next section for more details on reverse proxying a
+URL to a local port.
** Nginx Reverse Proxy
-I am using Nginx as my reverse proxy so that the =cgit= Docker container
-can use =git.example.com= as its URL. To do so, I simply created the
-following configuration file:
+I am using Nginx as my reverse proxy so that the =cgit= Docker container can use
+=git.example.com= as its uniform resource locator (URL). To do so, I simply
+created the following configuration file:
#+begin_src sh
sudo nano /etc/nginx/sites-available/git.example.com
@@ -410,29 +403,26 @@ sudo ln -s /etc/nginx/sites-available/git.example.com /etc/nginx/sites-enabled/
sudo systemctl restart nginx.service
#+end_src
-As we can see below, my site at =git.example.com= is available and
-running:
+As we can see below, my site at =git.example.com= is available and running:
** Settings Up Git Details
-Once you have =cgit= running, you can add some small details, such as
-repository owners and descriptions by editing the following files within
-each repository.
+Once you have =cgit= running, you can add some small details, such as repository
+owners and descriptions by editing the following files within each repository.
-Alternatively, you can use the =cgitrc= file to edit these details if
-you only care to edit them for the purpose of seeing them on your
-website.
+Alternatively, you can use the =cgitrc= file to edit these details if you only
+care to edit them for the purpose of seeing them on your website.
-The =description= file within the repository on your server will display
-the description online.
+The =description= file within the repository on your server will display the
+description online.
#+begin_src sh
cd /git/example.git
nano description
#+end_src
-You can add a =[gitweb]= block to the =config= file in order to display
-the owner of the repository.
+You can add a =[gitweb]= block to the =config= file in order to display the
+owner of the repository.
#+begin_src sh
cd /git/example.git
@@ -444,22 +434,20 @@ nano config
owner = "YourName"
#+end_src
-Note that you can ignore the configuration within each repository and
-simply set up this information in the =cgitrc= file, if you want to do
-it that way.
+Note that you can ignore the configuration within each repository and simply set
+up this information in the =cgitrc= file, if you want to do it that way.
** Editing =cgit=
-In order to edit certain items within =cgit=, you need to edit the
-=cgitrc= file.
+In order to edit certain items within =cgit=, you need to edit the =cgitrc=
+file.
#+begin_src sh
nano ~/cgit/cgitrc
#+end_src
Below is an example configuration for =cgitrc=. You can find all the
-configuration options within the [configuration manual]
-([[https://git.zx2c4.com/cgit/plain/cgitrc.5.txt]]).
+configuration options within the [[https://git.zx2c4.com/cgit/plain/cgitrc.5.txt][configuration manual]].
#+begin_src conf
css=/cgit.css
@@ -537,15 +525,14 @@ repo.desc=An example repository!
** Final Fixes: Syntax Highlighting & README Rendering
-After completing my initial install and playing around with it for a few
-days, I noticed two issues:
+After completing my initial install and playing around with it for a few days, I
+noticed two issues:
-1. Syntax highlighting did not work when viewing the source code within
- a file.
+1. Syntax highlighting did not work when viewing the source code within a file.
2. The =about= tab within a repository was not rendered to HTML.
-The following process fixes these issues. To start, let's go to the
-=cgit= directory where we were editing our configuration file earlier.
+The following process fixes these issues. To start, let's go to the =cgit=
+directory where we were editing our configuration file earlier.
#+begin_src sh
cd ~/cgit
@@ -575,14 +562,12 @@ curl https://git.zx2c4.com/cgit/plain/filters/html-converters/md2html > md2html
chmod 755 md2html
#+end_src
-If you need other filters or html-converters found within
-[[https://git.zx2c4.com/cgit/tree/filters][the cgit project files]],
-repeat the =curl= and =chmod= process above for whichever files you
-need.
+If you need other filters or html-converters found within [[https://git.zx2c4.com/cgit/tree/filters][the cgit project
+files]], repeat the =curl= and =chmod= process above for whichever files you need.
-However, formatting will not work quite yet since the Docker cgit
-container we're using doesn't have the formatting package installed. You
-can install this easily by install Python 3+ and the =pygments= package:
+However, formatting will not work quite yet since the Docker cgit container
+we're using doesn't have the formatting package installed. You can install this
+easily by install Python 3+ and the =pygments= package:
#+begin_src sh
# Enter the container's command line
@@ -601,8 +586,8 @@ exit
*You will need to enter the cgit docker container and re-run these =yum=
commands every time you kill and restart the container!*
-If not done already, we need to add the following variables to our
-=cgitrc= file in order for =cgit= to know where our filtering files are:
+If not done already, we need to add the following variables to our =cgitrc= file
+in order for =cgit= to know where our filtering files are:
#+begin_src conf
# Highlight source code with python pygments-based highlighter
@@ -613,26 +598,24 @@ source-filter=/var/www/htdocs/cgit/filters/syntax-highlighting.py
about-filter=/var/www/htdocs/cgit/filters/about-formatting.sh
#+end_src
-Now you should see that syntax highlighting and README rendering to the
-=about= tab is fixed.
+Now you should see that syntax highlighting and README rendering to the =about=
+tab is fixed.
** Theming
-I won't go into much detail in this section, but you can fully theme
-your installation of =cgit= since you have access to the =cgit.css= file
-in your web root. This is another file you can add as a volume to the
-=docker-compose.yml= file if you want to edit this without entering the
-container's command line.
+I won't go into much detail in this section, but you can fully theme your
+installation of =cgit= since you have access to the =cgit.css= file in your web
+root. This is another file you can add as a volume to the =docker-compose.yml=
+file if you want to edit this without entering the container's command line.
-*** :warning: Remember to Back Up Your Data!
+*** Remember to Back Up Your Data!
-The last thing to note is that running services on your own equipment
-means that you're assuming a level of risk that exists regarding data
-loss, catastrophes, etc. In order to reduce the impact of any such
-occurrence, I suggest backing up your data regularly.
+The last thing to note is that running services on your own equipment means that
+you're assuming a level of risk that exists regarding data loss, catastrophes,
+etc. In order to reduce the impact of any such occurrence, I suggest backing up
+your data regularly.
-Backups can be automated via =cron=, by hooking your base directory up
-to a cloud provider, or even setting up hooks to push all repository
-info to git mirrors on other git hosts. Whatever the method, make sure
-that your data doesn't vanish in the event that your drives or servers
-fail.
+Backups can be automated via =cron=, by hooking your base directory up to a
+cloud provider, or even setting up hooks to push all repository info to git
+mirrors on other git hosts. Whatever the method, make sure that your data
+doesn't vanish in the event that your drives or servers fail.
diff --git a/content/blog/2022-07-14-gnupg.org b/content/blog/2022-07-14-gnupg.org
index 05e8772..eda63b7 100644
--- a/content/blog/2022-07-14-gnupg.org
+++ b/content/blog/2022-07-14-gnupg.org
@@ -5,33 +5,30 @@
* The History of GPG
-[[https://gnupg.org/][GNU Privacy Guard]], also known as GnuPG and GPG,
-is a free ("free" as in both speech and beer) software that fully
-implements the OpenPGP Message Format documented in
-[[https://www.rfc-editor.org/rfc/rfc4880][RFC 4880]].
-
-I won't go in-depth on the full history of the software in this post,
-but it is important to understand that GPG is not the same as PGP
-(Pretty Good Privacy), which is a different implementation of RFC 4880.
-However, GPG was designed to interoperate with PGP.
-
-GPG was originally developed in the late 1990s by
-[[https://en.wikipedia.org/wiki/Werner_Koch][Werner Koch]] and has
+[[https://gnupg.org/][GNU Privacy Guard]], also known as GnuPG and GPG, is a free ("free" as in both
+speech and beer) software that fully implements the OpenPGP Message Format
+documented in [[https://www.rfc-editor.org/rfc/rfc4880][RFC 4880]].
+
+I won't go in-depth on the full history of the software in this post, but it is
+important to understand that GPG is not the same as PGP (Pretty Good Privacy),
+which is a different implementation of RFC 4880. However, GPG was designed to
+interoperate with PGP.
+
+GPG was originally developed in the late 1990s by [[https://en.wikipedia.org/wiki/Werner_Koch][Werner Koch]] and has
historically been funded generously by the German government.
-Now that we have all the high-level info out of the way, let's dive into
-the different aspects of GPG and its uses.
+Now that we have all the high-level info out of the way, let's dive into the
+different aspects of GPG and its uses.
* Encryption Algorithms
GPG supports a wide range of different encryption algorithms, including
-public-key, cipher, hash, and compression algorithms. The support for
-these algorithms has grown since the adoption of the Libgcrypt library
-in the 2.x versions of GPG.
+public-key, cipher, hash, and compression algorithms. The support for these
+algorithms has grown since the adoption of the Libgcrypt library in the 2.x
+versions of GPG.
-As you will be able to see below in an example of a full key generation
-with the GPG command line tool, GPG recommends the following algorithms
-to new users:
+As you will be able to see below in an example of a full key generation with the
+GPG command line tool, GPG recommends the following algorithms to new users:
#+begin_src sh
Please select what kind of key you want:
@@ -43,46 +40,39 @@ Please select what kind of key you want:
(10) ECC (sign only)
#+end_src
-I am not doing an in-depth explanation here in order to keep the focus
-on GPG and not encryption algorithms. If you want a deep dive into
-cryptography or encryption algorithms, please read my other posts:
+I am not doing an in-depth explanation here in order to keep the focus on GPG
+and not encryption algorithms. If you want a deep dive into cryptography or
+encryption algorithms, please read my other posts:
-- [[../aes-encryption/][AES Encryption]] (2018)
-- [[../cryptography-basics/][Cryptography Basics]] (2020)
+- [[https://cleberg.net/blog/aes-encryption.html][How AES Encryption Works]] (2018)
+- [[https://cleberg.net/blog/cryptography.html][A Practical Guide to Encryption, Keys, and Secure Communication]] (2020)
** Vulnerabilities
-As of 2022-07-14, there are a few different vulnerabilities associated
-with GPG or the libraries it uses:
-
-- GPG versions 1.0.2--1.2.3 contains a bug where "as soon as one
- (GPG-generated) ElGamal signature of an arbitrary message is released,
- one can recover the signer's private key in less than a second on a
- PC." ([[https://www.di.ens.fr/~pnguyen/pub_Ng04.htm][Source]])
-- GPG versions prior to 1.4.2.1 contain a false positive signature
- verification bug.
- ([[https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000211.html][Source]])
-- GPG versions prior to 1.4.2.2 cannot detect injection of unsigned
- data. (
+As of 2022-07-14, there are a few different vulnerabilities associated with GPG
+or the libraries it uses:
+
+- GPG versions 1.0.2--1.2.3 contains a bug where "as soon as one (GPG-generated)
+ ElGamal signature of an arbitrary message is released, one can recover the
+ signer's private key in less than a second on a PC." ([[https://www.di.ens.fr/~pnguyen/pub_Ng04.htm][Source]])
+- GPG versions prior to 1.4.2.1 contain a false positive signature verification
+ bug. ([[https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000211.html][Source]])
+- GPG versions prior to 1.4.2.2 cannot detect injection of unsigned data. (
[[https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000218.html][Source]])
-- Libgcrypt, a library used by GPG, contained a bug which enabled full
- key recovery for RSA-1024 and some RSA-2048 keys. This was resolved in
- a GPG update in 2017. ([[https://lwn.net/Articles/727179/][Source]])
-- The [[https://en.wikipedia.org/wiki/ROCA_vulnerability][ROCA
- Vulnerability]] affects RSA keys generated by YubiKey 4 tokens.
+- Libgcrypt, a library used by GPG, contained a bug which enabled full key
+ recovery for RSA-1024 and some RSA-2048 keys. This was resolved in a GPG
+ update in 2017. ([[https://lwn.net/Articles/727179/][Source]])
+- The [[https://en.wikipedia.org/wiki/ROCA_vulnerability][ROCA Vulnerability]] affects RSA keys generated by YubiKey 4 tokens.
([[https://crocs.fi.muni.cz/_media/public/papers/nemec_roca_ccs17_preprint.pdf][Source]])
-- The [[https://en.wikipedia.org/wiki/SigSpoof][SigSpoof Attack]] allows
- an attacker to spoof digital signatures.
- ([[https://arstechnica.com/information-technology/2018/06/decades-old-pgp-bug-allowed-hackers-to-spoof-just-about-anyones-signature/][Source]])
-- Libgcrypt 1.9.0 contains a severe flaw related to a heap buffer
- overflow, fixed in Libgcrypt 1.9.1
- ([[https://web.archive.org/web/20210221012505/https://www.theregister.com/2021/01/29/severe_libgcrypt_bug/][Source]])
+- The [[https://en.wikipedia.org/wiki/SigSpoof][SigSpoof Attack]] allows an attacker to spoof digital signatures. ([[https://arstechnica.com/information-technology/2018/06/decades-old-pgp-bug-allowed-hackers-to-spoof-just-about-anyones-signature/][Source]])
+- Libgcrypt 1.9.0 contains a severe flaw related to a heap buffer overflow,
+ fixed in Libgcrypt 1.9.1 ([[https://web.archive.org/web/20210221012505/https://www.theregister.com/2021/01/29/severe_libgcrypt_bug/][Source]])
*** Platforms
-Originally developed as a command-line program for *nix systems, GPG now
-has a wealth of front-end applications and libraries available for
-end-users. However, the most recommended programs remain the same:
+Originally developed as a command-line program for *nix systems, GPG now has a
+wealth of front-end applications and libraries available for end-users. However,
+the most recommended programs remain the same:
- [[https://gnupg.org][GnuPG]] for Linux (depending on distro)
- [[https://gpg4win.org][Gpg4win]] for Windows
@@ -90,27 +80,25 @@ end-users. However, the most recommended programs remain the same:
* Creating a Key Pair
-In order to create a GPG key pair, a user would first need to install
-GPG on their system. If we're assuming that the user is on Fedora Linux,
-they would execute the following:
+In order to create a GPG key pair, a user would first need to install GPG on
+their system. If we're assuming that the user is on Fedora Linux, they would
+execute the following:
#+begin_src sh
sudo dnf install gpg
#+end_src
-Once installed, a user can create a new key pair with the following
-command(s):
+Once installed, a user can create a new key pair with the following command(s):
#+begin_src sh
gpg --full-generate-key
#+end_src
-GPG will walk the user through an interactive setup that asks for an
-algorithm preference, expiration date, name, and email to associate with
-this key.
+GPG will walk the user through an interactive setup that asks for an algorithm
+preference, expiration date, name, and email to associate with this key.
-See the following example key set-up for a default key generation using
-the GnuPG command-line interface:
+See the following example key set-up for a default key generation using the
+GnuPG command-line interface:
#+begin_src sh
gpg (GnuPG) 2.3.6; Copyright (C) 2021 Free Software Foundation, Inc.
@@ -166,12 +154,13 @@ uid John Doe (test key) <[email protected]>
sub cv25519 2022-07-14 [E]
#+end_src
-Please note that GUI apps may differ slightly from the GPG command-line
+Please note that graphical apps may differ slightly from the GPG command-line
interface.
* Common Usage
-As noted in RFC 4880, the general functions of OpenPGP are as follows:
+As noted in RFC (Request for Comments) 4880, the general functions of OpenPGP
+are as follows:
- digital signatures
- encryption
@@ -179,59 +168,57 @@ As noted in RFC 4880, the general functions of OpenPGP are as follows:
- Radix-64 conversion
- key management and certificate services
-From this, you can probably gather that the main use of GPG is for
-encrypting data and/or signing the data with a key. The purpose of
-encrypting data with GPG is to ensure that no one except the intended
-recipient(s) can access the data.
+From this, you can probably gather that the main use of GPG is for encrypting
+data and/or signing the data with a key. The purpose of encrypting data with GPG
+is to ensure that no one except the intended recipient(s) can access the data.
Let's explore some specific GPG use-cases.
** Email
-One of the more popular uses of GPG is to sign and/or encrypt emails.
-With the use of a GPG keypair, you can encrypt a message, its subject,
-and even the attachments within.
-
-The first process, regarding the signing of a message without any
-encryption, is generally used to provide assurance that an email is
-truly coming from the sender that the message claims. When I send an
-email, and it's signed with my public key, the recipient(s) of the
-message can verify that the message was signed with my personal key.
-
-The second process, regarding the actual encryption of the message and
-its contents, works by using a combination of the sender's keys and the
-recipient's keys. This process may vary slightly by implementation, but
-it most commonly uses asymmetric cryptography, also known as public-key
-cryptography. In this version of encryption, the sender's private key to
-sign the message and a combination of the sender's keys and the
-recipient's public key to encrypt the message.
-
-If two people each have their own private keys and exchange their public
-keys, they can send encrypted messages back and forth with GPG. This is
-also possible with symmetric cryptography, but the process differs since
-there are no key pairs.
-
-Implementation of email encryption varies greatly between email clients,
-so you will need to reference your email client's documentation to
-ensure you are setting it up correctly for that specific client.
+One of the more popular uses of GPG is to sign and/or encrypt emails. With the
+use of a GPG keypair, you can encrypt a message, its subject, and even the
+attachments within.
+
+The first process, regarding the signing of a message without any encryption, is
+generally used to provide assurance that an email is truly coming from the
+sender that the message claims. When I send an email, and it's signed with my
+public key, the recipient(s) of the message can verify that the message was
+signed with my personal key.
+
+The second process, regarding the actual encryption of the message and its
+contents, works by using a combination of the sender's keys and the recipient's
+keys. This process may vary slightly by implementation, but it most commonly
+uses asymmetric cryptography, also known as public-key cryptography. In this
+version of encryption, the sender's private key to sign the message and a
+combination of the sender's keys and the recipient's public key to encrypt the
+message.
+
+If two people each have their own private keys and exchange their public keys,
+they can send encrypted messages back and forth with GPG. This is also possible
+with symmetric cryptography, but the process differs since there are no key
+pairs.
+
+Implementation of email encryption varies greatly between email clients, so you
+will need to reference your email client's documentation to ensure you are
+setting it up correctly for that specific client.
** File Encryption
-As noted in the section above regarding emails, GPG enables users to be
-able to send a message to each other if they are both set-up with GPG
-keys. In this example, I am going to show how a user could send a file
-called =example_file.txt= to another user via the recipient's email.
+As noted in the section above regarding emails, GPG enables users to be able to
+send a message to each other if they are both set-up with GPG keys. In this
+example, I am going to show how a user could send a file called
+=example_file.txt= to another user via the recipient's email.
-The sender would find the file they want to send and execute the
-following command:
+The sender would find the file they want to send and execute the following
+command:
#+begin_src sh
gpg --encrypt --output example_file.txt.gpg --recipient \
[email protected] example_file.txt
#+end_src
-Once received, the recipient can decrypt the file with the following
-command:
+Once received, the recipient can decrypt the file with the following command:
#+begin_src sh
gpg --decrypt --output example_file.txt example_file.txt.gpg
@@ -239,29 +226,28 @@ gpg --decrypt --output example_file.txt example_file.txt.gpg
** Ownership Signatures
-One important aspect of GPG, especially for developers, is the ability
-to sign data without encrypting it. For example, developers often sign
-code changes when they commit the changes back to a central repository,
-in order to display ownership of who made the changes. This allows other
-users to look at a code change and determine that the change was valid.
+One important aspect of GPG, especially for developers, is the ability to sign
+data without encrypting it. For example, developers often sign code changes when
+they commit the changes back to a central repository, in order to display
+ownership of who made the changes. This allows other users to look at a code
+change and determine that the change was valid.
-In order to do this using [[https://git-scm.com][Git]], the developer
-simply needs to alter the =git commit= command to include the =-S= flag.
-Here's an example:
+In order to do this using [[https://git-scm.com][Git]], the developer simply needs to alter the =git
+commit= command to include the =-S= flag. Here's an example:
#+begin_src sh
git commit -S -m "my commit message"
#+end_src
-As an expansion of the example above, Git users can configure their
-environment with a default key to use by adding their GPG signature:
+As an expansion of the example above, Git users can configure their environment
+with a default key to use by adding their GPG signature:
#+begin_src sh
git config --global user.signingkey XXXXXXXXXXXXXXXX
#+end_src
-If you're not sure what your signature is, you can find it titled =sig=
-in the output of this command:
+If you're not sure what your signature is, you can find it titled =sig= in the
+output of this command:
#+begin_src sh
gpg --list-signatures
@@ -269,12 +255,11 @@ gpg --list-signatures
** File Integrity
-When a person generates a signature for data, they are allowing users
-the ability to verify the signature on that data in the future to ensure
-the data has not been corrupted. This is most common with software
-applications hosted on the internet - developers provide signatures so
-that users can verify a website was not hijacked and download links
-replaced with dangerous software.
+When a person generates a signature for data, they are allowing users the
+ability to verify the signature on that data in the future to ensure the data
+has not been corrupted. This is most common with software applications hosted on
+the internet - developers provide signatures so that users can verify a website
+was not hijacked and download links replaced with dangerous software.
In order to verify signed data, a user needs to have:
@@ -282,9 +267,8 @@ In order to verify signed data, a user needs to have:
2. A signature file
3. The public GPG key of the signer
-Once the signer's public key is imported on the user's system, and they
-have the data and signature, they can verify the data with the following
-commands:
+Once the signer's public key is imported on the user's system, and they have the
+data and signature, they can verify the data with the following commands:
#+begin_src sh
# If the signature is attached to the data
@@ -296,11 +280,11 @@ gpg --verify [signature-file] [original-file]
*** Finding Public Keys
-In order to use GPG with others, a user needs to know the other user(s)
-keys. This is easy to do if the user knows the other user(s) in person,
-but may be hard if the relationship is strictly digital. Luckily, there
-are a few options. The first option is to look at a user's web page or
-social pages if they have them.
+In order to use GPG with others, a user needs to know the other user(s) keys.
+This is easy to do if the user knows the other user(s) in person, but may be
+hard if the relationship is strictly digital. Luckily, there are a few options.
+The first option is to look at a user's web page or social pages if they have
+them.
Otherwise, the best option is to use a keyserver, such as:
diff --git a/content/blog/2022-07-25-curseradio.org b/content/blog/2022-07-25-curseradio.org
index 236d136..686ccba 100644
--- a/content/blog/2022-07-25-curseradio.org
+++ b/content/blog/2022-07-25-curseradio.org
@@ -6,28 +6,25 @@
* Overview
While exploring some interesting Linux applications, I stumbled across
-[[https://github.com/chronitis/curseradio][curseradio]], a command-line
-radio player based on Python.
+[[https://github.com/chronitis/curseradio][curseradio]], a command-line radio player based on Python.
-This application is fantastic and incredibly easy to install, so I
-wanted to dedicate a post today to this app. Let's look at the features
-within the app and then walk through the installation process I took to
-get =curseradio= working.
+This application is fantastic and incredibly easy to install, so I wanted to
+dedicate a post today to this app. Let's look at the features within the app and
+then walk through the installation process I took to get =curseradio= working.
* Features
-The radio player itself is quite minimal. As you can see in the
-screenshot above, it contains a simple plaintext list of all available
-categories, which can be broken down further and further. In addition,
-radio shows are available for listening, alongside regular radio
-stations.
+The radio player itself is quite minimal. As you can see in the screenshot
+above, it contains a simple plaintext list of all available categories, which
+can be broken down further and further. In addition, radio shows are available
+for listening, alongside regular radio stations.
-For example, the =Sports= > =Pro Basketball= > =Shows= category contains
-a number of specific shows related to Professional Basketball.
+For example, the =Sports= > =Pro Basketball= > =Shows= category contains a
+number of specific shows related to Professional Basketball.
-Aside from being able to play any of the listed stations/shows, you can
-make a channel your favorite by pressing =f=. It will now show up at the
-top of the radio player in the =Favourites= category.
+Aside from being able to play any of the listed stations/shows, you can make a
+channel your favorite by pressing =f=. It will now show up at the top of the
+radio player in the =Favourites= category.
** Commands/Shortcuts
@@ -45,11 +42,10 @@ top of the radio player in the =Favourites= category.
** Dependencies
-Before installing =curseradio=, a handful of system and Python packages
-are required. To get started, install =python3=, =pip3=, and =mpv= on
-your system. In this example, I'm using Fedora Linux, which uses the
-=dnf= package manager. You may need to adjust this if you're using a
-different system.
+Before installing =curseradio=, a handful of system and Python packages are
+required. To get started, install =python3=, =pip3=, and =mpv= on your system.
+In this example, I'm using Fedora Linux, which uses the =dnf= package manager.
+You may need to adjust this if you're using a different system.
#+begin_src sh
sudo dnf install python3 pip3 mpv
@@ -63,23 +59,23 @@ pip3 install requests xdg lxml
** Repository Source Installation
-Once all the dependencies are installed, we can clone the source code
-and enter that directory:
+Once all the dependencies are installed, we can clone the source code and enter
+that directory:
#+begin_src sh
git clone https://github.com/chronitis/curseradio && cd curseradio
#+end_src
-Once you're within the =curseradio= directory, you can install the
-application with the provided =setup.py= script.
+Once you're within the =curseradio= directory, you can install the application
+with the provided =setup.py= script.
#+begin_src sh
sudo python3 setup.py install
#+end_src
-In my case, I ran into a few errors and needed to create the folders
-that curseradio wanted to use for its installation. If you don't get any
-errors, you can skip this and run the app.
+In my case, I ran into a few errors and needed to create the folders that
+curseradio wanted to use for its installation. If you don't get any errors, you
+can skip this and run the app.
#+begin_src sh
sudo mkdir /usr/local/lib/python3.10/
diff --git a/content/blog/2022-07-30-flac-to-opus.org b/content/blog/2022-07-30-flac-to-opus.org
index 36d9fe7..0c1910e 100644
--- a/content/blog/2022-07-30-flac-to-opus.org
+++ b/content/blog/2022-07-30-flac-to-opus.org
@@ -6,17 +6,15 @@
* Converting FLAC to OPUS
I am currently rebuilding my music library from scratch so that I can
-effectively archive all the music I own in the
-[[https://en.wikipedia.org/wiki/FLAC][FLAC file format]], a lossless
-audio codec.
+effectively archive all the music I own in [[https://wikipedia.org/wiki/FLAC][FLAC]] (Free Lossless Audio Codec)
+files.
-However, streaming FLAC files outside the home can be difficult due to
-the size of the files, especially if you're using a weak connection.
+However, streaming FLAC files outside the home can be difficult due to the size
+of the files, especially if you're using a weak connection.
-So, in order to archive the music in a lossless format and still be able
-to stream it easily, I opted to create a copy of my FLAC files in the
-[[https://en.wikipedia.org/wiki/Opus_(audio_format)][Opus audio codec]].
-This allows me to archive a quality, lossless version of the music and
+So, in order to archive the music in a lossless format and still be able to
+stream it easily, I opted to create a copy of my FLAC files in the [[https://en.wikipedia.org/wiki/Opus_(audio_format)][Opus audio
+codec]]. This allows me to archive a quality, lossless version of the music and
then point my streaming service to the smaller, stream-ready version.
** Dependencies
@@ -28,39 +26,38 @@ proceeding, install the package:
sudo apt install opus-tools
#+end_src
-If you want to use a different conversion method, such as =ffmpeg= or
-=avconv=, simply install that package instead.
+If you want to use a different conversion method, such as =ffmpeg= or =avconv=,
+simply install that package instead.
** Conversion Process
-The script I'm using is stored in my home directory, but feel free to
-create it wherever you want. It does not need to be in the same
-directory as your music files.
+The script I'm using is stored in my home directory, but feel free to create it
+wherever you want. It does not need to be in the same directory as your music
+files.
#+begin_src sh
cd ~ && nano transform.sh
#+end_src
-Once you have your new bash script opened in an editor, go ahead and
-paste the following logic into the script.
+Once you have your new bash script opened in an editor, go ahead and paste the
+following logic into the script.
You *MUST* edit the following variables in order for it to work:
- =source=: The source directory where your FLAC files are stored.
-- =dest=: The destination directory where you want the resulting Opus
- files to be stored.
+- =dest=: The destination directory where you want the resulting Opus files to
+ be stored.
You *MAY* want to edit the following variables to suit your needs:
-- =filename=: If you are converting to a file format other than Opus,
- you'll need to edit this so that your resulting files have the correct
- filename extension.
-- =reldir=: This variable can be edited to strip out more leading
- directories in the file path. As you'll see later, I ignore this for
- now and simply clean it up afterward.
-- =opusenc=: This is the actual conversion process. You may want to edit
- the bitrate to suit your needs. I set mine at 128 but some prefer 160
- or higher.
+- =filename=: If you are converting to a file format other than Opus, you'll
+ need to edit this so that your resulting files have the correct filename
+ extension.
+- =reldir=: This variable can be edited to strip out more leading directories in
+ the file path. As you'll see later, I ignore this for now and simply clean it
+ up afterward.
+- =opusenc=: This is the actual conversion process. You may want to edit the
+ bitrate to suit your needs. I set mine at 128 but some prefer 160 or higher.
#+begin_src sh
#!/bin/bash
@@ -126,8 +123,8 @@ opusenc --vbr --bitrate 128 --date "$DATE" \
done
#+end_src
-Once you're done, simply save the file and exit your editor. Don't
-forget to enable execution of the script:
+Once you're done, simply save the file and exit your editor. Don't forget to
+enable execution of the script:
#+begin_src sh
chmod +x transform.sh
@@ -139,16 +136,16 @@ Finally, you may now run the script:
./transform.sh
#+end_src
-If you used =opusenc=, you'll see the conversions happen within the
-terminal as it progresses. You will also see variables printed if you
-uncommented any of the bash script's comments.
+If you used =opusenc=, you'll see the conversions happen within the terminal as
+it progresses. You will also see variables printed if you uncommented any of the
+bash script's comments.
** Cleanup
-As I noted above, I didn't customize my =reldir= variable in the script,
-which caused my output directory to be =/mnt/music/library/archives=
-instead of =/mnt/music/library=. So, I moved the output up one level and
-deleted the accidental directory.
+As I noted above, I didn't customize my =reldir= variable in the script, which
+caused my output directory to be =/mnt/music/library/archives= instead of
+=/mnt/music/library=. So, I moved the output up one level and deleted the
+accidental directory.
#+begin_src sh
cd /mnt/music/library
@@ -158,8 +155,8 @@ rm -rf archives
** Check the Resulting Size
-If you want to see what kind of file size savings you've gained, you can
-always use the =du= command to check:
+If you want to see what kind of file size savings you've gained, you can always
+use the =du= command to check:
#+begin_src sh
cd /mnt/music
diff --git a/content/blog/2022-07-31-bash-it.org b/content/blog/2022-07-31-bash-it.org
index d32e973..2d04d7b 100644
--- a/content/blog/2022-07-31-bash-it.org
+++ b/content/blog/2022-07-31-bash-it.org
@@ -5,14 +5,12 @@
* Bash
-For those who are not familiar,
-[[https://en.wikipedia.org/wiki/Bash_(Unix_shell)][Bash]] is a Unix
-shell that is used as the default login shell for most Linux
-distributions. This shell and command processor should be familiar if
-you've used Linux (or older version of macOS) before.
+For those who are not familiar, [[https://en.wikipedia.org/wiki/Bash_(Unix_shell)][Bash]] is a Unix shell that is used as the default
+login shell for most Linux distributions. This shell and command processor
+should be familiar if you've used Linux (or older version of macOS) before.
-However, bash is not the only option. There are numerous other shells
-that exist. Here are some popular examples:
+However, bash is not the only option. There are numerous other shells that
+exist. Here are some popular examples:
- [[https://en.wikipedia.org/wiki/Z_shell][zsh]]
- [[https://en.wikipedia.org/wiki/Fish_(Unix_shell)][fish]]
@@ -20,16 +18,15 @@ that exist. Here are some popular examples:
- [[https://wiki.gentoo.org/wiki/Mksh][mksh]]
- [[https://en.wikipedia.org/wiki/Debian_Almquist_shell][dash]]
-While each shell has its differences, bash is POSIX compliant and the
-default for many Linux users. Because of this, I am going to explore a
-program called =bash-it= below that helps bash users increase the
-utility of their shell without installing a completely new shell.
+While each shell has its differences, bash is POSIX compliant and the default
+for many Linux users. Because of this, I am going to explore a program called
+=bash-it= below that helps bash users increase the utility of their shell
+without installing a completely new shell.
** Installation
-First, if bash is not already installed on your system, you can
-[[https://www.gnu.org/software/bash/][download bash from GNU]] or use
-your package manager to install it.
+First, if bash is not already installed on your system, you can [[https://www.gnu.org/software/bash/][download bash
+from GNU]] or use your package manager to install it.
For example, this is how you can install bash on Fedora Linux:
@@ -37,19 +34,19 @@ For example, this is how you can install bash on Fedora Linux:
sudo dnf install bash
#+end_src
-If you are not using bash as your default shell, use the =chsh= command
-to change your shell:
+If you are not using bash as your default shell, use the =chsh= command to
+change your shell:
#+begin_src sh
chsh
#+end_src
-You should see a prompt like the one below. If the brackets (=[]=)
-contain =bash= already, you're done, and you can simply continue by
-hitting the Enter key.
+You should see a prompt like the one below. If the brackets (=[]=) contain
+=bash= already, you're done, and you can simply continue by hitting the Enter
+key.
-If the brackets contain another shell path (e.g. =/usr/bin/zsh=), enter
-the path to the bash program on your system (it's most likely located at
+If the brackets contain another shell path (e.g. =/usr/bin/zsh=), enter the path
+to the bash program on your system (it's most likely located at
=/usr/bin/bash=).
#+begin_src sh
@@ -57,9 +54,9 @@ Changing shell for <user>.
New shell [/usr/bin/bash]:
#+end_src
-You must log out or restart the machine in order for the login shell to
-be refreshed. You can do it now or wait until you're finished
-customizing the shell.
+You must log out or restart the machine in order for the login shell to be
+refreshed. You can do it now or wait until you're finished customizing the
+shell.
#+begin_src sh
sudo reboot now
@@ -67,31 +64,30 @@ sudo reboot now
* Bash-it
-As noted on the [[https://github.com/Bash-it/bash-it][Bash-it]]
-repository:
+As noted on the [[https://github.com/Bash-it/bash-it][Bash-it]] repository:
#+begin_quote
Bash-it is a collection of community Bash commands and scripts for Bash
3.2+. (And a shameless ripoff of oh-my-zsh 😃)
#+end_quote
-Bash-it makes it easy to install plugins, set up aliases for common
-commands, and easily change the visual theme of your shell.
+Bash-it makes it easy to install plugins, set up aliases for common commands,
+and easily change the visual theme of your shell.
** Installation
To install the framework, simply copy the repository files and use the
-=install.sh= script provided. If you want, you can (and should!) inspect
-the contents of the installation script before you run it.
+=install.sh= script provided. If you want, you can (and should!) inspect the
+contents of the installation script before you run it.
#+begin_src sh
git clone --depth=1 https://github.com/Bash-it/bash-it.git ~/.bash_it
~/.bash_it/install.sh
#+end_src
-If you didn't restart your session after making bash the default, and
-are currently working within another shell, be sure to enter a bash
-session before using =bash-it=:
+If you didn't restart your session after making bash the default, and are
+currently working within another shell, be sure to enter a bash session before
+using =bash-it=:
#+begin_src sh
bash
@@ -100,16 +96,16 @@ bash
** Aliases
Bash-it contains a number of aliases for common commands to help improve
-efficiency in the terminal. To list all available options, use the
-following command:
+efficiency in the terminal. To list all available options, use the following
+command:
#+begin_src sh
bash-it show aliases
#+end_src
-This will provide you a list that looks like the following text block.
-Within this screen, you will be able to see all available options and
-which ones are currently enabled.
+This will provide you a list that looks like the following text block. Within
+this screen, you will be able to see all available options and which ones are
+currently enabled.
#+begin_src txt
Alias Enabled? Description
@@ -140,9 +136,8 @@ bash-it disable alias <alias name> [alias name]... -or- $ bash-it disable alias
** Plugins
-Similar to aliases, plugins are available with bash-it. You can find a
-complete list of plugins in the same way as aliases. Simply execute the
-following:
+Similar to aliases, plugins are available with bash-it. You can find a complete
+list of plugins in the same way as aliases. Simply execute the following:
#+begin_src sh
bash-it show plugins
@@ -177,9 +172,7 @@ bash-it disable plugin <plugin name> [plugin name]... -or- $ bash-it disable plu
** Themes
-There are quite a few pre-defined
-[[https://bash-it.readthedocs.io/en/latest/themes-list/#list-of-themes][themes]]
-available with bash-it.
+There are quite a few pre-defined [[https://bash-it.readthedocs.io/en/latest/themes-list/#list-of-themes][themes]] available with bash-it.
To list all themes:
@@ -187,9 +180,8 @@ To list all themes:
ls ~/.bash_it/themes/
#+end_src
-To use a new theme, you'll need to edit =.bashrc= and alter the
-=BASH_IT_THEME= variable to your desired theme. For example, I am using
-the =zork= theme.
+To use a new theme, you'll need to edit =.bashrc= and alter the =BASH_IT_THEME=
+variable to your desired theme. For example, I am using the =zork= theme.
#+begin_src sh
nano ~/.bashrc
@@ -199,23 +191,22 @@ nano ~/.bashrc
export BASH_IT_THEME='zork'
#+end_src
-Once you save your changes, you just need to exit your terminal and
-create a new one in order to see your changes to the =.bashrc= file. You
-can also =source= the file to see changes, but I recommend starting a
-completely new shell instead.
+Once you save your changes, you just need to exit your terminal and create a new
+one in order to see your changes to the =.bashrc= file. You can also =source=
+the file to see changes, but I recommend starting a completely new shell
+instead.
*** ble.sh
-One big feature I was missing in Bash that both =zsh= and =fish= have is
-an autosuggestion feature. To explain: as you type, an autosuggestion
-feature in the shell will offer suggestions in a lighter font color
-beyond the characters already typed. Once you see the command you want,
-you can click the right arrow and have the shell auto-complete that line
-for you.
+One big feature I was missing in Bash that both =zsh= and =fish= have is an
+autosuggestion feature. To explain: as you type, an autosuggestion feature in
+the shell will offer suggestions in a lighter font color beyond the characters
+already typed. Once you see the command you want, you can click the right arrow
+and have the shell auto-complete that line for you.
-Luckily, the [[https://github.com/akinomyoga/ble.sh][Bash Line Editor]]
-(ble.sh) exists! This program provides a wonderful autosuggestions
-feature perfectly, among other features that I haven't tested yet.
+Luckily, the [[https://github.com/akinomyoga/ble.sh][Bash Line Editor]] (ble.sh) exists! This program provides a wonderful
+autosuggestions feature perfectly, among other features that I haven't tested
+yet.
In order to install ble.sh, execute the following:
@@ -225,16 +216,16 @@ make -C ble.sh install PREFIX=~/.local
echo 'source ~/.local/share/blesh/ble.sh' >> ~/.bashrc
#+end_src
-Again, exit the terminal and open a new one in order to see the
-newly-configured shell.
+Again, exit the terminal and open a new one in order to see the newly-configured
+shell.
* Restart the Session
-Finally, as mentioned above, you'll need to restart the session to
-ensure that your user is using bash by default.
+Finally, as mentioned above, you'll need to restart the session to ensure that
+your user is using bash by default.
-You will also need to exit and re-open a shell (e.g., terminal or
-terminal tab) any time you make changes to the =.bashrc= file.
+You will also need to exit and re-open a shell (e.g., terminal or terminal tab)
+any time you make changes to the =.bashrc= file.
#+begin_src sh
sudo reboot now
diff --git a/content/blog/2022-08-31-privacy-com-changes.org b/content/blog/2022-08-31-privacy-com-changes.org
index 7dc86d2..e030b35 100644
--- a/content/blog/2022-08-31-privacy-com-changes.org
+++ b/content/blog/2022-08-31-privacy-com-changes.org
@@ -5,50 +5,46 @@
* Privacy.com Changes Their Terms
-Recently, Privacy.com reached out to their customers regarding a change
-in their terms of use. Further, all customers are required to agree to
-the changes in order to continue using their accounts.
+Recently, Privacy.com reached out to their customers regarding a change in their
+terms of use. Further, all customers are required to agree to the changes in
+order to continue using their accounts.
-[[https://privacy.com/commercial-cardholder-agreement][You can view the
-new cardholder agreement here]].
+[[https://privacy.com/commercial-cardholder-agreement][You can view the new cardholder agreement here]].
-When you log in, you'll be greeted with a pop-up window asking you to
-review and agree to the new terms of use. You will also not be able to
-open any new cards until the terms are agreed to.
+When you log in, you'll be greeted with a pop-up window asking you to review and
+agree to the new terms of use. You will also not be able to open any new cards
+until the terms are agreed to.
** Changing from a "Prepaid Debit" Model to a "Charge Card" Model
-The actual content of the changes is interesting. While the historical
-model of using Privacy.com was akin to prepaid debit cards, the new
-model is very similar to a credit card (they use the term "charge
-card").
+The actual content of the changes is interesting. While the historical model of
+using Privacy.com was akin to prepaid debit cards, the new model is very similar
+to a credit card (they use the term "charge card").
-I have used Privacy.com for 1-2 years, and the process was always that
-you would create a single-use or merchant-locked card. This card could
-be used for any dollar limit you set and would immediately draw the
-funds from whatever funding source you connected, e.g. PayPal account or
-a bank account.
+I have used Privacy.com for 1-2 years, and the process was always that you would
+create a single-use or merchant-locked card. This card could be used for any
+dollar limit you set and would immediately draw the funds from whatever funding
+source you connected, e.g. PayPal account or a bank account.
-The benefit this service provides with a premium account is masking the
-merchant names from your funding source. If you have a concern that your
-bank account uses merchant data from your account, you could direct all
-charges through Privacy.com and set the merchant as one of their pre-set
-options, such as "Smiley's Corner Store" or "NSA Gift Shop."
+The benefit this service provides with a premium account is masking the merchant
+names from your funding source. If you have a concern that your bank account
+uses merchant data from your account, you could direct all charges through
+Privacy.com and set the merchant as one of their pre-set options, such as
+"Smiley's Corner Store" or "NSA Gift Shop."
-The new model still works with a bank account as a funding source, but
-the model is changed so that you get a "line of credit" set according to
-a 14-day billing cycle. It seems that Privacy.com will now allow charges
-to be incurred without being immediately paid.
+The new model still works with a bank account as a funding source, but the model
+is changed so that you get a "line of credit" set according to a 14-day billing
+cycle. It seems that Privacy.com will now allow charges to be incurred without
+being immediately paid.
** Daily Payments and Available Credit
-Instead of paying as charges are incurred, you must make a "Daily
-Payment" and your "Available Credit" will be locked until you make that
-payment. There are also "End of Billing Cycle Payments" that are
-assigned a due date.
+Instead of paying as charges are incurred, you must make a "Daily Payment" and
+your "Available Credit" will be locked until you make that payment. There are
+also "End of Billing Cycle Payments" that are assigned a due date.
-Further, Privacy.com will decline charges that would cause you to exceed
-your Available Credit or Credit Limit.
+Further, Privacy.com will decline charges that would cause you to exceed your
+Available Credit or Credit Limit.
One particular interesting section states the following:
@@ -63,37 +59,34 @@ FOR MORE INFORMATION.
** Personal Information
-Now that Privacy.com is more of a financial institution, they are
-obligated to comply with the
-[[https://en.wikipedia.org/wiki/Know_your_customer][know your customer]]
-guidelines/laws.
+Now that Privacy.com is more of a financial institution, they are obligated to
+comply with the [[https://en.wikipedia.org/wiki/Know_your_customer][know your customer]] guidelines/laws.
-I did not proceed with the change to my Privacy.com account, but I have
-heard from some peers that the changes require more personal information
-to be submitted, such as SSN. I am not aware of all new personal
-information required or if the funding source is now required to only be
-a bank account.
+I did not proceed with the change to my Privacy.com account, but I have heard
+from some peers that the changes require more personal information to be
+submitted, such as SSN (Social Security Number). I am not aware of all new
+personal information required or if the funding source is now required to only
+be a bank account.
** Fees
-Luckily, the fees section did not change much. The subscription fees for
-a premium account are still the only fees.
+Luckily, the fees section did not change much. The subscription fees for a
+premium account are still the only fees.
* My Thoughts
-Personally, I wiped my personal information from my account and then
-permanently deleted it when I heard about these changes. I have no
-interest in yet another method of credit lending offered by private
-companies. While I accepted that they would have access to my bank
-account information for the purposes of paying off my prepaid debit
-payments, I have no interest in incurring charges that will need to be
-paid back at a later date. I also have no interest in submitting
+Personally, I wiped my personal information from my account and then permanently
+deleted it when I heard about these changes. I have no interest in yet another
+method of credit lending offered by private companies. While I accepted that
+they would have access to my bank account information for the purposes of paying
+off my prepaid debit payments, I have no interest in incurring charges that will
+need to be paid back at a later date. I also have no interest in submitting
personal information to Privacy.com.
-This type of change toward a "buy it now, pay us later" model is
-concerning, and I will be watching Privacy.com to see if they further
-their interests in the credit model as time goes on.
+This type of change toward a "buy it now, pay us later" model is concerning, and
+I will be watching Privacy.com to see if they further their interests in the
+credit model as time goes on.
-Could we see them start charging interest, fees, etc.? I'm not sure, but
-this change does not inspire confidence in their mission as a
-privacy-focused company.
+Could we see them start charging interest, fees, etc.? I'm not sure, but this
+change does not inspire confidence in their mission as a privacy-focused
+company.
diff --git a/content/blog/2022-09-17-serenity-os.org b/content/blog/2022-09-17-serenity-os.org
index 51b0df5..58c9551 100644
--- a/content/blog/2022-09-17-serenity-os.org
+++ b/content/blog/2022-09-17-serenity-os.org
@@ -5,13 +5,13 @@
* Overview
-[[https://serenityos.org][SerenityOS]] is a unique operating system (OS)
-that I have seen pop up in my news feed a few times over the last few
-years, but I have never had time to test it out until now.
+[[https://serenityos.org][SerenityOS]] is a unique operating system (OS) that I have seen pop up in my news
+feed a few times over the last few years, but I have never had time to test it
+out until now.
Testing out this system brought back fond memories of yellowed,
-modem-screeching, 100-pound computers that brought so many fond memories
-to my youth.
+modem-screeching, 100-pound computers that brought so many fond memories to my
+youth.
Per their website:
@@ -31,11 +31,10 @@ This is a system by us, for us, based on the things we like.
* Building
-Your first question may be "Where's the iso?" and the answer is... there
-are none. SerenityOS does not provide pre-built images for testing. You
-must build the images yourself. This seems intentionally to limit
-participation to only those who are truly interested enough to learn how
-to build the OS.
+Your first question may be "Where's the iso?" and the answer is... there are
+none. SerenityOS does not provide pre-built images for testing. You must build
+the images yourself. This seems intentionally to limit participation to only
+those who are truly interested enough to learn how to build the OS.
** Clone
@@ -47,25 +46,22 @@ git clone https://github.com/SerenityOS/serenity && cd serenity
** Build
-Note that I followed the
-[[https://github.com/SerenityOS/serenity/blob/master/Documentation/BuildInstructions.md][Build
-Instructions]] in the SerenityOS repository as of commit
-=660d2b53b1206e868d5470eee80b5e62d7e30da7=. Things may have changed
-since my installation, and you should double-check the instructions
-first.
+Note that I followed the [[https://github.com/SerenityOS/serenity/blob/master/Documentation/BuildInstructions.md][Build Instructions]] in the SerenityOS repository as of
+commit =660d2b53b1206e868d5470eee80b5e62d7e30da7=. Things may have changed since
+my installation, and you should double-check the instructions first.
-Regardless, I want to repeat my steps here to illustrate any errors or
-differing commands I needed to run in order to build and run SerenityOS.
+Regardless, I want to repeat my steps here to illustrate any errors or differing
+commands I needed to run in order to build and run SerenityOS.
-Since I am running Fedora, I needed to install these packages in order
-to build the OS images:
+Since I am running Fedora, I needed to install these packages in order to build
+the OS images:
#+begin_src sh
sudo dnf install texinfo binutils-devel curl cmake mpfr-devel libmpc-devel gmp-devel e2fsprogs ninja-build patch ccache rsync @"C Development Tools and Libraries" @Virtualization
#+end_src
-Next, make sure you're inside the =serenity= directory created earlier
-during the git cloning process and process to build the toolchain:
+Next, make sure you're inside the =serenity= directory created earlier during
+the git cloning process and process to build the toolchain:
#+begin_src sh
Meta/serenity.sh rebuild-toolchain
@@ -82,29 +78,27 @@ launch.
* Issues
-I played around in SerenityOS for an hour or two in order to see what I
-could do and had a lot of fun with it. The only issue I ran into was a
-lack of working internet. I didn't try very hard, but I could tell that
-the main network link wasn't connecting to my Fedora host properly.
+I played around in SerenityOS for an hour or two in order to see what I could do
+and had a lot of fun with it. The only issue I ran into was a lack of working
+internet. I didn't try very hard, but I could tell that the main network link
+wasn't connecting to my Fedora host properly.
* Screenshots
-The initial launch of the image displays the SerenityOS desktop, with a
-simple terminal already launched.
+The initial launch of the image displays the SerenityOS desktop, with a simple
+terminal already launched.
-There is also a "Fire" application (literally just shows fire burning),
-a browser with the local Serenity Browser page loaded, and a text
-editor.
+There is also a "Fire" application (literally just shows fire burning), a
+browser with the local Serenity Browser page loaded, and a text editor.
-I also poked around the system utilities and found most tools you'd
-expect to find within a standard desktop, such as a system monitoring
-tool.
+I also poked around the system utilities and found most tools you'd expect to
+find within a standard desktop, such as a system monitoring tool.
-Lastly, I noted that the default desktop contains numerous pre-defined
-themes to choose from. This is a small piece, but it's actually
-wonderful to see desktop developers consider theming directly out of the
-box rather than using an addon-based mentality.
+Lastly, I noted that the default desktop contains numerous pre-defined themes to
+choose from. This is a small piece, but it's actually wonderful to see desktop
+developers consider theming directly out of the box rather than using an
+addon-based mentality.
-I didn't take a screenshot of the other pre-installed games, but I did
-spend nearly 30 minutes playing Solitaire before remembering that I was
-supposed to be writing a post about the OS.
+I didn't take a screenshot of the other pre-installed games, but I did spend
+nearly 30 minutes playing Solitaire before remembering that I was supposed to be
+writing a post about the OS.
diff --git a/content/blog/2022-09-21-graphene-os.org b/content/blog/2022-09-21-graphene-os.org
index 8cb8420..5e2663c 100644
--- a/content/blog/2022-09-21-graphene-os.org
+++ b/content/blog/2022-09-21-graphene-os.org
@@ -5,26 +5,24 @@
* Introduction
-After using iOS for a couple of years, I finally took the plunge and
-purchased a Pixel 6 Pro in order to test and use [GrapheneOS]
-([[https://grapheneos.org]]).
+After using iOS for a couple of years, I finally took the plunge and purchased a
+Pixel 6 Pro in order to test and use [[https://grapheneos.org][GrapheneOS]].
-The installation process was rather quick once you have the tools and
-files you need. Overall, it can be done in just a few minutes.
+The installation process was rather quick once you have the tools and files you
+need. Overall, it can be done in just a few minutes.
* Gathering Tools & Files
** Android Tools
-First, in order to interact with the device, we will need the
-[[https://developer.android.com/studio/releases/platform-tools.html][Android
-platform tools]]. Find the Linux download and save the ZIP folder to
-your preferred location.
+First, in order to interact with the device, we will need the [[https://developer.android.com/studio/releases/platform-tools.html][Android platform
+tools]]. Find the Linux download and save the ZIP folder to your preferred
+location.
Once we've downloaded the files, we will need to unzip them, enter the
-directory, and move the necessary executables to a central location,
-such as =/usr/bin/=. For this installation, we only need the =fastboot=
-and =adb= executables.
+directory, and move the necessary executables to a central location, such as
+=/usr/bin/=. For this installation, we only need the =fastboot= and =adb=
+executables.
#+begin_src sh
cd ~/Downloads
@@ -39,9 +37,8 @@ sudo mv adb /usr/bin
** GrapheneOS Files
-Next, we need the [[https://grapheneos.org/releases][GrapheneOS files]]
-for our device and model. For example, the Pixel 6 Pro is codenamed
-=raven= on the release page.
+Next, we need the [[https://grapheneos.org/releases][GrapheneOS files]] for our device and model. For example, the
+Pixel 6 Pro is codenamed =raven= on the release page.
Once we have the links, let's download them to our working directory:
@@ -53,8 +50,8 @@ curl -0 https://releases.grapheneos.org/raven-factory-2022091400.zip.sig
1. Validate Integrity
- In order to validate the integrity of the downloaded files, we will
- need the =signify= package and Graphene's =factory.pub= file.
+ In order to validate the integrity of the downloaded files, we will need the
+ =signify= package and Graphene's =factory.pub= file.
#+begin_src sh
sudo dnf install signify
@@ -64,8 +61,8 @@ curl -0 https://releases.grapheneos.org/raven-factory-2022091400.zip.sig
curl -O https://releases.grapheneos.org/factory.pub
#+end_src
- Then we can validate the files and ensure that no data was corrupted
- or modified before it was saved to our device.
+ Then we can validate the files and ensure that no data was corrupted or
+ modified before it was saved to our device.
#+begin_src sh
signify -Cqp factory.pub -x raven-factory-2022091400.zip.sig && echo verified
@@ -73,8 +70,8 @@ curl -0 https://releases.grapheneos.org/raven-factory-2022091400.zip.sig
2. Unzip Files
- Once the files are verified, we can unzip the Graphene image and
- enter the directory:
+ Once the files are verified, we can unzip the Graphene image and enter the
+ directory:
#+begin_src sh
unzip raven-factory-2022091400.zip && cd raven-factory-2022091400
@@ -84,35 +81,35 @@ curl -0 https://releases.grapheneos.org/raven-factory-2022091400.zip.sig
** Enable Developer Debugging & OEM Unlock
-Before we can actually flash anything to the phone, we will need to
-enable OEM Unlocking, as well as either USB Debugging or Wireless
-Debugging, depending on which method we will be using.
+Before we can actually flash anything to the phone, we will need to enable OEM
+(Original Equipment Manufacturer) Unlocking, as well as either USB (Universal
+Serial Bus) Debugging or Wireless Debugging, depending on which method we will
+be using.
-To start, enable developer mode by going to =Settings= > =About= and
-tapping =Build Number= seven (7) times. You may need to enter your PIN
-to enable this mode.
+To start, enable developer mode by going to =Settings= > =About= and tapping
+=Build Number= seven (7) times. You may need to enter your personal identified
+number (PIN) to enable this mode.
-Once developer mode is enabled, go to =Settings= > =System= >
-=Devloper Options= and enable OEM Unlocking, as well as USB or Wireless
-Debugging. In my case, I chose USB Debugging and performed all actions
-via USB cable.
+Once developer mode is enabled, go to =Settings= > =System= > =Devloper Options=
+and enable OEM Unlocking, as well as USB or Wireless Debugging. In my case, I
+chose USB Debugging and performed all actions via USB cable.
-Once these options are enabled, plug the phone into the computer and
-execute the following command:
+Once these options are enabled, plug the phone into the computer and execute the
+following command:
#+begin_src sh
adb devices
#+end_src
-If an unauthorized error occurs, make sure the USB mode on the phone is
-changed from charging to something like "File Transfer" or "PTP." You
-can find the USB mode in the notification tray.
+If an unauthorized error occurs, make sure the USB mode on the phone is changed
+from charging to something like "File Transfer" or "PTP" (Picture Transfer
+Protocol). You can find the USB mode in the notification tray.
** Reboot Device
-Once we have found the device via =adb=, we can either boot into the
-bootloader interface by holding the volume down button while the phone
-reboots or by executing the following command:
+Once we have found the device via =adb=, we can either boot into the bootloader
+interface by holding the volume down button while the phone reboots or by
+executing the following command:
#+begin_src sh
adb reboot bootloader
@@ -120,17 +117,14 @@ adb reboot bootloader
** Unlock the Bootloader
-The phone will reboot and load the bootloader screen upon startup. At
-this point, we are ready to start the actual flashing of GrapheneOS onto
-the device.
+The phone will reboot and load the bootloader screen upon startup. At this
+point, we are ready to start the actual flashing of GrapheneOS onto the device.
-*NOTE*: In my situation, I needed to use =sudo= with every =fastboot=
-command, but not with =adb= commands. I am not sure if this is standard
-or a Fedora quirk, but I'm documenting my commands verbatim in this
-post.
+*NOTE*: In my situation, I needed to use =sudo= with every =fastboot= command,
+but not with =adb= commands. I am not sure if this is standard or a Fedora
+quirk, but I'm documenting my commands verbatim in this post.
-First, we start by unlocking the bootloader so that we can load other
-ROMs:
+First, we start by unlocking the bootloader so that we can load other ROMs:
#+begin_src sh
sudo fastboot flashing unlock
@@ -138,24 +132,23 @@ sudo fastboot flashing unlock
** Flashing Factory Images
-Once the phone is unlocked, we can flash it with the =flash-all.sh=
-script found inside the =raven-factory-2022091400= folder we entered
-earlier:
+Once the phone is unlocked, we can flash it with the =flash-all.sh= script found
+inside the =raven-factory-2022091400= folder we entered earlier:
#+begin_src sh
sudo ./flash-all.sh
#+end_src
-This process should take a few minutes and will print informational
-messages as things progress. Avoid doing anything on the phone while
-this process is operating.
+This process should take a few minutes and will print informational messages as
+things progress. Avoid doing anything on the phone while this process is
+operating.
** Lock the Bootloader
-If everything was successful, the phone should reboot a few times and
-finally land back on the bootloader screen. At this point, we can
-re-lock the bootloader to enable full verified boot and protect the
-device from unwanted flashing or erasure of data.
+If everything was successful, the phone should reboot a few times and finally
+land back on the bootloader screen. At this point, we can re-lock the bootloader
+to enable full verified boot and protect the device from unwanted flashing or
+erasure of data.
#+begin_src sh
sudo fastboot flashing lock
diff --git a/content/blog/2022-10-04-mtp-linux.org b/content/blog/2022-10-04-mtp-linux.org
index 9275a8f..673d54d 100644
--- a/content/blog/2022-10-04-mtp-linux.org
+++ b/content/blog/2022-10-04-mtp-linux.org
@@ -3,31 +3,29 @@
#+description: Instructions for mounting and accessing Media Transfer Protocol (MTP) compatible mobile devices on Fedora Linux using jmtpfs for file transfer and management.
#+slug: mtp-linux
-I recently ran into trouble attempting to mount my GrapheneOS phone to
-my laptop running Fedora Linux via the
-[[https://en.wikipedia.org/wiki/Media_transfer_protocol][Media Transfer
-Protocol]] (MTP) and discovered a simple and effective solution.
+I recently ran into trouble attempting to mount my GrapheneOS phone to my laptop
+running Fedora Linux via the [[https://en.wikipedia.org/wiki/Media_transfer_protocol][Media Transfer Protocol]] (MTP) and discovered a
+simple and effective solution.
-* Use a USB 3.0 Port
+* Use a Universal Serial Bus (USB) 3.0 Port
-First, ensure that the device was plugged in to the laptop through a USB
-3.0 port, if possible. From a brief glance online, it seems that USB 2.0
-ports may cause issues with dropped connections over MTP. This is purely
-anecdotal since I don't have any evidence to link showing that USB 2.0
-causes issues, but I can confirm that switching to a USB 3.0 port seemed
-to cut out most of my issues.
+First, ensure that the device was plugged in to the laptop through a USB 3.0
+port, if possible. From a brief glance online, it seems that USB 2.0 ports may
+cause issues with dropped connections over MTP. This is purely anecdotal since I
+don't have any evidence to link showing that USB 2.0 causes issues, but I can
+confirm that switching to a USB 3.0 port seemed to cut out most of my issues.
* Switch USB Preferences to MTP
-Secondly, you need to ensure that the phone's USB preferences/mode is
-changed to MTP or File Transfer once the phone is plugged in. Other
-modes will not allow you to access the phone's file system.
+Secondly, you need to ensure that the phone's USB preferences/mode is changed to
+MTP or File Transfer once the phone is plugged in. Other modes will not allow
+you to access the phone's file system.
* Install =jmtpfs=
-Next, I used the =jmtpfs= package to mount my phone to my laptop. There
-are other packages that exist, but this one worked perfectly for me. On
-Fedora Linux, you can install it like this:
+Next, I used the =jmtpfs= package to mount my phone to my laptop. There are
+other packages that exist, but this one worked perfectly for me. On Fedora
+Linux, you can install it like this:
#+begin_src sh
sudo dnf install jmtpfs -y
@@ -35,8 +33,8 @@ sudo dnf install jmtpfs -y
* Create a Mount Point
-Once you have the package installed, you just need to create a folder
-for the device to use as a mount point. In my case, I used =/mnt/pixel=:
+Once you have the package installed, you just need to create a folder for the
+device to use as a mount point. In my case, I used =/mnt/pixel=:
#+begin_src sh
sudo mkdir /mnt/pixel
@@ -45,8 +43,8 @@ sudo chown -R $USER:$USER /mnt/pixel
* Mount & Access the Phone's File System
-Finally, plug-in and mount the device, and you should be able to see all
-storage (internal and external) inside your new folder!
+Finally, plug-in and mount the device, and you should be able to see all storage
+(internal and external) inside your new folder!
#+begin_src sh
jmtpfs /mnt/pixel
@@ -59,16 +57,15 @@ Device 0 (VID=18d1 and PID=4ee1) is a Google Inc Nexus/Pixel (MTP).
Android device detected, assigning default bug flags
#+end_src
-Now you are mounted and can do anything you'd like with the device's
-files:
+Now you are mounted and can do anything you'd like with the device's files:
#+begin_src sh
cd /mnt/pixel
ls -lha
#+end_src
-From here, you will be able to see any internal or external storage
-available on the device:
+From here, you will be able to see any internal or external storage available on
+the device:
#+begin_src sh
total 0
diff --git a/content/blog/2022-10-04-syncthing.org b/content/blog/2022-10-04-syncthing.org
index ff6e199..891541f 100644
--- a/content/blog/2022-10-04-syncthing.org
+++ b/content/blog/2022-10-04-syncthing.org
@@ -5,26 +5,24 @@
* An Overview of Syncthing
-If you've been looking around the self-hosted cloud storage space for a
-while, you've undoubtedly run into someone suggesting
-[[https://syncthing.net][Syncthing]] as an option. However, it is an
-unusual alternative for those users out there who are used to having a
+If you've been looking around the self-hosted cloud storage space for a while,
+you've undoubtedly run into someone suggesting [[https://syncthing.net][Syncthing]] as an option. However,
+it is an unusual alternative for those users out there who are used to having a
centralized cloud server that serves as the "controller" of the data and
interacts with clients on devices to fetch files.
-This post is a walkthrough of the Syncthing software, how I set up my
-personal storage, and some pros and cons of using the software.
+This post is a walkthrough of the Syncthing software, how I set up my personal
+storage, and some pros and cons of using the software.
* Installing Syncthing
-To install Syncthing, visit the
-[[https://syncthing.net/downloads/][Downloads]] page or install via your
-device's package manager.
+To install Syncthing, visit the [[https://syncthing.net/downloads/][Downloads]] page or install via your device's
+package manager.
** Server & Desktop
-You can install Syncthing on servers and desktops via the Downloads page
-linked above or via the command-line.
+You can install Syncthing on servers and desktops via the Downloads page linked
+above or via the command-line.
For Debian-based distros:
@@ -40,19 +38,13 @@ sudo dnf install syncthing
** Mobile
-Syncthing for Android is available on
-[[https://f-droid.org/packages/com.nutomic.syncthingandroid/][F-Droid]]
-and
-[[https://play.google.com/store/apps/details?id=com.nutomic.syncthingandroid][Google
-Play]]. Syncthing does not have an official iOS client, but there is a
-third-party client called
-[[https://apps.apple.com/us/app/m%C3%B6bius-sync/id1539203216][Möbius
+Syncthing for Android is available on [[https://f-droid.org/packages/com.nutomic.syncthingandroid/][F-Droid]] and [[https://play.google.com/store/apps/details?id=com.nutomic.syncthingandroid][Google Play]]. Syncthing does
+not have an official iOS client, but there is a third-party client called [[https://apps.apple.com/us/app/m%C3%B6bius-sync/id1539203216][Möbius
Sync]].
* How Does Syncthing Work?
-To start, I wanted to include the main marketing blurb from their
-website:
+To start, I wanted to include the main marketing blurb from their website:
#+begin_quote
Syncthing is a continuous file synchronization program. It synchronizes
@@ -62,19 +54,19 @@ where it is stored, whether it is shared with some third party, and how
it's transmitted over the internet.
#+end_quote
-Let's break this apart and add in some other details to help explain
-what exactly Syncthing does in order to sync files between devices.
+Let's break this apart and add in some other details to help explain what
+exactly Syncthing does in order to sync files between devices.
** Local Syncthing Server(s)
-Syncthing syncs files between multiple devices by creating a local
-server on each device. These local servers handle a few different
-things, such as watching files and directories for changes, hosting an
-administrative GUI website, and authenticating with connected devices.
+Syncthing syncs files between multiple devices by creating a local server on
+each device. These local servers handle a few different things, such as watching
+files and directories for changes, hosting an administrative GUI website, and
+authenticating with connected devices.
-You can also start, stop, and restart the Syncthing server via the
-command-line or web dashboard. If you're running Syncthing on a device
-with =systemd=, you can use the following commands:
+You can also start, stop, and restart the Syncthing server via the command-line
+or web dashboard. If you're running Syncthing on a device with =systemd=, you
+can use the following commands:
#+begin_src sh
sudo systemctl start [email protected]
@@ -84,13 +76,13 @@ sudo systemctl stop [email protected]
** Syncthing Dashboard
-This biggest part of Syncthing is the admin GUI website that runs on
-each device (note that mobile devices will use the Syncthing app rather
-than the web GUI). The admin GUI is available through the web browser on
-the local device that is running Syncthing - simply go to
-=http://localhost:8384= or =http://127.0.0.1:8384=. This web page is the
-place where you will change settings, add/modify synced files, and
-add/modify connected devices.
+This biggest part of Syncthing is the admin GUI website that runs on each device
+(note that mobile devices will use the Syncthing app rather than the web GUI).
+The administrative graphical user interface (GUI) is available through the web
+browser on the local device that is running Syncthing - simply go to
+=http://localhost:8384= or =http://127.0.0.1:8384=. This web page is the place
+where you will change settings, add/modify synced files, and add/modify
+connected devices.
Here's an example web GUI dashboard:
@@ -99,81 +91,74 @@ Here's an example web GUI dashboard:
** Remote Devices
-A cloud storage solution wouldn't be very useful if you aren't able to
-share data among various devices. Syncthing does this by sharing Device
-IDs to connect servers, and then by manually sharing Folders with
-devices that have been connected.
+A cloud storage solution wouldn't be very useful if you aren't able to share
+data among various devices. Syncthing does this by sharing Device IDs to connect
+servers, and then by manually sharing Folders with devices that have been
+connected.
-For instance, if you have a laptop running Syncthing and then install
-the Syncthing mobile app on a phone, you could scan the laptop's QR code
-for Device ID and then accept the authentication on the laptop's
-dashboard. Next, you can use either device to select a folder for
-sharing and dictating which device should send, receive, or both.
+For instance, if you have a laptop running Syncthing and then install the
+Syncthing mobile app on a phone, you could scan the laptop's QR (quick-response)
+code for Device ID and then accept the authentication on the laptop's dashboard.
+Next, you can use either device to select a folder for sharing and dictating
+which device should send, receive, or both.
-When you connect devices, you can set one device as an "Introducer,"
-which can add devices from the introducer to the device list, for
-mutually shared folders. You can also configure Auto Accept,
-compression, rate limits, and more settings per device.
+When you connect devices, you can set one device as an "Introducer," which can
+add devices from the introducer to the device list, for mutually shared folders.
+You can also configure Auto Accept, compression, rate limits, and more settings
+per device.
* My Personal Cloud Storage Set-up
-Personally, I use a model similar to a traditional cloud storage
-service. I have a "centralized" server running 24/7 that acts as an
-Introducer for my Syncthing network. I think of this as my main storage
-and all other devices as tertiary client devices. I will likely add
-additional servers as backups as time goes on so that I don't have to
-rely on my laptop or phone as the only backups.
+Personally, I use a model similar to a traditional cloud storage service. I have
+a "centralized" server running 24/7 that acts as an Introducer for my Syncthing
+network. I think of this as my main storage and all other devices as tertiary
+client devices. I will likely add additional servers as backups as time goes on
+so that I don't have to rely on my laptop or phone as the only backups.
-Currently, I have one desktop and one mobile device connected to the
-network, both running intermittently as they are not powered-on 24/7.
+Currently, I have one desktop and one mobile device connected to the network,
+both running intermittently as they are not powered-on 24/7.
-The initial set-up of the software was easy enough, but data transfer
-rates were incredibly slow for me due to the Wi-Fi. Instead, I plugged
-my laptop into the ethernet network that my server is on and manually
-copied my folders over to the server with =scp=. Once complete,
-Syncthing validated that all files were there and not missing, and it
-did not need to transfer any data through the WAN.
+The initial set-up of the software was easy enough, but data transfer rates were
+incredibly slow for me due to the Wi-Fi. Instead, I plugged my laptop into the
+ethernet network that my server is on and manually copied my folders over to the
+server with =scp=. Once complete, Syncthing validated that all files were there
+and not missing, and it did not need to transfer any data through the WAN.
-As slow as the transfer was going, this probably saved me a few days of
-waiting for my ~100GB sync.
+As slow as the transfer was going, this probably saved me a few days of waiting
+for my ~100 gigabytes to sync.
* Pros & Cons
-I've put together a short list of pros and cons for Syncthing. I thought
-about my experiences with Nextcloud, WebDAV, proprietary services
-(Google Drive, iCloud, etc.), and privacy-focused cloud solutions
-(pCloud, Tresorit, etc.).
+I've put together a short list of pros and cons for Syncthing. I thought about
+my experiences with Nextcloud, WebDAV, proprietary services (Google Drive,
+iCloud, etc.), and privacy-focused cloud solutions (pCloud, Tresorit, etc.).
*Pros:*
- I've faced no data loss at all through my two-month trial run.
- No third-parties store your data on their servers.
-- You have full control over your data and can take your data and leave
- at any time.
-- It's possible to encrypt client-side easily with software like
- Cryptomator.
-- No proprietary clients or mounted volumes, just plain files and
- folders.
+- You have full control over your data and can take your data and leave at any
+ time.
+- It's possible to encrypt client-side easily with software like Cryptomator.
+- No proprietary clients or mounted volumes, just plain files and folders.
*Cons:*
-- The learning curve is steeper than traditional cloud services and is
- focused on a technical audience.
-- If a device needs to modify files in a Folder, the devices will need
- to sync ALL files from the folder, which may be large. To avoid size
- restraints, split large folders into smaller folders for syncing.
+- The learning curve is steeper than traditional cloud services and is focused
+ on a technical audience.
+- If a device needs to modify files in a Folder, the devices will need to sync
+ ALL files from the folder, which may be large. To avoid size restraints, split
+ large folders into smaller folders for syncing.
- Syncing can be slow due to the clients/servers initially connecting or
re-connecting after sleeping.
-- Multiple personal devices are required and require the user to own or
- rent them as no third-party servers are involved in the storage of
- data.
-
-Overall, I've had a great experience with Syncthing so far. I've had no
-data loss, syncing has been quick and easy when changes are made to
-files, device connections are reliable, and I love the freedom of
-controlling the clients and servers as I choose.
-
-Not to mention that I appreciate that I - or someone else - could pull
-the Syncthing [[https://github.com/syncthing][source code]] and continue
-development/support if the Syncthing Foundation decides to stop
-developing the software or sells the business.
+- Multiple personal devices are required and require the user to own or rent
+ them as no third-party servers are involved in the storage of data.
+
+Overall, I've had a great experience with Syncthing so far. I've had no data
+loss, syncing has been quick and easy when changes are made to files, device
+connections are reliable, and I love the freedom of controlling the clients and
+servers as I choose.
+
+Not to mention that I appreciate that I - or someone else - could pull the
+Syncthing [[https://github.com/syncthing][source code]] and continue development/support if the Syncthing
+Foundation decides to stop developing the software or sells the business.
diff --git a/content/blog/2022-10-22-alpine-linux.org b/content/blog/2022-10-22-alpine-linux.org
index 743262b..88b0427 100644
--- a/content/blog/2022-10-22-alpine-linux.org
+++ b/content/blog/2022-10-22-alpine-linux.org
@@ -5,43 +5,40 @@
* Alpine Linux
-[[https://alpinelinux.org][Alpine Linux]] is a very small distro, built
-on musl libc and busybox. It uses ash as the default shell, OpenRC as
-the init system, and apk as the package manager. According to their
-website, an Alpine container "requires no more than 8 MB and a minimal
-installation to disk requires around 130 MB of storage." An actual bare
-metal machine is recommended to have 100 MB of RAM and 0-700 MB of
-storage space.
-
-Historically, I've used Ubuntu's minimal installation image as my server
-OS for the last five years. Ubuntu worked well and helped as my original
-server contained an nVidia GPU and no onboard graphics, so quite a few
-distros won't boot or install without a lot of tinkering.
-
-Alpine has given me a huge increase in performance across my Docker apps
-and Nginx websites. CPU load for the new server I'm using to test Alpine
-hovers around 0-5% on average with an Intel(R) Core(TM) i3-6100 CPU @
-3.70GHz.
-
-The only services I haven't moved over to Alpine are Plex Media Server
-and Syncthing, which may increase CPU load quite a bit depending on how
-many streams are running.
+[[https://alpinelinux.org][Alpine Linux]] is a very small distribution, built on musl libc and busybox. It
+uses ash as the default shell, OpenRC as the init system, and apk as the package
+manager. According to their website, an Alpine container "requires no more than
+8 megabytes (MB) and a minimal installation to disk requires around 130 MB of
+storage." An actual bare metal machine is recommended to have 100 MB of RAM and
+0-700 MB of storage space.
+
+Historically, I've used Ubuntu's minimal installation image as my server OS for
+the last five years. Ubuntu worked well and helped as my original server
+contained an nVidia GPU (graphics processing unit) and no onboard graphics, so
+quite a few distributions won't boot or install without a lot of tinkering.
+
+Alpine has given me a huge increase in performance across my Docker apps and
+Nginx websites. CPU (central processing unit) load for the new server I'm using
+to test Alpine hovers around 0-5% on average with an Intel(R) Core(TM) i3-6100
+CPU @ 3.70 Gigahertz (GHz).
+
+The only services I haven't moved over to Alpine are Plex Media Server and
+Syncthing, which may increase CPU load quite a bit depending on how many streams
+are running.
** Installation
-In terms of installation, Alpine has an incredibly useful
-[[https://wiki.alpinelinux.org/wiki/Installation][wiki]] that will guide
-a user throughout the installation and post-installation processes, as
-well as various other articles and guides.
+In terms of installation, Alpine has an incredibly useful [[https://wiki.alpinelinux.org/wiki/Installation][wiki]] that will guide a
+user throughout the installation and post-installation processes, as well as
+various other articles and guides.
-To install Alpine, find an appropriate
-[[https://alpinelinux.org/downloads/][image to download]] and flash it
-to a USB using software such as Rufus or Etcher. I opted to use the
-Standard image for my x86_{64} architecture.
+To install Alpine, find an appropriate [[https://alpinelinux.org/downloads/][image to download]] and flash it to a USB
+(Universal Serial Bus) using software such as Rufus or Etcher. I opted to use
+the Standard image for my x86_{64} architecture.
-Once the USB is ready, plug it into the machine and reboot. Note that
-you may have to use a key such as =Esc= or =F1-12= to access the boot
-menu. The Alpine Linux terminal will load quickly and for a login.
+Once the USB is ready, plug it into the machine and reboot. Note that you may
+have to use a key such as =Esc= or =F1-12= to access the boot menu. The Alpine
+Linux terminal will load quickly and for a login.
To log in to the installation image, use the =root= account; there is no
password. Once logged-in, execute the setup command:
@@ -50,34 +47,32 @@ password. Once logged-in, execute the setup command:
setup-alpine
#+end_src
-The setup script will ask a series of questions to configure the system.
-Be sure to answer carefully or else you may have to re-configure the
-system after boot.
+The setup script will ask a series of questions to configure the system. Be sure
+to answer carefully or else you may have to re-configure the system after boot.
-- Keyboard Layout (Local keyboard language and usage mode, e.g., us and
- variant of us-nodeadkeys.)
-- Hostname (The name for the computer.)
-- Network (For example, automatic IP address discovery with the "DHCP"
- protocol.)
-- DNS Servers (Domain Name Servers to query. For privacy reasons, it is
+- *Keyboard Layout*: Local keyboard language and usage mode, e.g., us and variant
+ of us-nodeadkeys.
+- *Hostname*: The name for the computer.
+- *Network*: For example, automatic internet protocol (IP) address discovery
+ with the Dynamic Host Configuration Protocol (DHCP) protocol.
+- *DNS (Domain Name System)*: DNS servers to query. For privacy reasons, it is
NOT recommended to route every local request to servers like Google's
- 8.8.8.8.)
-- Timezone
-- Proxy (Proxy server to use for accessing the web. Use "none" for
- direct connections to the internet.)
-- Mirror (From where to download packages. Choose the organization you
- trust giving your usage patterns to.)
-- SSH (Secure SHell remote access server. "Openssh" is part of the
- default install image. Use "none" to disable remote login, e.g. on
- laptops.)
-- NTP (Network Time Protocol client used for keeping the system clock in
- sync with a time-server. Package "chrony" is part of the default
- install image.)
-- Disk Mode (Select between diskless (disk="none"), "data" or "sys", as
- described above.)
-
-Once the setup script is finished, be sure to reboot the machine and
-remove the USB device.
+ 8.8.8.8.
+- *Timezone
+- *Proxy*: Proxy server to use for accessing the web. Use =none= for direct
+ connections to the internet.
+- *Mirror*: From where to download packages. Choose the organization you trust
+ giving your usage patterns to.
+- *SSH (Secure Shell Protocol)*: Remote access server. =Openssh= is part of the
+ default install image. Use =none= to disable remote login, e.g. on laptops.
+- *NTP (Network Time Protocol)*: Client used for keeping the system clock in
+ sync with a time-server. Package =chrony= is part of the default install
+ image.
+- *Disk Mode*: Select between diskless (=none=), =data= or =sys=, as described
+ above.
+
+Once the setup script is finished, be sure to reboot the machine and remove the
+USB device.
#+begin_src sh
reboot
@@ -86,9 +81,8 @@ reboot
** Post-Installation
There are many things you can do once your Alpine Linux system is up and
-running, and it largely depends on what you'll use the machine for. I'm
-going to walk through my personal post-installation setup for my web
-server.
+running, and it largely depends on what you'll use the machine for. I'm going to
+walk through my personal post-installation setup for my web server.
1. Upgrade the System
@@ -100,9 +94,9 @@ server.
2. Adding a User
- I needed to add a user so that I don't need to log in as root. Note
- that if you're used to using the =sudo= command, you will now need to
- use the =doas= command on Alpine Linux.
+ I needed to add a user so that I don't need to log in as root. Note that if
+ you're used to using the =sudo= command, you will now need to use the =doas=
+ command on Alpine Linux.
#+begin_src sh
apk add doas
@@ -118,16 +112,14 @@ server.
3. Enable Community Packages
- In order to install more common packages that aren't found in the
- =main= repository, you will need to enable the =community=
- repository:
+ In order to install more common packages that aren't found in the =main=
+ repository, you will need to enable the =community= repository:
#+begin_src sh
doas nano /etc/apk/repositories
#+end_src
- Uncomment the community line for whichever version of Alpine you're
- running:
+ Uncomment the community line for whichever version of Alpine you're running:
#+begin_src sh
/media/usb/apks
@@ -140,9 +132,9 @@ server.
4. Install Required Packages
- Now that the community packages are available, you can install any
- packages you need. In my case, I installed the web server packages I
- need for my services:
+ Now that the community packages are available, you can install any packages
+ you need. In my case, I installed the web server packages I need for my
+ services:
#+begin_src sh
doas apk add nano nginx docker docker-compose ufw
@@ -150,15 +142,14 @@ server.
5. SSH
- If you didn't install OpenSSH as part of the installation, you can do
- so now:
+ If you didn't install OpenSSH as part of the installation, you can do so now:
#+begin_src sh
doas apk add openssh
#+end_src
- Next, either create a new key or copy your SSH key to the server from
- your current machines:
+ Next, either create a new key or copy your SSH key to the server from your
+ current machines:
#+begin_src sh
# Create a new key
@@ -174,9 +165,9 @@ server.
6. Firewall
- Lastly, I installed =ufw= above as my firewall. To set up, default to
- deny incoming and allow outgoing connections. Then selectively allow
- other ports or apps as needed.
+ Lastly, I installed =ufw= above as my firewall. To set up, default to deny
+ incoming and allow outgoing connections. Then selectively allow other ports
+ or apps as needed.
#+begin_src sh
doas ufw default deny incoming
@@ -188,8 +179,8 @@ server.
7. Change Hostname
- If you don't like the hostname set during installation, you just need
- to edit two files. First, edit the simple hostname file:
+ If you don't like the hostname set during installation, you just need to edit
+ two files. First, edit the simple hostname file:
#+begin_src sh
doas nano /etc/hostname
@@ -223,17 +214,17 @@ doas chown -R www:www /var/lib/nginx/
doas chown -R www:www /www
#+end_src
-If you're running a simple webroot, you can alter the main =nginx.conf=
-file. Otherwise, you can drop configuration files in the following
-directory. You don't need to enable or symlink the configuration file
-like you do in other systems.
+If you're running a simple webroot, you can alter the main =nginx.conf= file.
+Otherwise, you can drop configuration files in the following directory. You
+don't need to enable or symlink the configuration file like you do in other
+systems.
#+begin_src sh
doas nano /etc/nginx/http.d/example_website.conf
#+end_src
-Once the configuration is set and pointed at the =/www= directory to
-serve files, enable the Nginx service:
+Once the configuration is set and pointed at the =/www= directory to serve
+files, enable the Nginx service:
#+begin_src sh
# Note that 'default' must be included or Nginx will not start on boot
@@ -242,18 +233,16 @@ doas rc-update add nginx default
* Docker Containers
-Docker works exactly the same as other systems. Either execute a
-=docker run= command or create a =docker-compose.yml= file and do
-=docker-compose up -d=.
+Docker works exactly the same as other systems. Either execute a =docker run=
+command or create a =docker-compose.yml= file and do =docker-compose up -d=.
* Git Server
-I went in-depth on how to self-host a git server in another post:
-[[../git-server/][Self-Hosting a Personal Git Server]].
+I went in-depth on how to self-host a git server in another post: [[https://cleberg.net/blog/git-server.html][Self-Hosting
+Guide: Git & cGit]].
-However, there are a few differences with Alpine. First note that in
-order to change the =git= user's shell, you must do a few things a
-little different:
+However, there are a few differences with Alpine. First note that in order to
+change the =git= user's shell, you must do a few things a little different:
#+begin_src sh
doas apk add libuser
@@ -265,12 +254,11 @@ doas lchsh git
* Thoughts on Alpine
-So far, I love Alpine Linux. I have no complaints about anything at this
-point, but I'm not completely finished with the migration yet. Once I'm
-able to upgrade my hardware to a rack-mounted server, I will migrate
-Plex and Syncthing over to Alpine as well - possibly putting Plex into a
-container or VM.
+So far, I love Alpine Linux. I have no complaints about anything at this point,
+but I'm not completely finished with the migration yet. Once I'm able to upgrade
+my hardware to a rack-mounted server, I will migrate Plex and Syncthing over to
+Alpine as well - possibly putting Plex into a container or VM.
-The performance is stellar, the =apk= package manager is seamless, and
-system administration tasks are effortless. My only regret is that I
-didn't install Alpine sooner.
+The performance is stellar, the =apk= package manager is seamless, and system
+administration tasks are effortless. My only regret is that I didn't install
+Alpine sooner.
diff --git a/content/blog/2022-10-30-linux-display-manager.org b/content/blog/2022-10-30-linux-display-manager.org
index c749a22..4dd9b22 100644
--- a/content/blog/2022-10-30-linux-display-manager.org
+++ b/content/blog/2022-10-30-linux-display-manager.org
@@ -5,18 +5,16 @@
* Display Manager Services
-In order to change the
-[[https://en.wikipedia.org/wiki/Display_manager][display manager]] on
-Void Linux - or any other Linux distro - you need to identify the
-currently enabled display manager.
+In order to change the [[https://en.wikipedia.org/wiki/Display_manager][display manager]] on Void Linux - or any other Linux
+distribution - you need to identify the currently enabled display manager.
** Disabling the Current Display Manager
-Void Linux only has one ISO available for download with a pre-built
-display manager at the time of this post: the XFCE ISO. If you've
-installed this version, the pre-assigned display manager is =lxdm=. If
-you installed another display manager, replace =lxdm= in the following
-command with the display manager you have installed.
+Void Linux only has one optical disc image (ISO) available for download with a
+pre-built display manager at the time of this post: the XFCE ISO. If you've
+installed this version, the pre-assigned display manager is =lxdm=. If you
+installed another display manager, replace =lxdm= in the following command with
+the display manager you have installed.
To disable =lxdm=, simply remove the service symlink:
@@ -26,9 +24,9 @@ sudo rm /var/service/lxdm
** Enabling a New Display Manager
-If you want to enable a new display manager, you can do so after =lxdm=
-is disabled. Make sure to replace =<new_display_manager>= with your new
-DM, such as =gdm=, =xdm=, etc.
+If you want to enable a new display manager, you can do so after =lxdm= is
+disabled. Make sure to replace =<new_display_manager>= with your new DM, such as
+=gdm=, =xdm=, etc.
#+begin_src sh
sudo ln -s /etc/sv/<new_display_manager> /var/service
@@ -37,8 +35,8 @@ sudo ln -s /etc/sv/<new_display_manager> /var/service
* Set Up =.xinitrc=
Depending on your setup, you may need to create a few X files, such as
-=~/.xinitrc=. For my personal set-up, I created this file to launch the
-i3wm as my desktop.
+=~/.xinitrc=. For my personal set-up, I created this file to launch the i3wm as
+my desktop.
#+begin_src sh
nano ~/.xinitrc
@@ -50,21 +48,20 @@ nano ~/.xinitrc
exec i3
#+end_src
-If you run a desktop other than i3, simply replace =i3= with the shell
-command that launches that desktop.
+If you run a desktop other than i3, simply replace =i3= with the shell command
+that launches that desktop.
* Set Up Your Shell Profile
-Finally, in order to automatically launch an X session upon login, you
-will need to edit the =.bash_profile= (bash) or =.zprofile= (zsh) files
-for your shell:
+Finally, in order to automatically launch an X session upon login, you will need
+to edit the =.bash_profile= (bash) or =.zprofile= (zsh) files for your shell:
#+begin_src sh
nano ~/.zprofile
#+end_src
-Add the following snippet to the end of the shell profile file. This
-will execute the =startx= command upon login.
+Add the following snippet to the end of the shell profile file. This will
+execute the =startx= command upon login.
#+begin_src sh
if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then
@@ -72,6 +69,6 @@ if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then
fi
#+end_src
-Alternatively, you can ignore this step and simply choose to manually
-execute =startx= upon login. This can be useful if you have issues with
-your desktop or like to manually launch different desktops by choice.
+Alternatively, you can ignore this step and simply choose to manually execute
+=startx= upon login. This can be useful if you have issues with your desktop or
+like to manually launch different desktops by choice.
diff --git a/content/blog/2022-11-07-self-hosting-matrix.org b/content/blog/2022-11-07-self-hosting-matrix.org
index cc7b303..20e5de1 100644
--- a/content/blog/2022-11-07-self-hosting-matrix.org
+++ b/content/blog/2022-11-07-self-hosting-matrix.org
@@ -5,21 +5,19 @@
* Synapse
-If you're reading this, you likely know that
-[[https://github.com/matrix-org/synapse/][Synapse]] is a popular
-[[https://matrix.org/][Matrix]] home server software that allows users
-to run their own Matrix home server.
+If you're reading this, you likely know that [[https://github.com/matrix-org/synapse/][Synapse]] is a popular [[https://matrix.org/][Matrix]] home
+server software that allows users to run their own Matrix home server.
-This post is a short guide describing how I was able to get Synapse
-working in a minimally-usable state on Alpine Linux.
+This post is a short guide describing how I was able to get Synapse working in a
+minimally-usable state on Alpine Linux.
* Installation Process
** Dependencies
-First, since there is no Alpine-specific package for Synapse, we need to
-ensure that Alpine has the required dependencies for the Python-based
-installation method.
+First, since there is no Alpine-specific package for Synapse, we need to ensure
+that Alpine has the required dependencies for the Python-based installation
+method.
#+begin_src sh
doas apk -U update
@@ -39,10 +37,9 @@ pip install matrix-synapse
** Running Synapse
-Once installed, running Synapse is easy. Simply execute the following
-command, replacing =example.com= with the domain name that will be used
-with this home server. This will generate the configuration files needed
-to run the server.
+Once installed, running Synapse is easy. Simply execute the following command,
+replacing =example.com= with the domain name that will be used with this home
+server. This will generate the configuration files needed to run the server.
#+begin_src sh
python -m synapse.app.homeserver \
@@ -60,17 +57,15 @@ synctl start
** Configuring Synapse
-To make any change to Synapse, we need to edit the =YAML= configuration
-file:
+To make any change to Synapse, we need to edit the =YAML= configuration file:
#+begin_src sh
nano ~/synapse/homeserver.yaml
#+end_src
-For now, we just need to ensure the =server_name= is accurate. However,
-there are a lot of other configuration options found in the
-[[https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html][Configuring
-Synapse]] documentation that can be enabled/disabled at any point.
+For now, we just need to ensure the =server_name= is accurate. However, there
+are a lot of other configuration options found in the [[https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html][Configuring Synapse]]
+documentation that can be enabled/disabled at any point.
#+begin_src yaml
server_name: "example.com"
@@ -84,9 +79,9 @@ synctl restart
** Nginx Reverse-Proxy
-To ensure that Synapse is reachable from the public, we need to connect
-our domain to the Synapse server. In my case, I use a Nginx
-reverse-proxy for this purpose.
+To ensure that Synapse is reachable from the public, we need to connect our
+domain to the Synapse server. In my case, I use a Nginx reverse-proxy for this
+purpose.
To use Nginx, we need to create a reverse-proxy configuration file:
@@ -94,9 +89,9 @@ To use Nginx, we need to create a reverse-proxy configuration file:
doas nano /etc/nginx/http.d/example.com.conf
#+end_src
-If you already have TLS certificates for this domain (=example.com=),
-you can simply use the SSL configuration and point toward your TLS
-certificates.
+If you already have TLS (Transport Layer Security) certificates for this domain
+(=example.com=), you can simply use the SSL (Secure Socket Layer) configuration
+and point toward your TLS certificates.
#+begin_src conf
server {
@@ -139,10 +134,9 @@ server {
}
#+end_src
-If you need to generate TLS certificates (I recommend
-[[https://certbot.eff.org/][Certbot]]), you'll need a more minimal Nginx
-conf file before you can use the TLS-enabled example above. Instead, use
-this configuration file during the Certbot certificate generation
+If you need to generate TLS certificates (I recommend [[https://certbot.eff.org/][Certbot]]), you'll need a
+more minimal Nginx conf file before you can use the TLS-enabled example above.
+Instead, use this configuration file during the Certbot certificate generation
process:
#+begin_src conf
@@ -161,13 +155,13 @@ Once you're done editing the Nginx conf file, restart Nginx:
doas rc-service nginx restart
#+end_src
-If you still need to generate TLS certificates, run =certbot= now and
-obtain the certificates. Certbot will ask if you want to use a webroot
-or spin up a temporary web server. I *highly* recommend using the
-temporary web server due to the many issues with using a webroot.
+If you still need to generate TLS certificates, run =certbot= now and obtain the
+certificates. Certbot will ask if you want to use a webroot or spin up a
+temporary web server. I *highly* recommend using the temporary web server due to
+the many issues with using a webroot.
-You will need to stop Nginx in order to user the temporary web server
-option with Certbot:
+You will need to stop Nginx in order to user the temporary web server option
+with Certbot:
#+begin_src sh
# Stop Nginx so certbot can spin up a temp webserver for cert generation
@@ -178,11 +172,11 @@ doas rc-service nginx start
** Open Firewall & Router Ports
-If you use a firewall on the server, open the =8448= port for discovery
-and federation, as well as the normal web server ports if you're using a
-reverse proxy. If you want additional services, such as voice calls, you
-will need to read the Synapse documentation to see which ports need to
-be opened for those features.
+If you use a firewall on the server, open the =8448= port for discovery and
+federation, as well as the normal web server ports if you're using a reverse
+proxy. If you want additional services, such as voice calls, you will need to
+read the Synapse documentation to see which ports need to be opened for those
+features.
Here's an example of the Universal Firewall (UFW) software:
@@ -193,14 +187,13 @@ doas ufw allow 8448
doas ufw allow "Nginx Full"
#+end_src
-Remember to forward any Synapse ports, such as =8448=, =80=, and =443=,
-in your Router from the internet to your server's IP address.
+Remember to forward any Synapse ports, such as =8448=, =80=, and =443=, in your
+Router from the internet to your server's internet protocol (IP) address.
** Adding Matrix Users
-Finally, if you didn't enable public registration in the
-=homeserver.yaml= file, you can manually create users via the
-command-line:
+Finally, if you didn't enable public registration in the =homeserver.yaml= file,
+you can manually create users via the command-line:
#+begin_src sh
cd ~/synapse
@@ -210,6 +203,6 @@ register_new_matrix_user -c homeserver.yaml
Remember that the format for federated Matrix usernames is
=@username:example.com= when logging in to client applications.
-Once Synapse is running, and you have a username, you are ready to log
-in to a Matrix client and start sending messages, joining rooms, and
-utilizing your very own Matrix server.
+Once Synapse is running, and you have a username, you are ready to log in to a
+Matrix client and start sending messages, joining rooms, and utilizing your very
+own Matrix server.
diff --git a/content/blog/2022-11-11-nginx-tmp-errors.org b/content/blog/2022-11-11-nginx-tmp-errors.org
index 9522c55..dd5d654 100644
--- a/content/blog/2022-11-11-nginx-tmp-errors.org
+++ b/content/blog/2022-11-11-nginx-tmp-errors.org
@@ -8,10 +8,10 @@ has occurred multiple times for me./
* The Problem
-After migrating to a new server OS, I started receiving quite a few
-permission errors like the one below. These popped up for various
-different websites I'm serving via Nginx on this server, but did not
-prevent the website from loading.
+After migrating to a new server operating system (OS), I started receiving quite
+a few permission errors like the one below. These popped up for various
+different websites I'm serving via Nginx on this server, but did not prevent the
+website from loading.
I found the errors in the standard log file:
@@ -23,19 +23,18 @@ cat /var/log/nginx/error.log
2022/11/11 11:30:34 [crit] 8970#8970: *10 open() "/var/lib/nginx/tmp/proxy/3/00/0000000003" failed (13: Permission denied) while reading upstream, client: 169.150.203.10, server: cyberchef.example.com, request: "GET /assets/main.css HTTP/2.0", upstream: "http://127.0.0.1:8111/assets/main.css", host: "cyberchef.example.com", referrer: "https://cyberchef.example.com/"
#+end_src
-You can see that the error is =13: Permission denied= and it occurs in
-the =/var/lib/nginx/tmp/= directory. In my case, I had thousands of
-errors where Nginx was denied permission to read/write files in this
-directory.
+You can see that the error is =13: Permission denied= and it occurs in the
+=/var/lib/nginx/tmp/= directory. In my case, I had thousands of errors where
+Nginx was denied permission to read/write files in this directory.
So how do I fix it?
* The Solution
-In order to resolve the issue, I had to ensure the =/var/lib/nginx=
-directory is owned by Nginx. Mine was owned by the =www= user and Nginx
-was not able to read or write files within that directory. This
-prevented Nginx from caching temporary files.
+In order to resolve the issue, I had to ensure the =/var/lib/nginx= directory is
+owned by Nginx. Mine was owned by the =www= user and Nginx was not able to read
+or write files within that directory. This prevented Nginx from caching
+temporary files.
#+begin_src sh
# Alpine Linux
@@ -45,9 +44,9 @@ doas chown -R nginx:nginx /var/lib/nginx
sudo chown -R nginx:nginx /var/lib/nginx
#+end_src
-You /may/ also be able to change the =proxy_temp_path= in your Nginx
-config, but I did not try this. Here's a suggestion I found online that
-may work if the above solution does not:
+You /may/ also be able to change the =proxy_temp_path= in your Nginx config, but
+I did not try this. Here's a suggestion I found online that may work if the
+above solution does not:
#+begin_src sh
nano /etc/nginx/http.d/example.com.conf
@@ -65,8 +64,8 @@ server {
}
#+end_src
-Finally, restart Nginx and your server should be able to cache temporary
-files again.
+Finally, restart Nginx and your server should be able to cache temporary files
+again.
#+begin_src sh
# Alpine Linux (OpenRC)
diff --git a/content/blog/2022-11-27-server-build.org b/content/blog/2022-11-27-server-build.org
index 7ae8a38..0383c7f 100644
--- a/content/blog/2022-11-27-server-build.org
+++ b/content/blog/2022-11-27-server-build.org
@@ -5,39 +5,37 @@
* The Dilemma
-For years, I have been using desktops and a Raspberry Pi as the backbone
-of my homelab. I have always wanted to move toward a single dedicated
-server that could handle all of my tasks, but was often put off by the
-complexity of the choices (and financial roadblocks at some times).
+For years, I have been using desktops and a Raspberry Pi as the backbone of my
+homelab. I have always wanted to move toward a single dedicated server that
+could handle all of my tasks, but was often put off by the complexity of the
+choices (and financial roadblocks at some times).
-However, after purchasing a small server rack this past year, I have
-been researching to see what kind of rack-mounted server I could buy. I
-initially bought a Dell R720XD loaded up with everything I could ever
-want in a server - but I did not care for it. It was far too loud, and
-the age of the CPU/RAM was something I wanted to improve upon.
+However, after purchasing a small server rack this past year, I have been
+researching to see what kind of rack-mounted server I could buy. I initially
+bought a Dell R720XD loaded up with everything I could ever want in a server -
+but I did not care for it. It was far too loud, and the age of the CPU/RAM was
+something I wanted to improve upon.
-After returning the R720XD, I decided that I wanted to build my own
-server with modern, consumer-grade PC components. This time, I am very
-happy with the results of my server.
+After returning the R720XD, I decided that I wanted to build my own server with
+modern, consumer-grade PC components. This time, I am very happy with the
+results of my server.
* Components
I'll start by listing all the components I used for this server build:
-- *Case*:
- [[https://www.rosewill.com/rosewill-rsv-r4100u-black/p/9SIA072GJ92825][Rosewill
- RSV-R4100U 4U Server Chassis Rackmount Case]]
+- *Case*: [[https://www.rosewill.com/rosewill-rsv-r4100u-black/p/9SIA072GJ92825][Rosewill RSV-R4100U 4U Server Chassis Rackmount Case]]
- *Motherboard*: [[https://nzxt.com/product/n7-b550][NZXT B550]]
- *CPU*: AMD Ryzen 7 5700G with Radeon Graphics
-- *GPU*: N/A - I specifically chose one of the few AMD CPUs that support
- onboard graphics.
+- *GPU*: N/A - I specifically chose one of the few AMD CPUs that support onboard
+ graphics.
- *RAM*: 64GB RAM (2x32GB) /Max of 128GB RAM on this motherboard/
- *Boot Drive*: Western Digital 500GB M.2 NVME SSD
- *HDD Bay*:
- 10TB WD White /(shucked, moved from previous server)/
- 8TB WD White /(shucked, moved from previous server)/
- - 2 x 8TB WD Red Plus /(Black Friday lined up perfectly with this
- build, so I grabbed two of these)/
+ - 2 x 8TB WD Red Plus /(Black Friday lined up perfectly with this build, so I
+ grabbed two of these)/
- *PSU*: Corsair RM850 PSU
- *Extras*:
- Corsair TM3Q Thermal Paste
@@ -47,54 +45,52 @@ I'll start by listing all the components I used for this server build:
* Building the Server
-This took quite a while for me to build (in my opinion of time),
-totaling around 3 hours from start to finish. The case has some peculiar
-construction, so you have to completely remove the ODD & HDD cages to
-install the motherboard and other components first.
+This took quite a while for me to build (in my opinion of time), totaling around
+3 hours from start to finish. The case has some peculiar construction, so you
+have to completely remove the ODD & HDD cages to install the motherboard and
+other components first.
-Now, I've never built a computer of any kind before, so I was quite
-nervous. Personally, the only challenging part was getting the CPU
-cooler to screw into the motherboard without sliding the thermal paste
-around too much underneath. I'm still not entirely sure if I did a great
-job of it, but nothing's broken yet.
+Now, I've never built a computer of any kind before, so I was quite nervous.
+Personally, the only challenging part was getting the CPU cooler to screw into
+the motherboard without sliding the thermal paste around too much underneath.
+I'm still not entirely sure if I did a great job of it, but nothing's broken
+yet.
-The main components were all fine and simple. However, installing the
-hard drives is slightly tedious as I need to power off the server and
-completely unscrew the HDD cage to install or remove any drives.
-Additionally, the drives are screwed directly into the metal cage with
-small screws, which are quite a bit different from the HDD trays I'm
-used to in other machines.
+The main components were all fine and simple. However, installing the hard
+drives is slightly tedious as I need to power off the server and completely
+unscrew the HDD cage to install or remove any drives. Additionally, the drives
+are screwed directly into the metal cage with small screws, which are quite a
+bit different from the HDD trays I'm used to in other machines.
-Seeing that the cases with hot-swap bays were 3-4x the price, I'm okay
-dealing with the tedium of removing the cage to install new drives.
+Seeing that the cases with hot-swap bays were 3-4x the price, I'm okay dealing
+with the tedium of removing the cage to install new drives.
* Software
-I'm not going to dive into the software as I have done so in other
-recent posts. However, I wanted to note that I am using Alpine Linux on
-this server and hosting most services inside Docker. No virtual machines
-(VMs) and very few bare-metal services.
+I'm not going to dive into the software as I have done so in other recent posts.
+However, I wanted to note that I am using Alpine Linux on this server and
+hosting most services inside Docker. No virtual machines (VMs) and very few
+bare-metal services.
* The Results
-How did my build turn out? Well, after migrating my other servers and
-their services over, I found that my server is blazing fast. The
-heaviest of my applications, Plex, is handled with ease. Even 4k
-streaming seems to be effortless.
+How did my build turn out? Well, after migrating my other servers and their
+services over, I found that my server is blazing fast. The heaviest of my
+applications, Plex, is handled with ease. Even 4k streaming seems to be
+effortless.
-I am very happy with the results and will likely continue to improve on
-this server as the years go by rather than buying another used server
-online.
+I am very happy with the results and will likely continue to improve on this
+server as the years go by rather than buying another used server online.
** Mistakes I Made
-This post wouldn't be complete unless I wrote about the mistakes I made
-while building. The only real mistake I made beyond a "whoops I dropped
-a screw" related to airflow and fan direction.
+This post wouldn't be complete unless I wrote about the mistakes I made while
+building. The only real mistake I made beyond a "whoops I dropped a screw"
+related to airflow and fan direction.
-While installing the two new hard drives that showed up on 2022-11-30
-and getting ready to install the case in my rack, I noticed that the
-hard drive temperatures were quite high.
+While installing the two new hard drives that showed up on 2022-11-30 and
+getting ready to install the case in my rack, I noticed that the hard drive
+temperatures were quite high.
I used the =smartctl= command for each of my drives (=/dev/sda= through
=/dev/sdd=):
@@ -104,9 +100,8 @@ doas smartctl -a /dev/sda | grep Temperature_Celsius
#+end_src
The results were unusual - all four drives were idling at ~44-46 degrees
-Celsius. The only drive that was cooler was my 10TB drive, which was at
-38 degrees Celsius. I noted that this 10TB drive was also closest to the
-case fan.
+Celsius. The only drive that was cooler was my 10TB drive, which was at 38
+degrees Celsius. I noted that this 10TB drive was also closest to the case fan.
#+begin_src sh
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
@@ -120,15 +115,14 @@ ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_
194 Temperature_Celsius 0x0002 171 171 000 Old_age Always - 38 (Min/Max 14/56)
#+end_src
-After looking to see if I could fit more fans into the case, I noticed
-that the 120mm fan used for intake from the front of the case was
-actually pushing air out of the case by mistake. This fan sits right in
-front of the hard drive bay.
+After looking to see if I could fit more fans into the case, I noticed that the
+120mm fan used for intake from the front of the case was actually pushing air
+out of the case by mistake. This fan sits right in front of the hard drive bay.
-Once I flipped the fan around to act as an intake fan, the temperatures
-dropped immediately! They are now idling at ~31-33 degrees Celsius. A
-single fan spinning the wrong way caused my drives to idle 10-15 degrees
-higher than they should have.
+Once I flipped the fan around to act as an intake fan, the temperatures dropped
+immediately! They are now idling at ~31-33 degrees Celsius. A single fan
+spinning the wrong way caused my drives to idle 10-15 degrees higher than they
+should have.
#+begin_src sh
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
@@ -142,6 +136,5 @@ ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_
194 Temperature_Celsius 0x0002 196 196 000 Old_age Always - 33 (Min/Max 22/46)
#+end_src
-This was a silly error to make, but I'm glad I found it today before I
-screwed the case into the rack and made things a lot more tedious to
-fix.
+This was a silly error to make, but I'm glad I found it today before I screwed
+the case into the rack and made things a lot more tedious to fix.
diff --git a/content/blog/2022-11-29-nginx-referrer-ban-list.org b/content/blog/2022-11-29-nginx-referrer-ban-list.org
index 0e7d72c..59fbe29 100644
--- a/content/blog/2022-11-29-nginx-referrer-ban-list.org
+++ b/content/blog/2022-11-29-nginx-referrer-ban-list.org
@@ -5,9 +5,9 @@
* Creating the Ban List
-In order to ban list referral domains or websites with Nginx, you need
-to create a ban list file. The file below will accept regexes for
-different domains or websites you wish to block.
+In order to ban list referral domains or websites with Nginx, you need to create
+a ban list file. The file below will accept regexes for different domains or
+websites you wish to block.
First, create the file in your nginx directory:
@@ -15,8 +15,8 @@ First, create the file in your nginx directory:
doas nano /etc/nginx/banlist.conf
#+end_src
-Next, paste the following contents in and fill out the regexes with
-whichever domains you're blocking.
+Next, paste the following contents in and fill out the regexes with whichever
+domains you're blocking.
#+begin_src conf
# /etc/nginx/banlist.conf
@@ -33,15 +33,15 @@ map $http_referer $bad_referer {
* Configuring Nginx
-In order for the ban list to work, Nginx needs to know it exists and how
-to handle it. For this, edit the =nginx.conf= file.
+In order for the ban list to work, Nginx needs to know it exists and how to
+handle it. For this, edit the =nginx.conf= file.
#+begin_src sh
doas nano /etc/nginx/nginx.conf
#+end_src
-Within this file, find the =http= block and add your ban list file
-location to the end of the block.
+Within this file, find the =http= block and add your ban list file location to
+the end of the block.
#+begin_src conf
# /etc/nginx/nginx.conf
@@ -56,23 +56,22 @@ http {
* Enabling the Ban List
-Finally, we need to take action when a bad referral site is found. To do
-so, edit the configuration file for your website. For example, I have
-all website configuration files in the =http.d= directory. You may have
-them in the =sites-available= directory on some distributions.
+Finally, we need to take action when a bad referral site is found. To do so,
+edit the configuration file for your website. For example, I have all website
+configuration files in the =http.d= directory. You may have them in the
+=sites-available= directory on some distributions.
#+begin_src sh
doas nano /etc/nginx/http.d/example.com.conf
#+end_src
-Within each website's configuration file, edit the =server= blocks that
-are listening to ports 80 and 443 and create a check for the
-=$bad_referrer= variable we created in the ban list file.
+Within each website's configuration file, edit the =server= blocks that are
+listening to ports 80 and 443 and create a check for the =$bad_referrer=
+variable we created in the ban list file.
-If a matching site is found, you can return any
-[[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes][HTTP Status
-Code]] you want. Code 403 (Forbidden) is logical in this case since you
-are preventing a client connection due to a banned domain.
+If a matching site is found, you can return any [[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes][HTTP Status Code]] you want. Code
+403 (Forbidden) is logical in this case since you are preventing a client
+connection due to a banned domain.
#+begin_src conf
server {
@@ -97,8 +96,8 @@ doas rc-service nginx restart
* Testing Results
-In order to test the results, let's curl the contents of our site. To
-start, I'll curl the site normally:
+In order to test the results, let's curl the contents of our site. To start,
+I'll curl the site normally:
#+begin_src sh
curl https://cleberg.net
@@ -117,8 +116,8 @@ curl --referer https://news.ycombinator.com https://cleberg.net
#+end_src
This time, I'm met with a 403 Forbidden response page. That means we are
-successful and any clients being referred from a banned domain will be
-met with this same response code.
+successful and any clients being referred from a banned domain will be met with
+this same response code.
#+begin_src html
<html>
diff --git a/content/blog/2022-12-01-nginx-compression.org b/content/blog/2022-12-01-nginx-compression.org
index 09b555b..c85c49b 100644
--- a/content/blog/2022-12-01-nginx-compression.org
+++ b/content/blog/2022-12-01-nginx-compression.org
@@ -5,24 +5,23 @@
* Text Compression
-Text compression allows a web server to serve text-based resources
-faster than uncompressed data. This can speed up things like First
-Contentful Paint, Tie to Interactive, and Speed Index.
+Text compression allows a web server to serve text-based resources faster than
+uncompressed data. This can speed up things like First Contentful Paint, Tie to
+Interactive, and Speed Index.
* Enable Nginx Compression with gzip
-In order to enable text compression on Nginx, we need to enable it
-within the configuration file:
+In order to enable text compression on Nginx, we need to enable it within the
+configuration file:
#+begin_src sh
nano /etc/nginx/nginx.conf
#+end_src
-Within the =http= block, find the section that shows something like the
-block below. This is the default gzip configuration I found in my
-=nginx.conf= file on Alpine Linux 3.17. Yours may look slightly
-different, just make sure that you're not creating any duplicate gzip
-options.
+Within the =http= block, find the section that shows something like the block
+below. This is the default gzip configuration I found in my =nginx.conf= file on
+Alpine Linux 3.17. Yours may look slightly different, just make sure that you're
+not creating any duplicate gzip options.
#+begin_src conf
# Enable gzipping of responses.
@@ -46,31 +45,27 @@ gzip_disable "MSIE [1-6]";
* Explanations of ngx_{httpgzipmodule} Options
-Each of the lines above enables a different aspect of the gzip response
-for Nginx. Here are the full explanations:
+Each of the lines above enables a different aspect of the gzip response for
+Nginx. Here are the full explanations:
-- =gzip= -- Enables or disables gzipping of responses.
-- =gzip_vary= -- Enables or disables inserting the "Vary:
- Accept-Encoding" response header field if the directives gzip,
- gzip_{static}, or gunzip are active.
-- =gzip_min_length= -- Sets the minimum length of a response that will
- be gzipped. The length is determined only from the "Content-Length"
- response header field.
-- =gzip_proxied= -- Enables or disables gzipping of responses for
- proxied requests depending on the request and response. The fact that
- the request is proxied is determined by the presence of the "Via"
- request header field.
-- =gzip_types= -- Enables gzipping of responses for the specified MIME
- types in addition to "text/html". The special value "*" matches any
- MIME type (0.8.29). Responses with the "text/html" type are always
- compressed.
-- =gzip_disable= -- Disables gzipping of responses for requests with
- "User-Agent" header fields matching any of the specified regular
- expressions.
- - The special mask "msie6" (0.7.12) corresponds to the regular
- expression "MSIE [4-6].", but works faster. Starting from version
- 0.8.11, "MSIE 6.0; ... SV1" is excluded from this mask.
+- =gzip=: Enables or disables gzipping of responses.
+- =gzip_vary=: Enables or disables inserting the "Vary: Accept-Encoding"
+ response header field if the directives gzip, gzip_{static}, or gunzip are
+ active.
+- =gzip_min_length=: Sets the minimum length of a response that will be
+ gzipped. The length is determined only from the "Content-Length" response
+ header field.
+- =gzip_proxied=: Enables or disables gzipping of responses for proxied
+ requests depending on the request and response. The fact that the request is
+ proxied is determined by the presence of the "Via" request header field.
+- =gzip_types=: Enables gzipping of responses for the specified MIME types in
+ addition to "text/html". The special value "*" matches any MIME type (0.8.29).
+ Responses with the "text/html" type are always compressed.
+- =gzip_disable=: Disables gzipping of responses for requests with
+ "User-Agent" header fields matching any of the specified regular expressions.
+ - The special mask "msie6" (0.7.12) corresponds to the regular expression
+ "MSIE [4-6].", but works faster. Starting from version 0.8.11, "MSIE 6.0;
+ ... SV1" is excluded from this mask.
-More information on these directives and their options can be found on
-the [[https://nginx.org/en/docs/http/ngx_http_gzip_module.html][Module
-ngx_{httpgzipmodule}]] page in Nginx's documentation.
+More information on these directives and their options can be found on the
+[[https://nginx.org/en/docs/http/ngx_http_gzip_module.html][Module ngx_{httpgzipmodule}]] page in Nginx's documentation.
diff --git a/content/blog/2022-12-07-nginx-wildcard-redirect.org b/content/blog/2022-12-07-nginx-wildcard-redirect.org
index 2e54fae..cc15887 100644
--- a/content/blog/2022-12-07-nginx-wildcard-redirect.org
+++ b/content/blog/2022-12-07-nginx-wildcard-redirect.org
@@ -5,18 +5,18 @@
* Problem
-I recently migrated domains and replaced the old webpage with a simple
-info page with instructions to users on how to edit their bookmarks and
-URLs to get to the page they were seeking.
+I recently migrated domains and replaced the old webpage with a simple info page
+with instructions to users on how to edit their bookmarks and URLs to get to the
+page they were seeking.
-This was not ideal as it left the work up to the user and may have
-caused friction for users who accessed my RSS feed.
+This was not ideal as it left the work up to the user and may have caused
+friction for users who accessed my RSS (Really Simple Syndication) feed.
* Solution
-Instead, I finally found a solution that allows me to redirect both
-subdomains AND trailing content. For example, both of these URLs now
-redirect properly using the logic I'll explain below:
+Instead, I finally found a solution that allows me to redirect both subdomains
+AND trailing content. For example, both of these URLs now redirect properly
+using the logic I'll explain below:
#+begin_src txt
# Example 1 - Simple base domain redirect with trailing content
@@ -28,19 +28,19 @@ https://libreddit.domain1.com/r/history/comments/7z8cbg/new_discovery_mode_turns
https://libreddit.domain2.com/r/history/comments/7z8cbg/new_discovery_mode_turns_video_game_assassins/
#+end_src
-Go ahead, try the URLs if you want to test them.
+Go ahead, try the URLs (uniform resource locators) if you want to test them.
** Nginx Config
-To make this possible. I needed to configure a proper redirect scheme in
-my Nginx configuration.
+To make this possible. I needed to configure a proper redirect scheme in my
+Nginx configuration.
#+begin_src sh
doas nano /etc/nginx/http.d/domain1.conf
#+end_src
-Within this file, I had one block configured to redirect HTTP requests
-to HTTPS for the base domain and all subdomains.
+Within this file, I had one block configured to redirect HTTP requests to HTTPS
+for the base domain and all subdomains.
#+begin_src conf
server {
@@ -60,10 +60,9 @@ server {
}
#+end_src
-For the base domain, I have another =server= block dedicated to
-redirecting all base domain requests. You can see that the =rewrite=
-line is instructing Nginx to gather all trailing content and append it
-to the new =domain2.com= URL.
+For the base domain, I have another =server= block dedicated to redirecting all
+base domain requests. You can see that the =rewrite= line is instructing Nginx
+to gather all trailing content and append it to the new =domain2.com= URL.
#+begin_src conf
server {
@@ -79,17 +78,16 @@ server {
}
#+end_src
-Finally, the tricky part is figuring out how to tell Nginx to redirect
-while keeping both a subdomain and trailing content intact. I found that
-the easiest way to do this is to give it a =server= block of its own.
+Finally, the tricky part is figuring out how to tell Nginx to redirect while
+keeping both a subdomain and trailing content intact. I found that the easiest
+way to do this is to give it a =server= block of its own.
-Within this block, we need to do some regex on the =server_name= line
-before we can rewrite anything. This creates a variable called
-=subdomain=.
+Within this block, we need to do some regex on the =server_name= line before we
+can rewrite anything. This creates a variable called =subdomain=.
-Once the server gets to the =rewrite= line, it pulls the =subdomain=
-variable from above and uses it on the new =domain2.com= domain before
-appending the trailing content (=$request_uri=).
+Once the server gets to the =rewrite= line, it pulls the =subdomain= variable
+from above and uses it on the new =domain2.com= domain before appending the
+trailing content (=$request_uri=).
#+begin_src conf
server {
@@ -105,15 +103,15 @@ server {
}
#+end_src
-That's all there is to it. With this, I simply restarted Nginx and
-watched the redirections work in-action.
+That's all there is to it. With this, I simply restarted Nginx and watched the
+redirections work in-action.
#+begin_src sh
doas rc-service nginx restart
#+end_src
-Looking back on it, I wish I had done this sooner. Who knows how many
-people went looking for my sites or bookmarks and gave up when they saw
-the redirect instructions page.
+Looking back on it, I wish I had done this sooner. Who knows how many people
+went looking for my sites or bookmarks and gave up when they saw the redirect
+instructions page.
Oh well, it's done now. Live and learn.
diff --git a/content/blog/2022-12-17-st.org b/content/blog/2022-12-17-st.org
index 725a0fa..8a4a164 100644
--- a/content/blog/2022-12-17-st.org
+++ b/content/blog/2022-12-17-st.org
@@ -5,12 +5,11 @@
* st
-[[https://st.suckless.org][st]] standards for Simple Terminal, a simple
-terminal implementation for X made by the
-[[https://suckless.org][suckless]] team.
+[[https://st.suckless.org][st]] standards for Simple Terminal, a simple terminal implementation for X made by
+the [[https://suckless.org][suckless]] team.
-This post walks through the dependencies needed and process to build and
-install =st= on Fedora Workstation.
+This post walks through the dependencies needed and process to build and install
+=st= on Fedora Workstation.
** Obtain Files
@@ -23,8 +22,8 @@ git clone https://git.suckless.org/st && cd st
** Dependencies
-Once you have the files and are in the =st= directory, ensure the
-following packages are installed.
+Once you have the files and are in the =st= directory, ensure the following
+packages are installed.
#+begin_src sh
sudo dnf update && sudo dnf upgrade
@@ -39,13 +38,12 @@ Before building, ensure that you read the README file.
cat README
#+end_src
-Once you've read the instructions, open the =config.mk= file and ensure
-it matches your setup. If you're not sure, leave the default options
-within the file.
+Once you've read the instructions, open the =config.mk= file and ensure it
+matches your setup. If you're not sure, leave the default options within the
+file.
-Finally, you can build =st= with the following command. Ensure you run
-as root (e.g., =sudo=) or else you may not end up with a usable
-application file.
+Finally, you can build =st= with the following command. Ensure you run as root
+(e.g., =sudo=) or else you may not end up with a usable application file.
#+begin_src sh
sudo make clean install
@@ -54,38 +52,34 @@ sudo make clean install
** Customization (Patches)
Note that customizing =st= requires you to modify the source files or to
-download one of the [[https://st.suckless.org/patches/][available
-patches]] for suckless.org.
+download one of the [[https://st.suckless.org/patches/][available patches]] for suckless.org.
-If you've already installed =st= and want to customize or install a
-patch, start by uninstalling the current program.
+If you've already installed =st= and want to customize or install a patch, start
+by uninstalling the current program.
#+begin_src sh
cd ~/suckless/st
sudo make uninstall
#+end_src
-Next, grab the =<path>.diff= file from the page of the patch you chose.
-For example, I will be using the
-[[https://st.suckless.org/patches/defaultfontsize/][defaultfontsize]]
-patch in the below example.
+Next, grab the =<path>.diff= file from the page of the patch you chose. For
+example, I will be using the [[https://st.suckless.org/patches/defaultfontsize/][defaultfontsize]] patch in the below example.
#+begin_src sh
wget https://st.suckless.org/patches/defaultfontsize/st-defaultfontsize-20210225-4ef0cbd.diff
#+end_src
Once the file is downloaded inside the =st= folder, apply the patch and
-re-install the program. You may need to install the =patch= command if
-you don't have it installed already (you should have installed it
-above).
+re-install the program. You may need to install the =patch= command if you don't
+have it installed already (you should have installed it above).
#+begin_src sh
patch -i st-defaultfontsize-20210225-4ef0cbd.diff
sudo make clean install
#+end_src
-Once installed, you can use the default font size patch to launch =st=
-with any font size you wish:
+Once installed, you can use the default font size patch to launch =st= with any
+font size you wish:
#+begin_src sh
st -z 16
diff --git a/content/blog/2022-12-23-alpine-desktop.org b/content/blog/2022-12-23-alpine-desktop.org
index f65f88c..d983571 100644
--- a/content/blog/2022-12-23-alpine-desktop.org
+++ b/content/blog/2022-12-23-alpine-desktop.org
@@ -5,30 +5,31 @@
* Isn't Alpine Linux for Servers?
-This is a question I see a lot when people are presented with an example
-of Alpine Linux running as a desktop OS.
+This is a question I see a lot when people are presented with an example of
+Alpine Linux running as a desktop operating system (OS).
-While Alpine is small, fast, and minimal, that doesn't stop it from
-functioning at a productive level for desktop users.
+While Alpine is small, fast, and minimal, that doesn't stop it from functioning
+at a productive level for desktop users.
-This post is documentation of how I installed and modified Alpine Linux
-to become my daily desktop OS.
+This post is documentation of how I installed and modified Alpine Linux to
+become my daily desktop OS.
* Installation
-Note that I cover the installation of Alpine Linux in my other post, so
-I won't repeat it here: [[../alpine-linux/][Alpine Linux: My New Server
-OS]].
+Note that I cover the installation of Alpine Linux in my other post, so I won't
+repeat it here: [[https://cleberg.net/blog/alpine-linux.html][Alpine Linux Essentials: Installing and Setting Up a Secure
+Minimal Server]].
-Basically, get a bootable USB or whatever you prefer with Alpine on it,
-boot the ISO, and run the setup script.
+Basically, get a bootable USB (Universal Serial Bus) device or whatever you
+prefer with Alpine on it, boot the optical disc image (ISO), and run the setup
+script.
#+begin_src sh
setup-alpine
#+end_src
-Once you have gone through all the options and installer finishes
-without errors, reboot.
+Once you have gone through all the options and installer finishes without
+errors, reboot.
#+begin_src sh
reboot
@@ -37,9 +38,9 @@ reboot
* Initial Setup
Once Alpine is installed and the machine has rebooted, login is as root
-initially or =su= to root once you log in as your user. From here, you
-should start by updating and upgrading the system in case the ISO was
-not fully up-to-date.
+initially or =su= to root once you log in as your user. From here, you should
+start by updating and upgrading the system in case the ISO was not fully
+up-to-date.
#+begin_src sh
# Update and upgrade system
@@ -49,8 +50,8 @@ apk -U update && apk -U upgrade
apk add nano
#+end_src
-You need to uncomment the =community= repository for your version of
-Alpine Linux.
+You need to uncomment the =community= repository for your version of Alpine
+Linux.
For v3.17, the =repositories= file should look like this:
@@ -77,11 +78,11 @@ adduser $USER wheel
* Window Manager (Desktop)
-The [[https://wiki.alpinelinux.org/wiki/Sway][Sway installation guide]]
-has everything you need to get Sway working on Alpine.
+The [[https://wiki.alpinelinux.org/wiki/Sway][Sway installation guide]] has everything you need to get Sway working on
+Alpine.
-However, I'll include a brief list of the commands I ran and their
-purpose for posterity here.
+However, I'll include a brief list of the commands I ran and their purpose for
+posterity here.
#+begin_src sh
# Add eudev and set it up
@@ -125,8 +126,8 @@ apk add \ # Install optional dependencies:
Once you have the packages installed and set-up, you need to export the
=XDG_RUNTIME_DIR= upon login. To do this, edit your =.profile= file.
-If you use another shell, such as =zsh=, you need to edit that shell's
-profile (e.g., =~/.zprofile=)!
+If you use another shell, such as =zsh=, you need to edit that shell's profile
+(e.g., =~/.zprofile=)!
#+begin_src sh
nano ~/.profile
@@ -152,8 +153,7 @@ dbus-run-session -- sway
** Personal Touches
-I also added the following packages, per my personal preferences and
-situation.
+I also added the following packages, per my personal preferences and situation.
#+begin_src sh
doas apk add brightnessctl \ # Brightness controller
@@ -174,8 +174,8 @@ stored from prior desktops, such as my [[https://git.cleberg.net/dotfiles.git][d
** WiFi Issues
-I initially tried to set up my Wi-Fi the standard way with =iwd=, but it
-didn't work.
+I initially tried to set up my Wi-Fi the standard way with =iwd=, but it didn't
+work.
Here is what I initially tried (I did all of this as =root=):
@@ -186,8 +186,7 @@ iwctl station wlan0 connect <SSID> # This will prompt for the password
rc-update add iwd boot && rc-update add dbus boot
#+end_src
-Then, I added the Wi-Fi entry to the bottom of the networking interface
-file:
+Then, I added the Wi-Fi entry to the bottom of the networking interface file:
#+begin_src sh
nano /etc/network/interfaces
@@ -204,13 +203,13 @@ Finally, restart the networking service:
rc-service networking restart
#+end_src
-My Wi-Fi interface would receive an IP address from the router, but it
-could not ping anything in the network. To solve the Wi-Fi issues, I
-originally upgraded to Alpine's =edge= repositories, which was
+My Wi-Fi interface would receive an internet protocol (IP) address from the
+router, but it could not ping anything in the network. To solve the Wi-Fi
+issues, I originally upgraded to Alpine's =edge= repositories, which was
unnecessary.
-Really, the solution was to enable the =NameResolvingService=resolvconf=
-in =/etc/iwd/main.conf=.
+Really, the solution was to enable the =NameResolvingService=resolvconf= in
+=/etc/iwd/main.conf=.
#+begin_src sh
doas nano /etc/iwd/main.conf
@@ -226,11 +225,10 @@ Once I finished this process, my Wi-Fi is working flawlessly.
** Sound Issues
-Same as with the Wi-Fi, I had no sound and could not control the
-mute/unmute or volume buttons on my laptop.
+Same as with the Wi-Fi, I had no sound and could not control the mute/unmute or
+volume buttons on my laptop.
-To resolve this, I installed
-[[https://wiki.alpinelinux.org/wiki/PipeWire][pipewire]].
+To resolve this, I installed [[https://wiki.alpinelinux.org/wiki/PipeWire][pipewire]].
#+begin_src sh
# Add your user to the following groups
@@ -242,8 +240,8 @@ apk add pipewire wireplumber pipewire-pulse pipewire-jack pipewire-alsa
#+end_src
Finally, I needed to add =/usr/libexec/pipewire-launcher= to my
-=.config/sway/config= file so that Pipewire would run every time I
-launched sway.
+=.config/sway/config= file so that Pipewire would run every time I launched
+sway.
#+begin_src sh
nano ~/.config/sway/config
@@ -260,8 +258,8 @@ bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ to
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle
#+end_src
-Note that I do not use bluetooth or screen sharing, so I won't cover
-those options in this post.
+Note that I do not use bluetooth or screen sharing, so I won't cover those
+options in this post.
-Other than these issues, I have a working Alpine desktop. No other
-complaints thus far!
+Other than these issues, I have a working Alpine desktop. No other complaints
+thus far!