diff options
| author | Christian Cleberg <[email protected]> | 2025-11-11 22:49:13 -0600 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2025-11-11 22:49:13 -0600 |
| commit | 51a7a02f0c96d49b68fbcc155414c218207fa270 (patch) | |
| tree | 845af8aad0e8769352efc02fcd1044eed9cc1ec1 /content | |
| parent | 7d3e80ebf1dc770eac0e21890b74f18ba2d15a6b (diff) | |
| download | cleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.tar.gz cleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.tar.bz2 cleberg.net-51a7a02f0c96d49b68fbcc155414c218207fa270.zip | |
fix grammar in 2022 posts
Diffstat (limited to 'content')
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! |
