Commit 7d3b5175f2

7d3b5175f2d9d016b06190273fcfeb380a460b3f

parent: 7c70a351e2

Unsigned

cmc <hello@cleberg.net> · 2024-05-02 02:45 UTC

prettier formatting and rewrap lines

Layout: unified · split

README.md +6 −11
@@ -2,15 +2,18 @@
22
33[cleberg.net](https://cleberg.net) is my personal webpage.
44
5This README is viewable on [git.cleberg.net](https://git.cleberg.net/?p=cleberg.net.git;a=blob;f=README.org;h=155f4696a09503411730afc422b7fb49acbef8f3;hb=HEAD).
5This README is viewable on
6[git.cleberg.net](https://git.cleberg.net/?p=cleberg.net.git;a=blob;f=README.org;h=155f4696a09503411730afc422b7fb49acbef8f3;hb=HEAD).
67
78## Overview
89
9This website & blog uses [Markdown](https://spec.commonmark.org/current/), published with [Zola](https://www.getzola.org/).
10This website & blog uses [Markdown](https://spec.commonmark.org/current/),
11published with [Zola](https://www.getzola.org/).
1012
1113## Configuration
1214
13All configuration options are available within the `config.toml` file. Refer to the Zola documentation for further configuration options.
15All configuration options are available within the `config.toml` file. Refer to
16the Zola documentation for further configuration options.
1417
1518## Building
1619
@@ -28,13 +31,5 @@ Use `zola build` and deploy to whichever deployment target you prefer.
2831
2932## Tasks
3033
31- [x] Format all blog posts
32 - [x] 2018
33 - [x] 2019
34 - [x] 2020
35 - [x] 2021
36 - [x] 2022
37 - [x] 2023
38 - [x] 2024
3934- [ ] Add descriptions to blog posts
4035- [ ] Figure out how to get file tags to show up
content/blog/2018-11-28-aes-encryption.md +9 −10
@@ -13,8 +13,7 @@ If you're not familiar with encryption techniques,
1313National Institute of Standards and Technology, sub-selected from the Rijndael
1414family of ciphers (128, 192, and 256 bits) in 2001. Furthering its popularity
1515and status, the US government chose AES as their default encryption method for
16top-secret data, removing the previous standard which had been in place since
171977.
16top-secret data, removing the previous standard which had been in place since 1977.
1817
1918AES has proven to be an extremely safe encryption method, with 7-round and
20198-round attacks making no material improvements since the release of this
@@ -24,8 +23,8 @@ encryption standard almost two decades ago.
2423> fastest single-key attacks on round-reduced AES variants [20, 33] so far are
2524> only slightly more powerful than those proposed 10 years ago [23,24].
2625>
27> - [Bogdonav, et
28> al.](http://research.microsoft.com/en-us/projects/cryptanalysis/aesbc.pdf)
26> - [Bogdonav, et
27> al.](http://research.microsoft.com/en-us/projects/cryptanalysis/aesbc.pdf)
2928
3029# How Secure is AES?
3130
@@ -99,8 +98,8 @@ where feasible:
99981. Privacy is a human right and is recognized as a national right in some
10099 countries (e.g., [US Fourth
101100 Amendment](https://www.law.cornell.edu/wex/fourth_amendment)).
1022. "Why not?" Encryption rarely affects performance or speed, so there's
103 usually not a reason to avoid it in the first place.
1012. "Why not?" Encryption rarely affects performance or speed, so there's usually
102 not a reason to avoid it in the first place.
1041033. Your digital identity and activity (texts, emails, phone calls, online
105104 accounts, etc.) are extremely valuable and can result in terrible
106105 consequences, such as identity theft, if leaked to other parties. Encrypting
@@ -110,10 +109,10 @@ where feasible:
110109 devices.
1111105. Corporations, governments, and other nefarious groups/individuals are
112111 actively looking for ways to collect personal information about anyone they
113 can. If someone's data is unencrypted, that person may become a target due
114 to the ease of data collection.
112 can. If someone's data is unencrypted, that person may become a target due to
113 the ease of data collection.
115114
116115​**Read More:**
117116
118- [Federal Information Processing Standards Publication
119 197](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf)
117- [Federal Information Processing Standards Publication
118 197](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf)
content/blog/2018-11-28-cpp-compiler.md +2 −2
@@ -16,7 +16,7 @@ executed. There are many steps and intricacies to the compilation process, and
1616this post was a personal exercise to learn and remember as much information as I
1717can.
1818
19``` cpp
19```cpp
2020#include <iostream>
2121
2222int main()
@@ -76,7 +76,7 @@ dynamically.
7676For example, the `Hello, world!` code snippet above compiles into the following
7777assembly code:
7878
79``` asm
79```asm
8080.LC0:
8181 .string "Hello, world!\n"
8282main:
content/blog/2019-01-07-useful-css.md +61 −61
@@ -34,15 +34,15 @@ extended, where extra variables could be defined for `primary-text`,
3434For example, here are some variables defined at the root of the website, which
3535allows for any subsequent CSS rules to use those variables:
3636
37``` css
37```css
3838:root {
39 --primary-color: black;
40 --secondary-color: white;
39 --primary-color: black;
40 --secondary-color: white;
4141}
4242
4343body {
44 background-color: var(--primary-color);
45 color: var(--secondary-color);
44 background-color: var(--primary-color);
45 color: var(--secondary-color);
4646}
4747```
4848
@@ -50,14 +50,14 @@ body {
5050
5151Box shadows were once my mortal enemy. No matter how hard I tried, I just
5252couldn't get them to work how I wanted. Because of this, my favorite discovery
53has been CSSMatic's [box shadow
54generator](https://www.cssmatic.com/box-shadow). It provides an excellent tool
55to generate box shadows using their simple sliders. Surprisingly, this is the
56reason I learned how box shadows work! You can use the sliders and watch how the
57CSS code changes in the image that is displayed. Through this, you should
58understand that the basic structure for box shadows is:
59
60``` css
53has been CSSMatic's [box shadow generator](https://www.cssmatic.com/box-shadow).
54It provides an excellent tool to generate box shadows using their simple
55sliders. Surprisingly, this is the reason I learned how box shadows work! You
56can use the sliders and watch how the CSS code changes in the image that is
57displayed. Through this, you should understand that the basic structure for box
58shadows is:
59
60```css
6161box-shadow: inset horizontal vertical blur spread color;
6262```
6363
@@ -67,55 +67,55 @@ with the code, experiment, and learn.
6767
6868**Box Shadow #1**
6969
70``` html
70```html
7171<div class="shadow-examples">
72 <div class="box effect1">
73 <h3>Effect 1</h3>
74 </div>
72 <div class="box effect1">
73 <h3>Effect 1</h3>
74 </div>
7575</div>
7676```
7777
78``` css
78```css
7979.box h3 {
80 text-align: center;
81 position: relative;
82 top: 80px;
80 text-align: center;
81 position: relative;
82 top: 80px;
8383}
8484.box {
85 width: 70%;
86 height: 200px;
87 background: #fff;
88 margin: 40px auto;
85 width: 70%;
86 height: 200px;
87 background: #fff;
88 margin: 40px auto;
8989}
9090.effect1 {
91 box-shadow: 0 10px 6px -6px #777;
91 box-shadow: 0 10px 6px -6px #777;
9292}
9393```
9494
9595**Box Shadow #2**
9696
97``` html
97```html
9898<div class="shadow-examples">
99 <div class="box effect2">
100 <h3>Effect 2</h3>
101 </div>
99 <div class="box effect2">
100 <h3>Effect 2</h3>
101 </div>
102102</div>
103103```
104104
105``` css
105```css
106106.box h3 {
107 text-align: center;
108 position: relative;
109 top: 80px;
107 text-align: center;
108 position: relative;
109 top: 80px;
110110}
111111.box {
112 width: 70%;
113 height: 200px;
114 background: #fff;
115 margin: 40px auto;
112 width: 70%;
113 height: 200px;
114 background: #fff;
115 margin: 40px auto;
116116}
117117.effect2 {
118 box-shadow: 10px 10px 5px -5px rgba(0, 0, 0, 0.75);
118 box-shadow: 10px 10px 5px -5px rgba(0, 0, 0, 0.75);
119119}
120120```
121121
@@ -128,7 +128,7 @@ Now, let's move on to the best part of this article: flexbox. The flexbox is by
128128far my favorite new toy. I originally stumbled across this solution after
129129looking for more efficient ways of centering content horizontally AND
130130vertically. I had used a few hack-ish methods before, but flexbox throws those
131out the window. The best part of it all is that flexbox is *dead simple*.
131out the window. The best part of it all is that flexbox is _dead simple_.
132132
133133Flexbox pertains to the parent div of any element. You want the parent to be the
134134flexbox in which items are arranged to use the flex methods. It's easier to see
@@ -136,34 +136,34 @@ this in action that explained, so let's see an example.
136136
137137**Flexbox**
138138
139``` html
139```html
140140<div class="flex-examples">
141 <div class="sm-box">
142 <h3>1</h3>
143 </div>
144 <div class="sm-box">
145 <h3>2</h3>
146 </div>
141 <div class="sm-box">
142 <h3>1</h3>
143 </div>
144 <div class="sm-box">
145 <h3>2</h3>
146 </div>
147147</div>
148148```
149149
150``` css
150```css
151151.flex-examples {
152 display: flex;
153 flex-wrap: wrap;
154 justify-content: flex-start;
155 align-items: center;
156 padding: 10px;
157 background-color: #f2f2f2;
152 display: flex;
153 flex-wrap: wrap;
154 justify-content: flex-start;
155 align-items: center;
156 padding: 10px;
157 background-color: #f2f2f2;
158158}
159159.sm-box {
160 display: flex;
161 justify-content: center;
162 align-items: center;
163 width: 20%;
164 height: 100px;
165 background: #fff;
166 margin: 40px 10px;
160 display: flex;
161 justify-content: center;
162 align-items: center;
163 width: 20%;
164 height: 100px;
165 background: #fff;
166 margin: 40px 10px;
167167}
168168```
169169
content/blog/2019-09-09-audit-analytics.md +29 −30
@@ -23,10 +23,10 @@ One of the common mistakes that managers (and anyone new to the process) make is
2323assuming that everything involved with this process is "data analytics". In
2424fact, data analytics are only a small part of the process.
2525
26See **Figure 1** for a more accurate representation of where data analysis
27sits within the full process. This means that data analysis does not include
28querying or extracting data, selecting samples, or performing audit tests. These
29steps can be necessary for an audit (and may even be performed by the same
26See **Figure 1** for a more accurate representation of where data analysis sits
27within the full process. This means that data analysis does not include querying
28or extracting data, selecting samples, or performing audit tests. These steps
29can be necessary for an audit (and may even be performed by the same
3030associates), but they are not data analytics.
3131
3232![The Intelligence
@@ -45,7 +45,7 @@ companies to perform their roles).
4545> a systematic, disciplined approach to evaluate and improve the effectiveness
4646> of risk management, control and governance processes.
4747>
48> - The IIA's Definition of Internal Audit
48> - The IIA's Definition of Internal Audit
4949
5050Part of the blame for the slow adoption of data analysis can be attributed to
5151the fact that internal auditing is strongly based on tradition and following the
@@ -73,15 +73,15 @@ look at **Figure 2** for a quick overview of the model.
7373The DELTA model sets a few guidelines for areas wanting to implement data
7474analytics so that the results can be as comprehensive as possible:
7575
76- **Data**: Must be clean, accessible, and (usually) unique.
77- **Enterprise-Wide Focus**: Key data systems and analytical resources must be
78 available for use (by the Internal Audit Function).
79- **Leaders**: Must promote a data analytics approach and show the value of
80 analytical results.
81- **Targets**: Must be set for key areas and risks that the analytics can be
82 compared against (KPIs).
83- **Analysts**: There must be auditors willing and able to perform data
84 analytics or else the system cannot be sustained.
76- **Data**: Must be clean, accessible, and (usually) unique.
77- **Enterprise-Wide Focus**: Key data systems and analytical resources must be
78 available for use (by the Internal Audit Function).
79- **Leaders**: Must promote a data analytics approach and show the value of
80 analytical results.
81- **Targets**: Must be set for key areas and risks that the analytics can be
82 compared against (KPIs).
83- **Analysts**: There must be auditors willing and able to perform data
84 analytics or else the system cannot be sustained.
8585
8686![The Delta
8787Model](https://img.cleberg.net/blog/20190909-data-analysis-in-auditing/delta-min.png)
@@ -110,12 +110,11 @@ some applicable standards, such as IPPF Standard 1300.
110110Additionally, IPPF Standard 2060 discusses reporting:
111111
112112> The chief audit executive must report periodically to senior management and
113> the board on the internal audit activity's purpose, authority,
114> responsibility, and performance relative to its plan and on its conformance
115> with the Code of Ethics and the Standards. Reporting must also include
116> significant risk and control issues, including fraud risks, governance issues,
117> and other matters that require the attention of senior management and/or the
118> board.
113> the board on the internal audit activity's purpose, authority, responsibility,
114> and performance relative to its plan and on its conformance with the Code of
115> Ethics and the Standards. Reporting must also include significant risk and
116> control issues, including fraud risks, governance issues, and other matters
117> that require the attention of senior management and/or the board.
119118>
120119> - IPPF Standard 2060
121120
@@ -163,12 +162,12 @@ where the auditor must write the scripts manually. Python and the R-language are
163162solely scripting languages.
164163
165164The general trend in the data analytics environment is that if the tool allows
166you to do everything by clicking buttons or dragging elements, you won't be
167able to fully utilize the analytics you need. The most robust solutions are
168created by those who understand how to write the scripts manually. It should be
169noted that as the utility of a tool increases, it usually means that the
170learning curve for that tool will also be higher. It will take auditors longer
171to learn how to utilize Python, R, or ACL versus learning how to utilize Excel.
165you to do everything by clicking buttons or dragging elements, you won't be able
166to fully utilize the analytics you need. The most robust solutions are created
167by those who understand how to write the scripts manually. It should be noted
168that as the utility of a tool increases, it usually means that the learning
169curve for that tool will also be higher. It will take auditors longer to learn
170how to utilize Python, R, or ACL versus learning how to utilize Excel.
172171
173172# Visualization
174173
@@ -192,13 +191,13 @@ Lastly, let's take a look at an example of data visualization. This example
192191comes from a [blog post written by Kushal
193192Chakrabarti](https://talent.works/2018/03/28/the-science-of-the-job-search-part-iii-61-of-entry-level-jobs-require-3-years-of-experience/)
194193in 2018 about the percent of entry-level US jobs that require experience.
195**Figure 3** shows us an easy-to-digest picture of the data. We can quickly
196tell that only about 12.5% of entry-level jobs don't require experience.
194**Figure 3** shows us an easy-to-digest picture of the data. We can quickly tell
195that only about 12.5% of entry-level jobs don't require experience.
197196
198197This is the kind of result that easily describes the data for you. However, make
199198sure to include an explanation of what the results mean. Don't let the reader
200assume what the data means, especially if it relates to a complex subject. *Tell
201a story* about the data and why the results matter. For example, **Figure 4**
199assume what the data means, especially if it relates to a complex subject. _Tell
200a story_ about the data and why the results matter. For example, **Figure 4**
202201shows a part of the explanation the author gives to illustrate his point.
203202
204203![Entry-Level
content/blog/2019-12-03-the-ansoff-matrix.md +6 −6
@@ -10,8 +10,8 @@ draft = false
1010As the world of business evolves, managers must approach business planning and
1111strategy with a contemporary mindset. According to Dess, McNamara, Eisner, and
1212Lee, managers must be willing to adapt to the modern business environment by
13going beyond "'incremental management', whereby they view their job as making
14a series of small, minor changes to improve the efficiency of the firm's
13going beyond "'incremental management', whereby they view their job as making a
14series of small, minor changes to improve the efficiency of the firm's
1515operations"(2019).
1616
1717One reason that strategic management is crucial is because most businesses that
@@ -34,8 +34,8 @@ companies to use in this framework: market penetration, market development,
3434product development, and diversification (see **Figure 1**). The x-axis of the
3535matrix focuses on the firm's markets and also determines if the firm is looking
3636to enter new markets or innovate in its current markets. The y-axis of the
37matrix focuses on the firm's products and determines if the firm wants to
38pursue strategies around their existing products or explore new products.
37matrix focuses on the firm's products and determines if the firm wants to pursue
38strategies around their existing products or explore new products.
3939
4040![The Ansoff Matrix by JaisonAbeySabu, Own work, CC BY-SA
41413.0](https://img.cleberg.net/blog/20191203-the-ansoff-matrix/ansoff_matrix-min.png)
@@ -75,8 +75,8 @@ increases in their investor dividends for 57 consecutive years(2019).
7575Diversification, the final strategy of the Ansoff Matrix, is more difficult than
7676the others since it involves exploring both new markets and new products.
7777Related diversification is a diversification strategy that closely relates to
78the firm's core business. Coca-Cola's best example of related diversification
79is its acquisition of Glaceau and Vitamin Water, which expanded their drinking
78the firm's core business. Coca-Cola's best example of related diversification is
79its acquisition of Glaceau and Vitamin Water, which expanded their drinking
8080lines of business(2019).
8181
8282## Unrelated Diversification
content/blog/2019-12-16-password-security.md +19 −19
@@ -32,10 +32,10 @@ Once you think you have a good idea of all your different authentication
3232methods, I recommend using a password manager such as
3333[Bitwarden](https://bitwarden.com/). Using a password manager allows you to
3434automatically save your logins, create randomized passwords, and transfer
35passwords across devices. However, you'll need to memorize your "vault
36password" that allows you to open the password manager. It's important to make
37this something hard to guess since it would allow anyone who has it to access
38every password you've stored in there.
35passwords across devices. However, you'll need to memorize your "vault password"
36that allows you to open the password manager. It's important to make this
37something hard to guess since it would allow anyone who has it to access every
38password you've stored in there.
3939
4040Personally, I recommend using a
4141[passphrase](https://en.wikipedia.org/wiki/Passphrase) instead of a
@@ -88,25 +88,25 @@ Guidelines and Authentication and Lifecycle Management.
8888> it would be impractical for an attacker to guess or otherwise discover the
8989> correct secret value. A memorized secret is something you know.
9090>
91> - NIST Special Publication 800-63B
91> - NIST Special Publication 800-63B
9292
9393NIST offers a lot of guidance on passwords, but I'm going to highlight just a
9494few of the important factors:
9595
96- Require passwords to be a minimum of 8 characters (6 characters if randomly
97 generated and be generated using an approved random bit generator).
98- Compare potential passwords against a list that contains values known to be
99 commonly-used, expected, or compromised.
100- Offer guidance on password strength, such as a strength meter.
101- Implement a rate-limiting mechanism to limit the number of failed
102 authentication attempts for each user account.
103- Do not require composition rules for passwords and do not require passwords to
104 be changed periodically (unless compromised).
105- Allow pasting of user identification and passwords to facilitate the use of
106 password managers.
107- Allow users to view the password as it is being entered.
108- Use secure forms of communication and storage, including salting and hashing
109 passwords using a one-way key derivation function.
96- Require passwords to be a minimum of 8 characters (6 characters if randomly
97 generated and be generated using an approved random bit generator).
98- Compare potential passwords against a list that contains values known to be
99 commonly-used, expected, or compromised.
100- Offer guidance on password strength, such as a strength meter.
101- Implement a rate-limiting mechanism to limit the number of failed
102 authentication attempts for each user account.
103- Do not require composition rules for passwords and do not require passwords
104 to be changed periodically (unless compromised).
105- Allow pasting of user identification and passwords to facilitate the use of
106 password managers.
107- Allow users to view the password as it is being entered.
108- Use secure forms of communication and storage, including salting and hashing
109 passwords using a one-way key derivation function.
110110
111111NIST offers further guidance on other devices that require specific security
112112policies, querying for passwords, and more. All the information discussed so far
content/blog/2020-01-25-linux-software.md +1 −1
@@ -184,7 +184,7 @@ sudo nano /etc/pacman.conf
184184
185185Now, scroll down and uncomment the `multilib` section.
186186
187``` config
187```config
188188# Before:
189189#[multilib]
190190#Include = /etc/pacman.d/mirrorlist
content/blog/2020-01-26-steam-on-ntfs.md +11 −11
@@ -13,11 +13,11 @@ Screenshot](https://img.cleberg.net/blog/20200125-the-best-linux-software/steam.
1313If you want to see how to install Steam on Linux, see my other post: [Linux
1414Software](../linux-software/).
1515
16Are you having trouble launching games, even though they've installed
17correctly? This may happen if you're storing your games on an NTFS-formatted
18drive. This shouldn't be an issue if you're storing your games on the same
19drive that Steam is on, but some gamers prefer to put Steam on their main drive
20and game files on another SSD or HDD.
16Are you having trouble launching games, even though they've installed correctly?
17This may happen if you're storing your games on an NTFS-formatted drive. This
18shouldn't be an issue if you're storing your games on the same drive that Steam
19is on, but some gamers prefer to put Steam on their main drive and game files on
20another SSD or HDD.
2121
2222To fix this problem, you'll need to try a few things. First, you'll need to
2323install the `ntfs-3g` package, which is meant for better interoperability with
@@ -44,12 +44,12 @@ mkdir /mnt/steam_library
4444```
4545
4646To automatically mount drives upon system boot, you will need to collect a few
47items. The UUID is the identification number connected to whichever drive
48you're using to store Steam games.
47items. The UUID is the identification number connected to whichever drive you're
48using to store Steam games.
4949
50Drives are usually labeled similar to `/dev/nvme0n1p1` or `/dev/sda1`, so
51you'll need to find the line in the output of the command below that correlates
52to your drive and copy the UUID over to the `/etc/fstab` file.
50Drives are usually labeled similar to `/dev/nvme0n1p1` or `/dev/sda1`, so you'll
51need to find the line in the output of the command below that correlates to your
52drive and copy the UUID over to the `/etc/fstab` file.
5353
5454```sh
5555sudo blkid | grep UUID=
@@ -72,7 +72,7 @@ sudo nano /etc/fstab
7272Each drive you want to mount on boot should have its own line in the
7373`/etc/fstab` file that looks similar to this:
7474
75``` config
75```config
7676UUID=B64E53824E5339F7 /mnt/steam_library ntfs-3g uid=1000,gid=1000 0 0
7777```
7878
content/blog/2020-02-09-cryptography-basics.md +26 −26
@@ -23,7 +23,7 @@ Glossary's definition:
2323> transformation is reversible, cryptography also deals with restoring encrypted
2424> data to an intelligible form.
2525>
26> - [Internet Security Glossary (2000)](https://tools.ietf.org/html/rfc2828)
26> - [Internet Security Glossary (2000)](https://tools.ietf.org/html/rfc2828)
2727
2828Cryptography cannot offer protection against the loss of data; it simply offers
2929encryption methods to protect data at-rest and data in-traffic. At a high-level,
@@ -37,15 +37,15 @@ utilizes one or more values called keys to encrypt or decrypt the data.
3737To create or evaluate a cryptographic system, you need to know the essential
3838pieces to the system:
3939
40- **Encryption Algorithm (Primitive):** A mathematical process that encrypts
41 and decrypts data.
42- **Encryption Key:** A string of bits used within the encryption algorithm as
43 the secret that allows successful encryption or decryption of data.
44- **Key Length (Size):** The maximum number of bits within the encryption key.
45 It's important to remember that key size is regulated in many countries.
46- **Message Digest:** A smaller, fixed-size bit string version of the original
47 message. This is practically infeasible to reverse, which is why it's
48 commonly used to verify integrity.
40- **Encryption Algorithm (Primitive):** A mathematical process that encrypts
41 and decrypts data.
42- **Encryption Key:** A string of bits used within the encryption algorithm as
43 the secret that allows successful encryption or decryption of data.
44- **Key Length (Size):** The maximum number of bits within the encryption key.
45 It's important to remember that key size is regulated in many countries.
46- **Message Digest:** A smaller, fixed-size bit string version of the original
47 message. This is practically infeasible to reverse, which is why it's
48 commonly used to verify integrity.
4949
5050# Symmetric Systems (Secret Key Cryptography)
5151
@@ -136,9 +136,9 @@ encrypts just the data portion of packets in the transport methods, but it
136136encrypts both the data and headers in the tunnel method (introducing an
137137additional header for authentication).
138138
139**Secure Shell (SSH):** SSH is another network protocol used to protect
140network services by authenticating users through a secure channel. This protocol
141is often used for command-line (shell) functions such as remote shell commands,
139**Secure Shell (SSH):** SSH is another network protocol used to protect network
140services by authenticating users through a secure channel. This protocol is
141often used for command-line (shell) functions such as remote shell commands,
142142logins, and file transfers.
143143
144144**Kerberos:** Developed by MIT, Kerberos is a computer-network authentication
@@ -152,16 +152,16 @@ encryption method for Windows Active Directory (AD).
152152If you're someone who needs solutions on how to control risks associated with
153153utilizing a crytograhpic system, start with a few basic controls:
154154
155- **Policies:** A policy on the use of cryptographic controls for protection
156 of information is implemented and is in accordance with organizational
157 objectives.
158- **Key management:** A policy on the use, protection and lifetime of
159 cryptographic keys is implemented through the entire application lifecycle.
160- **Key size:** The organization has researched the optimal key size for their
161 purposes, considering national laws, required processing power, and longevity
162 of the solution.
163- **Algorithm selection:** Implemented algorithms are sufficiently appropriate
164 for the business of the organization, robust, and align with recommended
165 guidelines.
166- **Protocol configuration:** Protocols have been reviewed and configured
167 suitable to the purpose of the business.
155- **Policies:** A policy on the use of cryptographic controls for protection
156 of information is implemented and is in accordance with organizational
157 objectives.
158- **Key management:** A policy on the use, protection and lifetime of
159 cryptographic keys is implemented through the entire application lifecycle.
160- **Key size:** The organization has researched the optimal key size for their
161 purposes, considering national laws, required processing power, and
162 longevity of the solution.
163- **Algorithm selection:** Implemented algorithms are sufficiently appropriate
164 for the business of the organization, robust, and align with recommended
165 guidelines.
166- **Protocol configuration:** Protocols have been reviewed and configured
167 suitable to the purpose of the business.
content/blog/2020-03-25-session-messenger.md +14 −14
@@ -44,16 +44,16 @@ Since most people are looking for an alternative to a popular chat app, I am
4444going to list out the features that Session has so that you are able to
4545determine if the app would suit your needs:
4646
47- Multiple device linking (via QR code or ID)
48- App locking via device screen lock, password, or fingerprint
49- Screenshot blocking
50- Incognito keyboard
51- Read receipts and typing indicators
52- Mobile notification customization
53- Old message deletion and conversation limit
54- Backups
55- Recovery phrase
56- Account deletion, including ID, messages, sessions, and contacts
47- Multiple device linking (via QR code or ID)
48- App locking via device screen lock, password, or fingerprint
49- Screenshot blocking
50- Incognito keyboard
51- Read receipts and typing indicators
52- Mobile notification customization
53- Old message deletion and conversation limit
54- Backups
55- Recovery phrase
56- Account deletion, including ID, messages, sessions, and contacts
5757
5858# Downloads
5959
@@ -76,8 +76,8 @@ Options](https://img.cleberg.net/blog/20200325-session-private-messenger/session
7676
7777# Creating an Account
7878
79Once you've installed the app, simply run the app and create your unique
80Session ID. It will look something like this:
79Once you've installed the app, simply run the app and create your unique Session
80ID. It will look something like this:
8181`05af1835afdd63c947b47705867501d6373f486aa1ae05b1f2f3fcd24570eba608`.
8282
8383You'll need to set a display name and, optionally, a password. If you set a
@@ -96,8 +96,8 @@ Authentication](https://img.cleberg.net/blog/20200325-session-private-messenger/
9696
9797Once you've created your account and set up your profile details, the next step
9898is to start messaging other people. To do so, you'll need to share your Session
99ID with other people. From this point, it's fairly straightforward and acts
100like any other messaging app, so I won't dive into much detail here.
99ID with other people. From this point, it's fairly straightforward and acts like
100any other messaging app, so I won't dive into much detail here.
101101
102102## macOS
103103
content/blog/2020-05-03-homelab.md +11 −11
@@ -32,11 +32,11 @@ Plex and Pi-hole until I grew tired with the slow performance.
3232
3333Here are the specifications for the Pi 4:
3434
35- Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz
36- 4GB LPDDR4-3200 SDRAM
37- Gigabit Ethernet
38- H.265 (4kp60 decode), H264 (1080p60 decode, 1080p30 encode)
39- 64 GB MicroSD Card
35- Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz
36- 4GB LPDDR4-3200 SDRAM
37- Gigabit Ethernet
38- H.265 (4kp60 decode), H264 (1080p60 decode, 1080p30 encode)
39- 64 GB MicroSD Card
4040
4141## Dell Optiplex 5040
4242
@@ -49,11 +49,11 @@ during quarantine.
4949
5050Here are the specifications for the Dell Optiplex 5040:
5151
52- Intel Core i3 6100
53- 8GB RAM DDR3
54- Intel HD Graphics
55- Gigabit Ethernet
56- 500GB Hard Drive
52- Intel Core i3 6100
53- 8GB RAM DDR3
54- Intel HD Graphics
55- Gigabit Ethernet
56- 500GB Hard Drive
5757
5858While this hardware would be awful for a work computer or a gaming rig, it
5959turned out to be wonderful for my server purposes. The only limitation I have
@@ -118,7 +118,7 @@ operating system.
118118
119119## Docker
120120
121I am *very* new to Docker, but I have had a lot of fun playing with it so far.
121I am _very_ new to Docker, but I have had a lot of fun playing with it so far.
122122Docker is used to create containers that can hold all the contents of a system
123123without interfering with other software on the same system. So far, I have
124124successfully installed pi-hole, GitLab, Gogs, and Nextcloud in containers.
content/blog/2020-05-19-customizing-ubuntu.md +7 −8
@@ -7,7 +7,7 @@ draft = false
77
88# More Information
99
10For inspiration on designing your *nix computer, check out the
10For inspiration on designing your \*nix computer, check out the
1111[r/unixporn](https://libredd.it/r/unixporn) subreddit!
1212
1313# Customizing Ubuntu
@@ -36,10 +36,9 @@ following command:
3636sudo apt install gnome-tweaks
3737```
3838
39After you've finished installing the tool, simply launch the Tweaks
40application, and you'll be able to access the various customization options
41available by default on Ubuntu. You might even like some of the pre-installed
42options.
39After you've finished installing the tool, simply launch the Tweaks application,
40and you'll be able to access the various customization options available by
41default on Ubuntu. You might even like some of the pre-installed options.
4342
4443## GNOME Application Themes
4544
@@ -66,8 +65,8 @@ Steps to import themes into Tweaks:
66654. Close tweaks if it is open. Re-open Tweaks and your new theme will be
6766 available in the Applications dropdown in the Appearance section of Tweaks.
6867
69If the theme is not showing up after you've moved it into the themes folder,
70you may have uncompressed the folder into a sub-folder. You can check this by
68If the theme is not showing up after you've moved it into the themes folder, you
69may have uncompressed the folder into a sub-folder. You can check this by
7170entering the theme folder and listing the contents:
7271
7372```sh
@@ -129,7 +128,7 @@ folders to the `/usr/share/fonts/` directory instead.
129128If you spend a lot of time typing commands, you know how important the style and
130129functionality of the terminal is. After spending a lot of time using the default
131130GNOME terminal with [unix
132shell](https://en.wikipedia.org/wiki/Bash_(Unix_shell)), I decided to try some
131shell](<https://en.wikipedia.org/wiki/Bash_(Unix_shell)>), I decided to try some
133132different options. I ended up choosing
134133[Terminator](https://terminator-gtk3.readthedocs.io/en/latest/) with
135134[zsh](https://en.wikipedia.org/wiki/Z_shell).
content/blog/2020-07-20-video-game-sales.md +21 −21
@@ -14,23 +14,23 @@ scrape of vgchartz.com.
1414
1515Fields include:
1616
17- Rank: Ranking of overall sales
18- Name: The game name
19- Platform: Platform of the game release (i.e. PC,PS4, etc.)
20- Year: Year of the game's release
21- Genre: Genre of the game
22- Publisher: Publisher of the game
23- NA~Sales~: Sales in North America (in millions)
24- EU~Sales~: Sales in Europe (in millions)
25- JP~Sales~: Sales in Japan (in millions)
26- Other~Sales~: Sales in the rest of the world (in millions)
27- Global~Sales~: Total worldwide sales.
17- Rank: Ranking of overall sales
18- Name: The game name
19- Platform: Platform of the game release (i.e. PC,PS4, etc.)
20- Year: Year of the game's release
21- Genre: Genre of the game
22- Publisher: Publisher of the game
23- NA~Sales~: Sales in North America (in millions)
24- EU~Sales~: Sales in Europe (in millions)
25- JP~Sales~: Sales in Japan (in millions)
26- Other~Sales~: Sales in the rest of the world (in millions)
27- Global~Sales~: Total worldwide sales.
2828
2929There are 16,598 records. 2 records were dropped due to incomplete information.
3030
3131# Import the Data
3232
33``` python
33```python
3434# Import the Python libraries we will be using
3535import pandas as pd
3636import numpy as np
@@ -48,7 +48,7 @@ Results](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales
4848
4949# Explore the Data
5050
51``` python
51```python
5252# With the description function, we can see the basic stats. For example, we can
5353# also see that the 'Year' column has some incomplete values.
5454df.describe()
@@ -56,7 +56,7 @@ df.describe()
5656
5757![df.describe()](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/02_describe-min.png)
5858
59``` python
59```python
6060# This function shows the rows and columns of NaN values. For example, df[179,3] = nan
6161np.where(pd.isnull(df))
6262
@@ -66,7 +66,7 @@ np.where(pd.isnull(df))
6666
6767# Visualize the Data
6868
69``` python
69```python
7070# This function plots the global sales by platform
7171sns.catplot(x='Platform', y='Global_Sales', data=df, jitter=False).set_xticklabels(rotation=90)
7272```
@@ -74,7 +74,7 @@ sns.catplot(x='Platform', y='Global_Sales', data=df, jitter=False).set_xticklabe
7474![Plot of Global Sales by
7575Platform](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/03_plot-min.png)
7676
77``` python
77```python
7878# This function plots the global sales by genre
7979sns.catplot(x='Genre', y='Global_Sales', data=df, jitter=False).set_xticklabels(rotation=45)
8080```
@@ -82,7 +82,7 @@ sns.catplot(x='Genre', y='Global_Sales', data=df, jitter=False).set_xticklabels(
8282![Plot of Global Sales by
8383Genre](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/04_plot-min.png)
8484
85``` python
85```python
8686# This function plots the global sales by year
8787sns.lmplot(x='Year', y='Global_Sales', data=df).set_xticklabels(rotation=45)
8888```
@@ -90,7 +90,7 @@ sns.lmplot(x='Year', y='Global_Sales', data=df).set_xticklabels(rotation=45)
9090![Plot of Global Sales by
9191Year](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/05_plot-min.png)
9292
93``` python
93```python
9494# This function plots four different lines to show sales from different regions.
9595# The global sales plot line is commented-out, but can be included for comparison
9696df2 = df.groupby('Year').sum()
@@ -121,7 +121,7 @@ Year](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/06
121121
122122## Investigate Outliers
123123
124``` python
124```python
125125# Find the game with the highest sales in North America
126126df.loc[df['NA_Sales'].idxmax()]
127127
@@ -146,7 +146,7 @@ df3.describe()
146146![Descriptive Statistics of 2006
147147Sales](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/07_2006_stats-min.png)
148148
149``` python
149```python
150150# Plot the results of the previous dataframe (games from 2006) - we can see the year's results were largely carried by Wii Sports
151151sns.catplot(x="Genre", y="Global_Sales", data=df3, jitter=False).set_xticklabels(rotation=45)
152152```
@@ -154,7 +154,7 @@ sns.catplot(x="Genre", y="Global_Sales", data=df3, jitter=False).set_xticklabels
154154![Plot of 2006
155155Sales](https://img.cleberg.net/blog/20200720-data-exploration-video-game-sales/08_plot-min.png)
156156
157``` python
157```python
158158# We can see 4 outliers in the graph above, so let's get the top 5 games from that dataframe
159159# The results below show that Nintendo had all top 5 games (3 on the Wii and 2 on the DS)
160160df3.sort_values(by=['Global_Sales'], ascending=False).head(5)
content/blog/2020-07-26-business-analysis.md +17 −17
@@ -13,10 +13,10 @@ project was obtained using Foursquare's developer API.
1313
1414Fields include:
1515
16- Venue Name
17- Venue Category
18- Venue Latitude
19- Venue Longitude
16- Venue Name
17- Venue Category
18- Venue Latitude
19- Venue Longitude
2020
2121There are 232 records found using the center of Lincoln as the area of interest
2222with a radius of 10,000.
@@ -26,7 +26,7 @@ with a radius of 10,000.
2626The first step is the simplest: import the applicable libraries. We will be
2727using the libraries below for this project.
2828
29``` python
29```python
3030# Import the Python libraries we will be using
3131import pandas as pd
3232import requests
@@ -42,7 +42,7 @@ are using in this project comes directly from the Foursquare API. The first step
4242is to get the latitude and longitude of the city being studied (Lincoln, NE) and
4343setting up the folium map.
4444
45``` python
45```python
4646# Define the latitude and longitude, then map the results
4747latitude = 40.806862
4848longitude = -96.681679
@@ -60,7 +60,7 @@ we use our first API call below to determine the total results that Foursquare
6060has found. Since the total results are 232, we perform the API fetching process
6161three times (100 + 100 + 32 = 232).
6262
63``` python
63```python
6464# Foursquare API credentials
6565CLIENT_ID = 'your-client-id'
6666CLIENT_SECRET = 'your-client-secret'
@@ -129,7 +129,7 @@ the categories and name from each business's entry in the Foursquare data
129129automatically. Once all the data has been labeled and combined, the results are
130130stored in the `nearby_venues` dataframe.
131131
132``` python
132```python
133133# This function will extract the category of the venue from the API dictionary
134134def get_category_type(row):
135135 try:
@@ -203,7 +203,7 @@ We now have a complete, clean data set. The next step is to visualize this data
203203onto the map we created earlier. We will be using folium's `CircleMarker()`
204204function to do this.
205205
206``` python
206```python
207207# add markers to map
208208for lat, lng, name, categories in zip(nearby_venues['lat'], nearby_venues['lng'], nearby_venues['name'], nearby_venues['categories']):
209209 label = '{} ({})'.format(name, categories)
@@ -224,18 +224,18 @@ map_LNK
224224\![Initial data
225225map](https://img.cleberg.net/blog/20200726-ibm-data-science/03_data_map-min.png)
226226
227# Clustering: *k-means*
227# Clustering: _k-means_
228228
229To cluster the data, we will be using the *k-means* algorithm. This algorithm is
229To cluster the data, we will be using the _k-means_ algorithm. This algorithm is
230230iterative and will automatically make sure that data points in each cluster are
231231as close as possible to each other, while being as far as possible away from
232232other clusters.
233233
234234However, we first have to figure out how many clusters to use (defined as the
235variable *'k'*). To do so, we will use the next two functions to calculate the
235variable _'k'_). To do so, we will use the next two functions to calculate the
236236sum of squares within clusters and then return the optimal number of clusters.
237237
238``` python
238```python
239239# This function will return the sum of squares found in the data
240240def calculate_wcss(data):
241241 wcss = []
@@ -275,7 +275,7 @@ Now that we have found that our optimal number of clusters is six, we need to
275275perform k-means clustering. When this clustering occurs, each business is
276276assigned a cluster number from 0 to 5 in the dataframe.
277277
278``` python
278```python
279279# set number of clusters equal to the optimal number
280280kclusters = n
281281
@@ -289,7 +289,7 @@ nearby_venues.insert(0, 'Cluster Labels', kmeans.labels_)
289289Success! We now have a dataframe with clean business data, along with a cluster
290290number for each business. Now let's map the data using six different colors.
291291
292``` python
292```python
293293# create map with clusters
294294map_clusters = folium.Map(location=[latitude, longitude], zoom_start=12)
295295colors = ['#0F9D58', '#DB4437', '#4285F4', '#800080', '#ce12c0', '#171717']
@@ -321,7 +321,7 @@ which clusters are more popular for businesses and which are less popular. The
321321results below show us that clusters 0 through 3 are popular, while clusters 4
322322and 5 are not very popular at all.
323323
324``` python
324```python
325325# Show how many venues are in each cluster
326326color_names = ['Dark Green', 'Red', 'Blue', 'Purple', 'Pink', 'Black']
327327for x in range(0,6):
@@ -337,7 +337,7 @@ Our last piece of analysis is to summarize the categories of businesses within
337337each cluster. With these results, we can clearly see that restaurants, coffee
338338shops, and grocery stores are the most popular.
339339
340``` python
340```python
341341# Calculate how many venues there are in each category
342342# Sort from largest to smallest
343343temp_df = nearby_venues.drop(columns=['name', 'lat', 'lng'])
content/blog/2020-08-22-redirect-github-pages.md +1 −1
@@ -25,7 +25,7 @@ DNS configuration.
2525
2626Add these 5 entries to the very top of your DNS configuration:
2727
28``` txt
28```txt
2929@ A 185.199.108.153
3030@ A 185.199.109.153
3131@ A 185.199.110.153
content/blog/2020-08-29-php-auth-flow.md +13 −13
@@ -17,7 +17,7 @@ copying and pasting the code from their library's documentation. For example,
1717here's the code I use to authenticate users with the Tumblr OAuth API for my
1818Tumblr client, Vox Populi:
1919
20``` php
20```php
2121// Start the session
2222session_start();
2323
@@ -52,13 +52,13 @@ MySQL database and PHP.
5252The beginning to any type of user authentication is to create a user account.
5353This process can take many formats, but the simplest is to accept user input
5454from a form (e.g., username and password) and send it over to your database. For
55example, here's a snippet that shows how to get username and password
56parameters that would come when a user submits a form to your PHP script.
55example, here's a snippet that shows how to get username and password parameters
56that would come when a user submits a form to your PHP script.
5757
5858**Note**: Ensure that your password column is large enough to hold the hashed
5959value (at least 60 characters or longer).
6060
61``` php
61```php
6262// Get the values from the URL
6363$username = $_POST['username'];
6464$raw_password = $_POST['password'];
@@ -99,7 +99,7 @@ To be able to verify that a returning user has a valid username and password in
9999your database is as simple as having users fill out a form and comparing their
100100inputs to your database.
101101
102``` php
102```php
103103// Query the database for username and password
104104// ...
105105
@@ -115,24 +115,24 @@ if(password_verify($password_input, $hashed_password)) {
115115# Storing Authentication State
116116
117117Once you've created the user's account, now you're ready to initialize the
118user's session. **You will need to do this on every page you load while the
119user is logged in.** To do so, simply enter the following code snippet:
118user's session. **You will need to do this on every page you load while the user
119is logged in.** To do so, simply enter the following code snippet:
120120
121``` php
121```php
122122session_start();
123123```
124124
125125Once you've initialized the session, the next step is to store the session in a
126126cookie so that you can access it later.
127127
128``` php
128```php
129129setcookie(session_name());
130130```
131131
132Now that the session name has been stored, you'll be able to check if there's
133an active session whenever you load a page.
132Now that the session name has been stored, you'll be able to check if there's an
133active session whenever you load a page.
134134
135``` php
135```php
136136if(isset(session_name())) {
137137 // The session is active
138138}
@@ -144,7 +144,7 @@ The next logical step is to give your users the option to log out once they are
144144done using your application. This can be tricky in PHP since a few of the
145145standard ways do not always work.
146146
147``` php
147```php
148148// Initialize the session.
149149// If you are using session_name("something"), don't forget it now!
150150session_start();
content/blog/2020-09-01-visual-recognition.md +10 −10
@@ -7,13 +7,13 @@ draft = false
77
88# What is IBM Watson?
99
10If you've never heard of [Watson](https://www.ibm.com/watson), this service is
11a suite of enterprise-ready AI services, applications, and tooling provided by
10If you've never heard of [Watson](https://www.ibm.com/watson), this service is a
11suite of enterprise-ready AI services, applications, and tooling provided by
1212IBM. Watson contains quite a few useful tools for data scientists and students,
1313including the subject of this post today: visual recognition.
1414
15If you'd like to view the official documentation for the Visual Recognition
16API, visit the [API
15If you'd like to view the official documentation for the Visual Recognition API,
16visit the [API
1717Docs](https://cloud.ibm.com/apidocs/visual-recognition/visual-recognition-v3?code=python).
1818
1919# Prerequisites
@@ -52,7 +52,7 @@ pip install --upgrade --user "ibm-watson>=4.5.0"
5252Next, we need to specify the API key, version, and URL given to us when we
5353created the Watson Visual Recognition service.
5454
55``` python
55```python
5656apikey = "<your-apikey>"
5757version = "2018-03-19"
5858url = "<your-url>"
@@ -60,7 +60,7 @@ url = "<your-url>"
6060
6161Now, let's import the necessary libraries and authenticate our service.
6262
63``` python
63```python
6464import json
6565from ibm_watson import VisualRecognitionV3
6666from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
@@ -77,14 +77,14 @@ visual_recognition.set_service_url(url)
7777**[Optional]** If you'd like to tell the API not to use any data to improve
7878their products, set the following header.
7979
80``` python
80```python
8181visual_recognition.set_default_headers({'x-watson-learning-opt-out': "true"})
8282```
8383
8484Now we have our API all set and ready to go. For this example, I'm going to
8585include a `dict` of photos to load as we test out the API.
8686
87``` python
87```python
8888data = [
8989 {
9090 "title": "Grizzly Bear",
@@ -122,7 +122,7 @@ each section.
122122In the case of an API error, the codes and explanations are output to the
123123console.
124124
125``` python
125```python
126126from ibm_watson import ApiException
127127
128128for x in range(len(data)):
@@ -164,7 +164,7 @@ or greater, you would simply adjust the `threshold` in the
164164When your program runs, it should show the output below for each photo you
165165provide.
166166
167``` txt
167```txt
168168----------------------------------------------------------------
169169Image Title: Grizzly Bear
170170Image URL: https://example.com/photos/image1.jpg
content/blog/2020-09-22-internal-audit.md +10 −9
@@ -12,8 +12,8 @@ Overview](https://img.cleberg.net/blog/20200922-what-is-internal-audit/internal-
1212
1313One of the many reasons that Internal Audit needs such thorough explaining to
1414non-auditors is that Internal Audit can serve many purposes, depending on the
15organization's size and needs. However, the Institute of Internal Auditors
16(IIA) defines Internal Auditing as:
15organization's size and needs. However, the Institute of Internal Auditors (IIA)
16defines Internal Auditing as:
1717
1818> Internal auditing is an independent, objective assurance and consulting
1919> activity designed to add value and improve an organization's operations. It
@@ -54,9 +54,10 @@ function, process, system, or other subject matters. The internal auditor
5454determines the nature and scope of an assurance engagement. Generally, three
5555parties are participants in assurance services: (1) the person or group directly
5656involved with the entity, operation, function, process, system, or other subject
57- (the process owner), (2) the person or group making the assessment - (the
58internal auditor), and (3) the person or group using the assessment - (the
59user).
57
58- (the process owner), (2) the person or group making the assessment - (the
59 internal auditor), and (3) the person or group using the assessment - (the
60 user).
6061
6162## Consulting
6263
@@ -121,10 +122,10 @@ model.
121122Looking at this model from an auditing perspective shows us that auditors will
122123need to align, communicate, and collaborate with management, including business
123124area managers and chief officers, as well as reporting to the governing body.
124The governing body will instruct internal audit *functionally* on their goals
125The governing body will instruct internal audit _functionally_ on their goals
125126and track their progress periodically.
126127
127However, the internal audit department will report *administratively* to a chief
128However, the internal audit department will report _administratively_ to a chief
128129officer in the company for the purposes of collaboration, direction, and
129130assistance with the business. Note that in most situations, the governing body
130131is the audit committee on the company's board of directors.
@@ -136,8 +137,8 @@ objective function that can provide assurance over the topics they audit.
136137
137138A normal audit will generally follow the same process, regardless of the topic.
138139However, certain special projects or abnormal business areas may call for
139changes to the audit process. The audit process is not set in stone, it's
140simply a set of best practices so that audits can be performed consistently.
140changes to the audit process. The audit process is not set in stone, it's simply
141a set of best practices so that audits can be performed consistently.
141142
142143![The Internal Audit
143144Process](https://img.cleberg.net/blog/20200922-what-is-internal-audit/internal-audit-process.jpg)
content/blog/2020-09-25-happiness-map.md +21 −21
@@ -14,14 +14,14 @@ scores, as well as other national scoring measures.
1414
1515Fields include:
1616
17- Overall rank
18- Country or region
19- GDP per capita
20- Social support
21- Healthy life expectancy
22- Freedom to make life choices
23- Generosity
24- Perceptions of corruption
17- Overall rank
18- Country or region
19- GDP per capita
20- Social support
21- Healthy life expectancy
22- Freedom to make life choices
23- Generosity
24- Perceptions of corruption
2525
2626There are 156 records. Since there are ~195 countries in the world, we can see
2727that around 40 countries will be missing from this dataset.
@@ -31,7 +31,7 @@ that around 40 countries will be missing from this dataset.
3131As always, run the `install` command for all packages needed to perform
3232analysis.
3333
34``` python
34```python
3535!pip install folium geopandas matplotlib numpy pandas
3636```
3737
@@ -42,7 +42,7 @@ We only need a couple packages to create a choropleth map. We will use
4242visualizations in Python. We will also use geopandas and pandas to wrangle our
4343data before we put it on a map.
4444
45``` python
45```python
4646# Import the necessary Python packages
4747import folium
4848import geopandas as gpd
@@ -58,7 +58,7 @@ GeoPandas will take this data and load it into a dataframe so that we can easily
5858match it to the data we're trying to analyze. Let's look at the GeoJSON
5959dataframe:
6060
61``` python
61```python
6262# Load the GeoJSON data with geopandas
6363geo_data = gpd.read_file('https://raw.githubusercontent.com/datasets/geo-countries/master/data/countries.geojson')
6464geo_data.head()
@@ -67,11 +67,11 @@ geo_data.head()
6767![GeoJSON
6868Dataframe](https://img.cleberg.net/blog/20200925-world-choropleth-map/geojson_df.png)
6969
70Next, let's load the data from the Kaggle dataset. I've downloaded this file,
71so update the file path if you have it somewhere else. After loading, let's
72take a look at this dataframe:
70Next, let's load the data from the Kaggle dataset. I've downloaded this file, so
71update the file path if you have it somewhere else. After loading, let's take a
72look at this dataframe:
7373
74``` python
74```python
7575# Load the world happiness data with pandas
7676happy_data = pd.read_csv(r'~/Downloads/world_happiness_data_2019.csv')
7777happy_data.head()
@@ -88,7 +88,7 @@ below showed empty countries. I searched both data frames for the missing
8888countries to see the naming differences. Any countries that do not have records
8989in the `happy_data` df will not show up on the map.
9090
91``` python
91```python
9292# Rename some countries to match our GeoJSON data
9393
9494# Rename USA
@@ -111,13 +111,13 @@ happy_data.at[democratic_congo_index, 'Country or region'] = 'Democratic Republi
111111# Merge the Data
112112
113113Now that we have clean data, we need to merge the GeoJSON data with the
114happiness data. Since we've stored them both in dataframes, we just need to
115call the `.merge()` function.
114happiness data. Since we've stored them both in dataframes, we just need to call
115the `.merge()` function.
116116
117117We will also rename a couple columns, just so that they're a little easier to
118118use when we create the map.
119119
120``` python
120```python
121121# Merge the two previous dataframes into a single geopandas dataframe
122122merged_df = geo_data.merge(happy_data,left_on='ADMIN', right_on='Country or region')
123123
@@ -136,7 +136,7 @@ simplest way to find the center of the map and create a Folium map object. The
136136important part is to remember to reference the merged dataframe for our GeoJSON
137137data and value data. The columns specify which geo data and value data to use.
138138
139``` python
139```python
140140# Assign centroids to map
141141x_map = merged_df.centroid.x.mean()
142142y_map = merged_df.centroid.y.mean()
@@ -173,7 +173,7 @@ Now that we have a map set up, we could stop. However, I want to add a tooltip
173173so that I can see more information about each country. The `tooltip_data` code
174174below will show a popup on hover with all the data fields shown.
175175
176``` python
176```python
177177 # Adding labels to map
178178 style_function = lambda x: {'fillColor': '#ffffff',
179179 'color':'#000000',
content/blog/2020-10-12-mediocrity.md +6 −6
@@ -16,7 +16,7 @@ allowed us to reach a lesser yet still superb solution.
1616
1717Philosophers throughout history have inspected this plight from many viewpoints.
1818Greek mythology speaks of the [golden
19mean](https://en.wikipedia.org/wiki/Golden_mean_(philosophy)), which uses the
19mean](<https://en.wikipedia.org/wiki/Golden_mean_(philosophy)>), which uses the
2020story of Icarus to illustrate that sometimes "the middle course" is the best
2121solution. In this story, Daedalus, a famous artist of his time, built feathered
2222wings for himself and his son so that they might escape the clutches of King
@@ -40,9 +40,9 @@ considered.
4040
4141Over and over throughout history, we've found that perfection is often
4242unrealistic and unachievable. However, we push ourselves and our peers to "give
43100%" or "go the extra mile," while it may be that the better course is to
44give a valuable level of effort while considering the effects of further effort
45on the outcome. Working harder does not always help us achieve loftier goals.
43100%" or "go the extra mile," while it may be that the better course is to give
44a valuable level of effort while considering the effects of further effort on
45the outcome. Working harder does not always help us achieve loftier goals.
4646
4747This has presented itself to me most recently during my time studying at my
4848university. I was anxious and feeling the stresses of my courses, career, and
@@ -56,8 +56,8 @@ talking to my father when he said something simple that hit home:
5656The thought was extremely straightforward and uncomplicated, yet it was
5757something that I had lost sight of during my stress-filled years at school. Ever
5858since then, I've found myself pausing and remembering that quote every time I
59get anxious or stressed. It helps to stop and think "Can I do anything to
60affect the outcome, or am I simply worrying over something I can't change?"
59get anxious or stressed. It helps to stop and think "Can I do anything to affect
60the outcome, or am I simply worrying over something I can't change?"
6161
6262# When Mediocrity Isn't Enough
6363
content/blog/2020-12-27-website-redesign.md +18 −19
@@ -15,17 +15,16 @@ subdomains.
1515
1616One of the parts I've enjoyed the most about web development is the aspect of
1717designing an identity for a web page and working to find exciting ways to
18display the site's content. Inevitably, this means I've changed the designs
19for my websites more times than I could possibly count. Since I don't really
20host anything on my main webpage that's vital, it allows me the freedom to
21change things as inspiration strikes.
22
23Historically, I've relied on core utilities for spacing, components, and
24layouts from [Bootstrap](https://getbootstrap.com) and added custom CSS for
25fonts, accents, colors, and other items. I also tend to create sites with no
26border radius on items, visible borders, and content that takes up the entire
27screen (using whitespace inside components instead of whitespace around my
28components).
18display the site's content. Inevitably, this means I've changed the designs for
19my websites more times than I could possibly count. Since I don't really host
20anything on my main webpage that's vital, it allows me the freedom to change
21things as inspiration strikes.
22
23Historically, I've relied on core utilities for spacing, components, and layouts
24from [Bootstrap](https://getbootstrap.com) and added custom CSS for fonts,
25accents, colors, and other items. I also tend to create sites with no border
26radius on items, visible borders, and content that takes up the entire screen
27(using whitespace inside components instead of whitespace around my components).
2928
3029# The Redesign Process
3130
@@ -45,8 +44,8 @@ brutalist web design doesn't have to be minimal, it often is.
4544
4645I suppose, in a way, I did create a brutalist website since my HTML is semantic
4746and accessible, hyperlinks are colored and underlined, and all native browser
48functions like scrolling and the back button work as expected. However, I
49didn't think about brutalism while designing these sites.
47functions like scrolling and the back button work as expected. However, I didn't
48think about brutalism while designing these sites.
5049
5150The new design followed a simple design process. I walked through the screens on
5251my blog and asked myself: "Is this element necessary for a user?" This allowed
@@ -60,10 +59,10 @@ blog post descriptions, and the scroll-to-top button. It also helped to move all
6059categories to a single page, rather than have each category on its own page.
6160
6261The final big piece to finish the
63"[KonMari](https://en.wikipedia.org/wiki/Marie_Kondo#KonMari_method)"-like
64part of my process was to remove Bootstrap CSS in its entirety. However, this
65meant pulling out a few very useful classes, such as `.img-fluid` and the
66default font stacks to keep in my custom CSS.
62"[KonMari](https://en.wikipedia.org/wiki/Marie_Kondo#KonMari_method)"-like part
63of my process was to remove Bootstrap CSS in its entirety. However, this meant
64pulling out a few very useful classes, such as `.img-fluid` and the default font
65stacks to keep in my custom CSS.
6766
6867After removing all the unnecessary pieces, I was finally able to reorganize my
6968content and add a very small amount of custom CSS to make everything pretty.
@@ -91,5 +90,5 @@ for all four categories! First contextual paints of the blog homepage are under
9190is within a separate CSS file, and the CSS for my main website is simply
9291embedded in the HTML file.
9392
94Now that everything is complete, I can confidently say I'm happy with the
95result and proud to look at the fastest set of websites I've created so far.
93Now that everything is complete, I can confidently say I'm happy with the result
94and proud to look at the fastest set of websites I've created so far.
content/blog/2020-12-28-neon-drive.md +7 −7
@@ -70,19 +70,19 @@ endurance game mode.
7070Neon Drive sits nicely within the well-founded cult genre of Outrun. Other games
7171that I've enjoyed in this same spectrum are:
7272
73- [Far Cry 3: Blood
73- [Far Cry 3: Blood
7474 Dragon](https://store.steampowered.com/app/233270/Far_Cry_3__Blood_Dragon/)
75- [Retrowave](https://store.steampowered.com/app/1239690/Retrowave/)
76- [Slipstream](https://store.steampowered.com/app/732810/Slipstream/)
75- [Retrowave](https://store.steampowered.com/app/1239690/Retrowave/)
76- [Slipstream](https://store.steampowered.com/app/732810/Slipstream/)
7777
7878Although these games aren't necessarily in the same genre, they do have aspects
7979that place them close enough to interest gamers that enjoyed Neon Drive:
8080
81- [Black Ice](https://store.steampowered.com/app/311800/Black_Ice/)
82- [Cloudpunk](https://store.steampowered.com/app/746850/Cloudpunk/)
83- [Need for Speed:
81- [Black Ice](https://store.steampowered.com/app/311800/Black_Ice/)
82- [Cloudpunk](https://store.steampowered.com/app/746850/Cloudpunk/)
83- [Need for Speed:
8484 Heat](https://store.steampowered.com/app/1222680/Need_for_Speed_Heat/)
85- [VirtuaVerse](https://store.steampowered.com/app/1019310/VirtuaVerse/)
85- [VirtuaVerse](https://store.steampowered.com/app/1019310/VirtuaVerse/)
8686
8787Of course, if all you really care about is the arcade aspect of these games, you
8888can check out the [Atari
content/blog/2020-12-29-zork.md +13 −14
@@ -14,8 +14,8 @@ up and take a ride back to the 1980s with this masterpiece.
1414
1515# Game Description
1616
17Zork is an interactive, text-based computer game originally released in
181980. This series, split into three separate games, introduced a robust and
17Zork is an interactive, text-based computer game originally released in 1980.
18This series, split into three separate games, introduced a robust and
1919sophisticated text parser to gamers. People were largely used to the simple
2020commands used in the popular game [Colossal Cave
2121Adventure](https://en.wikipedia.org/wiki/Colossal_Cave_Adventure), but Zork
@@ -37,7 +37,7 @@ intended, you should try to play it without using the map.
3737
3838![Zork Map](https://img.cleberg.net/blog/20201229-zork/zork_map.png)
3939
40*[Map Source](https://www.filfre.net/2012/01/exploring-zork-part-1/)*
40_[Map Source](https://www.filfre.net/2012/01/exploring-zork-part-1/)_
4141
4242# In-Game Screenshots
4343
@@ -45,25 +45,24 @@ After playing the game (for the first time ever) for several weeks around 2014,
4545I was finally able to beat the game with some online help to find the last
4646couple items. As I was writing this post, I installed the game again to grab
4747some screenshots to show off the true glory of this game. As noted in [Jimmy
48Maher's playthrough](https://www.filfre.net/2012/01/exploring-zork-part-1/),
49the original Zork games looked quite a bit different due to the older hardware
50of computers like the Apple II and multiple bug fixes that Infocom pushed out
51after the game's initial release. My play-through uses the [Zork
48Maher's playthrough](https://www.filfre.net/2012/01/exploring-zork-part-1/), the
49original Zork games looked quite a bit different due to the older hardware of
50computers like the Apple II and multiple bug fixes that Infocom pushed out after
51the game's initial release. My play-through uses the [Zork
5252Anthology](https://store.steampowered.com/app/570580/Zork_Anthology/) version,
5353which utilizes DOSBox on Windows.
5454
5555The first screenshot here shows the introductory information, which doesn't
5656include instructions of any kind for the player. If you haven't played text
57adventures before, try to use simple commands like "go west," "look around,"
58or "hit troll with elvish sword."
57adventures before, try to use simple commands like "go west," "look around," or
58"hit troll with elvish sword."
5959
6060![Zork Screen, pt. 1](https://img.cleberg.net/blog/20201229-zork/zork_01.png)
6161
6262In this second screenshot, we see the player has entered the house and found the
6363trophy case in the living room. The lantern and sword in this room allow the
6464player to explore dark areas and attack enemies. If you don't use the lantern,
65you won't be able to see anything in dark areas, and you may be eaten by a
66grue.
65you won't be able to see anything in dark areas, and you may be eaten by a grue.
6766
6867![Zork Screen, pt. 2](https://img.cleberg.net/blog/20201229-zork/zork_02.png)
6968
@@ -78,9 +77,9 @@ case or carried until you feel like you want to put things away.
7877It's been quite a few years since I first played Zork, but I clearly remember
7978the late nights and bloodshot eyes that helped me find all the treasures. This
8079game is well worth the time and effort, even though the text-based aspect may be
81off-putting to gamers who didn't have to grow up playing games without
82graphics. However, I believe that the strategy and skills learned in early video
83games like Zork can actually help you, even when playing newer games.
80off-putting to gamers who didn't have to grow up playing games without graphics.
81However, I believe that the strategy and skills learned in early video games
82like Zork can actually help you, even when playing newer games.
8483
8584If you do decide to play Zork, you can download Zork I, II, and III from
8685Infocom's [download page](http://infocom-if.org/downloads/downloads.html) for
content/blog/2021-01-01-seum.md +7 −7
@@ -47,13 +47,13 @@ existing orange portals, light all yellow beacons, avoid things like fireballs
4747and blades, or use any satanic power orbs lying around. These special abilities
4848include:
4949
50- Gravity
51- Teleport
52- Rewind
53- Spawn platform
54- Roar (DLC)
55- Rocket (DLC)
56- Shadow world (DLC)
50- Gravity
51- Teleport
52- Rewind
53- Spawn platform
54- Roar (DLC)
55- Rocket (DLC)
56- Shadow world (DLC)
5757
5858For the main storyline, there are nine floors to beat. Each floor contains nine
5959regular levels, one boss level, and one bonus level; although you don't
content/blog/2021-01-04-fediverse.md +19 −19
@@ -34,13 +34,13 @@ users.
3434This strategy is great for making sure control of the social web isn't
3535controlled by a single organization, but it also has some downsides. If I create
3636a Mastodon instance and get a ton of users to sign up, I can shut the server
37down at any time. That means you're at risk of losing the content you've
38created unless you back it up, or the server backs it up for you. Also,
39depending on the software used (e.g. Mastodon, Pixelfed, etc.), censorship may
40still be an issue if the server admins decide they want to censor their users.
41Now, censorship isn't always a bad thing and can even benefit the community as
42a whole, but you'll want to determine which servers align with your idea of
43proper censorship.
37down at any time. That means you're at risk of losing the content you've created
38unless you back it up, or the server backs it up for you. Also, depending on the
39software used (e.g. Mastodon, Pixelfed, etc.), censorship may still be an issue
40if the server admins decide they want to censor their users. Now, censorship
41isn't always a bad thing and can even benefit the community as a whole, but
42you'll want to determine which servers align with your idea of proper
43censorship.
4444
4545However, these are risks that we take when we sign up for any online platform.
4646Whatever your reason is for trying out federated social networks, they are part
@@ -58,39 +58,39 @@ might just find the perfect home.
5858
5959## Reddit
6060
61- [Lemmy](https://lemmy.ml/instances)
61- [Lemmy](https://lemmy.ml/instances)
6262
6363## Twitter/Facebook/Tumblr
6464
65- [Mastodon](https://joinmastodon.org)
66- [Diaspora](https://diasporafoundation.org)
67- [Friendica](https://friendi.ca)
68- [GNU Social](https://gnusocial.network)
69- [Pleroma](https://pleroma.social)
65- [Mastodon](https://joinmastodon.org)
66- [Diaspora](https://diasporafoundation.org)
67- [Friendica](https://friendi.ca)
68- [GNU Social](https://gnusocial.network)
69- [Pleroma](https://pleroma.social)
7070
7171## Instagram
7272
73- [Pixelfed](https://pixelfed.org)
73- [Pixelfed](https://pixelfed.org)
7474
7575## Slack/Discord
7676
77- [Matrix](https://element.io)
77- [Matrix](https://element.io)
7878
7979## Youtube/Vimeo
8080
81- [Peertube](https://joinpeertube.org)
81- [Peertube](https://joinpeertube.org)
8282
8383## Spotify/Soundcloud
8484
85- [Funkwhale](https://funkwhale.audio)
85- [Funkwhale](https://funkwhale.audio)
8686
8787## Podcasting
8888
89- [Pubcast](https://pubcast.pub)
89- [Pubcast](https://pubcast.pub)
9090
9191## Medium/Blogger
9292
93- [WriteFreely](https://writefreely.org)
93- [WriteFreely](https://writefreely.org)
9494
9595# Get Started
9696
content/blog/2021-01-07-ufw.md +14 −14
@@ -9,8 +9,8 @@ draft = false
99
1010Uncomplicated Firewall, also known as ufw, is a convenient and beginner-friendly
1111way to enforce OS-level firewall rules. For those who are hosting servers or any
12device that is accessible to the world (i.e., by public IP or domain name),
13it's critical that a firewall is properly implemented and active.
12device that is accessible to the world (i.e., by public IP or domain name), it's
13critical that a firewall is properly implemented and active.
1414
1515Ufw is available by default in all Ubuntu installations after 8.04 LTS. For
1616other distributions, you can look to install ufw or check if there are
@@ -57,9 +57,9 @@ sudo ufw default allow outgoing
5757
5858# Adding Port Rules
5959
60Now that we've disabled all incoming traffic by default, we need to open up
61some ports (or else no traffic would be able to come in). If you need to be able
62to `ssh` into the machine, you'll need to open up port 22.
60Now that we've disabled all incoming traffic by default, we need to open up some
61ports (or else no traffic would be able to come in). If you need to be able to
62`ssh` into the machine, you'll need to open up port 22.
6363
6464```sh
6565sudo ufw allow 22
@@ -102,7 +102,7 @@ Now that the firewall is enabled, let's check and see what the rules look like.
102102sudo ufw status numbered
103103```
104104
105``` txt
105```txt
106106Status: active
107107
108108 To Action From
@@ -114,8 +114,8 @@ Status: active
114114# Deleting Rules
115115
116116If you need to delete a rule, you need to know the number associated with that
117rule. Let's delete the first rule in the table above. You'll be asked to
118confirm the deletion as part of this process.
117rule. Let's delete the first rule in the table above. You'll be asked to confirm
118the deletion as part of this process.
119119
120120```sh
121121sudo ufw delete 1
@@ -134,7 +134,7 @@ sudo ufw app list
134134
135135The results should look something like this:
136136
137``` txt
137```txt
138138Available applications:
139139 OpenSSH
140140 Samba
@@ -152,7 +152,7 @@ sudo ufw app info plexmediaserver-dlna
152152
153153You'll get a blurb of info back like this:
154154
155``` txt
155```txt
156156Profile: plexmediaserver-dlna
157157Title: Plex Media Server (DLNA)
158158Description: The Plex Media Server (additional DLNA capability only)
@@ -182,7 +182,7 @@ make sure the content is properly formatted.
182182For example, here are the contents my `plexmediaserver` file, which creates
183183three distinct app rules for ufw:
184184
185``` config
185```config
186186[plexmediaserver]
187187title=Plex Media Server (Standard)
188188description=The Plex Media Server
@@ -199,14 +199,14 @@ description=The Plex Media Server (with additional DLNA capability)
199199ports=32400/tcp|3005/tcp|5353/udp|8324/tcp|32410:32414/udp|1900/udp|32469/tcp
200200```
201201
202So, if I wanted to create a custom app rule called "mycustomrule," I'd create
203a file and add my content like this:
202So, if I wanted to create a custom app rule called "mycustomrule," I'd create a
203file and add my content like this:
204204
205205```sh
206206sudo nano /etc/ufw/applications.d/mycustomrule
207207```
208208
209``` config
209```config
210210[mycustomrule]
211211title=My Custom Rule
212212description=This is a temporary ufw app rule.
content/blog/2021-02-19-macos.md +4 −4
@@ -29,7 +29,7 @@ The desktop itself reminds me of GNOME more than anything else I've seen: even
2929Pantheon from [ElementaryOS](https://elementary.io/), which people commonly
3030refer to as the closest Linux distro to macOS. The desktop toolbar is great and
3131far surpasses the utility of the GNOME toolbar due to the fact that the
32extensions and icons *actually work*. I launch macOS and immediately see my
32extensions and icons _actually work_. I launch macOS and immediately see my
3333shortcuts for Tresorit, Bitwarden, and Mullvad pop up as the computer loads.
3434
3535Even further, the app dock is very useful and will be yet another familiarity
@@ -171,9 +171,9 @@ want](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes), save the file, and exit.
171171ZSH_THEME="af-magic"
172172```
173173
174After changing the `.zshrc` file, you'll need to close your terminal and
175re-open it to see the changes. Optionally, just open a new tab if you're using
176iTerm2, and you'll see the new shell config.
174After changing the `.zshrc` file, you'll need to close your terminal and re-open
175it to see the changes. Optionally, just open a new tab if you're using iTerm2,
176and you'll see the new shell config.
177177
178178# Oh-My-Zsh Plugins
179179
content/blog/2021-03-19-clone-github-repos.md +4 −4
@@ -20,8 +20,8 @@ nano clone_github_repos.sh
2020```
2121
2222Next, paste in the following information. Note that you can replace the word
23`users` in the first line with `orgs` and type an organization's name instead
24of a user's name.
23`users` in the first line with `orgs` and type an organization's name instead of
24a user's name.
2525
2626```sh
2727CNTX=users; NAME=YOUR-USERNAME; PAGE=1
@@ -45,8 +45,8 @@ Now you can run the script and should see the cloning process begin.
4545
4646# Cloning from Sourcehut
4747
48I haven't fully figured out how to directly incorporate Sourcehut's GraphQL
49API into a bash script yet, so this one will take two steps.
48I haven't fully figured out how to directly incorporate Sourcehut's GraphQL API
49into a bash script yet, so this one will take two steps.
5050
5151First, log-in to Sourcehut and go to their [GraphQL playground for
5252Git](https://git.sr.ht/graphql). Next, paste the following query into the left
content/blog/2021-03-28-gemini-capsule.md +18 −18
@@ -8,21 +8,21 @@ draft = false
88# What is Gemini?
99
1010[Gemini](https://gemini.circumlunar.space/) is an internet protocol introduced
11in June 2019 as an alternative to HTTP(S) or Gopher. In layman's terms, it's
12an alternative way to browse sites (called capsules) that requires a special
11in June 2019 as an alternative to HTTP(S) or Gopher. In layman's terms, it's an
12alternative way to browse sites (called capsules) that requires a special
1313browser. Since Gemini is not standardized as an internet standard, normal web
14browsers won't be able to load a Gemini capsule. Instead, you'll need to use
15[a Gemini-specific browser](https://gemini.%20circumlunar.space/clients.html).
14browsers won't be able to load a Gemini capsule. Instead, you'll need to use [a
15Gemini-specific browser](https://gemini.%20circumlunar.space/clients.html).
1616
1717The content found within a Gemini page is called
1818[Gemtext](https://gemini.circumlunar.space/docs/cheatsheet.gmi) and is
19*extremely* basic (on purpose). Gemini only processes the text, no media content
19_extremely_ basic (on purpose). Gemini only processes the text, no media content
2020like images. However, you're able to style 3 levels of headings, regular text,
2121links (which will display on their own line), quotes, and an unordered list.
2222
2323Here's a complete listing of valid Gemtext:
2424
25``` txt
25````txt
2626# Heading 1
2727## Heading 2
2828### Heading 3
@@ -39,7 +39,7 @@ My List:
3939** Item
4040
4141```Anything between three backticks will be rendered as code.```
42```
42````
4343
4444### Free Option
4545
@@ -87,8 +87,8 @@ tools, but mostly surrounds their hosted Git repository service. Simply put,
8787it's a minimal and more private alternative to services like GitHub.
8888
8989This walkthrough is more advanced and involves things like Git, SSH, the command
90line. If you don't think you know enough to do this, check out my walkthrough
91on creating a Gemini capsule for the Midnight Pub instead.
90line. If you don't think you know enough to do this, check out my walkthrough on
91creating a Gemini capsule for the Midnight Pub instead.
9292
9393The first thing you'll need to do is create an SSH key pair, if you don't
9494already have one on your system. Once created, grab the contents of `id_rsa.pub`
@@ -107,8 +107,8 @@ format exactly:
107107mkdir your-username.srht.site && cd your-username.srht.site
108108```
109109
110Now that we've created the repo, let's initialize Git and add the proper
111remote URL.
110Now that we've created the repo, let's initialize Git and add the proper remote
111URL.
112112
113113```sh
114114git init
@@ -121,13 +121,13 @@ git remote add origin git@git.sr.ht:~your-username/your-username.srht.site
121121Now that our repository is set up and configured, we will need to create at
122122least two files:
123123
124- `index.gmi`
125- `.build.yml`
124- `index.gmi`
125- `.build.yml`
126126
127127For your `.build.yml` file, use the following content and be sure to update the
128128`site` line with your username!
129129
130``` yaml
130```yaml
131131image: alpine/latest
132132oauth: pages.sr.ht/PAGES:RW
133133environment:
@@ -146,7 +146,7 @@ even just copy and paste the Gemtext cheatsheet.
146146If you want to serve both HTML and Gemini files from this repository, just add a
147147second command to the `upload` section:
148148
149``` yaml
149```yaml
150150- upload: |
151151 acurl -f https://pages.sr.ht/publish/$site -Fcontent=@site.tar.gz -Fprotocol=GEMINI
152152 acurl -f https://pages.sr.ht/publish/$site -Fcontent=@site.tar.gz
@@ -158,9 +158,9 @@ Lastly, commit your changes and push them to the remote repo.
158158git add .; git commit -m "initial commit"; git push --set-upstream origin HEAD
159159```
160160
161If you've successfully created the files with the proper format, you'll see
162the terminal print a message that lets you know where the automatic build is
163taking place. For example, here's what the terminal tells me:
161If you've successfully created the files with the proper format, you'll see the
162terminal print a message that lets you know where the automatic build is taking
163place. For example, here's what the terminal tells me:
164164
165165```sh
166166remote: Build started:
content/blog/2021-03-28-vaporwave-vs-outrun.md +2 −2
@@ -47,8 +47,8 @@ specific aspects that make Vaporwave unique:
4747
4848The time frame for references, logos, etc. focuses mostly on the 1990s in
4949Vaporwave. You'll see old school Pepsi logos, Microsoft 95 screens, tropical
50plants, classic marble sculptures, and many references from Japan's influence
51in the 90s.
50plants, classic marble sculptures, and many references from Japan's influence in
51the 90s.
5252
5353## Art
5454
content/blog/2021-03-30-vps-web-server.md +27 −28
@@ -85,9 +85,9 @@ increase the resources at any time.
8585# Configuring DNS Settings
8686
8787Okay, so now let's get into some actual work that has to be done to get content
88moved from a shared host to a VPS. At this point, I'm assuming you have a
89shared host with website content that you can still access, and you've
90purchased a new VPS and can SSH into that server.
88moved from a shared host to a VPS. At this point, I'm assuming you have a shared
89host with website content that you can still access, and you've purchased a new
90VPS and can SSH into that server.
9191
9292The first change is minor, but it should be done immediately in order to get
9393things moving: DNS settings. Go to wherever your DNS settings are handled. If
@@ -98,15 +98,15 @@ DNS over to your new VPS provider. For me, I route my DNS through
9898Once you know where your DNS settings are, go ahead and update the `A` records
9999to match the public IP address of your VPS. For example:
100100
101``` txt
101```txt
102102A example.com xxx.xxx.xxx.xxx
103103A subdomain xxx.xxx.xxx.xxx
104104CNAME www example.com.
105105```
106106
107107If you have any other records that require updates, such as MX or TXT records
108for a mail server, be sure to update those accordingly. Personally, I don't
109host my own mail server. I route all mail on my custom domains to
108for a mail server, be sure to update those accordingly. Personally, I don't host
109my own mail server. I route all mail on my custom domains to
110110[Migadu](https://www.migadu.com). Hosting your own email server can become
111111complex quickly and is not for beginners.
112112
@@ -132,8 +132,8 @@ set it up.
132132
133133First, let's update and upgrade our server.
134134
135**NOTE:** Since we have logged in to the server as `root` for now, we don't
136need to use the `sudo` modifier before our commands.
135**NOTE:** Since we have logged in to the server as `root` for now, we don't need
136to use the `sudo` modifier before our commands.
137137
138138```sh
139139apt update && apt upgrade -y
@@ -173,8 +173,8 @@ from the VPS):
173173ssh-copy-id testuser@xxx.xxx.xxx.xxx
174174```
175175
176If you've disabled password-based SSH, you'll need to manually copy your SSH
177key into the `~/.ssh/authorized_keys` file.
176If you've disabled password-based SSH, you'll need to manually copy your SSH key
177into the `~/.ssh/authorized_keys` file.
178178
179179# Install Software
180180
@@ -209,9 +209,9 @@ sudo mkdir example.com
209209```
210210
211211We have a folder for `example.com` now, so let's add an `index.html` file and
212put it within a specific `public_html` folder. You don't need this
213`public_html` if you don't want it, but it helps with organizing items related
214to `example.com` that you don't want to publish to the internet.
212put it within a specific `public_html` folder. You don't need this `public_html`
213if you don't want it, but it helps with organizing items related to
214`example.com` that you don't want to publish to the internet.
215215
216216```sh
217217cd example.com
@@ -222,23 +222,22 @@ sudo nano index.html
222222You can put anything you want in this `index.html` file. If you can't think of
223223anything, paste this in there:
224224
225``` html
225```html
226226<!DOCTYPE html>
227227<html lang="en">
228 <head>
229 <meta charset="utf-8" />
230 <meta name="viewport" content="width=device-width, initial-scale=1" />
231 <title>Hello, world!</title>
232 </head>
233 <body>
234 <h1>Hello, world!</h1>
235 </body>
228 <head>
229 <meta charset="utf-8" />
230 <meta name="viewport" content="width=device-width, initial-scale=1" />
231 <title>Hello, world!</title>
232 </head>
233 <body>
234 <h1>Hello, world!</h1>
235 </body>
236236</html>
237237```
238238
239If you want something to be served at `example.com/page01/file.txt`, you'll
240have to create the `page01` directory under the `example.com` directory. For
241example:
239If you want something to be served at `example.com/page01/file.txt`, you'll have
240to create the `page01` directory under the `example.com` directory. For example:
242241
243242```sh
244243cd /var/www/example.com/public_html
@@ -261,7 +260,7 @@ sudo nano example.com.conf
261260This configuration file will have a few default lines, but you'll need to edit
262261it to look similar to this (settings may change based on your personal needs):
263262
264``` config
263```config
265264<VirtualHost *:80>
266265 ServerAdmin your-email@email-provider.com
267266 ServerName example.com
@@ -290,8 +289,8 @@ sudo apache2ctl configtest
290289
291290Now, restart the web server entirely. After this, you should be able to browse
292291to `http://example.com` and see the HTML content you provided earlier. Note that
293SSL/TLS has not been enabled yet, so you won't be able to use the secure
294version yet (`https://example.com`).
292SSL/TLS has not been enabled yet, so you won't be able to use the secure version
293yet (`https://example.com`).
295294
296295```sh
297296sudo systemctl restart apache2
content/blog/2021-04-17-gemini-server.md +11 −12
@@ -76,9 +76,9 @@ sudo ./install.sh
7676# Configure the Gemini Service
7777
7878We have a little more to do, but since this script tries to immediately run the
79service, it will likely fail with an exit code. Let's add our finishing
80touches. Edit the following file and replace the hostname with your desired URL.
81You can also change the directory where content will be served.
79service, it will likely fail with an exit code. Let's add our finishing touches.
80Edit the following file and replace the hostname with your desired URL. You can
81also change the directory where content will be served.
8282
8383```sh
8484sudo nano /etc/systemd/system/gemini.service
@@ -130,19 +130,18 @@ sudo ufw reload
130130
131131# Creating Content
132132
133Let's create the Gemini capsule. Note that wherever you set the
134WorkingDirectory variable to earlier, Agate will expect you to put your Gemini
135capsule contents in a sub-folder called "content." So, I place my files in
136"/var/gmi/content." I'm going to create that folder now and put a file in
137there.
133Let's create the Gemini capsule. Note that wherever you set the WorkingDirectory
134variable to earlier, Agate will expect you to put your Gemini capsule contents
135in a sub-folder called "content." So, I place my files in "/var/gmi/content."
136I'm going to create that folder now and put a file in there.
138137
139138```sh
140139sudo mkdir /var/gemini/content
141140sudo nano /var/gemini/content/index.gmi
142141```
143142
144You can put whatever you want in the "index.gmi" file, just make sure it's
145valid Gemtext.
143You can put whatever you want in the "index.gmi" file, just make sure it's valid
144Gemtext.
146145
147146# The Results
148147
@@ -153,9 +152,9 @@ Here are some screenshots of the Gemini page I just created in the
153152![GUI Gemini
154153browser](https://img.cleberg.net/blog/20210417-hosting-a-gemini-server/lagrange.png)
155154
156*Lagrange*
155_Lagrange_
157156
158157![CLI Gemini
159158browser](https://img.cleberg.net/blog/20210417-hosting-a-gemini-server/amfora.png)
160159
161*Amfora*
160_Amfora_
content/blog/2021-04-23-php-comment-system.md +60 −60
@@ -16,15 +16,15 @@ that should be standard.
1616
1717Of course, there are some really terrible options:
1818
19- Facebook Comments
20- Discourse
19- Facebook Comments
20- Discourse
2121
2222There are some options that are better but still use too many scripts, frames,
2323or social integrations on your web page that could impact some users:
2424
25- Disqus
26- Isso
27- Remark42
25- Disqus
26- Isso
27- Remark42
2828
2929Lastly, I looked into a few unique ways of generating blog comments, such as
3030using Twitter threads or GitHub issues to automatically post issues. However,
@@ -52,22 +52,22 @@ database for any other part of my websites.
5252I blog in plain Markdown files, commit all articles to Git, and ensure that
5353future readers will be able to see the source data long after I'm gone, or the
5454website has gone offline. However, I still haven't committed any images served
55on my blog to Git, as I'm not entirely sold on Git LFS yet - for now, images
56can be found at [img.cleberg.net](https://img.cleberg.net).
55on my blog to Git, as I'm not entirely sold on Git LFS yet - for now, images can
56be found at [img.cleberg.net](https://img.cleberg.net).
5757
5858Saving my comments back to the Git repository ensures that another aspect of my
5959site will degrade gracefully.
6060
6161# Create a Comment Form
6262
63Okay, let's get started. The first step is to create an HTML form that users
64can see and utilize to submit comments. This is fairly easy and can be changed
63Okay, let's get started. The first step is to create an HTML form that users can
64see and utilize to submit comments. This is fairly easy and can be changed
6565depending on your personal preferences.
6666
6767Take a look at the code block below for the form I currently use. Note that
68`<current-url>` is replaced automatically in PHP with the current post's URL,
69so that my PHP script used later will know which blog post the comment is
70related to.
68`<current-url>` is replaced automatically in PHP with the current post's URL, so
69that my PHP script used later will know which blog post the comment is related
70to.
7171
7272The form contains the following structure:
7373
@@ -81,45 +81,45 @@ The form contains the following structure:
8181 Markdown is allowed.
82825. `<button>` - A button to submit the form.
8383
84``` html
84```html
8585<form action="/comment.php" method="POST">
86 <h3>Leave a Comment</h3>
87 <section hidden>
88 <label class="form-label" for="postURL">Post URL</label>
89 <input
90 class="form-control"
91 id="postURL"
92 name="postURL"
93 type="text"
94 value="<current-url>"
95 />
96 </section>
97 <section>
98 <label class="form-label" for="userName">Display Name</label>
99 <input
100 class="form-control"
101 id="userName"
102 name="userName"
103 placeholder="John Doe"
104 type="text"
105 />
106 </section>
107 <section>
108 <label class="form-label" for="userContent">Your Comment</label>
109 <textarea
110 class="form-control"
111 id="userContent"
112 name="userContent"
113 rows="3"
114 placeholder="# Feel free to use Markdown"
115 aria-describedby="commentHelp"
116 required
117 ></textarea>
118 <div id="commentHelp" class="form-text">
119 Comments are saved as Markdown and cannot be edited or deleted.
120 </div>
121 </section>
122 <button type="submit">Submit</button>
86 <h3>Leave a Comment</h3>
87 <section hidden>
88 <label class="form-label" for="postURL">Post URL</label>
89 <input
90 class="form-control"
91 id="postURL"
92 name="postURL"
93 type="text"
94 value="<current-url>"
95 />
96 </section>
97 <section>
98 <label class="form-label" for="userName">Display Name</label>
99 <input
100 class="form-control"
101 id="userName"
102 name="userName"
103 placeholder="John Doe"
104 type="text"
105 />
106 </section>
107 <section>
108 <label class="form-label" for="userContent">Your Comment</label>
109 <textarea
110 class="form-control"
111 id="userContent"
112 name="userContent"
113 rows="3"
114 placeholder="# Feel free to use Markdown"
115 aria-describedby="commentHelp"
116 required
117 ></textarea>
118 <div id="commentHelp" class="form-text">
119 Comments are saved as Markdown and cannot be edited or deleted.
120 </div>
121 </section>
122 <button type="submit">Submit</button>
123123</form>
124124```
125125
@@ -144,7 +144,7 @@ the following tasks in this script:
1441448. Finally, send the user back to the `#comments` section of the blog post they
145145 just read.
146146
147``` php
147```php
148148// Get the content sent from the comment form
149149$comment = htmlentities($_POST['userContent']);
150150$post_url = $_POST['postURL'];
@@ -202,7 +202,7 @@ This piece of code should **really** be inside a function (or at least in an
202202organized PHP workflow). Don't just copy-and-paste and expect it to work. You
203203need to at least supply a `$query` variable depending on the page visited.
204204
205``` php
205```php
206206$query = 'your-blog-post.html';
207207
208208// Load saved comments
@@ -251,11 +251,11 @@ make sure it is printed when someone visits `https://example.com/comments/`.
251251This comment system is by no means a fully-developed system. I have noted a few
252252possible enhancements here that I may implement in the future:
253253
254- Create a secure moderator page with user authentication at
255 `https://blog.example.com/mod/`. This page could have the option to edit or
256 delete any comment found in `comments.json`.
257- Create a temporary file, such as `pending_comments.json`, that will store
258 newly-submitted comments and won't display on blog posts until approved by a
259 moderator.
260- Create a `/modlog/` page with a chronological log, showing which moderator
261 approved which comments and why certain comments were rejected.
254- Create a secure moderator page with user authentication at
255 `https://blog.example.com/mod/`. This page could have the option to edit or
256 delete any comment found in `comments.json`.
257- Create a temporary file, such as `pending_comments.json`, that will store
258 newly-submitted comments and won't display on blog posts until approved by a
259 moderator.
260- Create a `/modlog/` page with a chronological log, showing which moderator
261 approved which comments and why certain comments were rejected.
content/blog/2021-04-28-photography.md +4 −4
@@ -48,10 +48,10 @@ perfect for me.
4848For lenses, I decided to buy two lenses that could carry me through most
4949situations:
5050
51- [Vario-Tessar T** FE 24-70 mm F4 ZA
52 OSS](https://electronics.sony.com/imaging/lenses/full-frame-e-mount/p/sel2470z)
53- [Tamron 70-300mm f4.5-6.3 Di III
54 RXD](https://www.tamron-usa.com/product/lenses/a047.html)
51- [Vario-Tessar T\*\* FE 24-70 mm F4 ZA
52 OSS](https://electronics.sony.com/imaging/lenses/full-frame-e-mount/p/sel2470z)
53- [Tamron 70-300mm f4.5-6.3 Di III
54 RXD](https://www.tamron-usa.com/product/lenses/a047.html)
5555
5656In addition, I grabbed a couple [HGX Prime
575767mm](https://www.promaster.com/Product/6725) protection filters for the lenses.
content/blog/2021-05-30-changing-git-authors.md +3 −3
@@ -23,9 +23,9 @@ nano change_git_authors.sh
2323The following information can be pasted directly into your bash script. The only
2424changes you need to make are to the following variables:
2525
26- `OLD_EMAIL`
27- `CORRECT_NAME`
28- `CORRECT_EMAIL`
26- `OLD_EMAIL`
27- `CORRECT_NAME`
28- `CORRECT_EMAIL`
2929
3030```sh
3131#!/bin/sh
content/blog/2021-07-15-delete-gitlab-repos.md +3 −3
@@ -47,7 +47,7 @@ nano main.py
4747
4848Enter the following code into your `main.py` script.
4949
50``` python
50```python
5151import request
5252import json
5353
@@ -107,8 +107,8 @@ Now that you have the proper information, replace `{user-id}` with your GitLab
107107username and `{auth-token}` with the authorization token you created earlier.
108108
109109Finally, simply run the script and watch the output. You can also use PyCharm
110Community Edition to edit and run the Python script if you don't want to work
111in a terminal.
110Community Edition to edit and run the Python script if you don't want to work in
111a terminal.
112112
113113```sh
114114python3 main.py
content/blog/2021-08-25-audit-sampling.md +20 −21
@@ -46,7 +46,7 @@ Now that you know what you're using, you can always check out the code behind
4646`pandas.DataFrame.sample`. This function does a lot of work, but we really only
4747care about the following snippets of code:
4848
49``` python
49```python
5050# Process random_state argument
5151rs = com.random_state(random_state)
5252
@@ -64,9 +64,9 @@ The block of code above shows you that if you assign a `random_state` argument
6464when you run the function, that will be used as a seed number in the random
6565generation and will allow you to reproduce a sample, given that nothing else
6666changes. This is critical to the posterity of audit work. After all, how can you
67say your audit process is adequately documented if the next person can't run
68the code and get the same sample? The final piece here on randomness is to look
69at the [choice](https://docs.%20python.org/3/library/random.html#random.choice)
67say your audit process is adequately documented if the next person can't run the
68code and get the same sample? The final piece here on randomness is to look at
69the [choice](https://docs.%20python.org/3/library/random.html#random.choice)
7070function used above. This is the crux of the generation and can also be examined
7171for more detailed analysis on its reliability. As far as auditing goes, we will
7272trust that these functions are mathematically random.
@@ -90,23 +90,22 @@ that will instruct auditors which sample sizes to choose. This allows for
9090uniform testing and reduces overall workload. See the table below for a common
9191implementation of sample sizes:
9292
93 Control Frequency Sample Size - High Risk Sample Size - Low Risk
94 ------------------- ------------------------- ------------------------
95 More Than Daily 40 25 Daily 40
96 25 Weekly 12 5 Monthly 5
97 3 Quarterly 2 2 Semi-Annually 1
98 1 Annually 1 1 Ad-hoc 1
99 1
93Control Frequency Sample Size - High Risk Sample Size - Low Risk
94
95---
96
97More Than Daily 40 25 Daily 40 25 Weekly 12 5 Monthly 5 3 Quarterly 2 2
98Semi-Annually 1 1 Annually 1 1 Ad-hoc 1 1
10099
101100### Sampling with Python & Pandas
102101
103102In this section, I am going to cover a few basic audit situations that require
104103sampling. While some situations may require more effort, the syntax,
105104organization, and intellect used remain largely the same. If you've never used
106Python before, note that lines starting with a '`#`' symbol are called
107comments, and they will be skipped by Python. I highly recommend taking a quick
108tutorial online to understand the basics of Python if any of the code below is
109confusing to you.
105Python before, note that lines starting with a '`#`' symbol are called comments,
106and they will be skipped by Python. I highly recommend taking a quick tutorial
107online to understand the basics of Python if any of the code below is confusing
108to you.
110109
111110## Simple Random Sample
112111
@@ -114,7 +113,7 @@ First, let's look at a simple, random sample. The code block below will import
114113the `pandas` module, load a data file, sample the data, and export the sample to
115114a file.
116115
117``` python
116```python
118117# Import the Pandas module
119118import pandas
120119
@@ -139,7 +138,7 @@ sample.to_excel(file_output)
139138Now that we've created a simple sample, let's create a sample from multiple
140139files.
141140
142``` python
141```python
143142# Import the Pandas module
144143import pandas
145144
@@ -171,10 +170,10 @@ sample.to_excel(file_output)
171170## Stratified Random Sample
172171
173172Well, what if you need to sample distinct parts of a single file? For example,
174let's write some code to separate our data by "Region" and sample those
175regions independently.
173let's write some code to separate our data by "Region" and sample those regions
174independently.
176175
177``` python
176```python
178177# Import the Pandas module
179178import pandas
180179
@@ -209,7 +208,7 @@ period. This code will generate samples for each month in the data and combine
209208them all together at the end. Obviously, this code can be modified to stratify
210209by something other than months, if needed.
211210
212``` python
211```python
213212# Import the Pandas module
214213import pandas
215214
content/blog/2021-10-09-apache-redirect.md +4 −4
@@ -24,10 +24,10 @@ To solve this problem, I really needed to solve two pieces:
2424 `/blog/some-post/`.
25252. Ensure that no other `.html` files are redirected, such as `index.html`.
2626
27After *a lot* of tweaking and testing, I believe I have finally found the
27After _a lot_ of tweaking and testing, I believe I have finally found the
2828solution. The solution is shown below.
2929
30``` conf
30```conf
3131RewriteEngine On
3232RewriteCond %{REQUEST_URI} !\index.html$ [NC]
3333RewriteRule ^(.*).html$ https://example.com/$1 [R=301,L]
@@ -41,5 +41,5 @@ following:
41413. Find any `.html` files within the website directory and redirect it to
4242 exclude the file extension.
43434. The final piece is adding the trailing slash (`/`) at the end of the URL -
44 you'll notice that I don't have an Apache rule for that since Apache
45 handles that automatically.
44 you'll notice that I don't have an Apache rule for that since Apache handles
45 that automatically.
content/blog/2021-12-04-cisa.md +14 −15
@@ -25,7 +25,7 @@ hired, getting a raise/bonus, or earning respect in the field.
2525However, to be honest, I am a skeptic of most certifications. I understand the
2626value they hold in terms of how much you need to commit to studying or learning
2727on the job, as well as the market value for certifications such as the CISA. But
28I also have known some very ~~incompetent~~ *less than stellar* auditors who
28I also have known some very ~~incompetent~~ _less than stellar_ auditors who
2929have CPAs, CISAs, CIAs, etc.
3030
3131The same goes for most industries: if a person is good at studying, they can
@@ -49,7 +49,7 @@ sections](https://img.cleberg.net/blog/20211204-i-passed-the-cisa/cisa-exam-sect
4949Since the exam contains 150 questions, here's how those sections break down:
5050
5151| Exam Section | Percentage of Exam | Questions |
52|-----------------|--------------------|-----------|
52| --------------- | ------------------ | --------- |
5353| 1 | 21% | 32 |
5454| 2 | 17% | 26 |
5555| 3 | 12% | 18 |
@@ -68,19 +68,18 @@ Let me approach this from a few different viewpoints.
6868
6969## Study Materials
7070
71Let's start by discussing the study materials I purchased. I'll be referring
72to #1 as the CRM and #2 as the QAE.
71Let's start by discussing the study materials I purchased. I'll be referring to
72#1 as the CRM and #2 as the QAE.
7373
74741. [CISA Review Manual, 27th Edition |
75Print](https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCbEAK)
75 Print](https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCbEAK)
76762. [CISA Review Questions, Answers & Explanations Manual, 12th Edition |
77Print](https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCcEAK)
77 Print](https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCcEAK)
7878
7979The CRM is an excellent source of information and could honestly be used as a
8080reference for most IS auditors as a learning reference during their daily audit
81responsibilities. However, it is **full** of information and can be
82overloading if you're not good at filtering out useless information while
83studying.
81responsibilities. However, it is **full** of information and can be overloading
82if you're not good at filtering out useless information while studying.
8483
8584The QAE is the real star of the show here. This book contains 1000 questions,
8685separated by exam section, and a practice exam. My only complaint about the QAE
@@ -117,7 +116,7 @@ from the QAE manual and scored 70% (105/150).
117116Here's a breakdown of my initial practice exam:
118117
119118| Exam Section | Incorrect | Correct | Grand Total | Percent |
120|-----------------|-----------|---------|-------------|---------|
119| --------------- | --------- | ------- | ----------- | ------- |
121120| 1 | 8 | 25 | 33 | 76% |
122121| 2 | 5 | 20 | 25 | 80% |
123122| 3 | 6 | 12 | 18 | 67% |
@@ -136,11 +135,11 @@ total.
136135While some practice sessions were worse and some were better, the final results
137136were similar to my practice exam results. As you can see below, my averages were
138137slightly worse than my practice exam. However, I got in over 700 questions of
139practice and, most importantly, *I read through the explanations every time I
140answered incorrectly and learned from my mistakes*.
138practice and, most importantly, _I read through the explanations every time I
139answered incorrectly and learned from my mistakes_.
141140
142141| Exam Section | Incorrect | Correct | Grand Total | Percent |
143|-----------------|-----------|---------|-------------|---------|
142| --------------- | --------- | ------- | ----------- | ------- |
144143| 1 | 33 | 108 | 141 | 77% |
145144| 2 | 33 | 109 | 142 | 77% |
146145| 3 | 55 | 89 | 144 | 62% |
@@ -157,7 +156,7 @@ Now, how do the practice scores reflect my actual results? After all, it's hard
157156to tell how good a practice regimen is unless you see how it turns out.
158157
159158| Exam Section | Section Name | Score |
160|--------------|------------------------------------------------------------------|-------|
159| ------------ | ---------------------------------------------------------------- | ----- |
161160| 1 | Information Systems Auditing Process | 678 |
162161| 2 | Governance and Management of IT | 590 |
163162| 3 | Information Systems Acquisition, Development, and Implementation | 721 |
@@ -166,7 +165,7 @@ to tell how good a practice regimen is unless you see how it turns out.
166165
167166Now, in order to pass the CISA, you need at least 450 on a sliding scale of
168167200-800. Personally, I really have no clue what an average CISA score is. After
169a *very* brief look online, I can see that the high end is usually in the low
168a _very_ brief look online, I can see that the high end is usually in the low
170169700s. In addition, only about 50-60% of people pass the exam.
171170
172171Given this information, I feel great about my scores. 616 may not be phenomenal,
content/blog/2022-02-10-leaving-the-office.md +5 −5
@@ -61,9 +61,9 @@ desk feature (I'm over 6 feet tall, so probably not an issue for most people).
6161
6262I loved this environment, it allowed me to focus on my work with minimal
6363distractions, but also allowed easy access, so I could spin around in my chair
64and chat with my friends without leaving my chair. This is the closest I've
65been to a home office environment (which is my personal favorite, as I'll get
66to later in this post).
64and chat with my friends without leaving my chair. This is the closest I've been
65to a home office environment (which is my personal favorite, as I'll get to
66later in this post).
6767
6868## Semi-Open Floor Concept
6969
@@ -108,8 +108,8 @@ pairs of desk rows are repeated through the office.
108108This means that when I go, I need to rent a random desk or try to remember the
109109unique ID numbers on desks I like. Once I rent it, I have to make sure no one
110110sat down in that desk without renting it. Then, I can sit down and work, but
111will probably need to adjust the monitors so that I'm not staring in the face
112of the person across from me all day. Finally, I need to wear headphones as this
111will probably need to adjust the monitors so that I'm not staring in the face of
112the person across from me all day. Finally, I need to wear headphones as this
113113environment does nothing to provide you with peace or quiet.
114114
115115Luckily, you can rent offices with doors that offer quiet and privacy, which can
content/blog/2022-02-10-njalla-dns-api.md +12 −10
@@ -46,7 +46,7 @@ For this demo, we are using the `list-records` and `edit-record` requests.
4646The `list-records` request requires the following payload to be sent when
4747calling the API:
4848
49``` txt
49```txt
5050params: {
5151 domain: string
5252}
@@ -55,7 +55,7 @@ params: {
5555The `edit-record` request requires the following payload to be sent when calling
5656the API:
5757
58``` txt
58```txt
5959params: {
6060 domain: string
6161 id: int
@@ -84,19 +84,21 @@ Next, create a Python script file:
8484nano ~/ddns/ddns.py
8585```
8686
87The following code snippet is quite long, so I won't go into depth on each
88part. However, I suggest you read through the entire script before running it;
89it is quite simple and contains comments to help explain each code block.
87The following code snippet is quite long, so I won't go into depth on each part.
88However, I suggest you read through the entire script before running it; it is
89quite simple and contains comments to help explain each code block.
9090
9191:warning: **Note**: You will need to update the following variables for this to
9292work:
9393
94- `token`: This is the Njalla API token you created earlier.
95- `user_domain`: This is the top-level domain you want to modify.
96- `include_subdomains`: Set this to `True` if you also want to modify subdomains found under the TLD.
97- `subdomains`: If `include_subdomains` = `True`, you can include your list of subdomains to be modified here.
94- `token`: This is the Njalla API token you created earlier.
95- `user_domain`: This is the top-level domain you want to modify.
96- `include_subdomains`: Set this to `True` if you also want to modify
97 subdomains found under the TLD.
98- `subdomains`: If `include_subdomains` = `True`, you can include your list of
99 subdomains to be modified here.
98100
99``` python
101```python
100102#!/usr/bin/python
101103# -*- coding: utf-8 -*-
102104# Import Python modules
content/blog/2022-02-16-debian-and-nginx.md +3 −3
@@ -10,9 +10,9 @@ draft = false
1010![Debian +
1111neofetch](https://img.cleberg.net/blog/20220216-migrating-to-debian-and-nginx/neofetch.png)
1212
13I've used various Linux distributions throughout the years, but I've never
14used anything except Ubuntu for my servers. Why? I really have no idea, mostly
15just comfort around the commands and software availability.
13I've used various Linux distributions throughout the years, but I've never used
14anything except Ubuntu for my servers. Why? I really have no idea, mostly just
15comfort around the commands and software availability.
1616
1717However, I have always wanted to try Debian as a server OS after testing it out
1818in a VM a few years ago (side-note: I'd love to try Alpine too, but I always
content/blog/2022-02-17-exiftool.md +10 −10
@@ -16,16 +16,16 @@ There are various components of image metadata that you may want to delete
1616before releasing a photo to the public. Here's an incomplete list of things I
1717could easily see just by inspecting a photo on my laptop:
1818
19- Location (Latitude & Longitude)
20- Dimensions
21- Device Make & Model
22- Color Space
23- Color Profile
24- Focal Length
25- Alpha Channel
26- Red Eye
27- Metering Mode
28- F Number
19- Location (Latitude & Longitude)
20- Dimensions
21- Device Make & Model
22- Color Space
23- Color Profile
24- Focal Length
25- Alpha Channel
26- Red Eye
27- Metering Mode
28- F Number
2929
3030Regardless of your reasoning, I'm going to explain how I used the `exiftool`
3131package in Linux to automatically strip metadata from all images in a directory
content/blog/2022-02-20-nginx-caching.md +5 −5
@@ -17,7 +17,7 @@ to cache and determining the expiration length. To include more file types,
1717simply use the bar separator (`|`) and type the new file extension you want to
1818include.
1919
20``` config
20```config
2121server {
2222 ...
2323
@@ -35,9 +35,9 @@ changes (i.e., I'm never content with my website), I need to know that my
3535readers are seeing the new content without waiting too long.
3636
3737So, I went ahead and set the expiration date at `30d`, which is short enough to
38refresh for readers but long enough that clients/browsers won't be
39re-requesting the static files too often, hopefully resulting in faster loading
40times, as images should be the only thing slowing down my site.
38refresh for readers but long enough that clients/browsers won't be re-requesting
39the static files too often, hopefully resulting in faster loading times, as
40images should be the only thing slowing down my site.
4141
4242# Testing Results
4343
@@ -48,7 +48,7 @@ recent image from my blog.
4848
4949In the image below, you can see that the `Cache-Control` header is now present
5050and set to 2592000, which is 30 days represented in seconds (30 days \_ 24
51hours/day \_ 60 minutes/hour ** 60 seconds/minute = 2,592,000 seconds).
51hours/day \_ 60 minutes/hour \*\* 60 seconds/minute = 2,592,000 seconds).
5252
5353The `Expires` field is now showing 22 March 2022, which is 30 days from the day
5454of this post, 20 February 2022.
content/blog/2022-03-02-reliable-notes.md +2 −2
@@ -96,8 +96,8 @@ Here's an example of how my Markdown notes look when opened in plain-text mode:
9696![Obsidian Markdown Source
9797Mode](https://img.cleberg.net/blog/20220302-easy-reliable-note-taking/obsidian_source_mode.png)
9898
99Here's the "live preview" version, where the Markdown is rendered into its
100HTML format:
99Here's the "live preview" version, where the Markdown is rendered into its HTML
100format:
101101
102102![Obsidian Markdown Live
103103Preview](https://img.cleberg.net/blog/20220302-easy-reliable-note-taking/obsidian_live_preview.png)
content/blog/2022-03-03-financial-database.md +24 −26
@@ -62,7 +62,7 @@ The Accounts table contains summary information about an account, such as a car
6262loan or a credit card. By viewing this table, you can find high-level data, such
6363as interest rate, credit line, or owner.
6464
65``` sql
65```sql
6666CREATE TABLE "Accounts" (
6767 "AccountID" INTEGER NOT NULL UNIQUE,
6868 "AccountType" TEXT,
@@ -83,7 +83,7 @@ meaning you can join the tables to find a monthly statement for any of the
8383accounts listed in the Accounts table. Each statement has an account ID,
8484statement date, and total balance.
8585
86``` sql
86```sql
8787CREATE TABLE "Statements" (
8888 "StatementID" INTEGER NOT NULL UNIQUE,
8989 "AccountID" INTEGER,
@@ -101,7 +101,7 @@ tables. This table contains all information you would find on a pay statement
101101from an employer. As you change employers or obtain new perks/benefits, just add
102102new columns to adapt to the new data.
103103
104``` sql
104```sql
105105CREATE TABLE "Payroll" (
106106 "PaycheckID" INTEGER NOT NULL UNIQUE,
107107 "PayDate" TEXT,
@@ -141,13 +141,13 @@ was to create a process to report and visualize on various aspects of the data.
141141In order to explore and create the reports I'm interested in, I utilized a
142142two-part process involving Jupyter Notebooks and Python scripts.
143143
144### Step 1: Jupyter Notebooks
144### Step 1: Jupyter Notebooks
145145
146146When I need to explore data, try different things, and re-run my code
147cell-by-cell, I use Jupyter Notebooks. For example, I explored the
148`Accounts` table until I found the following useful information:
147cell-by-cell, I use Jupyter Notebooks. For example, I explored the `Accounts`
148table until I found the following useful information:
149149
150``` python
150```python
151151import sqlite3
152152import pandas as pd
153153import matplotlib
@@ -169,12 +169,12 @@ matplotlib.rcParams['legend.labelcolor'] = 'black'
169169df.groupby(['AccountType']).sum().plot.pie(title='Credit Line by Account Type', y='CreditLine', figsize=(5,5), autopct='%1.1f%%')
170170```
171171
172### Step 2: Python Scripts
172### Step 2: Python Scripts
173173
174Once I explored enough through the notebooks and had a list of reports I
175wanted, I moved on to create a Python project with the following structure:
174Once I explored enough through the notebooks and had a list of reports I wanted,
175I moved on to create a Python project with the following structure:
176176
177``` txt
177```txt
178178finance/
179179├── notebooks/
180180│ │ ├── account_summary.ipynb
@@ -199,16 +199,15 @@ This structure allows me to:
199199 installation if I move to a new machine.
2002002. Activate a virtual environment in `venv/` so I don't need to maintain a
201201 system-wide Python environment just for this project.
2023. Keep my `notebooks/` folder to continuously explore the data as I see
203 fit.
2023. Keep my `notebooks/` folder to continuously explore the data as I see fit.
2042034. Maintain a local copy of the database in `src/` for easy access.
2052045. Export reports, images, HTML files, etc. to `public/`.
206205
207Now, onto the differences between the code in a Jupyter Notebook and the
208actual Python files. To create the report in the Notebook snippet above, I
209created the following function inside `process.py`:
206Now, onto the differences between the code in a Jupyter Notebook and the actual
207Python files. To create the report in the Notebook snippet above, I created the
208following function inside `process.py`:
210209
211``` python
210```python
212211# Create summary pie chart
213212def summary_data(accounts: pandas.DataFrame) -> None:
214213 accounts_01 = accounts[accounts["Owner"] == "Person01"]
@@ -244,13 +243,12 @@ Chart](https://img.cleberg.net/blog/20220303-maintaining-a-personal-financial-da
244243
245244Other charts generated by this project include:
246245
247- Charts of account balances over time.
248- Line chart of effective tax rate (taxes divided by taxable income).
249- Salary projections and error limits using past income and inflation
250 rates.
251- Multi-line chart of gross income, taxable income, and net income.
246- Charts of account balances over time.
247- Line chart of effective tax rate (taxes divided by taxable income).
248- Salary projections and error limits using past income and inflation rates.
249- Multi-line chart of gross income, taxable income, and net income.
252250
253The best thing about this project? I can improve it at any given time,
254shaping it into whatever helps me the most for that time. I imagine that I
255will be introducing an asset tracking table soon to track the depreciating
256value of cars, houses, etc. Who knows what's next?
251The best thing about this project? I can improve it at any given time, shaping
252it into whatever helps me the most for that time. I imagine that I will be
253introducing an asset tracking table soon to track the depreciating value of
254cars, houses, etc. Who knows what's next?
content/blog/2022-03-08-plex-migration.md +11 −11
@@ -52,9 +52,9 @@ with the device - it's a good idea to take a photo of this screen, so you can
5252enter these commands on the next screen (along with adding support for Nvidia).
5353
5454Finally, type `Ctrl + C` to enter the command line. From this command line,
55enter the commands found on the `e` screen. *Remember to add `nomodeset` to the
55enter the commands found on the `e` screen. _Remember to add `nomodeset` to the
5656`linux ...` line so that your Nvidia device will display the installation
57screens properly!*
57screens properly!_
5858
5959Here's an example of the commands I pulled from the `e` screen and entered on
6060the command line.
@@ -101,7 +101,7 @@ source/destination.
101101
102102## Step 01: [Client] Update Settings
103103
104Open up a Plex app and *disable* the `Account` > `Library` > `Empty trash
104Open up a Plex app and _disable_ the `Account` > `Library` > `Empty trash
105105automatically after every scan` preference for the source server.
106106
107107## Step 02: [Destination] Install Plex
@@ -133,8 +133,8 @@ Server data directory
133133located?](https://support.plex.tv/articles/202915258-where-is-the-plex-media-server-data-directory-located/).
134134
135135There are many ways to copy the data to the new server and will largely depend
136on the size of the folder being copied. Personally, my data folder was ~23GB
137and I opted to simply use the `scp` command to copy the files over SSH.
136on the size of the folder being copied. Personally, my data folder was ~23GB and
137I opted to simply use the `scp` command to copy the files over SSH.
138138
139139This process was throttled by the old server's slow HDD and ports and took
140140approximately 90 minutes to complete. In comparison, moving the data from the
@@ -179,12 +179,12 @@ drives from the source server to the destination server.
179179Next, perform the following actions in the client:
180180
1811811. On the left sidebar, click `More` > Three-Dot Menu > `Scan Library Files`
1822. *Enable* the `Account` > `Library` > `Empty trash automatically after every
183 scan` preference for the source server.
1843. On the left sidebar, click `More` > Three-Dot Menu > `Manage Server` >
185 `Empty Trash`
1864. On the left sidebar, click `More` > Three-Dot Menu > `Manage Server` >
187 `Clean Bundles`
1822. _Enable_ the `Account` > `Library` > `Empty trash automatically after every
183scan` preference for the source server.
1843. On the left sidebar, click `More` > Three-Dot Menu > `Manage Server` > `Empty
185 Trash`
1864. On the left sidebar, click `More` > Three-Dot Menu > `Manage Server` > `Clean
187 Bundles`
1881885. On the left sidebar, click `More` > Three-Dot Menu > `Manage Server` >
189189 `Optimize Database`
190190
content/blog/2022-03-23-nextcloud-on-ubuntu.md +4 −4
@@ -34,7 +34,7 @@ sudo mysql -uroot -p
3434Once you've logged in, you must create a new user so that Nextcloud can manage
3535the database. You will also create a `nextcloud` database and assign privileges:
3636
37``` sql
37```sql
3838CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
3939CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
4040GRANT ALL PRIVILEGES ON nextcloud.** TO 'username'@'localhost';
@@ -74,7 +74,7 @@ sudo nano /etc/apache2/sites-available/nextcloud.conf
7474Once the editor is open, paste the following information in. Then, save and
7575close the file.
7676
77``` config
77```config
7878<VirtualHost *:80>
7979 DocumentRoot /var/www/example.com
8080 ServerName example.com
@@ -154,9 +154,9 @@ of Nextcloud, using the `Breeze Dark` theme I installed from the Apps page.
154154![Nextcloud
155155Dashboard](https://img.cleberg.net/blog/20220323-installing-nextcloud-on-ubuntu/nextcloud_dashboard.png)
156156
157*Figure 01: Nextcloud Dashboard*
157_Figure 01: Nextcloud Dashboard_
158158
159159![Nextcloud
160160Settings](https://img.cleberg.net/blog/20220323-installing-nextcloud-on-ubuntu/nextcloud_settings.png)
161161
162*Figure 02: Nextcloud Security Settings*
162_Figure 02: Nextcloud Security Settings_
content/blog/2022-03-24-server-hardening.md +64 −63
@@ -16,7 +16,7 @@ draft = false
1616
1717## My Personal Data Flow
1818
19``` txt
19```txt
2020 ┌───────┐ ┌─────────────────┐
2121 ┌──► VLAN1 ├───► Private Devices │
2222 │ └───────┘ └─────────────────┘
@@ -35,44 +35,44 @@ have to think about the transport of data from `server` to `client`.
3535
3636Let's start with the actual server itself. Think about the following:
3737
38- Do I have a firewall enabled? Do I need to update this to allow new ports or
39 IPs?
40- Do I have an IPS/IDS that may prevent outside traffic?
41- Do I have any other security software installed?
42- Are the services hosted inside Docker containers, behind a reverse proxy, or
43 virtualized? If so, are they configured to allow outside traffic?
38- Do I have a firewall enabled? Do I need to update this to allow new ports or
39 IPs?
40- Do I have an IPS/IDS that may prevent outside traffic?
41- Do I have any other security software installed?
42- Are the services hosted inside Docker containers, behind a reverse proxy, or
43 virtualized? If so, are they configured to allow outside traffic?
4444
4545Once the data leaves the server, where does it go? In my case, it goes to a
4646managed switch. In this case, I asked the following:
4747
48- What configurations is the switch using?
49- Am I using VLANs?
50 - Yes, I am using 802.1Q VLANs.
51- Are the VLANs configured properly?
52 - Yes, as shown in the Switch section below, I have a separate VLAN to allow
53 outside traffic to and from the server alone. No other devices, except for
54 a service port, and in that VLAN.
48- What configurations is the switch using?
49- Am I using VLANs?
50 - Yes, I am using 802.1Q VLANs.
51- Are the VLANs configured properly?
52 - Yes, as shown in the Switch section below, I have a separate VLAN to
53 allow outside traffic to and from the server alone. No other devices,
54 except for a service port, and in that VLAN.
5555
5656At this point, the data has been processed through the switch. Where does it go
5757next? In my case, it's pretty simple: it goes to the router/modem device.
5858
59- Does my ISP block any ports that I need?
60 - This is an important step that a lot of people run into when self-hosting
61 at home. Use an online port-checker tool for your IP or call your ISP if
62 you think ports are blocked.
63- Is there a router firewall?
64 - Yes, I checked that it's configured to allow the ports I need to run my
65 services publicly. Common web servers and reverse proxies require ports 80
66 and 443, but other services like media servers or games can require unique
67 ports, so be sure to check the documentation for your service(s).
68- Are there any other settings affecting inbound/outbound traffic?
69 - Schedules or access blocks
70 - Static Routing
71 - QoS
72 - Port Forwarding
73 - DMZ Hosting
74 - Remote Management (this can sometimes mess with services that also require
75 the use of ports 80 and 443)
59- Does my ISP block any ports that I need?
60 - This is an important step that a lot of people run into when
61 self-hosting at home. Use an online port-checker tool for your IP or
62 call your ISP if you think ports are blocked.
63- Is there a router firewall?
64 - Yes, I checked that it's configured to allow the ports I need to run my
65 services publicly. Common web servers and reverse proxies require ports
66 80 and 443, but other services like media servers or games can require
67 unique ports, so be sure to check the documentation for your service(s).
68- Are there any other settings affecting inbound/outbound traffic?
69 - Schedules or access blocks
70 - Static Routing
71 - QoS
72 - Port Forwarding
73 - DMZ Hosting
74 - Remote Management (this can sometimes mess with services that also
75 require the use of ports 80 and 443)
7676
7777Once the data leaves my router, it goes to the upstream ISP and can be accessed
7878publicly.
@@ -172,7 +172,7 @@ sudo ufw enable
172172 rules is commented-out or doesn't exist, create the rule at the bottom of
173173 the file.
174174
175 ``` config
175 ```config
176176 PermitRootLogin no
177177 PasswordAuthentication no
178178 PubkeyAuthentication yes
@@ -192,10 +192,10 @@ sudo ufw enable
192192
1931933. Enable MFA for `ssh`
194194
195 This part is optional, but I highly recommend it. So far, we've ensured
196 that no one can log into our user on the server without using our secret
197 key, and we've ensured that no one can log in remotely as `root`. Next, you
198 can enable MFA authentication for `ssh` connections.
195 This part is optional, but I highly recommend it. So far, we've ensured that
196 no one can log into our user on the server without using our secret key, and
197 we've ensured that no one can log in remotely as `root`. Next, you can
198 enable MFA authentication for `ssh` connections.
199199
200200 This process involves editing a couple files and installing an MFA package,
201201 so I will not include all the details in this post. To see how to configure
@@ -203,7 +203,7 @@ sudo ufw enable
203203 SSH](../enable-totp-mfa-for-ssh/).
204204
205205 ![SSH
206 MFA](https://img.cleberg.net/blog/20220324-hardening-a-public-facing-home-server/ssh_mfa.png)
206MFA](https://img.cleberg.net/blog/20220324-hardening-a-public-facing-home-server/ssh_mfa.png)
207207
208208## `fail2ban`
209209
@@ -239,10 +239,10 @@ order to SSH to this server, I need to plug my laptop into port 23 or else I
239239cannot SSH. Otherwise, I'd need to hook up a monitor and keyboard directly to
240240the server to manage it.
241241
242|
242|
243243
244244| VLAN ID | VLAN Name | Member Ports | Tagged Ports | Untagged Ports |
245|---------|-----------|--------------|--------------|----------------|
245| ------- | --------- | ------------ | ------------ | -------------- |
246246| 1 | Default | 1-24 | 1-24 | |
247247| 2 | Server | 1,8,23 | 1,8,23 | |
248248
@@ -253,7 +253,7 @@ any related ports (in this case, see that ports `8` and `23` have a PVID of
253253`2`).
254254
255255| Port | PVID |
256|------|------|
256| ---- | ---- |
257257| 1 | 1 |
258258| 2 | 1 |
259259| 3 | 1 |
@@ -285,9 +285,9 @@ On my router, the configuration was as easy as opening the firewall settings and
285285unblocking the ports I needed for my services (e.g., HTTP/S, Plex, SSH, MySQL,
286286etc.).
287287
288*Since I'm relying on an ISP-provided modem/router combo for now (not by
288_Since I'm relying on an ISP-provided modem/router combo for now (not by
289289choice), I do not use any other advanced settings on my router that would
290inhibit any valid traffic to these services.*
290inhibit any valid traffic to these services._
291291
292292The paragraph above regarding the ISP-owned router is no longer accurate as I
293293now use the Ubiquiti Unifi Dream Machine Pro as my router. Within this router, I
@@ -303,7 +303,7 @@ available to you.
303303
304304One large piece of self-hosting that people generally don't discuss online is
305305physical security. However, physical security is very important for everyone who
306hosts a server like this. Exactly *how* important it is depends on the server
306hosts a server like this. Exactly _how_ important it is depends on the server
307307use/purpose.
308308
309309If you self-host customer applications that hold protected data (HIPAA, GDPR,
@@ -315,24 +315,25 @@ minor consideration, but one you still need to think about.
315315
316316The first consideration is quite simple: location.
317317
318- Is the server within a property you own or housed on someone else's property?
319- Is it nearby (in your house, in your work office, in your neighbor's garage,
320 in a storage unit, etc.)?
321- Do you have 24/7 access to the server?
322- Are there climate considerations, such as humidity, fires, tornadoes,
323 monsoons?
324- Do you have emergency equipment nearby in case of emergency?
318- Is the server within a property you own or housed on someone else's
319 property?
320- Is it nearby (in your house, in your work office, in your neighbor's garage,
321 in a storage unit, etc.)?
322- Do you have 24/7 access to the server?
323- Are there climate considerations, such as humidity, fires, tornadoes,
324 monsoons?
325- Do you have emergency equipment nearby in case of emergency?
325326
326327## Hardware Ownership
327328
328329Secondly, consider the hardware itself:
329330
330- Do you own the server in its entirety?
331- Are any other users able to access the server, even if your data/space is
332 segregated?
333- If you're utilizing a third party, do they have any documentation to show
334 responsibility? This could be a SOC 1/2/3 report, ISO compliance report,
335 internal security/safety documentation.
331- Do you own the server in its entirety?
332- Are any other users able to access the server, even if your data/space is
333 segregated?
334- If you're utilizing a third party, do they have any documentation to show
335 responsibility? This could be a SOC 1/2/3 report, ISO compliance report,
336 internal security/safety documentation.
336337
337338## Physical Controls
338339
@@ -342,10 +343,10 @@ usually covered already if you're utilizing a third party.
342343
343344These can include:
344345
345- Server bezel locks
346- Server room locks - physical, digital, or biometric authentication
347- Security cameras
348- Raised floors/lowered ceilings with proper guards/gates in-place within the
349 floors or ceilings
350- Security personnel
351- Log sheets and/or guest badges
346- Server bezel locks
347- Server room locks - physical, digital, or biometric authentication
348- Security cameras
349- Raised floors/lowered ceilings with proper guards/gates in-place within the
350 floors or ceilings
351- Security personnel
352- Log sheets and/or guest badges
content/blog/2022-03-26-ssh-mfa.md +13 −13
@@ -11,10 +11,10 @@ If you are a sysadmin of a server anywhere (that includes at home!), you may
1111want an added layer of protection against intruders. This is not a replacement
1212for other security measures, such as:
1313
14- Disable root SSH
15- Disable SSH password authentication
16- Allow only certain users to login via SSH
17- Allow SSH only from certain IPs
14- Disable root SSH
15- Disable SSH password authentication
16- Allow only certain users to login via SSH
17- Allow SSH only from certain IPs
1818
1919However, MFA can be added as an additional security measure to ensure that your
2020server is protected. This is especially important if you need to allow password
@@ -52,7 +52,7 @@ If you are not sure how to answer, read the prompts carefully and think about
5252having to how each situation would affect your normal login attempts. If you are
5353still not sure, use my default responses below.
5454
55``` txt
55```txt
5656OUTPUT
5757
5858Do you want authentication tokens to be time-based (y/n) y
@@ -62,13 +62,13 @@ At this point, use an authenticator app somewhere one of your devices to scan
6262the QR code. Any future login attempts after our upcoming configuration changes
6363will require that TOTP.
6464
65``` txt
65```txt
6666OUTPUT
6767
6868Do you want me to update your "/home/user/.google_authenticator" file? (y/n) y
6969```
7070
71``` txt
71```txt
7272OUTPUT
7373
7474Do you want to disallow multiple uses of the same authentication
@@ -76,7 +76,7 @@ token? This restricts you to one login about every 30s, but it increases
7676your chances to notice or even prevent man-in-the-middle attacks (y/n) y
7777```
7878
79``` txt
79```txt
8080OUTPUT
8181
8282By default, a new token is generated every 30 seconds by the mobile app.
@@ -91,7 +91,7 @@ between client and server.
9191Do you want to do so? (y/n) n
9292```
9393
94``` txt
94```txt
9595OUTPUT
9696
9797If the computer that you are logging into isn't hardened against brute-force
@@ -112,7 +112,7 @@ google-authenticator -t -d -f -r 3 -R 30 -w 3
112112
113113The options referenced above are as follows:
114114
115``` txt
115```txt
116116google-authenticator [<options>]
117117 -h, --help Print this message
118118 -c, --counter-based Set up counter-based (HOTP) verification
@@ -152,7 +152,7 @@ sudo nano /etc/pam.d/sshd
152152You need to do two things in this file. First, add the following lines to the
153153bottom of the file:
154154
155``` config
155```config
156156auth required pam_google_authenticator.so nullok
157157auth required pam_permit.so
158158```
@@ -166,7 +166,7 @@ following three authentication factors:
1661662. Password
1671673. T/OTP code
168168
169``` config
169```config
170170#@include common-auth
171171```
172172
@@ -181,7 +181,7 @@ sudo nano /etc/ssh/sshd_config
181181You'll need to change `ChallengeResponseAuthentication` to yes and add the
182182`AuthenticationMethods` line to the bottom of the file.
183183
184``` config
184```config
185185ChallengeResponseAuthentication yes
186186AuthenticationMethods publickey,password publickey,keyboard-interactive
187187```
content/blog/2022-04-02-nginx-reverse-proxy.md +15 −15
@@ -16,13 +16,13 @@ where each request should be sent.
1616
1717For example, let's say that I run three servers in my home:
1818
19- Server01 (`example.com`)
20- Server02 (`service01.example.com`)
21- Server03 (`service02.example.com`)
19- Server01 (`example.com`)
20- Server02 (`service01.example.com`)
21- Server03 (`service02.example.com`)
2222
2323I also run a reverse proxy in my home that intercepts all public traffic:
2424
25- Reverse Proxy
25- Reverse Proxy
2626
2727Assume that I have a domain name (`example.com`) that allows clients to request
2828websites or services from my home servers.
@@ -36,7 +36,7 @@ Server~01~ holds that data, Nginx will send the user to Server~01~. If I were to
3636change the configuration so that `example.com` is routed to Server~02~, that
3737same user would be sent to Server~02~ instead.
3838
39``` txt
39```txt
4040┌──────┐ ┌───────────┐
4141│ User │─┐ ┌──► Server_01 │
4242└──────┘ │ │ └───────────┘
@@ -54,11 +54,11 @@ There are a lot of options when it comes to reverse proxy servers, so I'm just
5454going to list a few of the options I've heard recommended over the last few
5555years:
5656
57- [Nginx](https://nginx.com)
58- [Caddy](https://caddyserver.com)
59- [Traefik](https://traefik.io/)
60- [HAProxy](https://www.haproxy.org/)
61- [Squid](https://ubuntu.com/server/docs/proxy-servers-squid)
57- [Nginx](https://nginx.com)
58- [Caddy](https://caddyserver.com)
59- [Traefik](https://traefik.io/)
60- [HAProxy](https://www.haproxy.org/)
61- [Squid](https://ubuntu.com/server/docs/proxy-servers-squid)
6262
6363In this post, we will be using Nginx as our reverse proxy, running on Ubuntu
6464Server 20.04.4 LTS.
@@ -118,8 +118,8 @@ search box and ensuring the results are showing the correct IP address.
118118## Step 2: Open Network Ports
119119
120120This step will be different depending on which router you have in your home. If
121you're not sure, try to visit [192.168.1.1](http://192.168.1.1) in your
122browser. Login credentials are usually written on a sticker somewhere on your
121you're not sure, try to visit [192.168.1.1](http://192.168.1.1) in your browser.
122Login credentials are usually written on a sticker somewhere on your
123123modem/router.
124124
125125Once you're able to log in to your router, find the Port Forwarding settings.
@@ -131,7 +131,7 @@ this table, `xxx.xxx.xxx.xxx` is the local device IP of the reverse proxy
131131server, it will probably be an IP between `192.168.1.1` and `192.168.1.255`.
132132
133133| NAME | FROM PORT | DEST PORT/IP | ENABLED |
134|-------|-----------|-----------------|---------|
134| ----- | --------- | --------------- | ------- |
135135| HTTP | 80 | xxx.xxx.xxx.xxx | TRUE |
136136| HTTPS | 443 | xxx.xxx.xxx.xxx | TRUE |
137137
@@ -172,7 +172,7 @@ Dashy:
172172nano /etc/nginx/sites-available/dashy.example.com
173173```
174174
175``` config
175```config
176176server {
177177 listen 80;
178178 server_name dashy.example.com;
@@ -189,7 +189,7 @@ Uptime:
189189nano /etc/nginx/sites-available/uptime.example.com
190190```
191191
192``` config
192```config
193193server {
194194 listen 80;
195195 server_name uptime.example.com;
content/blog/2022-04-09-pinetime.md +20 −20
@@ -22,20 +22,20 @@ for each watch and the primary functions:
2222
23231. Price:
2424
25 - $26.99 (Sealed)
26 - $24.99 (Dev Kit)
27 - $51.98 (One Sealed + One Dev Kit)
25 - $26.99 (Sealed)
26 - $24.99 (Dev Kit)
27 - $51.98 (One Sealed + One Dev Kit)
2828
29292. Primary Functionality:
3030
31 - Clock (+ Smartphone Sync)
32 - Pedometer
33 - Heart Rate Monitor
34 - Sleep Monitor
35 - Calories burned
36 - Messaging
37 - Smartphone Notifications
38 - Media Controls
31 - Clock (+ Smartphone Sync)
32 - Pedometer
33 - Heart Rate Monitor
34 - Sleep Monitor
35 - Calories burned
36 - Messaging
37 - Smartphone Notifications
38 - Media Controls
3939
4040# Unboxing
4141
@@ -61,10 +61,10 @@ While turning on the watch for the first time, some of the main design choices
6161you can see in the watch OS,
6262[InfiniTime](https://wiki.pine64.org/wiki/InfiniTime), are:
6363
64- A square bezel, not too thin against the sides of the watch.
65- A simple, rubber band.
66- Basic font and screen pixel design.
67- Swipe gestures to access other screens.
64- A square bezel, not too thin against the sides of the watch.
65- A simple, rubber band.
66- Basic font and screen pixel design.
67- Swipe gestures to access other screens.
6868
6969![PineTime
7070Screens](https://img.cleberg.net/blog/20220409-pinetime-smart-watch/pinetime.png)
@@ -73,7 +73,7 @@ The OS itself is fantastic in terms of functionality for me. It does exactly
7373what a smartwatch should do - track time, steps, heart rates, and connect to
7474another smart device, without being overly burdensome to the user.
7575
76My only gripe so far is that it's *really* difficult to swipe to different
76My only gripe so far is that it's _really_ difficult to swipe to different
7777screens, such as pulling down the notification tray. I'm not sure if this is an
7878OS or hardware issue, but it makes it quite hard to quickly move around the
7979screens.
@@ -91,10 +91,10 @@ Since I am using iOS as my primary mobile device OS, I am using the
9191
9292This app provides the following for PineTime owners:
9393
94- Firmware updates
95- Steps
96- Charts
97- Notifications
94- Firmware updates
95- Steps
96- Charts
97- Notifications
9898
9999I mashed up a few screenshots to show off the home page, menu, firmware update,
100100and notification test screens:
content/blog/2022-06-01-ditching-cloudflare.md +2 −2
@@ -25,8 +25,8 @@ if they're worth the higher rates (one domain is 30€ and the other is 45€).+
2525
2626> **Update (2022.06.03)**: I ended up transferring my final two domains over to
2727> Njalla, clearing my Cloudflare account of personal data, and deleting the
28> Cloudflare account entirely. *I actually feel relieved to have moved on to a
29> provider I trust.*
28> Cloudflare account entirely. _I actually feel relieved to have moved on to a
29> provider I trust._
3030
3131# DNS
3232
content/blog/2022-06-07-self-hosting-freshrss.md +10 −10
@@ -46,7 +46,7 @@ of the server and an `AAAA` record with the IPv6 address of the server. Note:
4646assigning an IPv6 (`AAAA`) record is optional, but I like to enable IPV6 for my
4747services.
4848
49``` config
49```config
5050rss.example.com A xxx.xxx.xxx.xxx
5151rss.example.com AAAA xxxx:xxxx: ... :xxxx
5252```
@@ -55,8 +55,8 @@ rss.example.com AAAA xxxx:xxxx: ... :xxxx
5555
5656I initially tried to set up a `docker-compose.yml` file with a `.env` file
5757because I prefer to have a file I can look back at later to see how I initially
58started the container, but it simply wouldn't work for me. I'm not sure why,
59but I assume I wasn't telling `docker-compose` where the `.env` file was.
58started the container, but it simply wouldn't work for me. I'm not sure why, but
59I assume I wasn't telling `docker-compose` where the `.env` file was.
6060
6161Regardless, I chose to simply run the service with `docker run`. See the
6262following command for my `docker run` configuration:
@@ -79,8 +79,8 @@ instance at `localhost:8080`.
7979
8080I **HIGHLY** suggest that you set up your user account prior to exposing this
8181service to the public. It's unlikely that someone is trying to access the exact
82domain or IP/port you're assigning here, but as soon as you expose this
83service, the first person to open the URL will be able to create the admin user.
82domain or IP/port you're assigning here, but as soon as you expose this service,
83the first person to open the URL will be able to create the admin user.
8484
8585In order to set up your FreshRSS service, open the `localhost:8080` URL in your
8686browser (you may need to use a local IP instead of `localhost` if you're
@@ -104,7 +104,7 @@ sudo nano /etc/nginx/sites-available/rss.example.com
104104
105105Within the config file, I pasted the following code:
106106
107``` config
107```config
108108upstream freshrss {
109109 server 127.0.0.1:8080;
110110 keepalive 64;
@@ -171,7 +171,7 @@ Once that is set and saved, click the link below the API password field to open
171171the API check tool. It should look something like `https://localhost:8080/api/`
172172or `https://rss.example.com/api/`.
173173
174Within this page, you *should* see your correct external URL and "PASS" at the
174Within this page, you _should_ see your correct external URL and "PASS" at the
175175bottom of each API type. This would mean everything is set up correctly, and you
176176can now move on and login to any RSS apps that support self-hosted options.
177177
@@ -205,7 +205,7 @@ Within `config.php`, you will need to update the `base_url` variable and update
205205it to match your external URL. In my case, I simply commented-out the incorrect
206206URL with `//` and added the correct one on a new line:
207207
208``` php
208```php
209209<?php
210210 return array (
211211 ...
@@ -231,8 +231,8 @@ Next, just restart the container:
231231sudo docker restart freshrss
232232```
233233
234Voilà! Your API check should now "PASS" and you should be able to use one of
235the API URLs in your RSS apps.
234Voilà! Your API check should now "PASS" and you should be able to use one of the
235API URLs in your RSS apps.
236236
237237In my case, I use [NetNewsWire](https://netnewswire.com) on my desktop and
238238phone.
content/blog/2022-06-16-terminal-lifestyle.md +22 −23
@@ -7,31 +7,31 @@ draft = false
77
88# Text-Based Simplicity
99
10I've detailed my views on web-based minimalism and related topics in other
11posts throughout the years; e.g., JavaScript/CSS bloat slowing down websites
12that are essentially a text document. However, I have never really expanded
13beyond talking about the web and describing how I focus on minimizing
14distractions in other digital environments.
10I've detailed my views on web-based minimalism and related topics in other posts
11throughout the years; e.g., JavaScript/CSS bloat slowing down websites that are
12essentially a text document. However, I have never really expanded beyond
13talking about the web and describing how I focus on minimizing distractions in
14other digital environments.
1515
16This post is going to set the baseline for how I *try* to live my digital life.
16This post is going to set the baseline for how I _try_ to live my digital life.
1717It does not necessarily get into my physical life, which is often harder to
1818control and contain all the noise in our modern world.
1919
2020While there are new things to do every day in our digital world, I find that
2121keeping a core set of values and interests can ground you and keep you mindful
22of *why* you are participating in the digital world. For example, if - at your
22of _why_ you are participating in the digital world. For example, if - at your
2323core - you have no interest in what strangers think about random topics, it
2424would be unwise to start participating in social media. However, I am someone
2525who has been dragged in by effective advertising to participate in communities
2626that I realize I do not care for.
2727
28I won't dive much further into explaining the philosophy of all this, but I
29will link a few helpful articles that may pique your interest if you're in
30search of more meaningful experiences:
28I won't dive much further into explaining the philosophy of all this, but I will
29link a few helpful articles that may pique your interest if you're in search of
30more meaningful experiences:
3131
32- [Mindfulness](https://en.wikipedia.org/wiki/Mindfulness)
33- [Minimalism](https://en.wikipedia.org/wiki/Minimalism)
34- [Stoicism](https://en.wikipedia.org/wiki/Stoicism)
32- [Mindfulness](https://en.wikipedia.org/wiki/Mindfulness)
33- [Minimalism](https://en.wikipedia.org/wiki/Minimalism)
34- [Stoicism](https://en.wikipedia.org/wiki/Stoicism)
3535
3636# Living Life in the Terminal
3737
@@ -62,9 +62,8 @@ Now that we have some examples out of the way, let's dive into the specifics.
6262
6363I'm going to start off with a hard topic for those who prefer to live in the
6464terminal: web browsing. This task is made hard mostly by websites and web apps
65that require JavaScript to run. The other difficult part is that if you're
66using a text-based browser, that means images won't load (hopefully that's
67obvious).
65that require JavaScript to run. The other difficult part is that if you're using
66a text-based browser, that means images won't load (hopefully that's obvious).
6867
6968I am using [Lynx](https://lynx.invisible-island.net), a text-based browser that
7069runs quickly and easily in the terminal. Lynx allows me to browser most websites
@@ -79,10 +78,10 @@ using their text-only interface.
7978![DuckDuckGo
8079!Lite](https://img.cleberg.net/blog/20220616-terminal-lifestyle/ddg.png)
8180
82Eventually, you will run into websites that don't work (or are just too ugly
83and messy) in a text-only mode, and you'll be forced to switch over to a GUI
84browser to look at that site. Personally, I don't mind this as it doesn't
85happen as often as I thought it would.
81Eventually, you will run into websites that don't work (or are just too ugly and
82messy) in a text-only mode, and you'll be forced to switch over to a GUI browser
83to look at that site. Personally, I don't mind this as it doesn't happen as
84often as I thought it would.
8685
8786The only time I need to do this is when I want to browse an image/video-focused
8887webpage or if I need to log in to a site, and it doesn't support a text-only
@@ -94,8 +93,8 @@ login page. For example, I am able to easily log in to
9493After web browsing activities, my main form of terminal communication is Matrix.
9594I use the [gomuks](https://docs.mau.fi/gomuks/) client currently.
9695
97This was incredibly easy to install on macOS (but I will need to see if it'll
98be just as easy on Linux when my new laptop arrives):
96This was incredibly easy to install on macOS (but I will need to see if it'll be
97just as easy on Linux when my new laptop arrives):
9998
10099```sh
101100brew install gomuks
@@ -178,7 +177,7 @@ I am used to the easy extensions found in VSCodium and Kate, so I am slowly
178177learning how to mold the default editing tools to my needs. Currently, this
179178means I am using `nano` with the following configuration:
180179
181``` config
180```config
182181set breaklonglines
183182set autoindent
184183set linenumbers
content/blog/2022-06-22-daily-poetry.md +46 −46
@@ -7,8 +7,8 @@ draft = false
77
88# Source Code
99
10I don't want to bury the lede here, so if you'd like to see the full source
11code I use to email myself plaintext poems daily, visit the repository:
10I don't want to bury the lede here, so if you'd like to see the full source code
11I use to email myself plaintext poems daily, visit the repository:
1212[daily-poem.git](https://git.cleberg.net/?p=daily-poem.git;a=summary).
1313
1414# My Daily Dose of Poetry
@@ -20,8 +20,8 @@ In this case, I was looking for a simply and easy way to get a daily dose of
2020literature or poetry to read in the mornings.
2121
2222However, I don't want to sign up for a random mailing list on just any website.
23I also don't want to have to work to find the reading content each morning, as
24I know I would simply give up and stop reading daily.
23I also don't want to have to work to find the reading content each morning, as I
24know I would simply give up and stop reading daily.
2525
2626Thus, I found a way to deliver poetry to myself in plain-text format, on a daily
2727basis, and scheduled to deliver automatically.
@@ -31,8 +31,8 @@ basis, and scheduled to deliver automatically.
3131This solution uses Python and email, so the following process requires the
3232following to be installed:
3333
341. An SMTP server, which can be as easy as installing `mailutils` if you're on
35 a Debian-based distro.
341. An SMTP server, which can be as easy as installing `mailutils` if you're on a
35 Debian-based distro.
36362. Python (& pip!)
37373. The following Python packages: `email`, `smtplib`, `json`, and `requests`
3838
@@ -46,7 +46,7 @@ informational.
4646This program starts with a simple import of the required packages, so I wanted
4747to explain why each package is used:
4848
49``` python
49```python
5050from email.mime.text import MIMEText # Required for translating MIMEText
5151import smtplib # Required to process the SMTP mail delivery
5252import json # Required to parse the poetry API results
@@ -55,41 +55,41 @@ import requests # Required to send out a request to the API
5555
5656## Sending the API Request
5757
58Next, we need to actually send the API request. In my case, I'm calling a
59random poem from the entire API. If you want, you can call specific poems or
60authors from this API.
58Next, we need to actually send the API request. In my case, I'm calling a random
59poem from the entire API. If you want, you can call specific poems or authors
60from this API.
6161
62``` python
62```python
6363json_data = requests.get('https://poetrydb.org/random').json()
6464```
6565
6666This gives us the following result in JSON:
6767
68``` json
68```json
6969[
70 {
71 "title": "Sonnet XXII: With Fools and Children",
72 "author": "Michael Drayton",
73 "lines": [
74 "To Folly",
75 "",
76 "With fools and children, good discretion bears;",
77 "Then, honest people, bear with Love and me,",
78 "Nor older yet, nor wiser made by years,",
79 "Amongst the rest of fools and children be;",
80 "Love, still a baby, plays with gauds and toys,",
81 "And, like a wanton, sports with every feather,",
82 "And idiots still are running after boys,",
83 "Then fools and children fitt'st to go together.",
84 "He still as young as when he first was born,",
85 "No wiser I than when as young as he;",
86 "You that behold us, laugh us not to scorn;",
87 "Give Nature thanks you are not such as we.",
88 "Yet fools and children sometimes tell in play",
89 "Some, wise in show, more fools indeed than they."
90 ],
91 "linecount": "15"
92 }
70 {
71 "title": "Sonnet XXII: With Fools and Children",
72 "author": "Michael Drayton",
73 "lines": [
74 "To Folly",
75 "",
76 "With fools and children, good discretion bears;",
77 "Then, honest people, bear with Love and me,",
78 "Nor older yet, nor wiser made by years,",
79 "Amongst the rest of fools and children be;",
80 "Love, still a baby, plays with gauds and toys,",
81 "And, like a wanton, sports with every feather,",
82 "And idiots still are running after boys,",
83 "Then fools and children fitt'st to go together.",
84 "He still as young as when he first was born,",
85 "No wiser I than when as young as he;",
86 "You that behold us, laugh us not to scorn;",
87 "Give Nature thanks you are not such as we.",
88 "Yet fools and children sometimes tell in play",
89 "Some, wise in show, more fools indeed than they."
90 ],
91 "linecount": "15"
92 }
9393]
9494```
9595
@@ -102,17 +102,17 @@ presented by the API.
102102For the actual poem content, we need to loop over each line in the `lines`
103103variable since each line is a separate string by default.
104104
105> You *could* also extract the title or author and make another call out to the
105> You _could_ also extract the title or author and make another call out to the
106106> API to avoid having to build the plaintext poem with a loop, but it just
107> doesn't make sense to me to send multiple requests when we can create a
108> simple loop on our local machine to work with the data we already have.
107> doesn't make sense to me to send multiple requests when we can create a simple
108> loop on our local machine to work with the data we already have.
109109>
110110> For
111111> [example](https://poetrydb.org/title/Sonnet%20XXII:%20With%20Fools%20and%20Children/lines.text),
112> look at the raw data response of this link to see the poem's lines returned
113> in plaintext.
112> look at the raw data response of this link to see the poem's lines returned in
113> plaintext.
114114
115``` python
115```python
116116title = json_data[0]['title']
117117author = json_data[0]['author']
118118line_count = json_data[0]['linecount']
@@ -130,7 +130,7 @@ For my daily email, I want to see the title of the poem first, followed by the
130130author, then a blank line, and finally the full poem. This code snippet combines
131131that data and packages it into a MIMEText container, ready to be emailed.
132132
133``` python
133```python
134134msg_body = title + "\n" + author + "\n\n" + lines
135135msg = MIMEText(msg_body)
136136```
@@ -138,7 +138,7 @@ msg = MIMEText(msg_body)
138138Before we send the email, we need to prepare the metadata (subject, from, to,
139139etc.):
140140
141``` python
141```python
142142sender_email = 'example@server.local'
143143recipient_emails = ['user@example.com']
144144msg['Subject'] = 'Your Daily Poem (' + line_count + ' lines)'
@@ -152,7 +152,7 @@ Now that I have everything ready to be emailed, the last step is to simply
152152connect to an SMTP server and send the email out to the recipients. In my case,
153153I installed `mailutils` on Ubuntu and let my SMTP server be `localhost`.
154154
155``` python
155```python
156156smtp_server = 'localhost'
157157s = smtplib.SMTP(smtp_server)
158158s.sendmail(sender_email, recipient_emails, msg.as_string())
@@ -164,7 +164,7 @@ s.quit()
164164Instead of including a screenshot, I've copied the contents of the email that
165165was delivered to my inbox below since I set this process up in plaintext format.
166166
167``` txt
167```txt
168168Date: Wed, 22 Jun 2022 14:37:19 +0000 (UTC)
169169From: REDACTED
170170To: REDACTED
@@ -206,7 +206,7 @@ In the file, simply paste the following snippet at the bottom of the file and
206206ensure that the file path is correctly pointing to wherever you saved your
207207Python script:
208208
209``` config
209```config
2102100 8 ** ** ** python3 /home/<your_user>/dailypoem/main.py
211211```
212212
content/blog/2022-06-24-fedora-i3.md +71 −76
@@ -7,60 +7,56 @@ draft = false
77
88# Leaving macOS
99
10As I noted [in a recent post](../foss-macos-apps), I have been planning
11on migrating from macOS back to a Linux-based OS. I am happy to say that
12I have finally completed my migration and am now stuck in the wonderful
13world of Linux again.
14
15My decision to leave macOS really came down to just a few important
16things:
17
18- Apple Security (Gatekeeper) restricting me from running any software I want.
19 Even if you disable Gatekeeper and allow software to bypass the rest of the
20 device installation security, you still have to repeat that process every time
21 the allowed software is updated.
22- macOS sends out nearly constant connections, pings, telemetry, etc. to a
23 myriad of mysterious Apple services. I'm not even going to dive into how many
24 macOS apps have constant telemetry on, as well.
25- Lastly, I just *really* missed the customization and freedom that comes with
26 Linux. Being able to switch to entirely new kernel, OS, or desktop within
27 minutes is a freedom I took for granted when I switched to macOS.
28
29Now that I've covered macOS, I'm going to move on to more exciting
30topics: my personal choice of OS, DE, and various customizations I'm
31using.
10As I noted [in a recent post](../foss-macos-apps), I have been planning on
11migrating from macOS back to a Linux-based OS. I am happy to say that I have
12finally completed my migration and am now stuck in the wonderful world of Linux
13again.
14
15My decision to leave macOS really came down to just a few important things:
16
17- Apple Security (Gatekeeper) restricting me from running any software I want.
18 Even if you disable Gatekeeper and allow software to bypass the rest of the
19 device installation security, you still have to repeat that process every
20 time the allowed software is updated.
21- macOS sends out nearly constant connections, pings, telemetry, etc. to a
22 myriad of mysterious Apple services. I'm not even going to dive into how
23 many macOS apps have constant telemetry on, as well.
24- Lastly, I just _really_ missed the customization and freedom that comes with
25 Linux. Being able to switch to entirely new kernel, OS, or desktop within
26 minutes is a freedom I took for granted when I switched to macOS.
27
28Now that I've covered macOS, I'm going to move on to more exciting topics: my
29personal choice of OS, DE, and various customizations I'm using.
3230
3331# Fedora
3432
3533After trying a ton of distros (I think I booted and tested around 20-25
36distros), I finally landed on [Fedora Linux](https://getfedora.org/). I
37have quite a bit of experience with Fedora and enjoy the
38`dnf` package manager. Fedora allows me to keep up-to-date
39with recent software (I'm looking at you, Debian), but still provides a
40level of stability you don't find in every distro.
41
42In a very close second place was Arch Linux, as well as its spin-off:
43Garuda Linux (Garuda w/ sway is *beautiful*). Arch is great for
44compatibility and the massive community it has, but I have just never
45had the time to properly sit down and learn the methodology behind their
46packaging systems.
47
48Basically, everything else I tested was unacceptable in at least one way
49or another. Void (`glibc`) was great, but doesn't support
50all the software I need. Slackware worked well as a tui, but I wasn't
51skilled enough to get a tiling window manager (WM) working on it.
34distros), I finally landed on [Fedora Linux](https://getfedora.org/). I have
35quite a bit of experience with Fedora and enjoy the `dnf` package manager.
36Fedora allows me to keep up-to-date with recent software (I'm looking at you,
37Debian), but still provides a level of stability you don't find in every distro.
38
39In a very close second place was Arch Linux, as well as its spin-off: Garuda
40Linux (Garuda w/ sway is _beautiful_). Arch is great for compatibility and the
41massive community it has, but I have just never had the time to properly sit
42down and learn the methodology behind their packaging systems.
43
44Basically, everything else I tested was unacceptable in at least one way or
45another. Void (`glibc`) was great, but doesn't support all the software I need.
46Slackware worked well as a tui, but I wasn't skilled enough to get a tiling
47window manager (WM) working on it.
5248
5349## i3
5450
55One of the reasons I settled on Fedora is that it comes with an official
56i3 spin. Being able to use a tiling WM, such as i3 or sway, is one of
57the biggest things I wanted to do as soon as I adopted Linux again.
51One of the reasons I settled on Fedora is that it comes with an official i3
52spin. Being able to use a tiling WM, such as i3 or sway, is one of the biggest
53things I wanted to do as soon as I adopted Linux again.
5854
59I will probably set up a dotfile repository soon, so that I don't lose
60any of my configurations, but nothing big has been configured thus far.
55I will probably set up a dotfile repository soon, so that I don't lose any of my
56configurations, but nothing big has been configured thus far.
6157
62The two main things I have updated in i3wm are natural scrolling and
63binding my brightness keys to the `brightnessctl` program.
58The two main things I have updated in i3wm are natural scrolling and binding my
59brightness keys to the `brightnessctl` program.
6460
65611. Natural Scrolling
6662
@@ -70,12 +66,12 @@ binding my brightness keys to the `brightnessctl` program.
7066 sudo nano /usr/share/X11/xorg.conf.d/40-libinput.conf
7167 ```
7268
73 Within the `40-libinput.conf` file, find the following
74 input sections and enable the natural scrolling option.
69 Within the `40-libinput.conf` file, find the following input sections and
70 enable the natural scrolling option.
7571
7672 This is the `pointer` section:
7773
78 ``` conf
74 ```conf
7975 Section "InputClass"
8076 Identifier "libinput pointer catchall"
8177 MatchIsPointer "on"
@@ -87,7 +83,7 @@ binding my brightness keys to the `brightnessctl` program.
8783
8884 This is the `touchpad` section:
8985
90 ``` conf
86 ```conf
9187 Section "InputClass"
9288 Identifier "libinput touchpad catchall"
9389 MatchIsTouchpad "on"
@@ -99,8 +95,8 @@ binding my brightness keys to the `brightnessctl` program.
9995
100962. Enabling Brightness Keys
10197
102 Likewise, enabling brightness key functionality is as simple as
103 binding the keys to the `brightnessctl` program.
98 Likewise, enabling brightness key functionality is as simple as binding the
99 keys to the `brightnessctl` program.
104100
105101 To do this, open up your i3 config file. Mine is located here:
106102
@@ -108,7 +104,7 @@ binding my brightness keys to the `brightnessctl` program.
108104 nano /home/<my-user>/.config/i3/config
109105 ```
110106
111 ``` conf
107 ```conf
112108 # Use brightnessctl to adjust brightness.
113109 bindsym XF86MonBrightnessDown exec --no-startup-id brightnessctl --min-val=2 -q set 3%-
114110 bindsym XF86MonBrightnessUp exec --no-startup-id brightnessctl -q set 3%+
@@ -116,43 +112,42 @@ binding my brightness keys to the `brightnessctl` program.
116112
1171133. `polybar`
118114
119 Instead of using the default `i3status` bar, I have opted
120 to use `polybar` instead (as you can also see in the
121 screenshot above).
115 Instead of using the default `i3status` bar, I have opted to use `polybar`
116 instead (as you can also see in the screenshot above).
122117
123 My config for this menu bar is basically just the default settings
124 with modified colors and an added battery block to quickly show me
125 the machine's battery info.
118 My config for this menu bar is basically just the default settings with
119 modified colors and an added battery block to quickly show me the machine's
120 battery info.
126121
1271224. `alacritty`
128123
129 Not much to say on this part yet, as I haven't configured it much,
130 but I installed `alacritty` as my default terminal, and I
131 am using `zsh` and the shell.
124 Not much to say on this part yet, as I haven't configured it much, but I
125 installed `alacritty` as my default terminal, and I am using `zsh` and the
126 shell.
132127
133128# Software Choices
134129
135Again, I'm not going to say much that I haven't said yet in other blog
136posts, so I'll just do a quick rundown of the apps I installed
137immediately after I set up the environment.
130Again, I'm not going to say much that I haven't said yet in other blog posts, so
131I'll just do a quick rundown of the apps I installed immediately after I set up
132the environment.
138133
139134Flatpak Apps:
140135
141- Cryptomator
142- pCloud
143- Signal
136- Cryptomator
137- pCloud
138- Signal
144139
145140Fedora Packages:
146141
147- gomuks
148- neomutt
149- neofetch
150- Firefox
151 - uBlock Origin
152 - Bitwarden
153 - Stylus
154 - Privacy Redirect
142- gomuks
143- neomutt
144- neofetch
145- Firefox
146 - uBlock Origin
147 - Bitwarden
148 - Stylus
149 - Privacy Redirect
155150
156151Other:
157152
158- exiftool
153- exiftool
content/blog/2022-07-01-git-server.md +30 −30
@@ -17,22 +17,22 @@ anywhere.
1717Before I dive into the details, I want to state a high-level summary of my
1818self-hosted Git approach:
1919
20- This method uses the `ssh://` (read & write) and `git://` (read-only)
21 protocols for push and pull access.
22 - For the `git://` protocol, I create a `git-daemon-export-ok` file in any
23 repository that I want to be cloneable by anyone.
24 - The web interface I am using (`cgit`) allows simple HTTP cloning by default.
25 I do not disable this setting as I want beginners to be able to clone one of
26 my repositories even if they don't know the proper method.
27- I am not enabling Smart HTTPS for any repositories. Updates to repositories
28 must be pushed via SSH.
29- Beyond the actual repository management, I am using `cgit` for the front-end
30 web interface.
31 - If you use the `scan-path=<path>` configuration in the `cgitrc`
32 configuration file to automatically find repositories, you can't exclude a
33 repository from `cgit` if it's stored within the path that `cgit` reads. To
34 host private repositories, you'd need to set up another directory that
35 `cgit` can't read.
20- This method uses the `ssh://` (read & write) and `git://` (read-only)
21 protocols for push and pull access.
22 - For the `git://` protocol, I create a `git-daemon-export-ok` file in any
23 repository that I want to be cloneable by anyone.
24 - The web interface I am using (`cgit`) allows simple HTTP cloning by
25 default. I do not disable this setting as I want beginners to be able to
26 clone one of my repositories even if they don't know the proper method.
27- I am not enabling Smart HTTPS for any repositories. Updates to repositories
28 must be pushed via SSH.
29- Beyond the actual repository management, I am using `cgit` for the front-end
30 web interface.
31 - If you use the `scan-path=<path>` configuration in the `cgitrc`
32 configuration file to automatically find repositories, you can't exclude
33 a repository from `cgit` if it's stored within the path that `cgit`
34 reads. To host private repositories, you'd need to set up another
35 directory that `cgit` can't read.
3636
3737# Assumptions
3838
@@ -106,7 +106,7 @@ sudo nano /etc/ssh/sshd_config
106106Within this file, find the following settings and set them to the values I am
107107showing below:
108108
109``` conf
109```conf
110110PermitRootLogin no
111111PasswordAuthentication no
112112AuthenticationMethods publickey
@@ -177,8 +177,8 @@ other than the standard git commands.
177177
178178# Opening the Firewall
179179
180Don't forget to open up ports on the device firewall and network firewall if
181you want to access these repositories publicly. If you're using default ports,
180Don't forget to open up ports on the device firewall and network firewall if you
181want to access these repositories publicly. If you're using default ports,
182182forward ports `22` (ssh) and `9418` (git) from your router to your server's IP
183183address.
184184
@@ -203,7 +203,7 @@ your `~/.ssh/config` file:
203203nano ~/.ssh/config
204204```
205205
206``` conf
206```conf
207207Host git.example.com
208208 # HostName can be a URL or an IP address
209209 HostName git.example.com
@@ -215,8 +215,8 @@ Host git.example.com
215215
216216There are two main syntaxes you can use to manage git over SSH:
217217
218- `git clone [user@]server:project.git`
219- `git clone ssh://[user@]server/project.git`
218- `git clone [user@]server:project.git`
219- `git clone ssh://[user@]server/project.git`
220220
221221I prefer the first, which is an `scp`-like syntax. To test it, try to clone the
222222test repository you set up on the server:
@@ -238,7 +238,7 @@ sudo nano /etc/systemd/system/git-daemon.service
238238
239239Inside the `git-daemon.service` file, paste the following:
240240
241``` conf
241```conf
242242[Unit]
243243Description=Start Git Daemon
244244
@@ -322,7 +322,7 @@ mkdir ~/cgit && cd ~/cgit
322322nano docker-compose.yml
323323```
324324
325``` conf
325```conf
326326# docker-compose.yml
327327version: '3'
328328
@@ -361,7 +361,7 @@ configuration file:
361361sudo nano /etc/nginx/sites-available/git.example.com
362362```
363363
364``` conf
364```conf
365365server {
366366 listen 80;
367367 server_name git.example.com;
@@ -430,7 +430,7 @@ cd /git/example.git
430430nano config
431431```
432432
433``` conf
433```conf
434434[gitweb]
435435 owner = "YourName"
436436```
@@ -451,7 +451,7 @@ Below is an example configuration for `cgitrc`. You can find all the
451451configuration options within the [configuration manual]
452452(<https://git.zx2c4.com/cgit/plain/cgitrc.5.txt>).
453453
454``` conf
454```conf
455455css=/cgit.css
456456logo=/logo.png
457457favicon=/favicon.png
@@ -569,8 +569,8 @@ files](https://git.zx2c4.com/cgit/tree/filters), repeat the `curl` and `chmod`
569569process above for whichever files you need.
570570
571571However, formatting will not work quite yet since the Docker cgit container
572we're using doesn't have the formatting package installed. You can install
573this easily by install Python 3+ and the `pygments` package:
572we're using doesn't have the formatting package installed. You can install this
573easily by install Python 3+ and the `pygments` package:
574574
575575```sh
576576# Enter the container's command line
@@ -592,7 +592,7 @@ commands every time you kill and restart the container!**
592592If not done already, we need to add the following variables to our `cgitrc` file
593593in order for `cgit` to know where our filtering files are:
594594
595``` conf
595```conf
596596# Highlight source code with python pygments-based highlighter
597597source-filter=/var/www/htdocs/cgit/filters/syntax-highlighting.py
598598
content/blog/2022-07-14-gnupg.md +40 −40
@@ -47,45 +47,45 @@ I am not doing an in-depth explanation here in order to keep the focus on GPG
4747and not encryption algorithms. If you want a deep dive into cryptography or
4848encryption algorithms, please read my other posts:
4949
50- [AES Encryption](../aes-encryption/) (2018)
51- [Cryptography Basics](../cryptography-basics/) (2020)
50- [AES Encryption](../aes-encryption/) (2018)
51- [Cryptography Basics](../cryptography-basics/) (2020)
5252
5353## Vulnerabilities
5454
5555As of 2022-07-14, there are a few different vulnerabilities associated with GPG
5656or the libraries it uses:
5757
58- GPG versions 1.0.2--1.2.3 contains a bug where "as soon as one
59 (GPG-generated) ElGamal signature of an arbitrary message is released, one can
60 recover the signer's private key in less than a second on a PC."
61 ([Source](https://www.di.ens.fr/~pnguyen/pub_Ng04.htm))
62- GPG versions prior to 1.4.2.1 contain a false positive signature verification
63 bug.
64 ([Source](https://lists.gnupg.%20org/pipermail/gnupg-announce/2006q1/000211.html))
65- GPG versions prior to 1.4.2.2 cannot detect injection of unsigned data. (
66 [Source](https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000218.html))
67- Libgcrypt, a library used by GPG, contained a bug which enabled full key
68 recovery for RSA-1024 and some RSA-2048 keys. This was resolved in a GPG
69 update in 2017. ([Source](https://lwn.net/Articles/727179/))
70- The [ROCA Vulnerability](https://en.wikipedia.org/wiki/ROCA_vulnerability)
71 affects RSA keys generated by YubiKey 4 tokens.
72 ([Source](https://crocs.fi.%20muni.cz/_media/public/papers/nemec_roca_ccs17_preprint.pdf))
73- The [SigSpoof Attack](https://en.wikipedia.org/wiki/SigSpoof) allows an
74 attacker to spoof digital signatures.
75 ([Source](https://arstechnica.%20com/information-technology/2018/06/decades-old-pgp-bug-allowed-hackers-to-spoof-just-about-anyones-signature/))
76- Libgcrypt 1.9.0 contains a severe flaw related to a heap buffer overflow,
77 fixed in Libgcrypt 1.9.1
78 ([Source](https://web.archive.%20org/web/20210221012505/https://www.theregister.com/2021/01/29/severe_libgcrypt_bug/))
58- GPG versions 1.0.2--1.2.3 contains a bug where "as soon as one
59 (GPG-generated) ElGamal signature of an arbitrary message is released, one
60 can recover the signer's private key in less than a second on a PC."
61 ([Source](https://www.di.ens.fr/~pnguyen/pub_Ng04.htm))
62- GPG versions prior to 1.4.2.1 contain a false positive signature
63 verification bug.
64 ([Source](https://lists.gnupg.%20org/pipermail/gnupg-announce/2006q1/000211.html))
65- GPG versions prior to 1.4.2.2 cannot detect injection of unsigned data. (
66 [Source](https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000218.html))
67- Libgcrypt, a library used by GPG, contained a bug which enabled full key
68 recovery for RSA-1024 and some RSA-2048 keys. This was resolved in a GPG
69 update in 2017. ([Source](https://lwn.net/Articles/727179/))
70- The [ROCA Vulnerability](https://en.wikipedia.org/wiki/ROCA_vulnerability)
71 affects RSA keys generated by YubiKey 4 tokens.
72 ([Source](https://crocs.fi.%20muni.cz/_media/public/papers/nemec_roca_ccs17_preprint.pdf))
73- The [SigSpoof Attack](https://en.wikipedia.org/wiki/SigSpoof) allows an
74 attacker to spoof digital signatures.
75 ([Source](https://arstechnica.%20com/information-technology/2018/06/decades-old-pgp-bug-allowed-hackers-to-spoof-just-about-anyones-signature/))
76- Libgcrypt 1.9.0 contains a severe flaw related to a heap buffer overflow,
77 fixed in Libgcrypt 1.9.1
78 ([Source](https://web.archive.%20org/web/20210221012505/https://www.theregister.com/2021/01/29/severe_libgcrypt_bug/))
7979
8080### Platforms
8181
82Originally developed as a command-line program for *nix systems, GPG now has a
82Originally developed as a command-line program for \*nix systems, GPG now has a
8383wealth of front-end applications and libraries available for end-users. However,
8484the most recommended programs remain the same:
8585
86- [GnuPG](https://gnupg.org) for Linux (depending on distro)
87- [Gpg4win](https://gpg4win.org) for Windows
88- [GPGTools](https://gpgtools.org) for macOS
86- [GnuPG](https://gnupg.org) for Linux (depending on distro)
87- [Gpg4win](https://gpg4win.org) for Windows
88- [GPGTools](https://gpgtools.org) for macOS
8989
9090# Creating a Key Pair
9191
@@ -170,11 +170,11 @@ interface.
170170
171171As noted in RFC 4880, the general functions of OpenPGP are as follows:
172172
173- digital signatures
174- encryption
175- compression
176- Radix-64 conversion
177- key management and certificate services
173- digital signatures
174- encryption
175- compression
176- Radix-64 conversion
177- key management and certificate services
178178
179179From this, you can probably gather that the main use of GPG is for encrypting
180180data and/or signing the data with a key. The purpose of encrypting data with GPG
@@ -195,10 +195,10 @@ public key, the recipient(s) of the message can verify that the message was
195195signed with my personal key.
196196
197197The second process, regarding the actual encryption of the message and its
198contents, works by using a combination of the sender's keys and the
199recipient's keys. This process may vary slightly by implementation, but it most
200commonly uses asymmetric cryptography, also known as public-key cryptography. In
201this version of encryption, the sender's private key to sign the message and a
198contents, works by using a combination of the sender's keys and the recipient's
199keys. This process may vary slightly by implementation, but it most commonly
200uses asymmetric cryptography, also known as public-key cryptography. In this
201version of encryption, the sender's private key to sign the message and a
202202combination of the sender's keys and the recipient's public key to encrypt the
203203message.
204204
@@ -275,8 +275,8 @@ In order to verify signed data, a user needs to have:
2752752. A signature file
2762763. The public GPG key of the signer
277277
278Once the signer's public key is imported on the user's system, and they have
279the data and signature, they can verify the data with the following commands:
278Once the signer's public key is imported on the user's system, and they have the
279data and signature, they can verify the data with the following commands:
280280
281281```sh
282282# If the signature is attached to the data
@@ -296,5 +296,5 @@ them.
296296
297297Otherwise, the best option is to use a keyserver, such as:
298298
299- [pgp.mit.edu](https://pgp.mit.edu)
300- [keys.openpgp.org](https://keys.openpgp.org)
299- [pgp.mit.edu](https://pgp.mit.edu)
300- [keys.openpgp.org](https://keys.openpgp.org)
content/blog/2022-07-25-curseradio.md +3 −4
@@ -12,9 +12,8 @@ While exploring some interesting Linux applications, I stumbled across
1212player based on Python.
1313
1414This application is fantastic and incredibly easy to install, so I wanted to
15dedicate a post today to this app. Let's look at the features within the app
16and then walk through the installation process I took to get `curseradio`
17working.
15dedicate a post today to this app. Let's look at the features within the app and
16then walk through the installation process I took to get `curseradio` working.
1817
1918# Features
2019
@@ -35,7 +34,7 @@ radio player in the `Favourites` category.
3534## Commands/Shortcuts
3635
3736| Key(s) | Command |
38|------------|---------------------------------|
37| ---------- | ------------------------------- |
3938| ↑, ↓ | navigate |
4039| PgUp, PgDn | navigate quickly |
4140| Home, End | to top/bottom |
content/blog/2022-07-30-flac-to-opus.md +13 −13
@@ -16,7 +16,7 @@ of the files, especially if you're using a weak connection.
1616
1717So, in order to archive the music in a lossless format and still be able to
1818stream it easily, I opted to create a copy of my FLAC files in the [Opus audio
19codec](https://en.wikipedia.org/wiki/Opus_(audio_format)). This allows me to
19codec](<https://en.wikipedia.org/wiki/Opus_(audio_format)>). This allows me to
2020archive a quality, lossless version of the music and then point my streaming
2121service to the smaller, stream-ready version.
2222
@@ -47,20 +47,20 @@ following logic into the script.
4747
4848You **MUST** edit the following variables in order for it to work:
4949
50- `source`: The source directory where your FLAC files are stored.
51- `dest`: The destination directory where you want the resulting Opus files to
52 be stored.
50- `source`: The source directory where your FLAC files are stored.
51- `dest`: The destination directory where you want the resulting Opus files to
52 be stored.
5353
5454You **MAY** want to edit the following variables to suit your needs:
5555
56- `filename`: If you are converting to a file format other than Opus, you'll
57 need to edit this so that your resulting files have the correct filename
58 extension.
59- `reldir`: This variable can be edited to strip out more leading directories in
60 the file path. As you'll see later, I ignore this for now and simply clean it
61 up afterward.
62- `opusenc`: This is the actual conversion process. You may want to edit the
63 bitrate to suit your needs. I set mine at 128 but some prefer 160 or higher.
56- `filename`: If you are converting to a file format other than Opus, you'll
57 need to edit this so that your resulting files have the correct filename
58 extension.
59- `reldir`: This variable can be edited to strip out more leading directories
60 in the file path. As you'll see later, I ignore this for now and simply
61 clean it up afterward.
62- `opusenc`: This is the actual conversion process. You may want to edit the
63 bitrate to suit your needs. I set mine at 128 but some prefer 160 or higher.
6464
6565```sh
6666#!/bin/bash
@@ -168,7 +168,7 @@ du -h --max-depth=1 .
168168
169169In my case, my small library went from 78GB to 6.3GB!
170170
171``` txt
171```txt
17217278G ./archives
1731736.3G ./library
174174```
content/blog/2022-07-31-bash-it.md +9 −9
@@ -8,19 +8,19 @@ draft = false
88# Bash
99
1010For those who are not familiar,
11[Bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) is a Unix shell that is
12used as the default login shell for most Linux distributions. This shell and
11[Bash](<https://en.wikipedia.org/wiki/Bash_(Unix_shell)>) is a Unix shell that
12is used as the default login shell for most Linux distributions. This shell and
1313command processor should be familiar if you've used Linux (or older version of
1414macOS) before.
1515
1616However, bash is not the only option. There are numerous other shells that
1717exist. Here are some popular examples:
1818
19- [zsh](https://en.wikipedia.org/wiki/Z_shell)
20- [fish](https://en.wikipedia.org/wiki/Fish_(Unix_shell))
21- [oksh](https://github.com/ibara/oksh)
22- [mksh](https://wiki.gentoo.org/wiki/Mksh)
23- [dash](https://en.wikipedia.org/wiki/Debian_Almquist_shell)
19- [zsh](https://en.wikipedia.org/wiki/Z_shell)
20- [fish](<https://en.wikipedia.org/wiki/Fish_(Unix_shell)>)
21- [oksh](https://github.com/ibara/oksh)
22- [mksh](https://wiki.gentoo.org/wiki/Mksh)
23- [dash](https://en.wikipedia.org/wiki/Debian_Almquist_shell)
2424
2525While each shell has its differences, bash is POSIX compliant and the default
2626for many Linux users. Because of this, I am going to explore a program called
@@ -110,7 +110,7 @@ This will provide you a list that looks like the following text block. Within
110110this screen, you will be able to see all available options and which ones are
111111currently enabled.
112112
113``` txt
113```txt
114114Alias Enabled? Description
115115ag [ ] the silver searcher (ag) aliases
116116ansible [ ] ansible abbreviations
@@ -148,7 +148,7 @@ bash-it show plugins
148148
149149You will see the following output showing enabled and disabled plugins:
150150
151``` txt
151```txt
152152Plugin Enabled? Description
153153alias-completion [ ]
154154autojump [ ] Autojump configuration, see https://github.com/wting/autojump for more details
content/blog/2022-08-31-privacy-com-changes.md +8 −8
@@ -14,9 +14,9 @@ order to continue using their accounts.
1414[You can view the new cardholder agreement
1515here](https://privacy.com/commercial-cardholder-agreement).
1616
17When you log in, you'll be greeted with a pop-up window asking you to review
18and agree to the new terms of use. You will also not be able to open any new
19cards until the terms are agreed to.
17When you log in, you'll be greeted with a pop-up window asking you to review and
18agree to the new terms of use. You will also not be able to open any new cards
19until the terms are agreed to.
2020
2121## Changing from a "Prepaid Debit" Model to a "Charge Card" Model
2222
@@ -36,9 +36,9 @@ Privacy.com and set the merchant as one of their pre-set options, such as
3636"Smiley's Corner Store" or "NSA Gift Shop."
3737
3838The new model still works with a bank account as a funding source, but the model
39is changed so that you get a "line of credit" set according to a 14-day
40billing cycle. It seems that Privacy.com will now allow charges to be incurred
41without being immediately paid.
39is changed so that you get a "line of credit" set according to a 14-day billing
40cycle. It seems that Privacy.com will now allow charges to be incurred without
41being immediately paid.
4242
4343## Daily Payments and Available Credit
4444
@@ -83,8 +83,8 @@ off my prepaid debit payments, I have no interest in incurring charges that will
8383need to be paid back at a later date. I also have no interest in submitting
8484personal information to Privacy.com.
8585
86This type of change toward a "buy it now, pay us later" model is concerning,
87and I will be watching Privacy.com to see if they further their interests in the
86This type of change toward a "buy it now, pay us later" model is concerning, and
87I will be watching Privacy.com to see if they further their interests in the
8888credit model as time goes on.
8989
9090Could we see them start charging interest, fees, etc.? I'm not sure, but this
content/blog/2022-09-17-serenity-os.md +1 −1
@@ -24,7 +24,7 @@ Per their website:
2424> other systems.
2525>
2626> Roughly speaking, the goal is a marriage between the aesthetic of late-1990s
27> productivity software and the power-user accessibility of late-2000s *nix.
27> productivity software and the power-user accessibility of late-2000s \*nix.
2828>
2929> This is a system by us, for us, based on the things we like.
3030
content/blog/2022-09-21-graphene-os.md +5 −5
@@ -92,9 +92,9 @@ To start, enable developer mode by going to `Settings` > `About` and tapping
9292`Build Number` seven (7) times. You may need to enter your PIN to enable this
9393mode.
9494
95Once developer mode is enabled, go to `Settings` > `System` > `Devloper
96Options` and enable OEM Unlocking, as well as USB or Wireless Debugging. In my
97case, I chose USB Debugging and performed all actions via USB cable.
95Once developer mode is enabled, go to `Settings` > `System` > `Devloper Options`
96and enable OEM Unlocking, as well as USB or Wireless Debugging. In my case, I
97chose USB Debugging and performed all actions via USB cable.
9898
9999Once these options are enabled, plug the phone into the computer and execute the
100100following command:
@@ -104,8 +104,8 @@ adb devices
104104```
105105
106106If an unauthorized error occurs, make sure the USB mode on the phone is changed
107from charging to something like "File Transfer" or "PTP." You can find the
108USB mode in the notification tray.
107from charging to something like "File Transfer" or "PTP." You can find the USB
108mode in the notification tray.
109109
110110## Reboot Device
111111
content/blog/2022-10-04-mtp-linux.md +2 −2
@@ -20,8 +20,8 @@ confirm that switching to a USB 3.0 port seemed to cut out most of my issues.
2020
2121# Switch USB Preferences to MTP
2222
23Secondly, you need to ensure that the phone's USB preferences/mode is changed
24to MTP or File Transfer once the phone is plugged in. Other modes will not allow
23Secondly, you need to ensure that the phone's USB preferences/mode is changed to
24MTP or File Transfer once the phone is plugged in. Other modes will not allow
2525you to access the phone's file system.
2626
2727# Install `jmtpfs`
content/blog/2022-10-04-syncthing.md +21 −21
@@ -11,8 +11,8 @@ If you've been looking around the self-hosted cloud storage space for a while,
1111you've undoubtedly run into someone suggesting
1212[Syncthing](https://syncthing.net) as an option. However, it is an unusual
1313alternative for those users out there who are used to having a centralized cloud
14server that serves as the "controller" of the data and interacts with clients
15on devices to fetch files.
14server that serves as the "controller" of the data and interacts with clients on
15devices to fetch files.
1616
1717This post is a walkthrough of the Syncthing software, how I set up my personal
1818storage, and some pros and cons of using the software.
@@ -114,10 +114,10 @@ per device.
114114# My Personal Cloud Storage Set-up
115115
116116Personally, I use a model similar to a traditional cloud storage service. I have
117a "centralized" server running 24/7 that acts as an Introducer for my
118Syncthing network. I think of this as my main storage and all other devices as
119tertiary client devices. I will likely add additional servers as backups as time
120goes on so that I don't have to rely on my laptop or phone as the only backups.
117a "centralized" server running 24/7 that acts as an Introducer for my Syncthing
118network. I think of this as my main storage and all other devices as tertiary
119client devices. I will likely add additional servers as backups as time goes on
120so that I don't have to rely on my laptop or phone as the only backups.
121121
122122Currently, I have one desktop and one mobile device connected to the network,
123123both running intermittently as they are not powered-on 24/7.
@@ -139,24 +139,24 @@ iCloud, etc.), and privacy-focused cloud solutions (pCloud, Tresorit, etc.).
139139
140140**Pros:**
141141
142- I've faced no data loss at all through my two-month trial run.
143- No third-parties store your data on their servers.
144- You have full control over your data and can take your data and leave at any
145 time.
146- It's possible to encrypt client-side easily with software like Cryptomator.
147- No proprietary clients or mounted volumes, just plain files and folders.
142- I've faced no data loss at all through my two-month trial run.
143- No third-parties store your data on their servers.
144- You have full control over your data and can take your data and leave at any
145 time.
146- It's possible to encrypt client-side easily with software like Cryptomator.
147- No proprietary clients or mounted volumes, just plain files and folders.
148148
149149**Cons:**
150150
151- The learning curve is steeper than traditional cloud services and is focused
152 on a technical audience.
153- If a device needs to modify files in a Folder, the devices will need to sync
154 ALL files from the folder, which may be large. To avoid size restraints, split
155 large folders into smaller folders for syncing.
156- Syncing can be slow due to the clients/servers initially connecting or
157 re-connecting after sleeping.
158- Multiple personal devices are required and require the user to own or rent
159 them as no third-party servers are involved in the storage of data.
151- The learning curve is steeper than traditional cloud services and is focused
152 on a technical audience.
153- If a device needs to modify files in a Folder, the devices will need to sync
154 ALL files from the folder, which may be large. To avoid size restraints,
155 split large folders into smaller folders for syncing.
156- Syncing can be slow due to the clients/servers initially connecting or
157 re-connecting after sleeping.
158- Multiple personal devices are required and require the user to own or rent
159 them as no third-party servers are involved in the storage of data.
160160
161161Overall, I've had a great experience with Syncthing so far. I've had no data
162162loss, syncing has been quick and easy when changes are made to files, device
content/blog/2022-10-22-alpine-linux.md +28 −29
@@ -14,8 +14,8 @@ and apk as the package manager. According to their website, an Alpine container
1414130 MB of storage." An actual bare metal machine is recommended to have 100 MB
1515of RAM and 0-700 MB of storage space.
1616
17Historically, I've used Ubuntu's minimal installation image as my server OS
18for the last five years. Ubuntu worked well and helped as my original server
17Historically, I've used Ubuntu's minimal installation image as my server OS for
18the last five years. Ubuntu worked well and helped as my original server
1919contained an nVidia GPU and no onboard graphics, so quite a few distros won't
2020boot or install without a lot of tinkering.
2121
@@ -53,24 +53,24 @@ setup-alpine
5353The setup script will ask a series of questions to configure the system. Be sure
5454to answer carefully or else you may have to re-configure the system after boot.
5555
56- Keyboard Layout (Local keyboard language and usage mode, e.g., us and variant
57 of us-nodeadkeys.)
58- Hostname (The name for the computer.)
59- Network (For example, automatic IP address discovery with the "DHCP"
60 protocol.)
61- DNS Servers (Domain Name Servers to query. For privacy reasons, it is NOT
62 recommended to route every local request to servers like Google's 8.8.8.8.)
63- Timezone
64- Proxy (Proxy server to use for accessing the web. Use "none" for direct
65 connections to the internet.)
66- Mirror (From where to download packages. Choose the organization you trust
67 giving your usage patterns to.)
68- SSH (Secure SHell remote access server. "Openssh" is part of the default
69 install image. Use "none" to disable remote login, e.g. on laptops.)
70- NTP (Network Time Protocol client used for keeping the system clock in sync
71 with a time-server. Package "chrony" is part of the default install image.)
72- Disk Mode (Select between diskless (disk="none"), "data" or "sys", as
73 described above.)
56- Keyboard Layout (Local keyboard language and usage mode, e.g., us and
57 variant of us-nodeadkeys.)
58- Hostname (The name for the computer.)
59- Network (For example, automatic IP address discovery with the "DHCP"
60 protocol.)
61- DNS Servers (Domain Name Servers to query. For privacy reasons, it is NOT
62 recommended to route every local request to servers like Google's 8.8.8.8.)
63- Timezone
64- Proxy (Proxy server to use for accessing the web. Use "none" for direct
65 connections to the internet.)
66- Mirror (From where to download packages. Choose the organization you trust
67 giving your usage patterns to.)
68- SSH (Secure SHell remote access server. "Openssh" is part of the default
69 install image. Use "none" to disable remote login, e.g. on laptops.)
70- NTP (Network Time Protocol client used for keeping the system clock in sync
71 with a time-server. Package "chrony" is part of the default install image.)
72- Disk Mode (Select between diskless (disk="none"), "data" or "sys", as
73 described above.)
7474
7575Once the setup script is finished, be sure to reboot the machine and remove the
7676USB device.
@@ -82,8 +82,8 @@ reboot
8282## Post-Installation
8383
8484There are many things you can do once your Alpine Linux system is up and
85running, and it largely depends on what you'll use the machine for. I'm going
86to walk through my personal post-installation setup for my web server.
85running, and it largely depends on what you'll use the machine for. I'm going to
86walk through my personal post-installation setup for my web server.
8787
88881. Upgrade the System
8989
@@ -96,8 +96,8 @@ to walk through my personal post-installation setup for my web server.
96962. Adding a User
9797
9898 I needed to add a user so that I don't need to log in as root. Note that if
99 you're used to using the `sudo` command, you will now need to use the
100 `doas` command on Alpine Linux.
99 you're used to using the `sudo` command, you will now need to use the `doas`
100 command on Alpine Linux.
101101
102102 ```sh
103103 apk add doas
@@ -120,8 +120,7 @@ to walk through my personal post-installation setup for my web server.
120120 doas nano /etc/apk/repositories
121121 ```
122122
123 Uncomment the community line for whichever version of Alpine you're
124 running:
123 Uncomment the community line for whichever version of Alpine you're running:
125124
126125 ```sh
127126 /media/usb/apks
@@ -258,9 +257,9 @@ doas lchsh git
258257# Thoughts on Alpine
259258
260259So far, I love Alpine Linux. I have no complaints about anything at this point,
261but I'm not completely finished with the migration yet. Once I'm able to
262upgrade my hardware to a rack-mounted server, I will migrate Plex and Syncthing
263over to Alpine as well - possibly putting Plex into a container or VM.
260but I'm not completely finished with the migration yet. Once I'm able to upgrade
261my hardware to a rack-mounted server, I will migrate Plex and Syncthing over to
262Alpine as well - possibly putting Plex into a container or VM.
264263
265264The performance is stellar, the `apk` package manager is seamless, and system
266265administration tasks are effortless. My only regret is that I didn't install
content/blog/2022-11-07-self-hosting-matrix.md +8 −8
@@ -5,7 +5,7 @@ description = ""
55draft = false
66+++
77
8# Synpase
8# Synapse
99
1010If you're reading this, you likely know that
1111[Synapse](https://github.com/matrix-org/synapse/) is a popular
@@ -72,7 +72,7 @@ are a lot of other configuration options found in the [Configuring
7272Synapse](https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html)
7373documentation that can be enabled/disabled at any point.
7474
75``` yaml
75```yaml
7676server_name: "example.com"
7777```
7878
@@ -97,7 +97,7 @@ doas nano /etc/nginx/http.d/example.com.conf
9797If you already have TLS certificates for this domain (`example.com`), you can
9898simply use the SSL configuration and point toward your TLS certificates.
9999
100``` conf
100```conf
101101server {
102102 listen 443 ssl http2;
103103 listen [::]:443 ssl http2;
@@ -139,11 +139,11 @@ server {
139139```
140140
141141If you need to generate TLS certificates (I recommend
142[Certbot](https://certbot.eff.org/)), you'll need a more minimal Nginx conf
143file before you can use the TLS-enabled example above. Instead, use this
142[Certbot](https://certbot.eff.org/)), you'll need a more minimal Nginx conf file
143before you can use the TLS-enabled example above. Instead, use this
144144configuration file during the Certbot certificate generation process:
145145
146``` conf
146```conf
147147server {
148148 server_name example.com;
149149 location / {
@@ -196,8 +196,8 @@ Router from the internet to your server's IP address.
196196
197197## Adding Matrix Users
198198
199Finally, if you didn't enable public registration in the `homeserver.yaml`
200file, you can manually create users via the command-line:
199Finally, if you didn't enable public registration in the `homeserver.yaml` file,
200you can manually create users via the command-line:
201201
202202```sh
203203cd ~/synapse
content/blog/2022-11-11-nginx-tmp-errors.md +5 −5
@@ -5,8 +5,8 @@ description = ""
55draft = false
66+++
77
8*This is a brief post so that I personally remember the solution as it has
9occurred multiple times for me.*
8_This is a brief post so that I personally remember the solution as it has
9occurred multiple times for me._
1010
1111# The Problem
1212
@@ -45,7 +45,7 @@ doas chown -R nginx:nginx /var/lib/nginx
4545sudo chown -R nginx:nginx /var/lib/nginx
4646```
4747
48You *may* also be able to change the `proxy_temp_path` in your Nginx config, but
48You _may_ also be able to change the `proxy_temp_path` in your Nginx config, but
4949I did not try this. Here's a suggestion I found online that may work if the
5050above solution does not:
5151
@@ -53,11 +53,11 @@ above solution does not:
5353nano /etc/nginx/http.d/example.com.conf
5454```
5555
56``` conf
56```conf
5757server {
5858 ...
5959
60 # Set the proxy_temp_path to your preference, make sure it's owned by the
60 # Set the proxy_temp_path to your preference, make sure it's owned by the
6161 # `nginx` user
6262 proxy_temp_path /tmp;
6363
content/blog/2022-11-27-server-build.md +19 −19
@@ -26,25 +26,25 @@ results of my server.
2626
2727I'll start by listing all the components I used for this server build:
2828
29- **Case**: [Rosewill RSV-R4100U 4U Server Chassis Rackmount
29- **Case**: [Rosewill RSV-R4100U 4U Server Chassis Rackmount
3030 Case](https://www.rosewill.com/rosewill-rsv-r4100u-black/p/9SIA072GJ92825)
31- **Motherboard**: [NZXT B550](https://nzxt.com/product/n7-b550)
32- **CPU**: AMD Ryzen 7 5700G with Radeon Graphics
33- **GPU**: N/A - I specifically chose one of the few AMD CPUs that support
31- **Motherboard**: [NZXT B550](https://nzxt.com/product/n7-b550)
32- **CPU**: AMD Ryzen 7 5700G with Radeon Graphics
33- **GPU**: N/A - I specifically chose one of the few AMD CPUs that support
3434 onboard graphics.
35- **RAM**: 64GB RAM (2x32GB) *Max of 128GB RAM on this motherboard*
36- **Boot Drive**: Western Digital 500GB M.2 NVME SSD
37- **HDD Bay**:
38 - 10TB WD White *(shucked, moved from previous server)*
39 - 8TB WD White *(shucked, moved from previous server)*
40 - 2 x 8TB WD Red Plus *(Black Friday lined up perfectly with this build,
41 so I grabbed two of these)*
42- **PSU**: Corsair RM850 PSU
43- **Extras**:
44 - Corsair TM3Q Thermal Paste
45 - Noctua 120mm fan *(replacement for front case fan)*
46 - 2 x Noctua 80mm fans *(replacement for rear case fans)*
47 - CableMatters 6Gbps SATA Cables
35- **RAM**: 64GB RAM (2x32GB) _Max of 128GB RAM on this motherboard_
36- **Boot Drive**: Western Digital 500GB M.2 NVME SSD
37- **HDD Bay**:
38 - 10TB WD White _(shucked, moved from previous server)_
39 - 8TB WD White _(shucked, moved from previous server)_
40 - 2 x 8TB WD Red Plus _(Black Friday lined up perfectly with this build,
41 so I grabbed two of these)_
42- **PSU**: Corsair RM850 PSU
43- **Extras**:
44 - Corsair TM3Q Thermal Paste
45 - Noctua 120mm fan _(replacement for front case fan)_
46 - 2 x Noctua 80mm fans _(replacement for rear case fans)_
47 - CableMatters 6Gbps SATA Cables
4848
4949# Building the Server
5050
@@ -70,8 +70,8 @@ with the tedium of removing the cage to install new drives.
7070
7171# Software
7272
73I'm not going to dive into the software as I have done so in other recent
74posts. However, I wanted to note that I am using Alpine Linux on this server and
73I'm not going to dive into the software as I have done so in other recent posts.
74However, I wanted to note that I am using Alpine Linux on this server and
7575hosting most services inside Docker. No virtual machines (VMs) and very few
7676bare-metal services.
7777
content/blog/2022-11-29-nginx-referrer-ban-list.md +13 −10
@@ -20,7 +20,7 @@ doas nano /etc/nginx/banlist.conf
2020Next, paste the following contents in and fill out the regexes with whichever
2121domains you're blocking.
2222
23``` conf
23```conf
2424# /etc/nginx/banlist.conf
2525
2626map $http_referer $bad_referer {
@@ -45,7 +45,7 @@ doas nano /etc/nginx/nginx.conf
4545Within this file, find the `http` block and add your ban list file location to
4646the end of the block.
4747
48``` conf
48```conf
4949# /etc/nginx/nginx.conf
5050
5151http {
@@ -76,7 +76,7 @@ Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) you want. Code
7676403 (Forbidden) is logical in this case since you are preventing a client
7777connection due to a banned domain.
7878
79``` conf
79```conf
8080server {
8181 ...
8282
@@ -108,7 +108,7 @@ curl https://cleberg.net
108108
109109The HTML contents of the page come back successfully:
110110
111``` html
111```html
112112<!doctype html>...</html>
113113```
114114
@@ -122,12 +122,15 @@ This time, I'm met with a 403 Forbidden response page. That means we are
122122successful and any clients being referred from a banned domain will be met with
123123this same response code.
124124
125``` html
125```html
126126<html>
127<head><title>403 Forbidden</title></head>
128<body>
129<center><h1>403 Forbidden</h1></center>
130<hr><center>nginx</center>
131</body>
127 <head>
128 <title>403 Forbidden</title>
129 </head>
130 <body>
131 <center><h1>403 Forbidden</h1></center>
132 <hr />
133 <center>nginx</center>
134 </body>
132135</html>
133136```
content/blog/2022-12-01-nginx-compression.md +23 −23
@@ -22,10 +22,10 @@ nano /etc/nginx/nginx.conf
2222
2323Within the `http` block, find the section that shows something like the block
2424below. This is the default gzip configuration I found in my `nginx.conf` file on
25Alpine Linux 3.17. Yours may look slightly different, just make sure that
26you're not creating any duplicate gzip options.
25Alpine Linux 3.17. Yours may look slightly different, just make sure that you're
26not creating any duplicate gzip options.
2727
28``` conf
28```conf
2929# Enable gzipping of responses.
3030#gzip on;
3131
@@ -35,7 +35,7 @@ gzip_vary on;
3535
3636Remove the default gzip lines and replace them with the following:
3737
38``` conf
38```conf
3939# Enable gzipping of responses.
4040gzip on;
4141gzip_vary on;
@@ -50,25 +50,25 @@ gzip_disable "MSIE [1-6]";
5050Each of the lines above enables a different aspect of the gzip response for
5151Nginx. Here are the full explanations:
5252
53- `gzip` -- Enables or disables gzipping of responses.
54- `gzip_vary` -- Enables or disables inserting the "Vary: Accept-Encoding"
55 response header field if the directives gzip, gzip~static~, or gunzip are
56 active.
57- `gzip_min_length` -- Sets the minimum length of a response that will be
58 gzipped. The length is determined only from the "Content-Length" response
59 header field.
60- `gzip_proxied` -- Enables or disables gzipping of responses for proxied
61 requests depending on the request and response. The fact that the request is
62 proxied is determined by the presence of the "Via" request header field.
63- `gzip_types` -- Enables gzipping of responses for the specified MIME types in
64 addition to "text/html". The special value "*" matches any MIME type
65 (0.8.29). Responses with the "text/html" type are always compressed.
66- `gzip_disable` -- Disables gzipping of responses for requests with
67 "User-Agent" header fields matching any of the specified regular
68 expressions.
69 - The special mask "msie6" (0.7.12) corresponds to the regular expression
70 "MSIE [4-6].", but works faster. Starting from version 0.8.11, "MSIE
71 6.0; ... SV1" is excluded from this mask.
53- `gzip` -- Enables or disables gzipping of responses.
54- `gzip_vary` -- Enables or disables inserting the "Vary: Accept-Encoding"
55 response header field if the directives gzip, gzip~static~, or gunzip are
56 active.
57- `gzip_min_length` -- Sets the minimum length of a response that will be
58 gzipped. The length is determined only from the "Content-Length" response
59 header field.
60- `gzip_proxied` -- Enables or disables gzipping of responses for proxied
61 requests depending on the request and response. The fact that the request is
62 proxied is determined by the presence of the "Via" request header field.
63- `gzip_types` -- Enables gzipping of responses for the specified MIME types
64 in addition to "text/html". The special value "\*" matches any MIME type
65 (0.8.29). Responses with the "text/html" type are always compressed.
66- `gzip_disable` -- Disables gzipping of responses for requests with
67 "User-Agent" header fields matching any of the specified regular
68 expressions.
69 - The special mask "msie6" (0.7.12) corresponds to the regular expression
70 "MSIE [4-6].", but works faster. Starting from version 0.8.11, "MSIE
71 6.0; ... SV1" is excluded from this mask.
7272
7373More information on these directives and their options can be found on the
7474[Module
content/blog/2022-12-07-nginx-wildcard-redirect.md +4 −4
@@ -20,7 +20,7 @@ Instead, I finally found a solution that allows me to redirect both subdomains
2020AND trailing content. For example, both of these URLs now redirect properly
2121using the logic I'll explain below:
2222
23``` txt
23```txt
2424# Example 1 - Simple base domain redirect with trailing content
2525https://domain1.com/blog/alpine-linux/ -> https://domain2.com/blog/alpine-linux/
2626
@@ -44,7 +44,7 @@ doas nano /etc/nginx/http.d/domain1.conf
4444Within this file, I had one block configured to redirect HTTP requests to HTTPS
4545for the base domain and all subdomains.
4646
47``` conf
47```conf
4848server {
4949 listen [::]:80;
5050 listen 80;
@@ -66,7 +66,7 @@ For the base domain, I have another `server` block dedicated to redirecting all
6666base domain requests. You can see that the `rewrite` line is instructing Nginx
6767to gather all trailing content and append it to the new `domain2.com` URL.
6868
69``` conf
69```conf
7070server {
7171 listen [::]:443 ssl http2;
7272 listen 443 ssl http2;
@@ -91,7 +91,7 @@ Once the server gets to the `rewrite` line, it pulls the `subdomain` variable
9191from above and uses it on the new `domain2.com` domain before appending the
9292trailing content (`$request_uri`).
9393
94``` conf
94```conf
9595server {
9696 listen [::]:443 ssl http2;
9797 listen 443 ssl http2;
content/blog/2022-12-17-st.md +4 −4
@@ -57,8 +57,8 @@ Note that customizing `st` requires you to modify the source files or to
5757download one of the [available patches](https://st.suckless.org/patches/) for
5858suckless.org.
5959
60If you've already installed `st` and want to customize or install a patch,
61start by uninstalling the current program.
60If you've already installed `st` and want to customize or install a patch, start
61by uninstalling the current program.
6262
6363```sh
6464cd ~/suckless/st
@@ -75,8 +75,8 @@ wget https://st.suckless.org/patches/defaultfontsize/st-defaultfontsize-20210225
7575```
7676
7777Once the file is downloaded inside the `st` folder, apply the patch and
78re-install the program. You may need to install the `patch` command if you
79don't have it installed already (you should have installed it above).
78re-install the program. You may need to install the `patch` command if you don't
79have it installed already (you should have installed it above).
8080
8181```sh
8282patch -i st-defaultfontsize-20210225-4ef0cbd.diff
content/blog/2022-12-23-alpine-desktop.md +4 −4
@@ -59,7 +59,7 @@ For v3.17, the `repositories` file should look like this:
5959nano /etc/apk/repositories
6060```
6161
62``` conf
62```conf
6363#/media/sda/apks
6464http://mirrors.gigenet.com/alpinelinux/v3.17/main
6565http://mirrors.gigenet.com/alpinelinux/v3.17/community
@@ -193,7 +193,7 @@ Then, I added the Wi-Fi entry to the bottom of the networking interface file:
193193nano /etc/network/interfaces
194194```
195195
196``` conf
196```conf
197197auto wlan0
198198iface wlan0 inet dhcp
199199```
@@ -215,7 +215,7 @@ Really, the solution was to enable the `NameResolvingService=resolvconf` in
215215doas nano /etc/iwd/main.conf
216216```
217217
218``` conf
218```conf
219219[Network]
220220
221221NameResolvingService=resolvconf
@@ -248,7 +248,7 @@ sway.
248248nano ~/.config/sway/config
249249```
250250
251``` conf
251```conf
252252# Run pipewire audio server
253253exec /usr/libexec/pipewire-launcher
254254
content/blog/2023-01-05-mass-unlike-tumblr-posts.md +20 −16
@@ -26,14 +26,18 @@ buttons.
2626Tumblr's unlike buttons are structured as you can see in the following code
2727block. All unlike buttons have an `aria-label` with a value of `Unlike`.
2828
29``` html
29```html
3030<button class="TRX6J" aria-label="Unlike">
31 <span class="EvhBA B1Z5w ztpfZ" tabindex="-1">
32 <svg xmlns="http://www.w3.org/2000/svg" height="21" width="23"
33 role="presentation">
34 <use href="#managed-icon__like-filled"></use>
35 </svg>
36 </span>
31 <span class="EvhBA B1Z5w ztpfZ" tabindex="-1">
32 <svg
33 xmlns="http://www.w3.org/2000/svg"
34 height="21"
35 width="23"
36 role="presentation"
37 >
38 <use href="#managed-icon__like-filled"></use>
39 </svg>
40 </span>
3741</button>
3842```
3943
@@ -46,8 +50,8 @@ Further, be sure to scroll down to the bottom and force Tumblr to load more
4650posts so that this script unlikes more posts at a time.
4751
4852Once you are logged in and the page is loaded, open the Developer Tools and be
49sure you're on the "Console" tab. It should look something like this (this is
50in Firefox, Chromium should be similar):
53sure you're on the "Console" tab. It should look something like this (this is in
54Firefox, Chromium should be similar):
5155
5256![Firefox Dev
5357!Tools](https:///img.cleberg.net/blog/20230105-mass-unlike-tumblr-posts/dev_console.png)
@@ -58,17 +62,17 @@ unlike it.
5862
5963Optionally, you can comment-out the line `elements[i].click();` and uncomment
6064the `console.log()` lines to simply print out information without performing any
61actions. This can be useful to debug issues or confirm that the code below
62isn't doing anything you don't want it to.
65actions. This can be useful to debug issues or confirm that the code below isn't
66doing anything you don't want it to.
6367
64``` javascript
68```javascript
6569const elements = document.querySelectorAll('[aria-label="Unlike"]');
6670// console.log(elements); // 👉 [button]
6771
68for (let i=0; i < elements.length; i++) {
69 // console.log(elements[i]);
70 elements[i].click();
71}
72for (let i = 0; i < elements.length; i++) {
73 // console.log(elements[i]);
74 elements[i].click();
75}
7276```
7377
7478# Results
content/blog/2023-01-08-fedora-login-manager.md +1 −1
@@ -33,7 +33,7 @@ In order to launch i3 manually, you need to set up your X session properly. To
3333start, create or edit the `~/.xinitrc` file to include the following at the
3434bottom.
3535
36``` config
36```config
3737exec i3
3838```
3939
content/blog/2023-01-21-flatpak-symlinks.md +3 −4
@@ -14,8 +14,8 @@ and manually running the Flatpak app with the lengthy `flatpak run ...` command.
1414In the past, I manually created aliases in my `.zshrc` file for certain apps.
1515For example, an alias would look like the example below.
1616
17This would allow me to run the command fast within the terminal, but it
18wouldn't allow me to run it in an application launcher.
17This would allow me to run the command fast within the terminal, but it wouldn't
18allow me to run it in an application launcher.
1919
2020```sh
2121# ~/.zshrc
@@ -27,8 +27,7 @@ tiling WMs I use and their application launchers - `dmenu` and `bemenu`.
2727
2828# Creating Symlinks for Flatpak Apps
2929
30Let's use the example of Librewolf below. I can install the application like
31so:
30Let's use the example of Librewolf below. I can install the application like so:
3231
3332```sh
3433flatpak install flathub io.gitlab.librewolf-community
content/blog/2023-01-23-random-wireguard.md +7 −7
@@ -7,8 +7,8 @@ draft = false
77
88# Mullvad Wireguard
99
10If you're using an OS that does not support one of Mullvad's apps, you're
11likely using the Wireguard configuration files instead.
10If you're using an OS that does not support one of Mullvad's apps, you're likely
11using the Wireguard configuration files instead.
1212
1313If not, the first step is to visit Mullvad's [Wireguard configuration
1414files](https://mullvad.net/en/account/#/wireguard-config) page and download a
@@ -64,7 +64,7 @@ chmod +x ~/vpn.sh
6464
6565The output should look like the following:
6666
67``` txt
67```txt
6868doas (user@host) password:
6969
7070# ... The script will process all of the iptables and wg commands here
@@ -75,8 +75,8 @@ Printing new IP info:
7575You are connected to Mullvad (server country-city-wg-num). Your IP address is 12.345.678.99
7676```
7777
78That's all there is to it. You can see your new location and IP via the
79`printf` and `curl` commands included in the script.
78That's all there is to it. You can see your new location and IP via the `printf`
79and `curl` commands included in the script.
8080
8181You can also go to the [Connection Check ​\|
8282Mullvad](https://mullvad.net/en/check/) page to see if you are fully connected
@@ -104,8 +104,8 @@ wg-quick down /home/user/mullvad/us-lax-wg-104.conf
104104```
105105
106106I have a TODO item on figuring out how to easily export an environment variable
107that contains the configuration file's full name, so that I can just execute
108the following:
107that contains the configuration file's full name, so that I can just execute the
108following:
109109
110110```sh
111111# Ideal situation if I can export the $file variable to the environment
content/blog/2023-01-28-self-hosting-wger.md +26 −26
@@ -18,29 +18,29 @@ own after installing wger:
1818
19191. Dashboard
2020
21 - Dashboard view of Workout Schedule, Nutrition Plan, Weight Graph, & last
21 - Dashboard view of Workout Schedule, Nutrition Plan, Weight Graph, & last
2222 5 Weight Logs
2323
24242. Training
2525
26 - Workout Log
27 - Workout Schedule
28 - Calendar (shows weight logs and Bad/Neutral/Good days)
29 - Gallery (shows images you upload)
30 - Workout templates
31 - Public templates
32 - Exercises
26 - Workout Log
27 - Workout Schedule
28 - Calendar (shows weight logs and Bad/Neutral/Good days)
29 - Gallery (shows images you upload)
30 - Workout templates
31 - Public templates
32 - Exercises
3333
34343. Nutrition
3535
36 - Nutrition plans
37 - BMI calculator
38 - Daily calories calculator
39 - Ingredient overview
36 - Nutrition plans
37 - BMI calculator
38 - Daily calories calculator
39 - Ingredient overview
4040
41414. Body Weight
4242
43 - Weight overview
43 - Weight overview
4444
4545## Documentation
4646
@@ -67,14 +67,14 @@ above.
6767
6868A few notes to explain the changes I made to the default files:
6969
70- I updated the `ALLOW_REGISTRAION` variable in `prod.env` to `False` after I
71 created an account via my LAN connection, **before** I connected this app to a
72 publicly-available domain.
73- I uncommented and updated `CSRF_TRUSTED_ORIGINS` to be equal to the public
74 version of this app: `https://wger.example.com`.
75- I updated the port within `docker-compose.yml`, within the `nginx` block. The
76 port I updated this to will be reflected in my nginx configuration file on the
77 server (NOT the wger nginx.conf file).
70- I updated the `ALLOW_REGISTRAION` variable in `prod.env` to `False` after I
71 created an account via my LAN connection, **before** I connected this app to
72 a publicly-available domain.
73- I uncommented and updated `CSRF_TRUSTED_ORIGINS` to be equal to the public
74 version of this app: `https://wger.example.com`.
75- I updated the port within `docker-compose.yml`, within the `nginx` block.
76 The port I updated this to will be reflected in my nginx configuration file
77 on the server (NOT the wger nginx.conf file).
7878
7979## Deploy
8080
@@ -89,17 +89,17 @@ You can now visit the website on your LAN by going to `localhost:YOUR_PORT` or
8989by the server's IP, if you're not on the same machine that is running the
9090container.
9191
92If you wish to connect this app to a public domain name, you'll need to point
93an `A` DNS record from the domain to your server's public IP. You'll then need
94to create a configuration file for whichever web server or reverse proxy you're
92If you wish to connect this app to a public domain name, you'll need to point an
93`A` DNS record from the domain to your server's public IP. You'll then need to
94create a configuration file for whichever web server or reverse proxy you're
9595using.
9696
9797Wger's README suggests the following reverse proxy configuration for Nginx:
9898
99``` conf
99```conf
100100upstream wger {
101101 # This port should match the port in the `nginx` block of docker-compose.yml
102 # If the container is running on this same machine, replace this with
102 # If the container is running on this same machine, replace this with
103103 # server 127.0.0.1:8080
104104 server 123.456.789.0:8080;
105105}
content/blog/2023-02-02-exploring-hare.md +6 −6
@@ -33,8 +33,8 @@ program.
3333
3434## Installation
3535
36I'm currently running Alpine Linux on my Thinkpad, so the installation was
37quite easy as there is a package for Hare in the `apk` repositories.
36I'm currently running Alpine Linux on my Thinkpad, so the installation was quite
37easy as there is a package for Hare in the `apk` repositories.
3838
3939```sh
4040doas apk add hare hare-doc
@@ -132,8 +132,8 @@ hare build -o example file.ha
132132
133133 While I was able to piece everything together eventually, the biggest
134134 downfall right now in Hare's documentation. For such a new project, the
135 documentation is in a great spot. However, bare specifications don't help
136 as much as a brief examples section would.
135 documentation is in a great spot. However, bare specifications don't help as
136 much as a brief examples section would.
137137
138138 For example, it took me a while to figure out what the `u64n` function was
139139 looking for. I could tell that it took two parameters and the second was my
@@ -150,8 +150,8 @@ hare build -o example file.ha
150150 enjoy seeing in Hare, such as one to convert decimal (base 10) values to
151151 hexadecimal (base 16).
152152
153 If I'm feeling comfortable with my math, I may work on the list of
154 functions I want and see if any can make it into the Hare source code.
153 If I'm feeling comfortable with my math, I may work on the list of functions
154 I want and see if any can make it into the Hare source code.
155155
1561563. Overall Thoughts
157157
content/blog/2023-05-22-burnout.md +3 −3
@@ -5,7 +5,7 @@ description = ""
55draft = false
66+++
77
8# RE: Burnout {#re-burnout-1}
8# RE: Burnout
99
1010I recently read [Drew DeVault's post on
1111burnout](https://drewdevault.com/2023/05/01/2023-05-01-Burnout.html) around the
@@ -41,5 +41,5 @@ programming, athletics, games, etc.
4141You may have noticed my absence if you're in the same channels, forums, and
4242rooms that I am, but I should finally be active again.
4343
44I'm hoping to break an item out of my backlog soon and start working on
45building a new project or hack around with a stale one.
44I'm hoping to break an item out of my backlog soon and start working on building
45a new project or hack around with a stale one.
content/blog/2023-06-08-goaccess-geoip.md +1 −1
@@ -8,7 +8,7 @@ draft = false
88# Overview
99
1010[GoAccess](https://goaccess.io/) is an open source real-time web log analyzer
11and interactive viewer that runs in a terminal in *nix systems or through your
11and interactive viewer that runs in a terminal in \*nix systems or through your
1212browser.
1313
1414# Installation
content/blog/2023-06-08-self-hosting-baikal.md +3 −3
@@ -28,14 +28,14 @@ the `ports` section to use any port on your server to pass through to port 80 in
2828the container. You can also edit the `volumes` section to use docker volumes
2929instead of local folders.
3030
31``` conf
31```conf
3232version: "2"
3333services:
3434 baikal:
3535 image: ckulka/baikal:nginx
3636 restart: always
3737 ports:
38 - "8567:80"
38 - "8567:80"
3939 volumes:
4040 - ./config:/var/www/baikal/config
4141 - ./data:/var/www/baikal/Specific
@@ -93,7 +93,7 @@ nano dav
9393Within this file, paste in the configuration from below and change
9494`dav.example.com` to match the URL you'll be using.
9595
96``` conf
96```conf
9797server {
9898 if ($host ~ ^[^.]+\.example\.com$) {
9999 return 301 https://$host$request_uri;
content/blog/2023-06-18-unifi-ip-blocklist.md +9 −8
@@ -7,8 +7,8 @@ draft = false
77
88# Identifying Abusive IPs
99
10If you're like me and use Unifi network equipment at the edge of the network
11you manage, you may know that Unifi is only somewhat decent at identifying and
10If you're like me and use Unifi network equipment at the edge of the network you
11manage, you may know that Unifi is only somewhat decent at identifying and
1212blocking IPs that represent abusive or threat actors.
1313
1414While Unifi has a [threat
@@ -28,6 +28,7 @@ blocked yet.
2828# Create an IP Group Profile
2929
3030To start, login to the Unifi machine's web GUI and navigate to the Network app
31
3132> Settings > Profiles.
3233
3334Within this page, choose the `IP Groups` tab and click `Create New`.
@@ -58,12 +59,12 @@ navigate to the Network app > Settings > Firewall & Security.
5859Within this screen, find the Firewall Rules table and click `Create Entry`. This
5960entry should contain the following settings:
6061
61- Type: `Internet In`
62- Description: `<Your Custom Rule>`
63- Rule Applied: `Before Predefined Rules`
64- Action: `Drop`
65- Source Type: `Port/IP Group`
66- IPv4 Address Group: `<Name of the Group Profile You Created Above>`
62- Type: `Internet In`
63- Description: `<Your Custom Rule>`
64- Rule Applied: `Before Predefined Rules`
65- Action: `Drop`
66- Source Type: `Port/IP Group`
67- IPv4 Address Group: `<Name of the Group Profile You Created Above>`
6768
6869Customize the remaining configurations to your liking, and then save and enable
6970the firewall rule.
content/blog/2023-06-20-audit-review-template.md +28 −27
@@ -7,7 +7,7 @@ draft = false
77
88# Overview
99
10This post is a *very* brief overview on the basic process to review audit test
10This post is a _very_ brief overview on the basic process to review audit test
1111results, focusing on work done as part of a financial statement audit (FSA) or
1212service organization controls (SOC) report.
1313
@@ -25,52 +25,53 @@ variety of engagements, while still ensuring that all key areas are covered.
25251. [ ] Check all documents for spelling and grammar.
26262. [ ] Ensure all acronyms are fully explained upon first use.
27273. [ ] For all people referenced, use their full names and job titles upon first
28 use.
28 use.
29294. [ ] All supporting documents must cross-reference to the lead sheet and
30 vice-versa.
30 vice-versa.
31315. [ ] Verify that the control has been adequately tested:
3232 - [ ] **Test of Design**: Did the tester obtain information regarding how
33 the control should perform normally and abnormally (e.g., emergency
34 scenarios)?
33 the control should perform normally and abnormally (e.g., emergency
34 scenarios)?
3535 - [ ] **Test of Operating Effectiveness**: Did the tester inquire, observe,
36 inspect, or re-perform sufficient evidence to support their conclusion
37 over the control? Inquiry alone is not adequate!
36 inspect, or re-perform sufficient evidence to support their conclusion
37 over the control? Inquiry alone is not adequate!
38386. [ ] For any information used in the control, whether by the control operator
39 or by the tester, did the tester appropriately document the source (system or
40 person), extraction method, parameters, and completeness and accuracy (C&A)?
39 or by the tester, did the tester appropriately document the source
40 (system or person), extraction method, parameters, and completeness and
41 accuracy (C&A)?
4142 - [ ] For any reports, queries, etc. used in the extraction, did the tester
42 include a copy and notate C&A considerations?
43 include a copy and notate C&A considerations?
43447. [ ] Did the tester document the specific criteria that the control is being
44 tested against?
45 tested against?
45468. [ ] Did the tester notate in the supporting documents where each criterion
46 was satisfied?
47 was satisfied?
47489. [ ] If testing specific policies or procedures, are the documents adequate?
4849 - [ ] e.g., a test to validate that a review of policy XYZ occurs
49 periodically should also evaluate the sufficiency of the policy itself, if
50 meant to cover the risk that such a policy does not exist and is not
51 reviewed.
50 periodically should also evaluate the sufficiency of the policy
51 itself, if meant to cover the risk that such a policy does not exist
52 and is not reviewed.
525310. [ ] Does the test cover the appropriate period under review?
5354 - [ ] If the test is meant to cover only a portion of the audit period, do
54 other controls exist to mitigate the risks that exist for the remainder of
55 the period?
55 other controls exist to mitigate the risks that exist for the
56 remainder of the period?
565711. [ ] For any computer-aided audit tools (CAATs) or other automation
57 techniques used in the test, is the use of such tools explained and
58 appropriately documented?
58 techniques used in the test, is the use of such tools explained and
59 appropriately documented?
596012. [ ] If prior-period documentation exists, are there any missing pieces of
60 evidence that would further enhance the quality of the test?
61 evidence that would further enhance the quality of the test?
616213. [ ] Was any information discovered during the walkthrough or inquiry phase
62 that was not incorporated into the test?
63 that was not incorporated into the test?
636414. [ ] Are there new rules or expectations from your company's internal
64 guidance or your regulatory bodies that would affect the audit approach for
65 this control?
65 guidance or your regulatory bodies that would affect the audit approach
66 for this control?
666715. [ ] Was an exception, finding, or deficiency identified as a result of this
67 test?
68 test?
6869 - [ ] Was the control deficient in design, operation, or both?
6970 - [ ] What was the root cause of the finding?
7071 - [ ] Does the finding indicate other findings or potential fraud?
7172 - [ ] What's the severity and scope of the finding?
7273 - [ ] Do other controls exist as a form of compensation against the
73 finding's severity, and do they mitigate the risk within the control
74 objective?
74 finding's severity, and do they mitigate the risk within the control
75 objective?
7576 - [ ] Does the finding exist at the end of the period, or was it resolved
76 within the audit period?
77 within the audit period?
content/blog/2023-06-23-byobu.md +2 −2
@@ -38,8 +38,8 @@ explore should be the keybindings section.
3838
3939The keybindings are configured as follows:
4040
41``` txt
42byobu keybindings can be user defined in /usr/share/byobu/keybindings/ (or
41```txt
42byobu keybindings can be user defined in /usr/share/byobu/keybindings/ (or
4343within .screenrc if byobu-export was used). The common key bindings are:
4444
4545F2 - Create a new window
content/blog/2023-06-23-self-hosting-convos.md +15 −15
@@ -10,15 +10,15 @@ draft = false
1010[Convos](https://convos.chat/) is an always-online web client for IRC. It has a
1111few features that made it attractive to me as a self-hosted option:
1212
13- Extremely simple Docker Compose installation method.
14- Runs in the background and monitors chats even while you're not logged in.
15- Neatly organized sidebar for conversation and client settings.
16- Ability to connect to different hosts and create profiles for hosts.
17- By default, registration is closed to the public. You can enable public
18 registration on the Settings page or generate invitation links on the Users
19 page.
20- Customization of the client theme, organization name and URL, admin email, and
21 video service.
13- Extremely simple Docker Compose installation method.
14- Runs in the background and monitors chats even while you're not logged in.
15- Neatly organized sidebar for conversation and client settings.
16- Ability to connect to different hosts and create profiles for hosts.
17- By default, registration is closed to the public. You can enable public
18 registration on the Settings page or generate invitation links on the Users
19 page.
20- Customization of the client theme, organization name and URL, admin email,
21 and video service.
2222
2323# Docker Installation
2424
@@ -34,7 +34,7 @@ file. You can customize the host port to be something unique, such as
3434`21897:3000`. You can also change the `data` folder to be a docker volume
3535instead, if you prefer.
3636
37``` config
37```config
3838version: '3'
3939
4040services:
@@ -71,7 +71,7 @@ Within the nginx configuration file, paste the following content and be sure to
7171update `convos.example.com` to match your domain and `127.0.0.1:3000` to match
7272the port you opened in the `docker-compose.yml` file.
7373
74``` config
74```config
7575# Host and port where convos is running
7676upstream convos_upstream { server 127.0.0.1:3000; }
7777
@@ -138,22 +138,22 @@ Convos, the default sever is libera.chat. Simply click the `libera` conversation
138138at the top of the sidebar to open it. Once the chat is open, you can claim a
139139nickname by typing:
140140
141``` txt
141```txt
142142/nick <nick>
143143```
144144
145145If the nickname is available, and you'd like to register the nickname to
146146yourself, you'll need to type another command:
147147
148``` txt
149/msg NickServ REGISTER
148```txt
149/msg NickServ REGISTER
150150<password> <email>
151151```
152152
153153On libera.chat, the server will send a confirmation email with a command that
154154you must message in IRC to verify registration of the nickname:
155155
156``` txt
156```txt
157157/msg NickServ VERIFY REGISTER <nick> <verification_code>
158158```
159159
content/blog/2023-06-28-backblaze-b2.md +14 −14
@@ -15,11 +15,11 @@ $0.01/GB/month.
1515
1616However, there are free tiers:
1717
18- The first 10 GB of storage is free.
19- The first 1 GB of data downloaded each day is free.
20- Class A transactions are free.
21- The first 2500 Class B transactions each day are free.
22- The first 2500 Class C transactions each day are free.
18- The first 10 GB of storage is free.
19- The first 1 GB of data downloaded each day is free.
20- Class A transactions are free.
21- The first 2500 Class B transactions each day are free.
22- The first 2500 Class C transactions each day are free.
2323
2424You can see which API calls fall into categories A, B, or C here: [Pricing
2525Organized by API
@@ -42,8 +42,8 @@ file upload and then sync an entire directory to my Backblaze bucket.
4242# Create a Bucket
4343
4444Before you can start uploading, you need to create a bucket. If you're familiar
45with other object storage services, this will feel familiar. If not, it's
46pretty simple to create one.
45with other object storage services, this will feel familiar. If not, it's pretty
46simple to create one.
4747
4848As their webpage says:
4949
@@ -55,10 +55,10 @@ As their webpage says:
5555Once you click the `Create a Bucket` button on their webpage or mobile app, you
5656need to provide the following:
5757
58- Bucket Unique Name
59- Files in Bucket are: `Private` or `Public`
60- Default Encryption: `Disable` or `Enable`
61- Object Lock: `Disable` or `Enable`
58- Bucket Unique Name
59- Files in Bucket are: `Private` or `Public`
60- Default Encryption: `Disable` or `Enable`
61- Object Lock: `Disable` or `Enable`
6262
6363For my bucket, I created a private bucket with encryption enabled and object
6464lock disabled.
@@ -126,7 +126,7 @@ bucket:
126126b2 ls <bucket_name>
127127```
128128
129``` txt
129```txt
130130test.md
131131```
132132
@@ -166,8 +166,8 @@ Note that symlinks are resolved by b2, so if you have a link from
166166has 10TB of data, `b2` will resolve that link and start uploading all 10TB of
167167data linked within the folder.
168168
169If you're not sure if you have any symlinks, a symlink will look like this
170(note the `->` symbol):
169If you're not sure if you have any symlinks, a symlink will look like this (note
170the `->` symbol):
171171
172172```sh
173173> ls -lha
content/blog/2023-06-30-self-hosting-voyager.md +4 −4
@@ -48,7 +48,7 @@ I will be using a `docker-compose.yml` file to run this container, instead of a
4848nano docker-compose.yml
4949```
5050
51``` conf
51```conf
5252version: "2"
5353services:
5454 voyager:
@@ -70,8 +70,8 @@ The web app will now be available at the following address:
7070
7171## Reverse Proxy
7272
73If you want to visit this app via an external URL or domain name, you'll need
74to set up a reverse proxy. The example below uses Nginx as a reverse proxy.
73If you want to visit this app via an external URL or domain name, you'll need to
74set up a reverse proxy. The example below uses Nginx as a reverse proxy.
7575
7676Simply create the configuration file, paste the contents below, save the file,
7777symlink the file, and restart Nginx.
@@ -80,7 +80,7 @@ symlink the file, and restart Nginx.
8080sudo nano /etc/nginx/sites-available/voyager
8181```
8282
83``` conf
83```conf
8484server {
8585 if ($host ~ ^[^.]+\.example\.com$) {
8686 return 301 https://$host$request_uri;
content/blog/2023-07-12-wireguard-lan.md +12 −12
@@ -25,7 +25,7 @@ doas mv *.conf /etc/wireguard/
2525
2626The default configuration files will look something like this:
2727
28``` conf
28```conf
2929[Interface]
3030# Device: <redacted>
3131PrivateKey = <redacted>
@@ -40,9 +40,9 @@ AllowedIPs = <redacted>
4040Endpoint = <redacted>
4141```
4242
43> Note: If you didn't select the kill switch option, you won't see the
44> `PostUp` and `PreDown` lines. In this case, you'll need to modify the script
45> below to simply append those lines to the `[Interface]` block.
43> Note: If you didn't select the kill switch option, you won't see the `PostUp`
44> and `PreDown` lines. In this case, you'll need to modify the script below to
45> simply append those lines to the `[Interface]` block.
4646
4747# Editing the Configuration Files
4848
@@ -51,15 +51,15 @@ Once you have the files, you'll need to edit them and replace the `PostUp` and
5151
5252I recommend that you do this process as root, since you'll need to be able to
5353access files in `/etc/wireguard`, which are generally owned by root. You can
54also try using `sudo` or `doas`, but I didn't test that scenario so you may
55need to adjust, as necessary.
54also try using `sudo` or `doas`, but I didn't test that scenario so you may need
55to adjust, as necessary.
5656
5757```sh
5858su
5959```
6060
61Create the Python file that we'll be using to update the Wireguard
62configuration files.
61Create the Python file that we'll be using to update the Wireguard configuration
62files.
6363
6464```sh
6565nano replace.py
@@ -73,7 +73,7 @@ commands.
7373> Note: If your LAN is on a subnet other than `192.168.1.0/24`, you'll need to
7474> update the Python script below appropriately.
7575
76``` python
76```python
7777import os
7878import fileinput
7979
@@ -94,8 +94,8 @@ for file in os.listdir(dir):
9494print("--- done ---")
9595```
9696
97Once you're done, save and close the file. You can now run the Python script
98and watch as each file is updated.
97Once you're done, save and close the file. You can now run the Python script and
98watch as each file is updated.
9999
100100```sh
101101python3 replace.py
@@ -110,7 +110,7 @@ cat /etc/wireguard/us-chi-wg-001.conf
110110
111111The configuration files should now look like this:
112112
113``` conf
113```conf
114114[Interface]
115115# Device: <redacted>
116116PrivateKey = <redacted>
content/blog/2023-07-19-plex-transcoder-errors.md +6 −6
@@ -10,21 +10,21 @@ draft = false
1010Occasionally, you may see an error in your Plex client that references a failure
1111with the transcoder conversion process. The specific error wording is:
1212
13``` txt
13```txt
1414Conversion failed. The transcoder failed to start up.
1515```
1616
1717# Debugging the Cause
1818
19In order to get a better look at what is causing the error, I'm going to
20observe the Plex console while the error occurs. To do this, open the Plex web
21client, go to `Settings` > `Manage` > `Console`. Now, try to play the title
22again and watch to see which errors occur.
19In order to get a better look at what is causing the error, I'm going to observe
20the Plex console while the error occurs. To do this, open the Plex web client,
21go to `Settings` > `Manage` > `Console`. Now, try to play the title again and
22watch to see which errors occur.
2323
2424In my case, you can see the errors below are related to a subtitle file (`.srt`)
2525causing the transcoder to crash.
2626
27``` txt
27```txt
2828Jul 19, 2023 16:49:34.945 [140184571120440] Error — Couldn't find the file to stream: /movies/Movie Title (2021)/Movie Title (2021).srt
2929Jul 19, 2023 16:49:34.947 [140184532732728] Error — [Req#7611/Transcode/42935159-67C1-4192-9336-DDC6F7BC9330] Error configuring transcoder: TPU: Failed to download sub-stream to temporary file
3030Jul 19, 2023 16:49:35.225 [140184532732728] Warning — [Req#760d/Transcode] Got a request to stop a transcode session without a valid session GUID.
content/blog/2023-08-18-agile-auditing.md +17 −17
@@ -52,20 +52,20 @@ processes and controls at hand.
5252
5353Audit Examples:
5454
55- Engagement teams must value the team members, client contacts, and their
56 interactions over the historical processes and tools that have been used.
57- Engagement teams must value a final report that contains sufficient audit
58 documentation over excessive documentation or scope creep.
59- Engagement teams must collaborate with the audit clients as much as feasible
60 to ensure that both sides are constantly updated with current knowledge of the
61 engagement's status and any potential findings, rather than waiting for
62 pre-set meetings or the end of the engagement to communicate.
63- Engagement teams must be able to respond to change in an engagement's
64 schedule, scope, or environment to ensure that the project is completed in a
65 timely manner and that all relevant areas are tested.
66 - In terms of an audit department's portfolio, they must be able to respond
67 to changes in their company's or client's environment and be able to
68 dynamically change their audit plan accordingly.
55- Engagement teams must value the team members, client contacts, and their
56 interactions over the historical processes and tools that have been used.
57- Engagement teams must value a final report that contains sufficient audit
58 documentation over excessive documentation or scope creep.
59- Engagement teams must collaborate with the audit clients as much as feasible
60 to ensure that both sides are constantly updated with current knowledge of
61 the engagement's status and any potential findings, rather than waiting for
62 pre-set meetings or the end of the engagement to communicate.
63- Engagement teams must be able to respond to change in an engagement's
64 schedule, scope, or environment to ensure that the project is completed in a
65 timely manner and that all relevant areas are tested.
66 - In terms of an audit department's portfolio, they must be able to
67 respond to changes in their company's or client's environment and be
68 able to dynamically change their audit plan accordingly.
6969
7070# Scrum
7171
@@ -74,9 +74,9 @@ how an audit team can potentially mold that mindset into the audit world, but
7474how does a team implement these ideas?
7575
7676There are many methods that use an Agile mindset, but I prefer
77[Scrum](https://en.wikipedia.org/wiki/Scrum_(software_development)). Scrum is a
78framework based on Agile that enables a team to work through a project through a
79series of roles, ceremonies, artifacts, and values.
77[Scrum](<https://en.wikipedia.org/wiki/Scrum_(software_development)>). Scrum is
78a framework based on Agile that enables a team to work through a project through
79a series of roles, ceremonies, artifacts, and values.
8080
8181Let's dive into each of these individually.
8282
content/blog/2023-09-15-self-hosting-gitweb.md +1 −1
@@ -34,7 +34,7 @@ Once installed, create an Nginx configuration file.
3434sudo nano /etc/nginx/sites-available/git.example.com
3535```
3636
37``` conf
37```conf
3838server {
3939 listen 80;
4040 server_name example.com;
content/blog/2023-09-19-audit-sql-scripts.md +52 −52
@@ -18,7 +18,7 @@ types: Oracle, Microsoft SQL, and MySQL.
1818You can use the following SQL script to see all users and their privileges in an
1919Oracle database:
2020
21``` sql
21```sql
2222SELECT
2323 grantee AS "User",
2424 privilege AS "Privilege"
@@ -52,11 +52,11 @@ You can also extract each table's information separately and perform processing
5252outside the database to explore and determine the information necessary for the
5353audit:
5454
55``` sql
55```sql
5656SELECT ** FROM sys.dba_role_privs;
5757SELECT ** FROM sys.dba_sys_privs;
5858SELECT ** FROM sys.dba_tab_privs;
59SELECT ** FROM sys.dba_users;
59SELECT ** FROM sys.dba_users;
6060```
6161
6262# Microsoft SQL
@@ -64,16 +64,16 @@ SELECT ** FROM sys.dba_users;
6464You can use the following SQL script to see all users and their privileges in a
6565Microsoft SQL Server database ([source](https://stackoverflow.com/a/30040784)):
6666
67``` sql
67```sql
6868/*
6969Security Audit Report
701) List all access provisioned to a sql user or windows user/group directly
701) List all access provisioned to a sql user or windows user/group directly
71712) List all access provisioned to a sql user or windows user/group through a database or application role
72723) List all access provisioned to the public role
7373
7474Columns Returned:
7575UserName : SQL or Windows/Active Directory user account. This could also be an Active Directory group.
76UserType : Value will be either 'SQL User' or 'Windows User'. This reflects the type of user defined for the
76UserType : Value will be either 'SQL User' or 'Windows User'. This reflects the type of user defined for the
7777 SQL Server user account.
7878DatabaseUserName: Name of the associated user as defined in the database user account. The database user may not be the
7979 same as the server user.
@@ -86,70 +86,70 @@ PermissionType : Type of permissions the user/role has on an object. Examples c
8686PermissionState : Reflects the state of the permission type, examples could include GRANT, DENY, etc.
8787 This value may not be populated for all roles. Some built in roles have implicit permission
8888 definitions.
89ObjectType : Type of object the user/role is assigned permissions on. Examples could include USER_TABLE,
90 SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc.
89ObjectType : Type of object the user/role is assigned permissions on. Examples could include USER_TABLE,
90 SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc.
9191 This value may not be populated for all roles. Some built in roles have implicit permission
92 definitions.
93ObjectName : Name of the object that the user/role is assigned permissions on.
92 definitions.
93ObjectName : Name of the object that the user/role is assigned permissions on.
9494 This value may not be populated for all roles. Some built in roles have implicit permission
9595 definitions.
9696ColumnName : Name of the column of the object that the user/role is assigned permissions on. This value
97 is only populated if the object is a table, view or a table value function.
97 is only populated if the object is a table, view or a table value function.
9898*/
9999
100--List all access provisioned to a sql user or windows user/group directly
101SELECT
102 [UserName] = CASE princ.[type]
100--List all access provisioned to a sql user or windows user/group directly
101SELECT
102 [UserName] = CASE princ.[type]
103103 WHEN 'S' THEN princ.[name]
104104 WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
105105 END,
106106 [UserType] = CASE princ.[type]
107107 WHEN 'S' THEN 'SQL User'
108108 WHEN 'U' THEN 'Windows User'
109 END,
110 [DatabaseUserName] = princ.[name],
111 [Role] = null,
112 [PermissionType] = perm.[permission_name],
113 [PermissionState] = perm.[state_desc],
114 [ObjectType] = obj.type_desc,--perm.[class_desc],
109 END,
110 [DatabaseUserName] = princ.[name],
111 [Role] = null,
112 [PermissionType] = perm.[permission_name],
113 [PermissionState] = perm.[state_desc],
114 [ObjectType] = obj.type_desc,--perm.[class_desc],
115115 [ObjectName] = OBJECT_NAME(perm.major_id),
116116 [ColumnName] = col.[name]
117FROM
117FROM
118118 --database user
119 sys.database_principals princ
119 sys.database_principals princ
120120LEFT JOIN
121121 --Login accounts
122122 sys.login_token ulogin on princ.[sid] = ulogin.[sid]
123LEFT JOIN
123LEFT JOIN
124124 --Permissions
125125 sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
126126LEFT JOIN
127127 --Table columns
128 sys.columns col ON col.[object_id] = perm.major_id
128 sys.columns col ON col.[object_id] = perm.major_id
129129 AND col.[column_id] = perm.[minor_id]
130130LEFT JOIN
131131 sys.objects obj ON perm.[major_id] = obj.[object_id]
132WHERE
132WHERE
133133 princ.[type] in ('S','U')
134134UNION
135135--List all access provisioned to a sql user or windows user/group through a database or application role
136SELECT
137 [UserName] = CASE memberprinc.[type]
136SELECT
137 [UserName] = CASE memberprinc.[type]
138138 WHEN 'S' THEN memberprinc.[name]
139139 WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
140140 END,
141141 [UserType] = CASE memberprinc.[type]
142142 WHEN 'S' THEN 'SQL User'
143143 WHEN 'U' THEN 'Windows User'
144 END,
145 [DatabaseUserName] = memberprinc.[name],
146 [Role] = roleprinc.[name],
147 [PermissionType] = perm.[permission_name],
148 [PermissionState] = perm.[state_desc],
149 [ObjectType] = obj.type_desc,--perm.[class_desc],
144 END,
145 [DatabaseUserName] = memberprinc.[name],
146 [Role] = roleprinc.[name],
147 [PermissionType] = perm.[permission_name],
148 [PermissionState] = perm.[state_desc],
149 [ObjectType] = obj.type_desc,--perm.[class_desc],
150150 [ObjectName] = OBJECT_NAME(perm.major_id),
151151 [ColumnName] = col.[name]
152FROM
152FROM
153153 --Role/member associations
154154 sys.database_role_members members
155155JOIN
@@ -161,39 +161,39 @@ JOIN
161161LEFT JOIN
162162 --Login accounts
163163 sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid]
164LEFT JOIN
164LEFT JOIN
165165 --Permissions
166166 sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
167167LEFT JOIN
168168 --Table columns
169 sys.columns col on col.[object_id] = perm.major_id
169 sys.columns col on col.[object_id] = perm.major_id
170170 AND col.[column_id] = perm.[minor_id]
171171LEFT JOIN
172172 sys.objects obj ON perm.[major_id] = obj.[object_id]
173173UNION
174174--List all access provisioned to the public role, which everyone gets by default
175SELECT
175SELECT
176176 [UserName] = '{All Users}',
177 [UserType] = '{All Users}',
178 [DatabaseUserName] = '{All Users}',
179 [Role] = roleprinc.[name],
180 [PermissionType] = perm.[permission_name],
181 [PermissionState] = perm.[state_desc],
182 [ObjectType] = obj.type_desc,--perm.[class_desc],
177 [UserType] = '{All Users}',
178 [DatabaseUserName] = '{All Users}',
179 [Role] = roleprinc.[name],
180 [PermissionType] = perm.[permission_name],
181 [PermissionState] = perm.[state_desc],
182 [ObjectType] = obj.type_desc,--perm.[class_desc],
183183 [ObjectName] = OBJECT_NAME(perm.major_id),
184184 [ColumnName] = col.[name]
185FROM
185FROM
186186 --Roles
187187 sys.database_principals roleprinc
188LEFT JOIN
188LEFT JOIN
189189 --Role permissions
190190 sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
191191LEFT JOIN
192192 --Table columns
193 sys.columns col on col.[object_id] = perm.major_id
194 AND col.[column_id] = perm.[minor_id]
195JOIN
196 --All objects
193 sys.columns col on col.[object_id] = perm.major_id
194 AND col.[column_id] = perm.[minor_id]
195JOIN
196 --All objects
197197 sys.objects obj ON obj.[object_id] = perm.[major_id]
198198WHERE
199199 --Only roles
@@ -222,7 +222,7 @@ mysql -u root -p
222222
223223Find all users and hosts with access to the database:
224224
225``` sql
225```sql
226226SELECT ** FROM information_schema.user_privileges;
227227```
228228
@@ -243,7 +243,7 @@ after extraction. I have marked the queries below with `SELECT ...` and excluded
243243most `WHERE` clauses for brevity. You should determine the relevant privileges
244244in-scope and query for those privileges to reduce the length of time to query.
245245
246``` sql
246```sql
247247-- Global Permissions
248248SELECT ... FROM mysql.user;
249249
@@ -260,6 +260,6 @@ SELECT ... FROM mysql.columns_priv
260260WHERE db = @db_name;
261261
262262-- Password Configuration
263SHOW GLOBAL VARIABLES LIKE 'validate_password%';
263SHOW GLOBAL VARIABLES LIKE 'validate_password%';
264264SHOW VARIABLES LIKE 'validate_password%';
265265```
content/blog/2023-10-04-digital-minimalism.md +49 −49
@@ -5,9 +5,9 @@ description = ""
55draft = false
66+++
77
8I've written [a note about minimalism](file:///wiki/#digital-garden) before,
9but I wanted to dedicate some time to reflect on digital minimalism and how
10I've been able to minimize the impact of digital devices in my life.
8I've written [a note about minimalism](file:///wiki/#digital-garden) before, but
9I wanted to dedicate some time to reflect on digital minimalism and how I've
10been able to minimize the impact of digital devices in my life.
1111
1212> These changes crept up on us and happened fast, before we had a chance to step
1313> back and ask what we really wanted out of the rapid advances of the past
@@ -16,29 +16,29 @@ I've been able to minimize the impact of digital devices in my life.
1616> our daily life. We didn't, in other words, sign up for the digital world in
1717> which we're currently entrenched; we seem to have stumbled backward into it.
1818>
19> *(Digital Minimalism, 2019)*
19> _(Digital Minimalism, 2019)_
2020
2121# The Principles of Digital Minimalism
2222
23As noted in Cal Newport's book, *Digital Minimalism*, there are three main
23As noted in Cal Newport's book, _Digital Minimalism_, there are three main
2424principles to digital minimalism that I tend to agree with:
2525
26261. Clutter is costly.
27 - Digital minimalists recognize that cluttering their time and attention
28 with too many devices, apps, and services creates an overall negative cost
29 that can swamp the small benefits that each individual item provides in
30 isolation.
27 - Digital minimalists recognize that cluttering their time and attention
28 with too many devices, apps, and services creates an overall negative
29 cost that can swamp the small benefits that each individual item
30 provides in isolation.
31312. Optimization is important.
32 - Digital minimalists believe that deciding a particular technology supports
33 something they value is only the first step. To truly extract its full
34 potential benefit, it's necessary to think carefully about how they'll
35 use the technology.
32 - Digital minimalists believe that deciding a particular technology
33 supports something they value is only the first step. To truly extract
34 its full potential benefit, it's necessary to think carefully about how
35 they'll use the technology.
36363. Intentionality is satisfying.
37 - Digital minimalists derive significant satisfaction from their general
38 commitment to being more intentional about how they engage with new
39 technologies. This source of satisfaction is independent of the specific
40 decisions they make and is one of the biggest reasons that minimalism
41 tends to be immensely meaningful to its practitioners.
37 - Digital minimalists derive significant satisfaction from their general
38 commitment to being more intentional about how they engage with new
39 technologies. This source of satisfaction is independent of the specific
40 decisions they make and is one of the biggest reasons that minimalism
41 tends to be immensely meaningful to its practitioners.
4242
4343# Taking Action
4444
@@ -47,47 +47,47 @@ continued performing old habits that are working well:
4747
4848## Using Devices With Intention
4949
50- I already rarely use "social media", mostly limited to forums such as Hacker
51 News and Tildes, so I've just tweaked my behavior to stop looking for content
52 in those places when I'm bored.
53- Use devices with intention. Each time I pick up a digital device, there should
54 be an intention to use the device to improve my current situation. No more
55 endless scrolling or searching for something to interest me.
50- I already rarely use "social media", mostly limited to forums such as Hacker
51 News and Tildes, so I've just tweaked my behavior to stop looking for
52 content in those places when I'm bored.
53- Use devices with intention. Each time I pick up a digital device, there
54 should be an intention to use the device to improve my current situation. No
55 more endless scrolling or searching for something to interest me.
5656
5757## Prevent Distractions
5858
59- Disable (most) notifications on all devices. I spent 15-30 minutes going
60 through the notifications on my phone, watch, and computer to ensure that only
61 a select few apps have the ability to interrupt me: Calendar, Messages, Phone,
62 Reminders, & Signal.
63- Disable badges for any apps except the ones mentioned in the bullet above.
64- Set-up focus profiles across devices so that I can enable different modes,
65 such as Personal when I only want to see notifications from people I care
66 about or Do Not Disturb, where absolutely nothing can interrupt me.
67- Clean up my home screens. This one was quite easy as I already maintain a
68 minimalist set-up, but I went extreme by limiting my phone to just eight apps
69 on the home screen and four in the dock. If I need another app, I'll have to
70 search or use the app library.
71- Remove the work profile from my phone. This was a tough decision as having my
72 work profile on my device definitely makes my life easier at times, but it
73 also has quite a negative effect when I'm "always online" and can see the
74 notifications and team activity 24/7. I believe creating a distinct barrier
75 between my work and personal devices will be beneficial in the end.
59- Disable (most) notifications on all devices. I spent 15-30 minutes going
60 through the notifications on my phone, watch, and computer to ensure that
61 only a select few apps have the ability to interrupt me: Calendar, Messages,
62 Phone, Reminders, & Signal.
63- Disable badges for any apps except the ones mentioned in the bullet above.
64- Set-up focus profiles across devices so that I can enable different modes,
65 such as Personal when I only want to see notifications from people I care
66 about or Do Not Disturb, where absolutely nothing can interrupt me.
67- Clean up my home screens. This one was quite easy as I already maintain a
68 minimalist set-up, but I went extreme by limiting my phone to just eight
69 apps on the home screen and four in the dock. If I need another app, I'll
70 have to search or use the app library.
71- Remove the work profile from my phone. This was a tough decision as having
72 my work profile on my device definitely makes my life easier at times, but
73 it also has quite a negative effect when I'm "always online" and can see the
74 notifications and team activity 24/7. I believe creating a distinct barrier
75 between my work and personal devices will be beneficial in the end.
7676
7777## Creating Alternative Activities
7878
7979This is the most difficult piece, as most of my hobbies and interests lie in the
80digital world. However, I'm making a concerted effort to put devices down
81unless necessary and force myself to perform other activities in the physical
82world instead.
80digital world. However, I'm making a concerted effort to put devices down unless
81necessary and force myself to perform other activities in the physical world
82instead.
8383
8484I've started with a few basics that are always readily available to me:
8585
86- Do a chore, such as organizing or cleaning.
87- Read a book, study a piece of art, etc.
88- Exercise or get outdoors.
89- Participate in a hobby, such as photography, birding, disc golf, etc.
90- Let yourself be bored and wander into creativity.
86- Do a chore, such as organizing or cleaning.
87- Read a book, study a piece of art, etc.
88- Exercise or get outdoors.
89- Participate in a hobby, such as photography, birding, disc golf, etc.
90- Let yourself be bored and wander into creativity.
9191
9292# Making Progress
9393
content/blog/2023-10-11-self-hosting-authelia.md +105 −105
@@ -23,11 +23,11 @@ portal.
2323
2424This guide assumes you have the following already set-up:
2525
26- A registered domain with DNS pointing to your server.
27- A subdomain for Authelia (`auth.example.com`) and a subdomain to protect via
28 Authelia (`app.example.com`).
29- A working Nginx web server.
30- Docker and docker-compose installed.
26- A registered domain with DNS pointing to your server.
27- A subdomain for Authelia (`auth.example.com`) and a subdomain to protect via
28 Authelia (`app.example.com`).
29- A working Nginx web server.
30- Docker and docker-compose installed.
3131
3232# Installation
3333
@@ -49,19 +49,19 @@ Within this file, paste the following content. If you prefer a different local
4949port, modify the port on the left side of the colon on the `9091:9091` line. Be
5050sure to modify the `TZ` variable to your timezone.
5151
52``` yml
53version: '3.3'
52```yml
53version: "3.3"
5454
5555services:
56 authelia:
57 image: authelia/authelia
58 container_name: authelia
59 volumes:
60 - ./config:/config
61 ports:
62 - 9091:9091
63 environment:
64 - TZ=America/Chicago
56 authelia:
57 image: authelia/authelia
58 container_name: authelia
59 volumes:
60 - ./config:/config
61 ports:
62 - 9091:9091
63 environment:
64 - TZ=America/Chicago
6565```
6666
6767Start the container with docker-compose:
@@ -93,107 +93,107 @@ and modify as necessary.
9393
9494The major required changes are:
9595
96- Any instances of `example.com` should be replaced by your domain.
97- `jwt_secret` - Use the `pwgen 40 1` command to generate a secret for yourself.
98- `access_control` - Set the Authelia domain to bypass here, as well as any
99 subdomains you want to protect.
100- `session` > `secret` - Use the `pwgen 40 1` command to generate a secret for
101 yourself.
102- `regulation` - Set the variables here to restrict login attempts and bans.
103- `storage` > `encryption_key` - Use the `pwgen 40 1` command to generate a
104 secret for yourself.
105- `smtp` - If you have access to an SMTP service, set up the information here to
106 active outgoing emails.
107
108``` yml
96- Any instances of `example.com` should be replaced by your domain.
97- `jwt_secret` - Use the `pwgen 40 1` command to generate a secret for
98 yourself.
99- `access_control` - Set the Authelia domain to bypass here, as well as any
100 subdomains you want to protect.
101- `session` > `secret` - Use the `pwgen 40 1` command to generate a secret for
102 yourself.
103- `regulation` - Set the variables here to restrict login attempts and bans.
104- `storage` > `encryption_key` - Use the `pwgen 40 1` command to generate a
105 secret for yourself.
106- `smtp` - If you have access to an SMTP service, set up the information here
107 to active outgoing emails.
108
109```yml
109110# yamllint disable rule:comments-indentation
110111---
111112###############################################################################
112113# Authelia Configuration #
113114###############################################################################
114115
115theme: dark
116theme: dark
116117jwt_secret: aiS5iedaiv6eeVaideeLeich5roo6ohvaf3Vee1a # pwgen 40 1
117118
118119default_redirection_url: https://example.com
119120
120121server:
121 host: 0.0.0.0
122 port: 9091
123 path: ""
124 read_buffer_size: 4096
125 write_buffer_size: 4096
126 enable_pprof: false
127 enable_expvars: false
128 disable_healthcheck: false
129 tls:
130 key: ""
131 certificate: ""
122 host: 0.0.0.0
123 port: 9091
124 path: ""
125 read_buffer_size: 4096
126 write_buffer_size: 4096
127 enable_pprof: false
128 enable_expvars: false
129 disable_healthcheck: false
130 tls:
131 key: ""
132 certificate: ""
132133
133134log:
134 level: debug
135 level: debug
135136
136137totp:
137 issuer: example.com
138 period: 30
139 skew: 1
138 issuer: example.com
139 period: 30
140 skew: 1
140141
141142authentication_backend:
142 disable_reset_password: false
143 refresh_interval: 5m
144 file:
145 path: /config/users_database.yml
146 password:
147 algorithm: argon2id
148 iterations: 1
149 key_length: 32
150 salt_length: 16
151 memory: 1024
152 parallelism: 8
143 disable_reset_password: false
144 refresh_interval: 5m
145 file:
146 path: /config/users_database.yml
147 password:
148 algorithm: argon2id
149 iterations: 1
150 key_length: 32
151 salt_length: 16
152 memory: 1024
153 parallelism: 8
153154
154155access_control:
155 default_policy: deny
156 rules:
157 - domain:
158 - "auth.example.com"
159 policy: bypass
160 - domain: "teddit.example.com"
161 policy: one_factor
156 default_policy: deny
157 rules:
158 - domain:
159 - "auth.example.com"
160 policy: bypass
161 - domain: "teddit.example.com"
162 policy: one_factor
162163
163164session:
164 name: authelia_session
165 secret: aiS5iedaiv6eeVaideeLeich5roo6ohvaf3Vee1a # pwgen 40 1
166 expiration: 3600
167 inactivity: 300
168 domain: example.com
165 name: authelia_session
166 secret: aiS5iedaiv6eeVaideeLeich5roo6ohvaf3Vee1a # pwgen 40 1
167 expiration: 3600
168 inactivity: 300
169 domain: example.com
169170
170171regulation:
171 max_retries: 5
172 find_time: 10m
173 ban_time: 12h
172 max_retries: 5
173 find_time: 10m
174 ban_time: 12h
174175
175176storage:
176 local:
177 path: /config/db.sqlite3
178 encryption_key: aiS5iedaiv6eeVaideeLeich5roo6ohvaf3Vee1a # pwgen 40 1
177 local:
178 path: /config/db.sqlite3
179 encryption_key: aiS5iedaiv6eeVaideeLeich5roo6ohvaf3Vee1a # pwgen 40 1
179180
180181notifier:
181 disable_startup_check: true
182 smtp:
183 username: user@example.com
184 password: password
185 host: smtp.example.com
186 port: 465
187 sender: user@example.com
188 identifier: example.com
189 subject: "[Authelia] {title}"
190 startup_check_address: user@example.com
191 disable_require_tls: false
192 disable_html_emails: true
193 tls:
194 skip_verify: false
195 minimum_version: TLS1.2
196...
182 disable_startup_check: true
183 smtp:
184 username: user@example.com
185 password: password
186 host: smtp.example.com
187 port: 465
188 sender: user@example.com
189 identifier: example.com
190 subject: "[Authelia] {title}"
191 startup_check_address: user@example.com
192 disable_require_tls: false
193 disable_html_emails: true
194 tls:
195 skip_verify: false
196 minimum_version: TLS1.2
197197```
198198
199199## Authelia Users
@@ -212,17 +212,17 @@ To generate the password, go to [Argon2 Hash Generator](https://argon2.online),
212212generate a random salt, and make sure the rest of the settings match the
213213`authentication_backend` section of `configuration.yml` file.
214214
215``` yaml
215```yaml
216216users:
217 my_username:
218 displayname: "My User"
219 # Generated at https://argon2.online/ -- match the settings in
220 # the `authentication_backend` section of configuration.yml
221 password: ""
222 email: email@example.com
223 groups:
224 - admins
225 - dev
217 my_username:
218 displayname: "My User"
219 # Generated at https://argon2.online/ -- match the settings in
220 # the `authentication_backend` section of configuration.yml
221 password: ""
222 email: email@example.com
223 groups:
224 - admins
225 - dev
226226```
227227
228228Once the app is configured, restart the container from scratch.
@@ -247,7 +247,7 @@ Within this file, paste the following information and be sure to update
247247`example.com` to your domain. Make sure the `$upstream_authelia` variable
248248matches the location of your Authelia container.
249249
250``` conf
250```conf
251251server {
252252 if ($host ~ ^[^.]+\.example\.com$) {
253253 return 301 https://$host$request_uri;
@@ -322,7 +322,7 @@ variables.
322322sudo nano /etc/nginx/sites-available/teddit
323323```
324324
325``` conf
325```conf
326326server {
327327 if ($host ~ ^[^.]+\.example\.com$) {
328328 return 301 https://$host$request_uri;
@@ -441,9 +441,9 @@ authentication domain and presented with the Authelia login portal.
441441![Authelia
442442Portal](https://img.cleberg.net/blog/20231010-authelia/authelia_portal.png)
443443
444Once you've successfully authenticated, you can visit your authentication
445domain directly and see that you're currently authenticated to any domain
446protected by Authelia.
444Once you've successfully authenticated, you can visit your authentication domain
445directly and see that you're currently authenticated to any domain protected by
446Authelia.
447447
448448![Authelia
449449Success](https://img.cleberg.net/blog/20231010-authelia/authelia_success.png)
content/blog/2023-10-15-alpine-ssh-hardening.md +1 −1
@@ -68,7 +68,7 @@ ssh-audit localhost
6868If everything succeeded, the results will show as all green. If anything is
6969yellow, orange, or red, you may need to tweak additional settings.
7070
71``` txt
71```txt
7272#+caption: ssh audit
7373```
7474
content/blog/2023-10-17-self-hosting-anonymousoverflow.md +7 −7
@@ -28,19 +28,19 @@ nano docker-compose.yml
2828Within this file, paste the following information. Be sure to change the
2929`APP_URL`, `JWT_SIGNING_SECRET`, and `ports` to match your needs.
3030
31``` yaml
32version: '3'
31```yaml
32version: "3"
3333
3434services:
3535 anonymousoverflow:
36 container_name: 'app'
37 image: 'ghcr.io/httpjamesm/anonymousoverflow:release'
36 container_name: "app"
37 image: "ghcr.io/httpjamesm/anonymousoverflow:release"
3838 environment:
3939 - APP_URL=https://ao.example.com
4040 - JWT_SIGNING_SECRET=secret #pwgen 40 1
4141 ports:
42 - '9380:8080'
43 restart: 'always'
42 - "9380:8080"
43 restart: "always"
4444```
4545
4646Save and exit the file when complete. You can now launch the container and
@@ -65,7 +65,7 @@ Within this file, paste the following content and repace `ao.example.com` with
6565your URL. You may need to update the SSL certificate statements if your
6666certificates are in a different location.
6767
68``` conf
68```conf
6969server {
7070 if ($host ~ ^[^.]+\.cleberg\.net$) {
7171 return 301 https://$host$request_uri;
content/blog/2023-11-08-scli.md +14 −14
@@ -20,15 +20,15 @@ and download the packaged binaries for an easier installation process.
2020
2121In order to use `scli`, you need a few dependencies:
2222
23- `openjdk17-jre` - Used as a dependency for the `signal-cli` tool. Version may
24 vary.
25- `signal-cli` - Used as the backbone of the `scli` tool.
26- `findutils` - Replaces the standard Busybox version of `xargs`.
27- `urwid` - A console user interface library for Python.
28- `urwid-readline` - For GNU emacs-like keybinds on the input line.
29- `qrencode` - Displays a QR code in the terminal to link the device using your
30 phone. Not necessary if you're only linking on desktop and can copy/paste the
31 connection URL.
23- `openjdk17-jre` - Used as a dependency for the `signal-cli` tool. Version
24 may vary.
25- `signal-cli` - Used as the backbone of the `scli` tool.
26- `findutils` - Replaces the standard Busybox version of `xargs`.
27- `urwid` - A console user interface library for Python.
28- `urwid-readline` - For GNU emacs-like keybinds on the input line.
29- `qrencode` - Displays a QR code in the terminal to link the device using
30 your phone. Not necessary if you're only linking on desktop and can
31 copy/paste the connection URL.
3232
3333Let's start by installing the packages available via Alpine's repositories. Be
3434sure to install the latest version of `openjdk`. If you run into Java-related
@@ -102,8 +102,8 @@ signal-cli -u USERNAME receive
102102```
103103
104104Also be sure to test the daemon to ensure it works properly. If no errors occur,
105it's working. If you run into errors because you're not running a DBUS
106session, see my notes below.
105it's working. If you run into errors because you're not running a DBUS session,
106see my notes below.
107107
108108```sh
109109signal-cli -u USERNAME daemon
@@ -115,8 +115,8 @@ This process will differ depending on your desktop environment (DE). If you are
115115running a DE, you likely have a DBUS session running already and can simply
116116launch the program.
117117
118However, if you're like me and running your computer straight on the TTY
119without a DE, you'll need to start a DBUS session for this program.
118However, if you're like me and running your computer straight on the TTY without
119a DE, you'll need to start a DBUS session for this program.
120120
121121```sh
122122# If you're not running a DBUS session yet, you need to start one for scli
@@ -136,7 +136,7 @@ information on configuration options.
136136nano ~/.config/sclirc
137137```
138138
139``` conf
139```conf
140140# ~/.config/sclirc
141141
142142wrap-at = 80
content/blog/2023-12-03-unifi-nextdns.md +6 −6
@@ -25,12 +25,12 @@ Install instructions for Unifi Dream Machine (UDM) standard and pro routers.
2525
2626Enable SSH:
2727
28- Go to your unifi admin interface and select your device (not the controller
29 settings, but the Dream Machine settings)
30- Click on "Settings" at the bottom of the page
31- Go to the "Advanced" section on the left pan
32- Enable SSH
33- Set a SSH password
28- Go to your unifi admin interface and select your device (not the controller
29 settings, but the Dream Machine settings)
30- Click on "Settings" at the bottom of the page
31- Go to the "Advanced" section on the left pan
32- Enable SSH
33- Set a SSH password
3434
3535Connect to your router using `ssh root@xxx.xxx.xxx.xxx` with the password you
3636configured.
content/blog/2024-01-08-dont-say-hello.md +4 −4
@@ -20,10 +20,10 @@ Therefore, I have always held a deep displeasure for conversations where people
2020start with "Hello" and then.
2121
2222I searched back through my work messages and found that I received ~50 messages
23from ~10 people last year from people that contained "hi", "hey", or
24"hello" and did not contain any indication of the purpose of the conversation.
25I also noticed that a few of the users were responsible for the large majority
26of the cliffhangers.
23from ~10 people last year from people that contained "hi", "hey", or "hello" and
24did not contain any indication of the purpose of the conversation. I also
25noticed that a few of the users were responsible for the large majority of the
26cliffhangers.
2727
2828There's no real point to this post, just a desparate request for people to
2929please stop doing this.
content/blog/2024-01-09-macos-customization.md +4 −4
@@ -61,7 +61,7 @@ Integrity Protection (SIP). However, I chose not to do this and it hasn't
6161affected my basic usage of yabai at all.
6262
6363Refer to the [yabai
64wiki](https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release))
64wiki](<https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)>)
6565for installation instructions. You will need to ensure that yabai is allowed to
6666access the accessibility and screen recording APIs.
6767
@@ -94,7 +94,7 @@ nano ~/.config/skhd/skhdrc
9494
9595For example, I have hotkeys to open my browser and terminal:
9696
97``` conf
97```conf
9898# Terminal
9999cmd - return : /Applications/iTerm.app/Contents/MacOS/iTerm2
100100
@@ -159,8 +159,8 @@ them by following this process.
1591592. Navigate to the `Applications` folder.
1601603. Right-click an application of your choice, and select `Get Info`.
1611614. Drag the image you downloaded on top of the application's icon at the top of
162 information window (you will see a green "plus" symbol when you're
163 hovering over it).
162 information window (you will see a green "plus" symbol when you're hovering
163 over it).
1641645. Release the new icon on top of the old icon and it will update!
165165
166166You can see an example of me dragging a new `signal.icns` file onto my
content/blog/2024-01-13-local-llm.md +12 −12
@@ -14,10 +14,10 @@ without sacrificing privacy or requiring in-depth technical setup.
1414
1515My requirements for this test:
1616
17- Open source platform
18- On-device model files
19- Minimal required configuration
20- Preferably pre-built, but a simple build process is acceptable
17- Open source platform
18- On-device model files
19- Minimal required configuration
20- Preferably pre-built, but a simple build process is acceptable
2121
2222I tested a handful of apps and have summarized my favorite (so far) for macOS
2323and iOS below.
@@ -25,8 +25,8 @@ and iOS below.
2525> TL;DR - Here are the two that met my requirements and I have found the easiest
2626> to install and use so far:
2727
28- macOS: [Ollama](https://ollama.ai/)
29- iOS : [LLM Farm](https://llmfarm.site/)
28- macOS: [Ollama](https://ollama.ai/)
29- iOS : [LLM Farm](https://llmfarm.site/)
3030
3131# macOS
3232
@@ -86,8 +86,8 @@ repository](https://github.com/guinmoon/LLMFarm) if you wish.
8686The caveat is that you will have to manually download the model files from the
8787links in the
8888[models.md](https://github.com/guinmoon/LLMFarm/blob/main/models.md) file to
89your iPhone to use the app - there's currently no option in the app to reach
90out and grab the latest version of any supported model.
89your iPhone to use the app - there's currently no option in the app to reach out
90and grab the latest version of any supported model.
9191
9292Once you have a file downloaded, you simply create a new chat and select the
9393downloaded model file and ensure the inference matches the requirement in the
@@ -96,10 +96,10 @@ downloaded model file and ensure the inference matches the requirement in the
9696See below for a test of the ORCA Mini v3 model:
9797
9898| Chat List | Chat |
99|-------------------------------------------------------------------------|-------------------------------------------------------------------|
99| ----------------------------------------------------------------------- | ----------------------------------------------------------------- |
100100| ![](https://img.cleberg.net/blog/20240113-local-llm/llm_farm_chats.png) | ![](https://img.cleberg.net/blog/20240113-local-llm/llm_farm.png) |
101101
102102[Enchanted](https://github.com/AugustDev/enchanted) is also an iOS for private
103AI models, but it requires a public-facing Ollama API, which did not meet my
104"on device requirement." Nonetheless, it's an interesting looking app and I
105will likely set it up to test soon.
103AI models, but it requires a public-facing Ollama API, which did not meet my "on
104device requirement." Nonetheless, it's an interesting looking app and I will
105likely set it up to test soon.
content/blog/2024-01-26-audit-dashboard.md +48 −49
@@ -18,11 +18,11 @@ With these tools, we are going to build the following dashboard:
1818
1919This project assumes the following:
2020
21- You have access to Alteryx Designer and Power BI Desktop.
22 - If you only have Power BI Desktop, you may need to perform some analysis
23 in Power BI instead of Alteryx.
24- Your data is in a format that can be imported into Alteryx and/or Power BI.
25- You have a basic understanding of data types and visualization.
21- You have access to Alteryx Designer and Power BI Desktop.
22 - If you only have Power BI Desktop, you may need to perform some analysis
23 in Power BI instead of Alteryx.
24- Your data is in a format that can be imported into Alteryx and/or Power BI.
25- You have a basic understanding of data types and visualization.
2626
2727# Alteryx: Data Preparation & Analysis
2828
@@ -42,25 +42,24 @@ Import](https://img.cleberg.net/blog/20240126-audit-dashboard/alteryx_import.png
4242
4343## Transform Data
4444
45Next, let's replace null data and remove whitespace to clean up our data. We
46can do this with the `Data Cleansing` tool in the `Preparation` tab in the
47Ribbon.
45Next, let's replace null data and remove whitespace to clean up our data. We can
46do this with the `Data Cleansing` tool in the `Preparation` tab in the Ribbon.
4847
4948Ensure that the following options are enabled:
5049
51- Replace Nulls
52 - Replace with Blanks (String Fields)
53 - Replace with 0 (Numeric Fields)
54- Remove Unwanted Characters
55 - Leading and Trailing Whitespace
50- Replace Nulls
51 - Replace with Blanks (String Fields)
52 - Replace with 0 (Numeric Fields)
53- Remove Unwanted Characters
54 - Leading and Trailing Whitespace
5655
5756![Data
5857Cleansing](https://img.cleberg.net/blog/20240126-audit-dashboard/alteryx_cleansing.png)
5958
6059For our next step, we will transform the date fields from strings to datetime
6160format. Add a `Datetime` tool for each field you want to transform - in the
62example below, I am using the tool twice for the "Started On" and "Submitted
63On" fields.
61example below, I am using the tool twice for the "Started On" and "Submitted On"
62fields.
6463
6564![Data
6665Transformation](https://img.cleberg.net/blog/20240126-audit-dashboard/alteryx_transformation.png)
@@ -70,7 +69,7 @@ on those fields. Start by adding a `Filter` tool, naming a new Output Column,
7069and pasting the formula below into it (the two fields used in this formula must
7170match the output of the `Datetime` tools above):
7271
73``` txt
72```txt
7473DateTimeDiff([SubmittedOn_Out],[StartedOn_Out], "days")
7574```
7675
@@ -93,8 +92,8 @@ To start, open the Power BI Desktop application. Upon first use, Power BI will
9392ask if you want to open an existing dashboard or import new data.
9493
9594As we are creating our first dashboard, let's import our data. In my example
96below, I'm importing data from the "Tracker" sheet of the Excel file I'm
97using for this project.
95below, I'm importing data from the "Tracker" sheet of the Excel file I'm using
96for this project.
9897
9998During this process, I also imported the export from the Alteryx workflow above.
10099Therefore, we have two different files available for use in our dashboard.
@@ -115,25 +114,25 @@ below and format as needed:
115114
116115Instructions to create the visuals above:
117116
118- `Text Box`: Explain the name and purpose of the dashboard. You can also add
119 images and logos at the top of the dashboard.
120- `Donut Chart`: Overall status of the project.
121 - `Legend`: Status
122 - `Values`: Count of Status
123- `Stacked Column Chart`: Task count by assignee.
124 - `X-axis`: Preparer
125 - `Y-axis`: Count of Control ID
126 - `Legend`: Status
127- `Treemap`: Top N client submitters by average days to submit.
128 - `Details`: Preparer
129 - `Values`: Sum of Avg~DaysToSubmit~
130- `Line Chart`: Projected vs. actual hours over time.
131- `Clustered Bar Chart`: Projected vs. actual hours per person.
132- `Slicer & Table` - Upcoming due dates.
133 - `Slicer`:
134 - `Values`: Date Due
135 - `Table`:
136 - `Columns`: Count of Control ID, Date Due, Preparer, Status
117- `Text Box`: Explain the name and purpose of the dashboard. You can also add
118 images and logos at the top of the dashboard.
119- `Donut Chart`: Overall status of the project.
120 - `Legend`: Status
121 - `Values`: Count of Status
122- `Stacked Column Chart`: Task count by assignee.
123 - `X-axis`: Preparer
124 - `Y-axis`: Count of Control ID
125 - `Legend`: Status
126- `Treemap`: Top N client submitters by average days to submit.
127 - `Details`: Preparer
128 - `Values`: Sum of Avg~DaysToSubmit~
129- `Line Chart`: Projected vs. actual hours over time.
130- `Clustered Bar Chart`: Projected vs. actual hours per person.
131- `Slicer & Table` - Upcoming due dates.
132 - `Slicer`:
133 - `Values`: Date Due
134 - `Table`:
135 - `Columns`: Count of Control ID, Date Due, Preparer, Status
137136
138137## Format the Dashboard
139138
@@ -144,18 +143,18 @@ created by your organization.
144143For each visual, you can click the `Format` button in the `Visualizations` side
145144pane and explore the options. You can custom options such as:
146145
147- Visual
148 - Legend
149 - Colors
150 - Data labels
151 - Category labels
152- General
153 - Properties
154 - Title
155 - Effects
156 - Header icons
157 - Tooltips
158 - Alt text
146- Visual
147 - Legend
148 - Colors
149 - Data labels
150 - Category labels
151- General
152 - Properties
153 - Title
154 - Effects
155 - Header icons
156 - Tooltips
157 - Alt text
159158
160159You can always look online for inspiration when trying to decide how best to
161160organize and style your dashboard.
content/blog/2024-01-27-tableau-dashboard.md +7 −7
@@ -42,7 +42,7 @@ nano data_processing.py
4242
4343Within the Python script, paste the following:
4444
45``` python
45```python
4646# Import modules
4747import pandas as pd
4848import glob
@@ -122,12 +122,12 @@ drag it into the `Columns` or `Rows` area of the canvas.
122122See below for the map visualization. You can recreate this by adding the
123123following fields:
124124
125- `Columns`: Lon
126- `Rows`: Lat
127- `Marks`:
128 - Description
129 - Datetime
130- `Filters`: Datetime
125- `Columns`: Lon
126- `Rows`: Lat
127- `Marks`:
128 - Description
129 - Datetime
130- `Filters`: Datetime
131131
132132![Worksheet
133133Editing](https://img.cleberg.net/blog/20240127-tableau-dashboard/worksheet_edit.png)
content/blog/2024-02-06-zfs.md +25 −24
@@ -10,10 +10,11 @@ snapshots on Ubuntu Server.
1010
1111I found the following pages very helpful while going through this process:
1212
13- [Setup a ZFS storage
14 pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool)
15- [Kernel/Reference/ZFS](https://wiki.ubuntu.com/Kernel/Reference/ZFS)
16- [ZFS for Dummies](https://blog.victormendonca.com/2020/11/03/zfs-for-dummies/)
13- [Setup a ZFS storage
14 pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool)
15- [Kernel/Reference/ZFS](https://wiki.ubuntu.com/Kernel/Reference/ZFS)
16- [ZFS for
17 Dummies](https://blog.victormendonca.com/2020/11/03/zfs-for-dummies/)
1718
1819# Installation
1920
@@ -40,13 +41,13 @@ You have various options for configuring ZFS pools that all come different pros
4041and cons. I suggest visiting the links at the top of this post or searching
4142online for the best configuration for your use-case.
4243
43- Striped VDEVs (Raid0)
44- Mirrored VDEVs (Raid1)
45- Striped Mirrored VDEVs (Raid10)
46- RAIDz (Raid5)
47- RAIDz2 (Raidd6)
48- RAIDz3
49- Nested RAIDz (Raid50, Raid60)
44- Striped VDEVs (Raid0)
45- Mirrored VDEVs (Raid1)
46- Striped Mirrored VDEVs (Raid10)
47- RAIDz (Raid5)
48- RAIDz2 (Raidd6)
49- RAIDz3
50- Nested RAIDz (Raid50, Raid60)
5051
5152I will be using Raid10 in this guide. However, the majority of the steps are the
5253same regardless of your chosen pool configuration.
@@ -84,8 +85,8 @@ sudo umount /dev/sda1
8485sudo umount /dev/sdb1
8586```
8687
87Now that I've identified the disks I want to use and have them unmounted,
88let's create the pool. For this example, I will call it `tank`.
88Now that I've identified the disks I want to use and have them unmounted, let's
89create the pool. For this example, I will call it `tank`.
8990
9091```sh
9192sudo zpool create -f -m /mnt/pool tank mirror /dev/sda /dev/sdb
@@ -176,10 +177,10 @@ command.
176177See below for instructions on how to use `fdisk`. Here's what I did to create
177178basic Linux formatted disks:
178179
179- `g` : Create GPT partition table
180- `n` : Create a new partition, hit Enter for all default options
181- `t` : Change partition type to `20` for `Linux filesystem`
182- `w` : Write the changes to disk and exit
180- `g` : Create GPT partition table
181- `n` : Create a new partition, hit Enter for all default options
182- `t` : Change partition type to `20` for `Linux filesystem`
183- `w` : Write the changes to disk and exit
183184
184185I repeated this process for both disks.
185186
@@ -314,10 +315,10 @@ no datasets available
314315
315316# My Thoughts on ZFS So Far
316317
317- I sacrificed 25TB to be able to mirror my data, but I feel more comfortable
318 with the potential to save my data by quickly replacing a disk if I need to.
319- The set-up was surprisingly easy and fast.
320- Disk I/O is fast as well. I was worried that the data transfer speeds would be
321 slower due to the RAID configuration.
322- Media streaming and transcoding has seen no noticeable drop in performance.
323- My only limitation really is the number of HDD bays in my server HDD cage.
318- I sacrificed 25TB to be able to mirror my data, but I feel more comfortable
319 with the potential to save my data by quickly replacing a disk if I need to.
320- The set-up was surprisingly easy and fast.
321- Disk I/O is fast as well. I was worried that the data transfer speeds would
322 be slower due to the RAID configuration.
323- Media streaming and transcoding has seen no noticeable drop in performance.
324- My only limitation really is the number of HDD bays in my server HDD cage.
content/blog/2024-02-13-ubuntu-emergency-mode.md +3 −3
@@ -14,7 +14,7 @@ creating the ZFS pool.
1414My server was stuck in the boot process and showed the following error on the
1515screen:
1616
17``` txt
17```txt
1818You are in emergency mode.
1919After logging in, type "journalctl -xb" to view system logs,
2020"systemctl reboot" to reboot, "systemctl default"
@@ -25,7 +25,7 @@ After rebooting the server and watching the logs scroll on a monitor, I noticed
2525the root cause was related to a very long search for certain drives. I kept
2626seeing errors like this:
2727
28``` txt
28```txt
2929[ TIME ] Timed out waiting of device dev-disk-by/[disk-uuid]
3030```
3131
@@ -49,7 +49,7 @@ Within the `fstab` file, I needed to comment/remove the following lines at the
4949bottom of the file. You can comment-out a line by prepending a `#` symbol at the
5050beginning of the line. You can also delete the line entirely.
5151
52``` conf
52```conf
5353# What it looked like when running into the issue:
5454UUID=B64E53824E5339F7 /mnt/white-01 ntfs-3g uid=1000,gid=1000 0 0
5555UUID=E69867E59867B32B /mnt/white-02 ntfs-3g uid=1000,gid=1000 0 0
content/blog/2024-02-21-self-hosting-otter-wiki.md +5 −6
@@ -24,8 +24,7 @@ Start by creating a directory for the container's files.
2424mkdir ~/otterwiki
2525```
2626
27Next, create the `docker-compose.yml` file to define the container's
28parameters.
27Next, create the `docker-compose.yml` file to define the container's parameters.
2928
3029```sh
3130nano ~/otterwiki/docker-compose.yml
@@ -34,7 +33,7 @@ nano ~/otterwiki/docker-compose.yml
3433Within the file, paste the following content. You can read the project's
3534documentation if you want to further override or customize the container.
3635
37``` conf
36```conf
3837version: '3'
3938services:
4039 otterwiki:
@@ -72,7 +71,7 @@ have a TLS/SSL cert to use with this subdomain. If not, simply remove the
7271`ssl_*` variables, remove the `80` server block, and change the `443` server
7372block to `80` to serve the app without SSL.
7473
75``` conf
74```conf
7675server {
7776 if ($host ~ ^[^.]+\.example\.com$) {
7877 return 301 https://$host$request_uri;
@@ -129,8 +128,8 @@ Wiki. Start by creating your admin account and configure the app as necessary.
129128![An Otter Wiki - Initial
130129Screen](https://img.cleberg.net/blog/20240221-otterwiki/otterwiki.png)
131130
132You can also see the default editing screen for creating and editing pages.
133It's as easy as typing Markdown and hitting the save button.
131You can also see the default editing screen for creating and editing pages. It's
132as easy as typing Markdown and hitting the save button.
134133
135134![An Otter Wiki - Editing
136135Screen](https://img.cleberg.net/blog/20240221-otterwiki/otterwiki-edit.png)
content/blog/2024-03-13-doom-emacs.md +8 −8
@@ -66,7 +66,7 @@ Once installed, you can configure Doom by editing the files within the
66663. `init.el` - Doom modules and load order, must run `doom sync` after
6767 modifying
68684. `packages.el` - Declare packages to install in this file, then run `doom
69 sync` to install
69sync` to install
7070
7171I only needed a few customizations for my configuration, so I'll list them
7272below.
@@ -167,7 +167,7 @@ changes, close files, and switch between open files. Here are some example
167167shortcuts I've written down in order to accomplish file-based actions.
168168
169169| Doom Hotkey | Emacs Hotkey | Description |
170|-----------------|--------------|----------------------------------------|
170| --------------- | ------------ | -------------------------------------- |
171171| `SPC :` | `C-x` | Run functions |
172172| `SPC f f` | `C-x f` | Open file in buffer |
173173| `SPC f d` | `C-x d` | Open directory with `dired` |
@@ -178,8 +178,8 @@ shortcuts I've written down in order to accomplish file-based actions.
178178| `SPC w h/j/k/l` | `C-x o`[^1] | Move left/down/up/right to next buffer |
179179
180180[^1]: Doom's evil-window functionality is a bit different from GNU Emacs, but
181you can always switch to the "other" buffer with `C-x o` or `C-x b` to get a
182list of buffers to select.
181 you can always switch to the "other" buffer with `C-x o` or `C-x b` to get a
182 list of buffers to select.
183183
184184In general, when in Doom, you can press `SPC` and wait a second for the help
185185pane to appear with all available hotkey options. For example, you can press
@@ -205,7 +205,7 @@ expands further, allowing you to insert various markdown elements and toggle
205205things like link hiding.
206206
207207| Doom Hotkey | Function |
208|------------------------------|--------------------------|
208| ---------------------------- | ------------------------ |
209209| `SPC m '` | markdown-edit-code-block |
210210| `SPC m e` | markdown-export |
211211| `SPC m i` | +insert |
@@ -226,7 +226,7 @@ are 865 possible org-related functions you can run. I won't possibly be able to
226226list them all, so I will simply cover a few of the basic commands I use myself.
227227
228228| Doom Hotkey | Function |
229|----------------|---------------------------------------|
229| -------------- | ------------------------------------- |
230230| `SPC m t` | org-todo |
231231| `SPC n t` | org-todo-list |
232232| `SPC o A` | org-agenda |
@@ -262,8 +262,8 @@ list them all, so I will simply cover a few of the basic commands I use myself.
262262 2. Add an empty `.projectile` file in the project root.
263263
264264 Once a project has been created, you can create custom publishing actions
265 within your `~/.doom.d/config.el` file. For example, here's a test project
266 I created to try and convert this blog to org-mode recently.
265 within your `~/.doom.d/config.el` file. For example, here's a test project I
266 created to try and convert this blog to org-mode recently.
267267
268268 ```lisp
269269 ;; org-publish
content/blog/2024-03-15-self-hosting-ddns-updater.md +28 −27
@@ -43,30 +43,31 @@ nano ~/ddns-updater/data/config.json
4343
4444When setting up the configuration for Cloudflare, you'll need the following:
4545
46- Required Parameters
47 - `"zone_identifier"` is the Zone ID of your site from the domain overview
48 page
49 - `"host"` is your host and can be `"@"`, a subdomain or the wildcard `"*"`.
50 See [this issue comment for
51 context](https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949).
52 - `"ttl"` integer value for record TTL in seconds (specify 1 for automatic)
53 - One of the following ([how to find API
54 keys](https://developers.cloudflare.com/fundamentals/api/get-started/)):
55 - Email `"email"` and Global API Key `"key"`
56 - User service key `"user_service_key"`
57 - API Token `"token"`, configured with DNS edit permissions for your DNS
58 name's zone
59- Optional Parameters
60 - `"proxied"` can be set to `true` to use the proxy services of Cloudflare
61 - `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or
62 `ipv4 or ipv6` (update one of the two, depending on the public ip
63 found). It defaults to `ipv4 or ipv6`.
64 - `"ipv6_suffix"` is the IPv6 interface identifier suffix to use. It can be
65 for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults
66 to no suffix and the raw public IPv6 address obtained is used in the
67 record updating.
68
69``` conf
46- Required Parameters
47 - `"zone_identifier"` is the Zone ID of your site from the domain overview
48 page
49 - `"host"` is your host and can be `"@"`, a subdomain or the wildcard
50 `"*"`. See [this issue comment for
51 context](https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949).
52 - `"ttl"` integer value for record TTL in seconds (specify 1 for
53 automatic)
54 - One of the following ([how to find API
55 keys](https://developers.cloudflare.com/fundamentals/api/get-started/)):
56 - Email `"email"` and Global API Key `"key"`
57 - User service key `"user_service_key"`
58 - API Token `"token"`, configured with DNS edit permissions for your
59 DNS name's zone
60- Optional Parameters
61 - `"proxied"` can be set to `true` to use the proxy services of Cloudflare
62 - `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or
63 `ipv4 or ipv6` (update one of the two, depending on the public ip
64 found). It defaults to `ipv4 or ipv6`.
65 - `"ipv6_suffix"` is the IPv6 interface identifier suffix to use. It can
66 be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it
67 defaults to no suffix and the raw public IPv6 address obtained is used
68 in the record updating.
69
70```conf
7071{
7172 "settings": [
7273 {
@@ -106,7 +107,7 @@ file.
106107nano ~/ddns_-pdater/docker-compose.yml
107108```
108109
109``` config
110```config
110111version: "3.7"
111112services:
112113 ddns-updater:
@@ -169,7 +170,7 @@ sudo nano /etc/nginx/sites-available/ddns
169170
170171Here's a basic example that should work properly.
171172
172``` conf
173```conf
173174server {
174175 # If using 443, remember to include your ssl_certificate
175176 # and ssl_certificate_key
@@ -190,7 +191,7 @@ server {
190191Here's a full example that uses my Authelia authentication service to require
191192authentication before someone can access the web page.
192193
193``` conf
194```conf
194195server {
195196 if ($host ~ ^[^.]+\.example\.com$) {
196197 return 301 https://$host$request_uri;
content/blog/2024-03-29-org-blog.md +3 −3
@@ -62,8 +62,8 @@ Either re-open Emacs or hit `SPC h r r` to reload the changes.
6262
6363## Configuration
6464
65Now that I've installed weblorg, I need to configure the project. I'll start
66by navigating to my site's source code and creating a `publish.el` file.
65Now that I've installed weblorg, I need to configure the project. I'll start by
66navigating to my site's source code and creating a `publish.el` file.
6767
6868```sh
6969cd ~/Source/cleberg.net && nano publish.el
@@ -187,7 +187,7 @@ restriction is that the `publish.el` file must point to the correct paths.
187187For my blog, I prefer to keep the blog content out of the top-level directory.
188188This results in the following structure (shortened for brevity):
189189
190``` txt
190```txt
191191.build/
192192content/
193193 blog/
content/blog/2024-04-08-docker-local-web-server.md +1 −1
@@ -84,7 +84,7 @@ docker run -it -d -p 8000:80 --name web -v ~/Source/cleberg.net/.build:/usr/shar
8484
8585Here's an example of my development configuration file.
8686
87``` conf
87```conf
8888# nginx-config.conf
8989server {
9090 server_name cleberg.net www.cleberg.net;
content/blog/2024-04-18-mu4e.md +2 −3
@@ -112,7 +112,7 @@ information and customize it to match your mail provider's information.
112112nano ~/.maildir/.mbsyncrc
113113```
114114
115``` conf
115```conf
116116IMAPAccount example
117117Host imap.example.com
118118User dummy@example.com
@@ -299,8 +299,7 @@ The emails will now to be ready to use!
299299You can now launch Doom and open Mu4e with `SPC o m`. You can also explore the
300300Mu4e options with `SPC : mu4e`.
301301
302The home page shows various options and metdata about the account you've
303opened.
302The home page shows various options and metdata about the account you've opened.
304303
305304![Mu4e Home Page](https://img.cleberg.net/blog/20240418-mu4e/mu4e.png)
306305
content/salary.md +26 −8
@@ -5,20 +5,33 @@ draft = false
55
66# Salary Transparency
77
8The data below details the base salary information for each job I've held. This information is posted publicly to ensure others in my position have a solid reference point when determining if their current or proposed salary is appropriate.
8The data below details the base salary information for each job I've held. This
9information is posted publicly to ensure others in my position have a solid
10reference point when determining if their current or proposed salary is
11appropriate.
912
10While sites like Glassdoor are locking salary data behind a paywall, LinkedIn is discontinuing LinkedIn Salary, and helpful websites like Big 4 Transparency are extremely rare, I wanted to provide my personal data publicly and freely to those who need it.
13While sites like Glassdoor are locking salary data behind a paywall, LinkedIn is
14discontinuing LinkedIn Salary, and helpful websites like Big 4 Transparency are
15extremely rare, I wanted to provide my personal data publicly and freely to
16those who need it.
1117
12I have seen what can happen when great employees don't know the market values for their skills and I happily help those in my teams, so I'm happy to extend this information to the online community.
18I have seen what can happen when great employees don't know the market values
19for their skills and I happily help those in my teams, so I'm happy to extend
20this information to the online community.
1321
14As a final note, there are numerous reasons that people in the same role are paid differently (expertise, years of experience, certifications, education, etc.) and that the data in this table should only be used as a single point of reference, not the whole story.
22As a final note, there are numerous reasons that people in the same role are
23paid differently (expertise, years of experience, certifications, education,
24etc.) and that the data in this table should only be used as a single point of
25reference, not the whole story.
1526
1627# Salary Data
1728
18Note: When in a role that gives periodic raises, I will create a new record with the new base salary in the table below. See the KPMG records for an example of a raise while in the same role.
29Note: When in a role that gives periodic raises, I will create a new record with
30the new base salary in the table below. See the KPMG records for an example of a
31raise while in the same role.
1932
2033| Title | Company | Location | Start | End | Salary |
21|------------------------------------------------|------------------------|----------------|---------|---------|----------|
34| ---------------------------------------------- | ---------------------- | -------------- | ------- | ------- | -------- |
2235| Senior Associate, Technology Assurance - Audit | KPMG | Omaha, NE | 2023-10 | Current | $116,700 |
2336| Senior Associate, Technology Assurance - Audit | KPMG | Omaha, NE | 2022-06 | 2023-10 | $110,000 |
2437| Senior Technology Risk Consultant | Ernst & Young | Des Moines, IA | 2021-09 | 2022-06 | $89,500 |
@@ -30,6 +43,11 @@ Note: When in a role that gives periodic raises, I will create a new record with
3043| Teaching Assistant | University of Nebraska | Lincoln, NE | 2017-08 | 2018-05 | $7/hour |
3144| Community Management Intern | Walgreens | Lincoln, NE | 2017-06 | 2018-02 | $14/hour |
3245
33This page was inspired by [Xe](https://xeiaso.net/salary-transparency/), and I'm quoting the following wording from them as I want to reiterate this piece:
46This page was inspired by [Xe](https://xeiaso.net/salary-transparency/), and I'm
47quoting the following wording from them as I want to reiterate this piece:
3448
35> Please consider publishing your salary data like this as well. By open, voluntary transparency we can help to end stigmas around discussing pay and help ensure that the next generations of people in tech are treated fairly. Stigmas thrive in darkness but die in the light of day. You can help end the stigma by playing your cards out in the open like this.
49> Please consider publishing your salary data like this as well. By open,
50> voluntary transparency we can help to end stigmas around discussing pay and
51> help ensure that the next generations of people in tech are treated fairly.
52> Stigmas thrive in darkness but die in the light of day. You can help end the
53> stigma by playing your cards out in the open like this.
content/services.md +16 −11
@@ -3,15 +3,20 @@ title = "Services"
33draft = false
44+++
55
6- [AnonymousOverflow](https://ao.cleberg.net/) - A StackOverflow proxy
7- [CyberChef](https://cyberchef.cleberg.net/) - The Cyber Swiss Army Knife
8- [FileArchive](https://files.cleberg.net/) - An interesting file archive
9- [FlashPaper](https://paste.cleberg.net/) - One-time encrypted password/secret sharing
10- [GotHub](https://gh.cleberg.net/) - An alternative front-end for GitHub
11- [ifconfig.php](https://ip.cleberg.net/) - A "whatsmyip" tool
12- [Invidious](https://invidious.cleberg.net/) - A YouTube proxy
13- [Office](https://office.cleberg.net/) - The world's smallest office suite
14- [Org-Live](https://org.cleberg.net/) - A basic org-mode editor for the web I built
15- [SearXNG](https://search.cleberg.net/) - A privacy-respecting, open metasearch engine
6- [AnonymousOverflow](https://ao.cleberg.net/) - A StackOverflow proxy
7- [CyberChef](https://cyberchef.cleberg.net/) - The Cyber Swiss Army Knife
8- [FileArchive](https://files.cleberg.net/) - An interesting file archive
9- [FlashPaper](https://paste.cleberg.net/) - One-time encrypted
10 password/secret sharing
11- [GotHub](https://gh.cleberg.net/) - An alternative front-end for GitHub
12- [ifconfig.php](https://ip.cleberg.net/) - A "whatsmyip" tool
13- [Invidious](https://invidious.cleberg.net/) - A YouTube proxy
14- [Office](https://office.cleberg.net/) - The world's smallest office suite
15- [Org-Live](https://org.cleberg.net/) - A basic org-mode editor for the web I
16 built
17- [SearXNG](https://search.cleberg.net/) - A privacy-respecting, open
18 metasearch engine
1619
17See the [git log](https://git.cleberg.net/?p=cleberg.net.git;a=history;f=content/services/index.org;h=b9ecca2567a02711a33bb633d45f790610ed9214;hb=HEAD) if you want to see changes that have been made.
20See the [git
21log](https://git.cleberg.net/?p=cleberg.net.git;a=history;f=content/services/index.org;h=b9ecca2567a02711a33bb633d45f790610ed9214;hb=HEAD)
22if you want to see changes that have been made.
content/wiki/blogroll.md +20 −16
@@ -6,30 +6,34 @@ draft = false
66
77## Aggregators
88
9 - [1MB Club](https://1mb.club/)
10 - [250KB Club](https://250kb.club/)
11 - [512KB Club](https://512kb.club/)
12 - [Darktheme Club](https://darktheme.club/)
13 - [No CSS Club](https://nocss.club/)
14 - [No-JS Club](https://no-js.club/)
15 - [Ye Olde Blogroll](https://blogroll.org/)
9- [1MB Club](https://1mb.club/)
10- [250KB Club](https://250kb.club/)
11- [512KB Club](https://512kb.club/)
12- [Darktheme Club](https://darktheme.club/)
13- [No CSS Club](https://nocss.club/)
14- [No-JS Club](https://no-js.club/)
15- [Ye Olde Blogroll](https://blogroll.org/)
1616
1717## Plain Text
1818
1919A list of various plaintext websites and lists.
2020
21 - [A List Of Text-Only & Minimalist News Sites](https://greycoder.com/a-list-of-text-only-new-sites/)
22 - [Harvard Law Review](https://harvardlawreview.org/)
23 - [Hyperlinked Text](https://sjmulder.nl/en/textonly.html)
24 - [Plain-text web design](https://medium.com/@letsworkshop/plain-text-web-design-a78ccaf9dbc0)
25 - [Plaintext World](https://plaintextworld.com/)
26 - [Words](https://justinjackson.ca/words.html)
21- [A List Of Text-Only & Minimalist News
22 Sites](https://greycoder.com/a-list-of-text-only-new-sites/)
23- [Harvard Law Review](https://harvardlawreview.org/)
24- [Hyperlinked Text](https://sjmulder.nl/en/textonly.html)
25- [Plain-text web
26 design](https://medium.com/@letsworkshop/plain-text-web-design-a78ccaf9dbc0)
27- [Plaintext World](https://plaintextworld.com/)
28- [Words](https://justinjackson.ca/words.html)
2729
2830## Webrings
2931
30Instead of listing my personal favorites, I'm just going to drop a link to [brisay's webring list](https://brisray.com/web/webring-list.htm), which contains 237 webrings for a total of 7078 websites, as of 2024-03-15.
32Instead of listing my personal favorites, I'm just going to drop a link to
33[brisay's webring list](https://brisray.com/web/webring-list.htm), which
34contains 237 webrings for a total of 7078 websites, as of 2024-03-15.
3135
3236## Everything Else
3337
34 - [Dead Simple Sites](https://deadsimplesites.com/)
35 - [Planet Emacslife](https://planet.emacslife.com/)
38- [Dead Simple Sites](https://deadsimplesites.com/)
39- [Planet Emacslife](https://planet.emacslife.com/)
content/wiki/hardware.md +63 −41
@@ -11,7 +11,7 @@ draft = false
1111Probably should have added more RAM but Macbooks are stupid expensive.
1212
1313| Category | Details |
14|----------|-------------------------------------------------------|
14| -------- | ----------------------------------------------------- |
1515| Model | [Macbook Pro 16"](https://www.apple.com/macbook-pro/) |
1616| CPU | Apple M2 Pro |
1717| RAM | 16GB |
@@ -21,19 +21,19 @@ Probably should have added more RAM but Macbooks are stupid expensive.
2121
2222A beauty.
2323
24| Category | Details |
25|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
26| Model | [Lenovo ThinkPad E15 Gen 4, model 21ED0048US](https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpade/thinkpad--e15-gen-4-(15-inch-amd)/len101t0023) |
27| CPU | AMD Ryzen 5 5625U with Radeon Graphics |
28| RAM | 16 GB |
29| Storage | 256 GB SSD |
24| Category | Details |
25| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
26| Model | [Lenovo ThinkPad E15 Gen 4, model 21ED0048US](<https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpade/thinkpad--e15-gen-4-(15-inch-amd)/len101t0023>) |
27| CPU | AMD Ryzen 5 5625U with Radeon Graphics |
28| RAM | 16 GB |
29| Storage | 256 GB SSD |
3030
3131## Mobile
3232
3333Previously used a Pixel 6 & Pixel 7 with GrapheneOS.
3434
3535| Category | Details |
36|----------|-----------------------------------------------------------|
36| -------- | --------------------------------------------------------- |
3737| Model | [iPhone 15 Pro Max](https://www.apple.com/iphone-15-pro/) |
3838| CPU | A17 Pro |
3939| RAM | 8GB |
@@ -41,55 +41,77 @@ Previously used a Pixel 6 & Pixel 7 with GrapheneOS.
4141
4242## Homelab
4343
44I run a small homelab with a mix of consumer (compute/storage) and
45enterprise (network) hardware. I try to keep the lab energy efficient
46and quiet as my top priorities.
44I run a small homelab with a mix of consumer (compute/storage) and enterprise
45(network) hardware. I try to keep the lab energy efficient and quiet as my top
46priorities.
4747
4848### IoT
4949
50A collection of mainly smart lights, sensors, and smart appliances. My first preference is to disable all networking for new smart devices or simply not connect internet in the first place (e.g. I never enable internet on my smart TVs). If the smart device requires LAN access, I will connect the device to my guest-restricted IoT network. As a last resort, I will set-up the internet but monitor the DNS lookups via NextDNS and forcibly block any domains I do not want the device to be using. If the device is egregious or shady, I'll just sell it and either replace it or live without it.
50A collection of mainly smart lights, sensors, and smart appliances. My first
51preference is to disable all networking for new smart devices or simply not
52connect internet in the first place (e.g. I never enable internet on my smart
53TVs). If the smart device requires LAN access, I will connect the device to my
54guest-restricted IoT network. As a last resort, I will set-up the internet but
55monitor the DNS lookups via NextDNS and forcibly block any domains I do not want
56the device to be using. If the device is egregious or shady, I'll just sell it
57and either replace it or live without it.
5158
5259- Other Appliances (washer, dryer, humidifier, fans, etc.)
53 - [Roomba i7+](https://about.irobot.com/sitecore/content/north-america/irobot-us/home/roomba/i7-series)
54 - [Philips Hue A19 Bulbs](https://www.philips-hue.com/en-us/p/hue-white-and-color-ambiance-a19---e26-smart-bulb---60-w--3-pack-/046677562786) x 15
55 - [Philips Hue Play Light Bars](https://www.philips-hue.com/en-us/p/hue-bundle-play-blk-ext/33001)
56 - [Philips Hue Smart Bridge](https://www.philips-hue.com/en-us/p/hue-bridge/046677458478) + play light bars and a ton of bulbs
57 - [UP Chime](https://store.ui.com/us/en/collections/unifi-camera-security-special-chime)
58 - [UP-Sense](https://store.ui.com/us/en/collections/unifi-camera-security-special-sensor) x 2
59 - [USP-Plug](https://store.ui.com/us/en/products/unifi-smart-power)
60 - [UVC G4 Instant](https://store.ui.com/us/en/collections/unifi-camera-security-compact-wifi-connected) x 3
61 - [UVC G4 Doorbell Pro](https://store.ui.com/us/en/collections/unifi-camera-security-special-wifi-doorbell)
60- [Roomba
61 i7+](https://about.irobot.com/sitecore/content/north-america/irobot-us/home/roomba/i7-series)
62- [Philips Hue A19
63 Bulbs](https://www.philips-hue.com/en-us/p/hue-white-and-color-ambiance-a19---e26-smart-bulb---60-w--3-pack-/046677562786)
64 x 15
65- [Philips Hue Play Light
66 Bars](https://www.philips-hue.com/en-us/p/hue-bundle-play-blk-ext/33001)
67- [Philips Hue Smart
68 Bridge](https://www.philips-hue.com/en-us/p/hue-bridge/046677458478) + play
69 light bars and a ton of bulbs
70- [UP
71 Chime](https://store.ui.com/us/en/collections/unifi-camera-security-special-chime)
72- [UP-Sense](https://store.ui.com/us/en/collections/unifi-camera-security-special-sensor)
73 x 2
74- [USP-Plug](https://store.ui.com/us/en/products/unifi-smart-power)
75- [UVC G4
76 Instant](https://store.ui.com/us/en/collections/unifi-camera-security-compact-wifi-connected)
77 x 3
78- [UVC G4 Doorbell
79 Pro](https://store.ui.com/us/en/collections/unifi-camera-security-special-wifi-doorbell)
6280
6381### Network
6482
65A rack-mounted Dream Machine Pro, connected downstream to an access point, mesh extender, and a couple ethernet switches.
83A rack-mounted Dream Machine Pro, connected downstream to an access point, mesh
84extender, and a couple ethernet switches.
6685
67 - [UDM-Pro](https://store.ui.com/us/en/collections/unifi-dream-machine/products/udm-pro)
68 - [USW-24-PoE](https://store.ui.com/us/en/collections/unifi-switching-standard-power-over-ethernet/products/usw-24-poe)
69 - [USW-Lite-8-PoE](https://store.ui.com/us/en/collections/unifi-switching-utility-poe/products/usw-lite-8-poe)
70 - [U6-Pro](https://store.ui.com/us/en/collections/unifi-wifi-flagship-high-capacity/products/u6-pro)
71 - [U6-Extender](https://store.ui.com/us/en/collections/unifi-wifi-inwall-outlet-mesh)
72 - [USW 24-Port Patch Panel](https://store.ui.com/us/en/collections/unifi-accessory-tech-installations-rackmount/products/uacc-rack-panel-patch-blank-24)
86- [UDM-Pro](https://store.ui.com/us/en/collections/unifi-dream-machine/products/udm-pro)
87- [USW-24-PoE](https://store.ui.com/us/en/collections/unifi-switching-standard-power-over-ethernet/products/usw-24-poe)
88- [USW-Lite-8-PoE](https://store.ui.com/us/en/collections/unifi-switching-utility-poe/products/usw-lite-8-poe)
89- [U6-Pro](https://store.ui.com/us/en/collections/unifi-wifi-flagship-high-capacity/products/u6-pro)
90- [U6-Extender](https://store.ui.com/us/en/collections/unifi-wifi-inwall-outlet-mesh)
91- [USW 24-Port Patch
92 Panel](https://store.ui.com/us/en/collections/unifi-accessory-tech-installations-rackmount/products/uacc-rack-panel-patch-blank-24)
7393
7494### Servers
7595
76961. Rack-Mount Server
7797
78 I wasn't happy with using low-powered PCs as servers and I knew I did not want the ear-shattering enterprise rack-mounted servers, so I built my own.
98 I wasn't happy with using low-powered PCs as servers and I knew I did not
99 want the ear-shattering enterprise rack-mounted servers, so I built my own.
79100
80 | Category | Details |
81 |--------------------|----------------------------------------|
82 | Case | Rosewill RSV-R4100U 4U |
83 | Motherboard | NZXT B550 |
84 | CPU | AMD Ryzen 7 5700G with Radeon Graphics |
85 | RAM | 64GB RAM (2x32GB) |
86 | Storage (On-board) | Western Digital 500GB M.2 NVME SSD |
87 | Storage (HDD Bay) | 48TB HDD |
88 | PSU | Corsair RM850 PSU |
101 | Category | Details |
102 | ------------------ | -------------------------------------- |
103 | Case | Rosewill RSV-R4100U 4U |
104 | Motherboard | NZXT B550 |
105 | CPU | AMD Ryzen 7 5700G with Radeon Graphics |
106 | RAM | 64GB RAM (2x32GB) |
107 | Storage (On-board) | Western Digital 500GB M.2 NVME SSD |
108 | Storage (HDD Bay) | 48TB HDD |
109 | PSU | Corsair RM850 PSU |
89110
901112. Other
91112
92 These ran as my main servers before I built the rack-mounted server above. I have shut these down indefinitely for now as I have no use for them.
113 These ran as my main servers before I built the rack-mounted server above. I
114 have shut these down indefinitely for now as I have no use for them.
93115
94 - Dell OptiPlex
95 - Raspberry Pi 4
116 - Dell OptiPlex
117 - Raspberry Pi 4
content/wiki/ios.md +135 −87
@@ -6,9 +6,10 @@ draft = false
66
77Related:
88
9- [Hardware](/wiki/hardware.html)
9- [Hardware](/wiki/hardware.html)
1010
11My primary mobile OS. Currently running iOS 17. This wiki page contains most of the apps I have used at one point or another across my different iPhones.
11My primary mobile OS. Currently running iOS 17. This wiki page contains most of
12the apps I have used at one point or another across my different iPhones.
1213
1314(`*`) = My favorites
1415
@@ -16,141 +17,188 @@ My primary mobile OS. Currently running iOS 17. This wiki page contains most of
1617
1718### Display
1819
19- Light Mode
20 - 10:00 to 16:00
21- Dark Mode
22 - 16:00 to 10:00
20- Light Mode
21 - 10:00 to 16:00
22- Dark Mode
23 - 16:00 to 10:00
2324
2425### Focus Modes
2526
26- Personal Focus
27 - 06:00 to 21:00
28 - Allow Notifications From:
29 - Alarms
30 - Calendar
31 - Contacts (1 person)
32 - Messages
33 - Phone
34 - Reminders
35 - Signal
36 - UniFi Protect
37- Sleep Focus
38 - 21:00 to 06:00
39 - Allow Notifications From:
40 - Alarms
41 - Contacts (1 person)
42 - Reminders
43 - Signal
27- Personal Focus
28 - 06:00 to 21:00
29 - Allow Notifications From:
30 - Alarms
31 - Calendar
32 - Contacts (1 person)
33 - Messages
34 - Phone
35 - Reminders
36 - Signal
37 - UniFi Protect
38- Sleep Focus
39 - 21:00 to 06:00
40 - Allow Notifications From:
41 - Alarms
42 - Contacts (1 person)
43 - Reminders
44 - Signal
4445
4546### Privacy & Security
4647
47I generally follow the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) by only permitting the bare minimum privileges and revoking as soon as they are no longer required.
48I generally follow the [principle of least
49privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) by only
50permitting the bare minimum privileges and revoking as soon as they are no
51longer required.
4852
4953Here's the baseline I start with:
5054
51- Disable:
52 - Analytics & Improvements
53 - Apple Advertising
54 - Apple ID > Sign-In & Security > Two-Factor Authentication
55 - Location Services > System Services > Product Improvement
56 - Tracking > Allow Apps to Request to Track
57 - Safari > Advanced > Privacy Preserving Ad Measurement
58- Enable:
59 - Apple ID > iCloud > Advanced Data Protection
60 - Apple ID > Personal Information > Communication Preferences
61 - App Privacy Report
62 - Location Services only for Camera, Find My, UDisc, & WiFiman
63 (`While Using`)
64 - Safari > Prevent Cross-Site Tracking
65 - Safari > Hide IP Address
66 - Safari > Advanced > Advanced Tracking and Fingerprinting
67 Protection
55- Disable:
56 - Analytics & Improvements
57 - Apple Advertising
58 - Apple ID > Sign-In & Security > Two-Factor Authentication
59 - Location Services > System Services > Product Improvement
60 - Tracking > Allow Apps to Request to Track
61 - Safari > Advanced > Privacy Preserving Ad Measurement
62- Enable:
63 - Apple ID > iCloud > Advanced Data Protection
64 - Apple ID > Personal Information > Communication Preferences
65 - App Privacy Report
66 - Location Services only for Camera, Find My, UDisc, & WiFiman (`While
67 Using`)
68 - Safari > Prevent Cross-Site Tracking
69 - Safari > Hide IP Address
70 - Safari > Advanced > Advanced Tracking and Fingerprinting Protection
6871
6972## Native Apps
7073
7174### Business
7275
73- [Element](https://apps.apple.com/us/app/element-messenger/id1083446067) - A cross-platform messenger, based on Matrix
74- [LinkedIn](https://apps.apple.com/us/app/linkedin-network-job-finder/id288429040) - One of the only social media apps I use
76- [Element](https://apps.apple.com/us/app/element-messenger/id1083446067) - A
77 cross-platform messenger, based on Matrix
78- [LinkedIn](https://apps.apple.com/us/app/linkedin-network-job-finder/id288429040)
79 - One of the only social media apps I use
7580
7681### Developer Tools
7782
78- [Harbour](https://testflight.apple.com/join/F2vK7xo4) - Easily manage your Portainer service
79- [iSH](https://apps.apple.com/us/app/ish-shell/id1436902243) - A local shell with SSH functionality
83- [Harbour](https://testflight.apple.com/join/F2vK7xo4) - Easily manage your
84 Portainer service
85- [iSH](https://apps.apple.com/us/app/ish-shell/id1436902243) - A local shell
86 with SSH functionality
8087
8188### Entertainment
8289
83- [Plex](https://apps.apple.com/us/app/plex-watch-live-tv-and-movies/id383457673) - A client for the Plex Media Server
84- [Steam](https://apps.apple.com/us/app/steam-mobile/id495369748) - The top gaming marketplace for computers
90- [Plex](https://apps.apple.com/us/app/plex-watch-live-tv-and-movies/id383457673)
91 - A client for the Plex Media Server
92- [Steam](https://apps.apple.com/us/app/steam-mobile/id495369748) - The top
93 gaming marketplace for computers
8594
8695### Lifestyle
8796
88- [Home](https://apps.apple.com/us/app/home/id1110145103) (`*`) - Apple homekit powered smart home manager
89- [Hue](https://apps.apple.com/us/app/philips-hue/id1055281310) - Philips Hue smart home manager
90- [iRobot](https://apps.apple.com/us/app/irobot-home/id1012014442) - Manage iRobot Roomba devices
91- [UniFi Protect](https://apps.apple.com/us/app/unifi-protect/id1392492235) - View and manage most UniFi Protect cameras and settings
97- [Home](https://apps.apple.com/us/app/home/id1110145103) (`*`) - Apple
98 homekit powered smart home manager
99- [Hue](https://apps.apple.com/us/app/philips-hue/id1055281310) - Philips Hue
100 smart home manager
101- [iRobot](https://apps.apple.com/us/app/irobot-home/id1012014442) - Manage
102 iRobot Roomba devices
103- [UniFi Protect](https://apps.apple.com/us/app/unifi-protect/id1392492235) -
104 View and manage most UniFi Protect cameras and settings
92105
93106### Music
94107
95- [Apple Music](https://apps.apple.com/us/app/apple-music/id1108187390) (`*`) - Apple's native music streaming app
96- [Plexamp](https://apps.apple.com/us/app/plexamp/id1500797510) (`*`) - Top-notch music app for your Plex Media Server, with a neural network that provides excellent radio/shuffle suggestions
108- [Apple Music](https://apps.apple.com/us/app/apple-music/id1108187390) (`*`)
109 - Apple's native music streaming app
110- [Plexamp](https://apps.apple.com/us/app/plexamp/id1500797510) (`*`) -
111 Top-notch music app for your Plex Media Server, with a neural network that
112 provides excellent radio/shuffle suggestions
97113
98114### Navigation
99115
100- [deedum](https://apps.apple.com/us/app/deedum/id1546810946) - A Gemini Protocol browser
116- [deedum](https://apps.apple.com/us/app/deedum/id1546810946) - A Gemini
117 Protocol browser
101118
102119### News
103120
104- [NetNewsWire](https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210) - A free and open source RSS reader for Mac, iPhone, and iPad
121- [NetNewsWire](https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210)
122 - A free and open source RSS reader for Mac, iPhone, and iPad
105123
106124### Photo & Video
107125
108- [Aislingeach](https://testflight.apple.com/join/Q6WyyEpS) - A quick way to generate and rate images from the Stable Horde
109- [Unsplash](https://apps.apple.com/us/app/unsplash/id1290631746) - Premium images, mostly free
126- [Aislingeach](https://testflight.apple.com/join/Q6WyyEpS) - A quick way to
127 generate and rate images from the Stable Horde
128- [Unsplash](https://apps.apple.com/us/app/unsplash/id1290631746) - Premium
129 images, mostly free
110130
111131### Productivity
112132
113- [beorg](https://apps.apple.com/us/app/beorg-to-do-list-agenda/id1238649962) - An org-mode editor, outline, and scheduler with paid extensions
114- [Bitwarden](https://apps.apple.com/us/app/bitwarden-password-manager/id1137397744) (`*`) - An open source password manager
115- [Bitwarden Authenticator](https://apps.apple.com/us/app/bitwarden-authenticator/id6497335175) (`*`) - Generate 2FA on your device
116- [Cryptomator](https://apps.apple.com/us/app/cryptomator/id1560822163) - A cross-platform encryption program
117- [Obsidian](https://apps.apple.com/us/app/obsidian-connected-notes/id1557175442) (`*`) - A nice Markdown-based editor based on a "vault" structure. Offers a paid sync solution and community extensions
118- [Strongbox](https://apps.apple.com/us/app/strongbox-password-manager/id897283731) - Keepass password manager for iOS & macOS
119- [UniFi Network](https://apps.apple.com/us/app/unifi/id1057750338) - View and manage most UniFi Network settings
133- [beorg](https://apps.apple.com/us/app/beorg-to-do-list-agenda/id1238649962)
134 - An org-mode editor, outline, and scheduler with paid extensions
135- [Bitwarden](https://apps.apple.com/us/app/bitwarden-password-manager/id1137397744)
136 (`*`) - An open source password manager
137- [Bitwarden
138 Authenticator](https://apps.apple.com/us/app/bitwarden-authenticator/id6497335175)
139 (`*`) - Generate 2FA on your device
140- [Cryptomator](https://apps.apple.com/us/app/cryptomator/id1560822163) - A
141 cross-platform encryption program
142- [Obsidian](https://apps.apple.com/us/app/obsidian-connected-notes/id1557175442)
143 (`*`) - A nice Markdown-based editor based on a "vault" structure. Offers a
144 paid sync solution and community extensions
145- [Strongbox](https://apps.apple.com/us/app/strongbox-password-manager/id897283731)
146 - Keepass password manager for iOS & macOS
147- [UniFi Network](https://apps.apple.com/us/app/unifi/id1057750338) - View and
148 manage most UniFi Network settings
120149
121150### Safari Extensions
122151
123- [AdGuard](https://apps.apple.com/us/app/adguard-adblock-privacy/id1047223162) -
124 Ad blocker
125- [Dark Reader](https://apps.apple.com/us/app/dark-reader-for-safari/id1438243180) - Dark mode for all the sites
126- [PiPifier](https://apps.apple.com/us/app/pipifier/id1234771095) - Force videos to support PiP
127- [Privacy Redirect](https://apps.apple.com/us/app/privacy-redirect/id1578144015) - Redirect select websites to others, usually to privacy-focused alternatives
152- [AdGuard](https://apps.apple.com/us/app/adguard-adblock-privacy/id1047223162)
153 - Ad blocker
154- [Dark
155 Reader](https://apps.apple.com/us/app/dark-reader-for-safari/id1438243180) -
156 Dark mode for all the sites
157- [PiPifier](https://apps.apple.com/us/app/pipifier/id1234771095) - Force
158 videos to support PiP
159- [Privacy
160 Redirect](https://apps.apple.com/us/app/privacy-redirect/id1578144015) -
161 Redirect select websites to others, usually to privacy-focused alternatives
128162
129163### Social Networking
130164
131- [MultiTab T](https://apps.apple.com/us/app/multitab-for-tumblr/id1071533778) (`*`) - A gallery-based Tumblr client with some unique features, such as tab history and sync
132- [Signal](https://apps.apple.com/us/app/signal-private-messenger/id874139669) (`*`) - A simple, powerful, and secure messenger
133- [Three Cheers](https://testflight.apple.com/join/mpVk1qIy) - A client for Tildes.net with a design focus that matches the intent of Tildes
134- [Voyager](https://apps.apple.com/us/app/voyager-for-lemmy/id6451429762) - A Lemmy client
165- [MultiTab T](https://apps.apple.com/us/app/multitab-for-tumblr/id1071533778)
166 (`*`) - A gallery-based Tumblr client with some unique features, such as tab
167 history and sync
168- [Signal](https://apps.apple.com/us/app/signal-private-messenger/id874139669)
169 (`*`) - A simple, powerful, and secure messenger
170- [Three Cheers](https://testflight.apple.com/join/mpVk1qIy) - A client for
171 Tildes.net with a design focus that matches the intent of Tildes
172- [Voyager](https://apps.apple.com/us/app/voyager-for-lemmy/id6451429762) - A
173 Lemmy client
135174
136175### Sports
137176
138- [Apple Sports](https://apps.apple.com/us/app/apple-sports/id6446788829) - Apple's new sports app - lacks notifications and live events
139- [UDisc](https://apps.apple.com/us/app/udisc-disc-golf/id1072228953) - Disc golf course maps, score cards, and more
177- [Apple Sports](https://apps.apple.com/us/app/apple-sports/id6446788829) -
178 Apple's new sports app - lacks notifications and live events
179- [UDisc](https://apps.apple.com/us/app/udisc-disc-golf/id1072228953) - Disc
180 golf course maps, score cards, and more
140181
141182### Utilities
142183
143- [Backblaze](https://apps.apple.com/us/app/backblaze/id628638330) - Quickly view and manage Backblaze b2 cloud storage
144- [Mullvad VPN](https://apps.apple.com/us/app/mullvad-vpn/id1488466513) (`*`) - A private VPN service
145- [OTP Auth](https://apps.apple.com/us/app/otp-auth/id659877384) (`*`) - A minimalistic OTP app with support for biometrics, custom icons, import/export, and iCloud sync
146- [Plex Dash](https://apps.apple.com/us/app/plex-dash/id1500797677) - Stats about your Plex Media Server
147- [Safari](https://apps.apple.com/us/app/safari/id1146562112) - iOS default browser
148- [Unifi WiFiman](https://apps.apple.com/us/app/ubiquiti-wifiman/id1385561119) - Create visual layouts of WiFi strength and save heat maps to your phone
184- [Backblaze](https://apps.apple.com/us/app/backblaze/id628638330) - Quickly
185 view and manage Backblaze b2 cloud storage
186- [Mullvad VPN](https://apps.apple.com/us/app/mullvad-vpn/id1488466513) (`*`)
187 - A private VPN service
188- [OTP Auth](https://apps.apple.com/us/app/otp-auth/id659877384) (`*`) - A
189 minimalistic OTP app with support for biometrics, custom icons,
190 import/export, and iCloud sync
191- [Plex Dash](https://apps.apple.com/us/app/plex-dash/id1500797677) - Stats
192 about your Plex Media Server
193- [Safari](https://apps.apple.com/us/app/safari/id1146562112) - iOS default
194 browser
195- [Unifi WiFiman](https://apps.apple.com/us/app/ubiquiti-wifiman/id1385561119)
196 - Create visual layouts of WiFi strength and save heat maps to your phone
149197
150198## Web Apps & Shortcuts
151199
152- [Brutalist Report](https://brutalist.report/) - Minimal news aggregator
153- [_Cyber.Report](https://cyber.report/) - Cybersecurity news aggregator
154- [Hacker News](https://news.ycombinator.com/) - Mostly technical news
155- [NextDNS](https://nextdns.io/) - NextDNS statistics dashboard
156- [Readspike](https://readspike.com/) - Minimal news aggregator
200- [Brutalist Report](https://brutalist.report/) - Minimal news aggregator
201- [\_Cyber.Report](https://cyber.report/) - Cybersecurity news aggregator
202- [Hacker News](https://news.ycombinator.com/) - Mostly technical news
203- [NextDNS](https://nextdns.io/) - NextDNS statistics dashboard
204- [Readspike](https://readspike.com/) - Minimal news aggregator
content/wiki/macos.md +99 −54
@@ -6,9 +6,10 @@ draft = false
66
77Related:
88
9- [Hardware](/wiki/hardware/)
9- [Hardware](/wiki/hardware/)
1010
11My primary OS. Currently running macOS Sonoma 14. This wiki page contains most of the apps I have used at one point or another across my different Macbooks.
11My primary OS. Currently running macOS Sonoma 14. This wiki page contains most
12of the apps I have used at one point or another across my different Macbooks.
1213
1314(`*`) = My favorites
1415
@@ -16,13 +17,14 @@ My primary OS. Currently running macOS Sonoma 14. This wiki page contains most o
1617
1718### Disable System Services
1819
19- [Disabling and Enabling System Integrity
20- [Disabling and Enabling System Integrity
2021 Protection](https://developer.apple.com/documentation/security/disabling_and_enabling_system_integrity_protection)
21- Disable Gatekeeper: `sudo spctl --master-disable`
22- Disable Gatekeeper: `sudo spctl --master-disable`
2223
2324### Dotfiles
2425
25These are probably out of date, but they give a general idea of how I configure my machine.
26These are probably out of date, but they give a general idea of how I configure
27my machine.
2628
2729```conf
2830# ~/.zshrc
@@ -81,70 +83,113 @@ echo "yabai configuration loaded.."
8183
8284### Browsers
8385
84- [Librewolf](https://librewolf.net/) (`*`) - Custom version of Firefox, focused on privacy and security
85 - [Bitwarden](https://bitwarden.com/) - An open source password manager
86 - [Dark Reader](https://darkreader.org/) - Dark mode for all the websites
87 - [Libredirect](https://libredirect.github.io/) - Automatic web redirections
88 - [Strongbox](https://strongboxsafe.com/) - Keepass password manager for iOS & macOS
89 - [uBlock Origin](https://ublockorigin.com/) - Free, open-source ad content blocker
90- [Ungoogled Chromium](https://github.com/ungoogled-software/ungoogled-chromium) - Google Chromium, sans integration with Google
91- [eww](https://www.gnu.org/software/emacs/manual/html_mono/eww.html) - Emacs Web Wowser, for TUI browsing
86- [Librewolf](https://librewolf.net/) (`*`) - Custom version of Firefox,
87 focused on privacy and security
88 - [Bitwarden](https://bitwarden.com/) - An open source password manager
89 - [Dark Reader](https://darkreader.org/) - Dark mode for all the websites
90 - [Libredirect](https://libredirect.github.io/) - Automatic web
91 redirections
92 - [Strongbox](https://strongboxsafe.com/) - Keepass password manager for
93 iOS & macOS
94 - [uBlock Origin](https://ublockorigin.com/) - Free, open-source ad
95 content blocker
96- [Ungoogled
97 Chromium](https://github.com/ungoogled-software/ungoogled-chromium) - Google
98 Chromium, sans integration with Google
99- [eww](https://www.gnu.org/software/emacs/manual/html_mono/eww.html) - Emacs
100 Web Wowser, for TUI browsing
92101
93102### Communications
94103
95- [Element](https://element.io/) (`*`) - Matrix's default GUI client
96- [gomuks](https://github.com/tulir/gomuks) - A terminal based Matrix client
97- [Thunderbird](https://www.thunderbird.net/) (`*`) - An open source email client by Mozilla
98- [Signal](https://signal.org/) (`*`) - A simple, powerful, and secure messenger
104- [Element](https://element.io/) (`*`) - Matrix's default GUI client
105- [gomuks](https://github.com/tulir/gomuks) - A terminal based Matrix client
106- [Thunderbird](https://www.thunderbird.net/) (`*`) - An open source email
107 client by Mozilla
108- [Signal](https://signal.org/) (`*`) - A simple, powerful, and secure
109 messenger
99110
100111### Development
101112
102- [Docker Desktop](https://www.docker.com/products/docker-desktop/) - Docker containers for your desktop
103 - [open-webui](https://github.com/open-webui/open-webui) - User-friendly WebUI for LLMs
104- [iTerm2](https://iterm2.com/) (`*`) - The best terminal for macOS, hands down
105- [Podman Desktop](https://podman-desktop.io/) (`*`) - Open source tool for containers and Kubernetes
106- [Xcode](https://developer.apple.com/xcode/) - Apple's IDE
107- [zsh](https://en.wikipedia.org/wiki/Z_shell) (`*`) - My shell preference due to its plugin and theme community
108 - [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) - Fish-like autosuggestions for zsh
109 - [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) - Fish shell like syntax highlighting for Zsh
113- [Docker Desktop](https://www.docker.com/products/docker-desktop/) - Docker
114 containers for your desktop
115 - [open-webui](https://github.com/open-webui/open-webui) - User-friendly
116 WebUI for LLMs
117- [iTerm2](https://iterm2.com/) (`*`) - The best terminal for macOS, hands
118 down
119- [Podman Desktop](https://podman-desktop.io/) (`*`) - Open source tool for
120 containers and Kubernetes
121- [Xcode](https://developer.apple.com/xcode/) - Apple's IDE
122- [zsh](https://en.wikipedia.org/wiki/Z_shell) (`*`) - My shell preference due
123 to its plugin and theme community
124 - [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)
125 - Fish-like autosuggestions for zsh
126 - [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)
127 - Fish shell like syntax highlighting for Zsh
110128
111129### Editors
112130
113- [Doom Emacs](https://github.com/doomemacs/doomemacs) (`*`) - An Emacs framework, great for working in org-mode
114- [Obsidian](https://obsidian.md/) - A nice Markdown-based editor based on a "vault" structure. Offers a paid sync solution and community extensions
115- [Standard Notes](https://standardnotes.com/) - A simple text editor focused on privacy and security. Offers a paid sync solution and community extensions
116- [VSCodium](https://vscodium.com/) - VS Code without proprietary blobs
131- [Doom Emacs](https://github.com/doomemacs/doomemacs) (`*`) - An Emacs
132 framework, great for working in org-mode
133- [Obsidian](https://obsidian.md/) - A nice Markdown-based editor based on a
134 "vault" structure. Offers a paid sync solution and community extensions
135- [Standard Notes](https://standardnotes.com/) - A simple text editor focused
136 on privacy and security. Offers a paid sync solution and community
137 extensions
138- [VSCodium](https://vscodium.com/) - VS Code without proprietary blobs
117139
118140### Media
119141
120- [Luminar](https://skylum.com/luminar) - Luminar offers top-notch photo editing features
121- [Minecraft](https://www.minecraft.net/) - Block mining simulator
122- [NetNewsWire](https://netnewswire.com/) - A free and open source RSS reader for Mac, iPhone, and iPad
123- [Plex](https://www.plex.tv/) (`*`) - Desktop client for the Plex Media Server
124- [Steam](https://store.steampowered.com/) - The top gaming marketplace for computers
125- [Transmission](https://transmissionbt.com/) (`*`) - A Fast, Easy and Free Bittorrent Client
126- [VLC](https://www.videolan.org/vlc/) - A free and open source cross-platform multimedia player
142- [Luminar](https://skylum.com/luminar) - Luminar offers top-notch photo
143 editing features
144- [Minecraft](https://www.minecraft.net/) - Block mining simulator
145- [NetNewsWire](https://netnewswire.com/) - A free and open source RSS reader
146 for Mac, iPhone, and iPad
147- [Plex](https://www.plex.tv/) (`*`) - Desktop client for the Plex Media
148 Server
149- [Steam](https://store.steampowered.com/) - The top gaming marketplace for
150 computers
151- [Transmission](https://transmissionbt.com/) (`*`) - A Fast, Easy and Free
152 Bittorrent Client
153- [VLC](https://www.videolan.org/vlc/) - A free and open source cross-platform
154 multimedia player
127155
128156### Package Management
129157
130- [Homebrew](https://brew.sh/) (`*`) - The Missing Package Manager for macOS (or Linux)
131- [MacPorts](https://www.macports.org/) - A system to compile, install, and manage open source software
158- [Homebrew](https://brew.sh/) (`*`) - The Missing Package Manager for macOS
159 (or Linux)
160- [MacPorts](https://www.macports.org/) - A system to compile, install, and
161 manage open source software
132162
133163### Utilities
134164
135- [Bartender 5](https://www.macbartender.com/Bartender5/) (`*`) - Easy control and customization over the native macOS menu bar
136- [BetterDisplay](https://betterdisplay.pro/) - Allows you to tweak a ton of features of built-in and external screens, such as scaling, configuration overrides, and color/brightness upscaling
137- [Bitwarden](https://bitwarden.com/) - An open source password manager
138- [LittleSnitch](https://obdev.at/products/littlesnitch/index.html) - Shows all network connections on your Macbook, including system and privileged services
139- [MicroSnitch](https://obdev.at/products/microsnitch/index.html) - Camera & microphone monitoring and alterting service
140- [Mullvad](https://mullvad.net/) (`*`) - A private VPN service
141- [Ollama](https://ollama.com/) - Run Llama 2, Code Llama, and other models locally on your machine
142 - [Ollama Swift](https://github.com/kghandour/Ollama-SwiftUI) - User Interface made for Ollama.ai using Swift
143- [OrbStack](https://orbstack.dev/) - A fast and convenient GUI to manage Docker contains and Linux VMs
144- [Raycast](https://www.raycast.com/) - A collection of tools and shortcuts, an alternative to Spotlight
145- [skhd](https://github.com/koekeishiya/skhd) (`*`) - Simple hotkey daemon for macOS
146- [Strongbox](https://strongboxsafe.com/) - Keepass password manager for iOS & macOS
147- [Syncthing](https://syncthing.net/) (`*`) - Continuous file synchronization
148- [TinkerTool](https://www.bresink.com/osx/TinkerTool.html) - Unlock hidden configuration options for macOS
149- [yabai](https://github.com/koekeishiya/yabai) (`*`) - Automatic window tiling
150- [yt-dlp](https://github.com/yt-dlp/yt-dlp) - A youtube-dl fork with additional features and fixes
165- [Bartender 5](https://www.macbartender.com/Bartender5/) (`*`) - Easy control
166 and customization over the native macOS menu bar
167- [BetterDisplay](https://betterdisplay.pro/) - Allows you to tweak a ton of
168 features of built-in and external screens, such as scaling, configuration
169 overrides, and color/brightness upscaling
170- [Bitwarden](https://bitwarden.com/) - An open source password manager
171- [LittleSnitch](https://obdev.at/products/littlesnitch/index.html) - Shows
172 all network connections on your Macbook, including system and privileged
173 services
174- [MicroSnitch](https://obdev.at/products/microsnitch/index.html) - Camera &
175 microphone monitoring and alterting service
176- [Mullvad](https://mullvad.net/) (`*`) - A private VPN service
177- [Ollama](https://ollama.com/) - Run Llama 2, Code Llama, and other models
178 locally on your machine
179 - [Ollama Swift](https://github.com/kghandour/Ollama-SwiftUI) - User
180 Interface made for Ollama.ai using Swift
181- [OrbStack](https://orbstack.dev/) - A fast and convenient GUI to manage
182 Docker contains and Linux VMs
183- [Raycast](https://www.raycast.com/) - A collection of tools and shortcuts,
184 an alternative to Spotlight
185- [skhd](https://github.com/koekeishiya/skhd) (`*`) - Simple hotkey daemon for
186 macOS
187- [Strongbox](https://strongboxsafe.com/) - Keepass password manager for iOS &
188 macOS
189- [Syncthing](https://syncthing.net/) (`*`) - Continuous file synchronization
190- [TinkerTool](https://www.bresink.com/osx/TinkerTool.html) - Unlock hidden
191 configuration options for macOS
192- [yabai](https://github.com/koekeishiya/yabai) (`*`) - Automatic window
193 tiling
194- [yt-dlp](https://github.com/yt-dlp/yt-dlp) - A youtube-dl fork with
195 additional features and fixes
templates/base.html +12 −10
@@ -5,20 +5,21 @@
55 <title>cleberg.net</title>
66 {% endblock %}
77 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta name="theme-color" content="#111" media="(prefers-color-scheme: dark)">
9 <meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)">
10 {% if page %}
11 {% if page.description %}
8 <meta name="theme-color" content="#111" media="(prefers-color-scheme:
9 dark)">
10 <meta name="theme-color" content="#fff" media="(prefers-color-scheme:
11 light)">
12 {% if page %} {% if page.description %}
1213 <meta name="description" content="{{ page.description }}">
1314 {% elif config.description %}
1415 <meta name="description" content="{{ config.description }}">
15 {% endif %}
16 {% elif config.description %}
17 <meta name="description" content="{{ config.description }}" />
18 {% endif %}
16 {% endif %} {% elif config.description %}
17 <meta name="description" content="{{ config.description }}" /> {% endif
18 %}
1919
2020 {% block rss %}
21 <link rel="alternate" type="application/atom+xml" title="RSS" href="{{ get_url(path="atom.xml", trailing_slash=false) }}">
21 <link rel="alternate" type="application/atom+xml" title="RSS" href="{{
22 get_url(path="atom.xml", trailing_slash=false) }}">
2223 {% endblock %}
2324
2425 {% block css %}
@@ -41,7 +42,8 @@
4142
4243 <footer>
4344 <p>Last build: {{ now() | date(format="%Y-%m-%d %H:%M:%S") }}</p>
44 <p><a href="https://git.cleberg.net/?p=cleberg.net.git;a=summary" target="_blank" rel="noopener">Source Code</a></p>
45 <p><a href="https://git.cleberg.net/?p=cleberg.net.git;a=summary"
46 target="_blank" rel="noopener">Source Code</a></p>
4547 <p><a href="/atom.xml">Atom RSS Feed</a></p>
4648 </footer>
4749</body>
templates/blog.html +6 −4
@@ -3,15 +3,17 @@
33{% block content %}
44<h1>{{ section.title }}</h1>
55<p>Use <code>Ctrl + F</code> to search blog post titles for keywords.</p>
6<p>You can also add the <a href="/atom.xml">Atom RSS Feed</a> to your feed reader.</p>
6<p>You can also add the <a href="/atom.xml">Atom RSS Feed</a> to your feed
7reader.</p>
78{% set post_date = "1970-01-01" | date(format="%Y") %}
89{% for page in section.pages %}
9 {% if post_date != page.date | date(format="%Y") %}
10 {% set_global post_date = page.date | date(format="%Y") %}
10{% if post_date != page.date | date(format="%Y") %}
11{% set_global post_date = page.date | date(format="%Y") %}
1112 <h2>{{ post_date }}</h2>
1213 {% endif %}
1314 <div class="post">
14 <time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S') }}">{{ page.date | date(format='%Y-%m-%d') }}</time>
15 <time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S') }}">{{
16 page.date | date(format='%Y-%m-%d') }}</time>
1517 <a href="/blog/{{ page.slug }}/">{{ page.title }}</a>
1618 </div>
1719{% endfor %}
templates/index.html +9 −7
@@ -12,14 +12,14 @@ uid [ultimate] Christian Cleberg &lt;hello@cleberg.net&gt;</pre>
1212 {% set section = get_section(path="blog/_index.md") %}
1313 {% set i = 0 %}
1414 {% for page in section.pages %}
15 {% if i < 3%}
16 {% set_global i = i + 1%}
15 {% if i < 3%}
16 {% set_global i = i + 1%}
1717 <div class="post">
18 <time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S') }}">{{ page.date | date(format='%Y-%m-%d') }}</time>
18 <time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S')
19 }}">{{ page.date | date(format='%Y-%m-%d') }}</time>
1920 <a href="/blog/{{ page.slug }}/">{{ page.title }}</a>
2021 </div>
21 {% endif %}
22 {% endfor %}
22 {% endif %} {% endfor %}
2323 <br>
2424 <a href="/blog/">All Posts &rarr;</a>
2525</section>
@@ -35,8 +35,10 @@ uid [ultimate] Christian Cleberg &lt;hello@cleberg.net&gt;</pre>
3535 <h2>Contact</h2>
3636 <ul>
3737 <li>hello [at] cleberg.net (<a href="/gpg.txt">GPG</a>)</li>
38 <li><a href="https://matrix.to/#/@cyborg:matrix.tchncs.de" target="_blank" rel="noopener">@cyborg:@matrix.tchncs.de</a></li>
39 <li><a href="https://git.cleberg.net/" target="_blank" rel="noopener">Git</a></li>
38 <li><a href="https://matrix.to/#/@cyborg:matrix.tchncs.de"
39 target="_blank" rel="noopener">@cyborg:@matrix.tchncs.de</a></li>
40 <li><a href="https://git.cleberg.net/" target="_blank"
41 rel="noopener">Git</a></li>
4042 </ul>
4143</section>
4244{% endblock content %}
templates/page.html +11 −7
@@ -5,8 +5,10 @@
55{% endblock %}
66
77{% block css %}
8<link rel="stylesheet" href="/syntax-theme-dark.css" media="(prefers-color-scheme: dark)">
9<link rel="stylesheet" href="/syntax-theme-light.css" media="(prefers-color-scheme: light)">
8<link rel="stylesheet" href="/syntax-theme-dark.css"
9media="(prefers-color-scheme: dark)">
10<link rel="stylesheet" href="/syntax-theme-light.css"
11media="(prefers-color-scheme: light)">
1012<link rel="stylesheet" href="/styles.css">
1113{% endblock css %}
1214
@@ -14,10 +16,11 @@
1416<section class="post-metadata">
1517 <h1>{{ page.title }}</h1>
1618 {% if page.date %}
17 <p><time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S') }}">{{ page.date }}</time></p>
18 {% endif %}
19 {% if page.updated %}
20 <p>Last Updated: <time datetime="{{ page.updated | date(format='%Y-%m-%d %H:%M:%S') }}">{{ page.updated }}</time></p>
19 <p><time datetime="{{ page.date | date(format='%Y-%m-%d %H:%M:%S') }}">{{
20 page.date }}</time></p>
21 {% endif %} {% if page.updated %}
22 <p>Last Updated: <time datetime="{{ page.updated | date(format='%Y-%m-%d
23 %H:%M:%S') }}">{{ page.updated }}</time></p>
2124 {% endif %}
2225 <p>{{ page.word_count }} words; {{ page.reading_time }} minute(s)</p>
2326{% if page.toc %}
@@ -32,7 +35,8 @@
3235 <ul>
3336 {% for h2 in h1.children %}
3437 <li>
35 <a href="{{ h2.permalink | safe }}">{{ h2.title }}</a>
38 <a href="{{ h2.permalink | safe }}">{{
39 h2.title }}</a>
3640 </li>
3741 {% endfor %}
3842 </ul>
templates/wiki.html +3 −3
@@ -10,7 +10,7 @@
1010{% for page in section.pages %}
1111 <div class="wiki-post">
1212 <p><a href="/wiki/{{ page.slug }}/">{{ page.title }}</a></p>
13 <time datetime="{{ page.updated | date(format='%Y-%m-%d %H:%M:%S') }}">{{ page.updated | date(format='%Y-%m-%d')}}</p>
13 <time datetime="{{ page.updated | date(format='%Y-%m-%d %H:%M:%S')
14 }}">{{ page.updated | date(format='%Y-%m-%d')}}</p>
1415 </div>
15{% endfor %}
16{% endblock content %}
16{% endfor %} {% endblock content %}