Commit ce7749abd0

ce7749abd0114d836d116ecbeb001d0a3827be3b

parent: af67e996dc

Unsigned

cmc <hello@cleberg.net> · 2025-11-12 03:25 UTC

fix grammar in 2021 posts

Layout: unified · split

content/blog/2021-01-01-seum.org +6 −8
@@ -5,12 +5,9 @@
5 5
6* Game Description 6* Game Description
7 7
8[[https://store.steampowered.com/app/457210/SEUM_Speedrunners_from_Hell/][SEUM: 8[[https://store.steampowered.com/app/457210/SEUM_Speedrunners_from_Hell/][SEUM: Speedrunners from Hell]] is an incredibly fast-paced mashup of a puzzle game
9Speedrunners from Hell]] is an incredibly fast-paced mashup of a puzzle 9and a free-running game. Created by [[https://pinestudio.co][Pine Studio]] in early 2016 and first released
10game and a free-running game. Created by [[https://pinestudio.co][Pine 10as a [[https://gamejolt.com/games/seum-speedrunners-from-hell-demo/154868][demo on GameJolt]], this game was successfully green-lit on Steam and has
11Studio]] in early 2016 and first released as a
12[[https://gamejolt.com/games/seum-speedrunners-from-hell-demo/154868][demo
13on GameJolt]], this game was successfully green-lit on Steam and has
14amassed a cult following on multiple consoles. 11amassed a cult following on multiple consoles.
15 12
16Here's the game description straight from the developers: 13Here's the game description straight from the developers:
@@ -57,8 +54,9 @@ contains nine regular levels, one boss level, and one bonus level;
57although you don't technically need to beat all levels to advance to the 54although you don't technically need to beat all levels to advance to the
58next floor. # In-Game Screenshots 55next floor. # In-Game Screenshots
59 56
60The main menu gives you plenty of options for tuning your system, 57The main menu gives you plenty of options for tuning your system, playing main
61playing main levels, playing the DLC, or exploring the other game modes. 58levels, playing the downloadable content (DLC), or exploring the other game
59modes.
62 60
63Once you enter a level, you can look around and strategize before 61Once you enter a level, you can look around and strategize before
64starting. Clicking any button will start the menu, and you'll have to 62starting. Clicking any button will start the menu, and you'll have to
content/blog/2021-01-04-fediverse.org +41 −44
@@ -5,53 +5,51 @@
5 5
6* What is the Fediverse? 6* What is the Fediverse?
7 7
8The fediverse is a federated universe of servers commonly used for 8The fediverse is a federated universe of servers commonly used for sharing
9sharing content, like social media. So, instead of having to rely on a 9content, like social media. So, instead of having to rely on a single
10single organization to run the server (e.g. Facebook), the fediverse is 10organization to run the server (e.g. Facebook), the fediverse is a giant
11a giant collection of servers across the world, owned by many people and 11collection of servers across the world, owned by many people and organizations.
12organizations. 12
13 13Take a look at this depiction of a federated network. Each server in this photo
14Take a look at this depiction of a federated network. Each server in 14is owned and run by different administrators/owners. Federated networks are best
15this photo is owned and run by different administrators/owners. 15explained as email servers: you have an email account that exists on a server
16Federated networks are best explained as email servers: you have an 16(e.g. Outlook), your friend has an account on a different server (e.g. GMail),
17email account that exists on a server (e.g. Outlook), your friend has an 17and another friend has an account on a third server (e.g. ProtonMail). All three
18account on a different server (e.g. GMail), and another friend has an 18of you can talk and communicate back and forth without having to be on the same
19account on a third server (e.g. ProtonMail). All three of you can talk 19server. However, responsible email admins are there to set rules and control the
20and communicate back and forth without having to be on the same server.
21However, responsible email admins are there to set rules and control the
22traffic going in/out of the server. 20traffic going in/out of the server.
23 21
24The main objective of this architecture is to decentralize the control 22The main objective of this architecture is to decentralize the control within
25within the internet connections. For example, if you run your own 23the internet connections. For example, if you run your own Mastodon instance,
26Mastodon instance, you and your users can't be censored or impacted in 24you and your users can't be censored or impacted in any way by authorities of
27any way by authorities of another Mastodon instance. Some users have 25another Mastodon instance. Some users have praised these features due to recent
28praised these features due to recent criticism of popular social media 26criticism of popular social media websites that may be over-censoring their
29websites that may be over-censoring their users. 27users.
30 28
31This strategy is great for making sure control of the social web isn't 29This strategy is great for making sure control of the social web isn't
32controlled by a single organization, but it also has some downsides. If 30controlled by a single organization, but it also has some downsides. If I create
33I create a Mastodon instance and get a ton of users to sign up, I can 31a Mastodon instance and get a ton of users to sign up, I can shut the server
34shut the server down at any time. That means you're at risk of losing 32down at any time. That means you're at risk of losing the content you've created
35the content you've created unless you back it up, or the server backs it 33unless you back it up, or the server backs it up for you. Also, depending on the
36up for you. Also, depending on the software used (e.g. Mastodon, 34software used (e.g. Mastodon, Pixelfed, etc.), censorship may still be an issue
37Pixelfed, etc.), censorship may still be an issue if the server admins 35if the server admins decide they want to censor their users. Now, censorship
38decide they want to censor their users. Now, censorship isn't always a 36isn't always a bad thing and can even benefit the community as a whole, but
39bad thing and can even benefit the community as a whole, but you'll want 37you'll want to determine which servers align with your idea of proper
40to determine which servers align with your idea of proper censorship. 38censorship.
41 39
42However, these are risks that we take when we sign up for any online 40However, these are risks that we take when we sign up for any online platform.
43platform. Whatever your reason is for trying out federated social 41Whatever your reason is for trying out federated social networks, they are part
44networks, they are part of the future of the internet. However, the 42of the future of the internet. However, the popularity of these services is
45popularity of these services is still yet to be determined, especially 43still yet to be determined, especially with the increased difficulty
46with the increased difficulty understanding and signing up for these 44understanding and signing up for these platforms. Perhaps increased regulation
47platforms. Perhaps increased regulation and litigation against current 45and litigation against current social media sites will push more users into the
48social media sites will push more users into the fediverse. 46fediverse.
49 47
50* Federated Alternatives to Popular Sites 48* Federated Alternatives to Popular Sites
51 49
52The list below is a small guide that will show you federated 50The list below is a small guide that will show you federated alternatives to
53alternatives to current popular websites. There are many more out there, 51current popular websites. There are many more out there, so go and explore: you
54so go and explore: you might just find the perfect home. 52might just find the perfect home.
55 53
56** Reddit 54** Reddit
57 55
@@ -91,10 +89,9 @@ so go and explore: you might just find the perfect home.
91 89
92* Get Started 90* Get Started
93 91
94The best way to get started is to simply sign up and learn as you go. If 92The best way to get started is to simply sign up and learn as you go. If you're
95you're comfortable signing up through a Mastodon, Pleroma, or Friendica 93comfortable signing up through a Mastodon, Pleroma, or Friendica server, here is
96server, here is [[https://fediverse.party/en/portal/servers][a list of 94[[https://fediverse.party/en/portal/servers][a list of themed servers]] to choose from. If you're looking for something else,
97themed servers]] to choose from. If you're looking for something else,
98try a web search for a federated alternative to your favorite sites. 95try a web search for a federated alternative to your favorite sites.
99 96
100Find a server that focuses on your passions and start there! 97Find a server that focuses on your passions and start there!
content/blog/2021-01-07-ufw.org +49 −53
@@ -5,22 +5,21 @@
5 5
6* Uncomplicated Firewall 6* Uncomplicated Firewall
7 7
8Uncomplicated Firewall, also known as ufw, is a convenient and 8Uncomplicated Firewall (UFW) is a convenient and beginner-friendly
9beginner-friendly way to enforce OS-level firewall rules. For those who 9way to enforce operating system (OS)-level firewall rules. For those who are
10are hosting servers or any device that is accessible to the world (i.e., 10hosting servers or any device that is accessible to the world (i.e., by public
11by public IP or domain name), it's critical that a firewall is properly 11IP or domain name), it's critical that a firewall is properly implemented and
12implemented and active. 12active.
13 13
14Ufw is available by default in all Ubuntu installations after 8.04 LTS. 14UFW is available by default in all Ubuntu installations after 8.04 LTS
15For other distributions, you can look to install ufw or check if there 15(long-term support). For other distributions, you can look to install UFW or
16are alternative firewalls installed already. There are usually 16check if there are alternative firewalls installed already. There are usually
17alternatives available, such as Fedora's =firewall= and the package 17alternatives available, such as Fedora's =firewall= and the package available on
18available on most distributions: =iptables=. Ufw is considered a 18most distributions: =iptables=. UFW is considered a beginner-friendly front-end
19beginner-friendly front-end to iptables. 19to iptables.
20 20
21[[https://gufw.org][Gufw]] is available as a graphical user interface 21[[https://gufw.org][Gufw]] is available as a graphical user interface (GUI) application for users who
22(GUI) application for users who are uncomfortable setting up a firewall 22are uncomfortable setting up a firewall through a terminal.
23through a terminal.
24 23
25* Getting Help 24* Getting Help
26 25
@@ -33,20 +32,19 @@ sudo ufw --help
33 32
34* Set Default State 33* Set Default State
35 34
36The proper way to run a firewall is to set a strict default state and 35The proper way to run a firewall is to set a strict default state and slowly
37slowly open up ports that you want to allow. This helps prevent anything 36open up ports that you want to allow. This helps prevent anything malicious from
38malicious from slipping through the cracks. The following command 37slipping through the cracks. The following command prevents all incoming traffic
39prevents all incoming traffic (other than the rules we specify later), 38(other than the rules we specify later), but you can also set this for outgoing
40but you can also set this for outgoing connections, if necessary. 39connections, if necessary.
41 40
42#+begin_src sh 41#+begin_src sh
43sudo ufw default deny incoming 42sudo ufw default deny incoming
44#+end_src 43#+end_src
45 44
46You should also allow outgoing traffic if you want to allow the device 45You should also allow outgoing traffic if you want to allow the device to
47to communicate back to you or other parties. For example, media servers 46communicate back to you or other parties. For example, media servers like Plex
48like Plex need to be able to send out data related to streaming the 47need to be able to send out data related to streaming the media.
49media.
50 48
51#+begin_src sh 49#+begin_src sh
52sudo ufw default allow outgoing 50sudo ufw default allow outgoing
@@ -54,23 +52,23 @@ sudo ufw default allow outgoing
54 52
55* Adding Port Rules 53* Adding Port Rules
56 54
57Now that we've disabled all incoming traffic by default, we need to open 55Now that we've disabled all incoming traffic by default, we need to open up some
58up some ports (or else no traffic would be able to come in). If you need 56ports (or else no traffic would be able to come in). If you need to be able to
59to be able to =ssh= into the machine, you'll need to open up port 22. 57=ssh= into the machine, you'll need to open up port 22.
60 58
61#+begin_src sh 59#+begin_src sh
62sudo ufw allow 22 60sudo ufw allow 22
63#+end_src 61#+end_src
64 62
65You can also issue more restrictive rules. The following rule will allow 63You can also issue more restrictive rules. The following rule will allow =ssh=
66=ssh= connections only from machines on the local subnet. 64(secure shell protocol) connections only from machines on the local subnet.
67 65
68#+begin_src sh 66#+begin_src sh
69sudo ufw allow proto tcp from 192.168.0.0/24 to any port 22 67sudo ufw allow proto tcp from 192.168.0.0/24 to any port 22
70#+end_src 68#+end_src
71 69
72If you need to set a rule that isn't tcp, just append your connection 70If you need to set a rule that isn't TCP (Transmission Control Protocol) just
73type to the end of the rule. 71append your connection type to the end of the rule.
74 72
75#+begin_src sh 73#+begin_src sh
76sudo ufw allow 1900/udp 74sudo ufw allow 1900/udp
@@ -93,8 +91,7 @@ sudo reboot now
93 91
94* Checking Status 92* Checking Status
95 93
96Now that the firewall is enabled, let's check and see what the rules 94Now that the firewall is enabled, let's check and see what the rules look like.
97look like.
98 95
99#+begin_src sh 96#+begin_src sh
100sudo ufw status numbered 97sudo ufw status numbered
@@ -111,9 +108,9 @@ Status: active
111 108
112* Deleting Rules 109* Deleting Rules
113 110
114If you need to delete a rule, you need to know the number associated 111If you need to delete a rule, you need to know the number associated with that
115with that rule. Let's delete the first rule in the table above. You'll 112rule. Let's delete the first rule in the table above. You'll be asked to confirm
116be asked to confirm the deletion as part of this process. 113the deletion as part of this process.
117 114
118#+begin_src sh 115#+begin_src sh
119sudo ufw delete 1 116sudo ufw delete 1
@@ -121,11 +118,10 @@ sudo ufw delete 1
121 118
122* Managing App Rules 119* Managing App Rules
123 120
124Luckily, there's a convenient way for installed applications to create 121Luckily, there's a convenient way for installed applications to create files
125files that ufw can easily implement so that you don't have to search and 122that ufw can easily implement so that you don't have to search and find which
126find which ports your application requires. To see if your device has 123ports your application requires. To see if your device has any applications with
127any applications with pre-installed ufw rules, execute the following 124pre-installed UFW rules, execute the following command:
128command:
129 125
130#+begin_src sh 126#+begin_src sh
131sudo ufw app list 127sudo ufw app list
@@ -142,8 +138,8 @@ Available applications:
142 plexmediaserver-dlna 138 plexmediaserver-dlna
143#+end_src 139#+end_src
144 140
145If you want to get more information on a specific app rule, use the 141If you want to get more information on a specific app rule, use the =info=
146=info= command. 142command.
147 143
148#+begin_src sh 144#+begin_src sh
149sudo ufw app info plexmediaserver-dlna 145sudo ufw app info plexmediaserver-dlna
@@ -161,8 +157,8 @@ Ports:
161 32469/tcp 157 32469/tcp
162#+end_src 158#+end_src
163 159
164You can add or delete app rules the same way that you'd add or delete 160You can add or delete app rules the same way that you'd add or delete specific
165specific port rules. 161port rules.
166 162
167#+begin_src sh 163#+begin_src sh
168sudo ufw allow plexmediaserver-dlna 164sudo ufw allow plexmediaserver-dlna
@@ -174,12 +170,12 @@ sudo ufw delete RULE|NUM
174 170
175* Creating App Rules 171* Creating App Rules
176 172
177If you'd like to create you own app rule, you'll need to create a file 173If you'd like to create you own app rule, you'll need to create a file in the
178in the =/etc/ufw/applications.d= directory. Within the file you create, 174=/etc/ufw/applications.d= directory. Within the file you create, you need to
179you need to make sure the content is properly formatted. 175make sure the content is properly formatted.
180 176
181For example, here are the contents my =plexmediaserver= file, which 177For example, here are the contents my =plexmediaserver= file, which creates
182creates three distinct app rules for ufw: 178three distinct app rules for ufw:
183 179
184#+begin_src config 180#+begin_src config
185[plexmediaserver] 181[plexmediaserver]
@@ -198,8 +194,8 @@ description=The Plex Media Server (with additional DLNA capability)
198ports=32400/tcp|3005/tcp|5353/udp|8324/tcp|32410:32414/udp|1900/udp|32469/tcp 194ports=32400/tcp|3005/tcp|5353/udp|8324/tcp|32410:32414/udp|1900/udp|32469/tcp
199#+end_src 195#+end_src
200 196
201So, if I wanted to create a custom app rule called "mycustomrule," I'd 197So, if I wanted to create a custom app rule called "mycustomrule," I'd create a
202create a file and add my content like this: 198file and add my content like this:
203 199
204#+begin_src sh 200#+begin_src sh
205sudo nano /etc/ufw/applications.d/mycustomrule 201sudo nano /etc/ufw/applications.d/mycustomrule
content/blog/2021-02-19-macos.org +87 −96
@@ -5,74 +5,69 @@
5 5
6* Diving into macOS 6* Diving into macOS
7 7
8After spending nearly 15 years working with Windows and 8 years on 8After spending nearly 15 years working with Windows and 8 years on Linux, I have
9Linux, I have experienced macOS for the first time. By chance, my spouse 9experienced macOS for the first time. By chance, my spouse happened to buy a new
10happened to buy a new MacBook and gifted me their 2013 model. Of course, 10MacBook and gifted me their 2013 model. Of course, I still consider my Linux
11I still consider my Linux desktop to be my daily driver and keep Windows 11desktop to be my daily driver and keep Windows around for gaming needs, but over
12around for gaming needs, but over the past week I've found myself using 12the past week I've found myself using the MacBook more and more for things that
13the MacBook more and more for things that don't require gaming specs or 13don't require gaming specs or advanced developer tools.
14advanced dev tools.
15 14
16* Initial Thoughts 15* Initial Thoughts
17 16
18Before I move on to the technical aspects of my set-up, I want to take 17Before I move on to the technical aspects of my set-up, I want to take some time
19some time and express my thoughts on the overall OS. 18and express my thoughts on the overall operating system (OS).
20 19
21As expected, the initial computer setup is a breeze with Mac's guided 20As expected, the initial computer setup is a breeze with Mac's guided graphical
22GUI installer. 21user interface (GUI) installer.
23 22
24The desktop itself reminds me of GNOME more than anything else I've 23The desktop itself reminds me of GNOME more than anything else I've seen: even
25seen: even Pantheon from [[https://elementary.io/][ElementaryOS]], which 24Pantheon from [[https://elementary.io/][ElementaryOS]], which people commonly refer to as the closest Linux
26people commonly refer to as the closest Linux distro to macOS. The 25distro to macOS. The desktop toolbar is great and far surpasses the utility of
27desktop toolbar is great and far surpasses the utility of the GNOME 26the GNOME toolbar due to the fact that the extensions and icons /actually work/.
28toolbar due to the fact that the extensions and icons /actually work/. I 27I launch macOS and immediately see my shortcuts for Tresorit, Bitwarden, and
29launch macOS and immediately see my shortcuts for Tresorit, Bitwarden, 28Mullvad pop up as the computer loads.
30and Mullvad pop up as the computer loads. 29
31 30Even further, the app dock is very useful and will be yet another familiarity
32Even further, the app dock is very useful and will be yet another 31for GNOME users. I know many people like panels instead of docks, but I've
33familiarity for GNOME users. I know many people like panels instead of 32always found docks to have a more pleasing UI. However, I had to disable the
34docks, but I've always found docks to have a more pleasing UI. However, 33"Show recent applications in Dock" preference; I can't stand items taking up
35I had to disable the "Show recent applications in Dock" preference; I 34precious screen space if I'm not currently using them. On that same note, it's
36can't stand items taking up precious screen space if I'm not currently 35taking me some time to get use to the fact that I have to manually quit an app
37using them. On that same note, it's taking me some time to get use to 36or else it will still stay open/active in the dock, even if I've closed out all
38the fact that I have to manually quit an app or else it will still stay 37windows for that app (e.g. Firefox).
39open/active in the dock, even if I've closed out all windows for that 38
40app (e.g. Firefox). 39Overall, I'm having a lot of fun and for users who spend a large majority of
41 40their time performing basic tasks like web browsing, writing, watching media,
42Overall, I'm having a lot of fun and for users who spend a large 41etc., macOS is a fantastic option.
43majority of their time performing basic tasks like web browsing, 42
44writing, watching media, etc., macOS is a fantastic option. 43The rest of this post explains the technicalities of how I set up my command
45 44line interface (CLI) environment to make me feel more at-home, similar to the
46The rest of this post explains the technicalities of how I set up my CLI 45environments I set up on Fedora, Ubuntu, etc.
47environment to make me feel more at-home, similar to the environments I
48set up on Fedora, Ubuntu, etc.
49 46
50* Making it Feel Like Home 47* Making it Feel Like Home
51 48
52If you're someone who uses Linux primarily, no doubt your first thought 49If you're someone who uses Linux primarily, no doubt your first thought when
53when booting macOS will be the same as mine was: "Where is the terminal 50booting macOS will be the same as mine was: "Where is the terminal and how do I
54and how do I set up my favorite utilities?" 51set up my favorite utilities?"
55 52
56Luckily, macOS hasn't completely hidden away the development tools from 53Luckily, macOS hasn't completely hidden away the development tools from the
57the average user. You can easily find the Terminal app in the Launchpad 54average user. You can easily find the Terminal app in the Launchpad area, but
58area, but it's probably not what you're used to. I was surprised (and 55it's probably not what you're used to. I was surprised (and happy) to see that
59happy) to see that the default shell is =zsh=, the shell I use on all of 56the default shell is =zsh=, the shell I use on all of my Linux distros. However,
60my Linux distros. However, the commands are not the same - even the ones 57the commands are not the same - even the ones you may think are native to the
61you may think are native to the shell. Commands like =dir= do not exist, 58shell. Commands like =dir= do not exist, so other native commands like =ls -la=
62so other native commands like =ls -la= or =pwd= are more useful here. 59or =pwd= are more useful here.
63 60
64With only a few minutes of installing and tweaking a few packages, I was 61With only a few minutes of installing and tweaking a few packages, I was able to
65able to recreate a terminal environment that I feel very comfortable 62recreate a terminal environment that I feel very comfortable using. See the
66using. See the image below for a preview of the iTerm2 app with a split 63image below for a preview of the iTerm2 app with a split view between my macOS
67view between my macOS desktop shell and an SSH session into my server. 64desktop shell and an SSH (secure shell protocol) session into my server.
68 65
69* Xcode 66* Xcode
70 67
71My first step was to search the web for any hints on how to get =zsh= 68My first step was to search the web for any hints on how to get =zsh= back up to
72back up to the state I like, with extensions, themes, etc. My first step 69the state I like, with extensions, themes, etc. My first step was to install the
73was to install the CLI tools for 70CLI tools for [[https://developer.apple.com/xcode/][Xcode]], Apple's suite of development tools.
74[[https://developer.apple.com/xcode/][Xcode]], Apple's suite of
75development tools.
76 71
77#+begin_src sh 72#+begin_src sh
78sudo xcode-select -r 73sudo xcode-select -r
@@ -84,25 +79,25 @@ sudo xcode-select --install
84 79
85* Homebrew 80* Homebrew
86 81
87Next up is to install [[https://brew.sh][Homebrew]], a nifty package 82Next up is to install [[https://brew.sh][Homebrew]], a nifty package manager for macOS.
88manager for macOS.
89 83
90#+begin_src sh 84#+begin_src sh
91/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 85/bin/bash -c "$(curl -fsSL
86https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
92#+end_src 87#+end_src
93 88
94I ran into a permission error when installing Homebrew: 89I ran into a permission error when installing Homebrew:
95 90
96#+begin_src sh 91#+begin_src sh
97Error: Failed to link all completions, docs and manpages: 92Error: Failed to link all completions, docs and manpages: Permission denied @
98 Permission denied @ rb_file_s_symlink - (../../../Homebrew/completions/zsh/_brew, /usr/local/share/zsh/site-functions/_brew) 93 rb_file_s_symlink - (../../../Homebrew/completions/zsh/_brew,
99Failed during: /usr/local/bin/brew update --force --quiet 94 /usr/local/share/zsh/site-functions/_brew) Failed during:
95 /usr/local/bin/brew update --force --quiet
100#+end_src 96#+end_src
101 97
102I found that the following permission modification worked like a charm. 98I found that the following permission modification worked like a charm. However,
103However, I noted that some users online discussed the fact that this 99I noted that some users online discussed the fact that this solution may not
104solution may not work if your system has multiple users who use 100work if your system has multiple users who use Homebrew.
105Homebrew.
106 101
107#+begin_src sh 102#+begin_src sh
108sudo chown -R $(whoami) $(brew --prefix)/* 103sudo chown -R $(whoami) $(brew --prefix)/*
@@ -120,16 +115,16 @@ brew cleanup
120 115
121* iTerm2 116* iTerm2
122 117
123Now that I've installed the basic utilities for development, I moved 118Now that I've installed the basic utilities for development, I moved onto
124onto installing iTerm2, a much better terminal than the default. 119installing iTerm2, a much better terminal than the default.
125 120
126#+begin_src sh 121#+begin_src sh
127brew install --cask iterm2 122brew install --cask iterm2
128#+end_src 123#+end_src
129 124
130I also used the =Make iTerm2 Default Term= and 125I also used the =Make iTerm2 Default Term= and =Install Shell Integration=
131=Install Shell Integration= options in the iTerm2 application menu to 126options in the iTerm2 application menu to make sure I don't run into any issues
132make sure I don't run into any issues later on with different terminals. 127later on with different terminals.
133 128
134We will also install =zsh= so we can use it in iTerm2. 129We will also install =zsh= so we can use it in iTerm2.
135 130
@@ -139,54 +134,50 @@ brew install zsh
139 134
140* Oh-My-Zsh 135* Oh-My-Zsh
141 136
142I've shown the great aspects of [[https://ohmyz.sh][Oh My Zsh]] in other 137I've shown the great aspects of [[https://ohmyz.sh][Oh My Zsh]] in other blog posts, so I'll skip over
143blog posts, so I'll skip over that speech for now. Simply install it and 138that speech for now. Simply install it and run an update.
144run an update.
145 139
146#+begin_src sh 140#+begin_src sh
147sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 141sh -c "$(curl -fsSL
142https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
148#+end_src 143#+end_src
149 144
150#+begin_src sh 145#+begin_src sh
151omz update 146omz update
152#+end_src 147#+end_src
153 148
154Finally, restart the iTerm2 application to ensure all changes go into 149Finally, restart the iTerm2 application to ensure all changes go into effect.
155effect.
156 150
157* Oh-My-Zsh Themes 151* Oh-My-Zsh Themes
158 152
159Let's change the theme of the terminal to make it a little more 153Let's change the theme of the terminal to make it a little more friendly.
160friendly.
161 154
162#+begin_src sh 155#+begin_src sh
163open ~/.zshrc 156open ~/.zshrc
164#+end_src 157#+end_src
165 158
166The third section of this file should contain a line like the code 159The third section of this file should contain a line like the code below. Change
167below. Change that theme to 160that theme to [[https://github.com/ohmyzsh/ohmyzsh/wiki/Themes][any theme you want]], save the file, and exit.
168[[https://github.com/ohmyzsh/ohmyzsh/wiki/Themes][any theme you want]],
169save the file, and exit.
170 161
171#+begin_src sh 162#+begin_src sh
172ZSH_THEME="af-magic" 163ZSH_THEME="af-magic"
173#+end_src 164#+end_src
174 165
175After changing the =.zshrc= file, you'll need to close your terminal and 166After changing the =.zshrc= file, you'll need to close your terminal and re-open
176re-open it to see the changes. Optionally, just open a new tab if you're 167it to see the changes. Optionally, just open a new tab if you're using iTerm2,
177using iTerm2, and you'll see the new shell config. 168and you'll see the new shell config.
178 169
179* Oh-My-Zsh Plugins 170* Oh-My-Zsh Plugins
180 171
181Of course, my customization of =zsh= would not be complete without 172Of course, my customization of =zsh= would not be complete without
182[[https://github.com/zsh-users/zsh-autosuggestions][zsh-autosuggestions]]. 173[[https://github.com/zsh-users/zsh-autosuggestions][zsh-autosuggestions]]. This will bring up commands you've run in the past as you
183This will bring up commands you've run in the past as you type them. For 174type them. For example, if you've run =ssh user@192.168.1.99= before, the
184example, if you've run =ssh user@192.168.1.99= before, the terminal will 175terminal will show this command as soon as you start typing it (e.g. =zsh u=),
185show this command as soon as you start typing it (e.g. =zsh u=), and you 176and you can hit the right arrow to autocomplete the command.
186can hit the right arrow to autocomplete the command.
187 177
188#+begin_src sh 178#+begin_src sh
189git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 179git clone https://github.com/zsh-users/zsh-autosuggestions
180${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
190#+end_src 181#+end_src
191 182
192#+begin_src sh 183#+begin_src sh
@@ -198,6 +189,6 @@ open ~/.zshrc
198plugins=(git zsh-autosuggestions) 189plugins=(git zsh-autosuggestions)
199#+end_src 190#+end_src
200 191
201Remember: After changing the =.zshrc= file, you'll need to close your 192Remember: After changing the =.zshrc= file, you'll need to close your terminal
202terminal and re-open it to see the changes. Optionally, just open a new 193and re-open it to see the changes. Optionally, just open a new tab if you're
203tab if you're using iTerm2, and you'll see the new shell config.\ No newline at end of file 194using iTerm2, and you'll see the new shell config.
content/blog/2021-03-19-clone-github-repos.org +27 −27
@@ -5,14 +5,14 @@
5 5
6* Cloning from GitHub 6* Cloning from GitHub
7 7
8If you're like me and use a lot of different devices (and sometimes 8If you're like me and use a lot of different devices [and sometimes decide to
9decide to just wipe your device and start with a new OS), you probably 9just wipe your device and start with a new operating system (OS)], you probably know
10know the pain of cloning all your old code repositories down to your 10the pain of cloning all your old code repositories down to your local file
11local file system. 11system.
12 12
13If you're using GitHub, you can easily clone all of your code back down 13If you're using GitHub, you can easily clone all of your code back down in just
14in just seconds. First, create a bash script. I do so by opening a new 14seconds. First, create a bash script. I do so by opening a new file in =nano=,
15file in =nano=, but you can use =gedit=, =vim=, or something else: 15but you can use =gedit=, =vim=, or something else:
16 16
17#+begin_src sh 17#+begin_src sh
18nano clone_github_repos.sh 18nano clone_github_repos.sh
@@ -44,12 +44,12 @@ Now you can run the script and should see the cloning process begin.
44 44
45* Cloning from Sourcehut 45* Cloning from Sourcehut
46 46
47I haven't fully figured out how to directly incorporate Sourcehut's 47I haven't fully figured out how to directly incorporate Sourcehut's GraphQL
48GraphQL API into a bash script yet, so this one will take two steps. 48application programming interface (API) into a bash script yet, so this one will
49take two steps.
49 50
50First, log-in to Sourcehut and go to their 51First, log-in to Sourcehut and go to their [[https://git.sr.ht/graphql][GraphQL playground for Git]]. Next,
51[[https://git.sr.ht/graphql][GraphQL playground for Git]]. Next, paste 52paste the following query into the left box:
52the following query into the left box:
53 53
54#+begin_src sh 54#+begin_src sh
55query { 55query {
@@ -65,10 +65,10 @@ query {
65} 65}
66#+end_src 66#+end_src
67 67
68The output on the right side will give you an object of all your 68The output on the right side will give you an object of all your repositories.
69repositories. Just grab that text and remove all the characters such as 69Just grab that text and remove all the characters such as quotation marks and
70quotation marks and curly brackets. You will need a single-line list of 70curly brackets. You will need a single-line list of space-separated values for
71space-separated values for the next step. 71the next step.
72 72
73Now let's create the bash script: 73Now let's create the bash script:
74 74
@@ -76,12 +76,12 @@ Now let's create the bash script:
76nano clone_sourcehut_repos.sh 76nano clone_sourcehut_repos.sh
77#+end_src 77#+end_src
78 78
79Next, paste the following bash script in with the list of repositories 79Next, paste the following bash script in with the list of repositories you
80you obtained above and replace =your-username= with your username. 80obtained above and replace =your-username= with your username.
81 81
82Note that this uses the SSH-based Git cloning method 82Note that this uses the secure shell protocol (SSH)-based Git cloning method
83(e.g. =git@git...=), so you'll need to ensure you have set up Sourcehut 83(e.g. =git@git...=), so you'll need to ensure you have set up Sourcehut with
84with your SSH key. 84your SSH key.
85 85
86#+begin_src sh 86#+begin_src sh
87repos=(repo1 repo2 repo3) 87repos=(repo1 repo2 repo3)
@@ -108,17 +108,17 @@ Now you can run the script and should see the cloning process begin.
108 108
109* Moving Repositories to a New Host 109* Moving Repositories to a New Host
110 110
111Now that you have all of your code repositories cloned to your local 111Now that you have all of your code repositories cloned to your local computer,
112computer, you may want to change the remote host (e.g., moving from 112you may want to change the remote host (e.g., moving from GitHub to GitLab). To
113GitHub to GitLab). To do this, let's create another bash script: 113do this, let's create another bash script:
114 114
115#+begin_src sh 115#+begin_src sh
116nano change_remote_urls.sh 116nano change_remote_urls.sh
117#+end_src 117#+end_src
118 118
119Past the following information and be sure to change the URL information 119Past the following information and be sure to change the URL (uniform resource
120to whichever host you are moving to. For this example, I am looping 120locator) information to whichever host you are moving to. For this example, I am
121through all of my cloned GitHub directories and changing them to 121looping through all of my cloned GitHub directories and changing them to
122Sourcehut (e.g. =<YOUR_NEW_REMOTE_URL>= -> =git@git.sr.ht:~myusername=). 122Sourcehut (e.g. =<YOUR_NEW_REMOTE_URL>= -> =git@git.sr.ht:~myusername=).
123 123
124#+begin_src sh 124#+begin_src sh
content/blog/2021-03-28-gemini-capsule.org +63 −73
@@ -5,21 +5,17 @@
5 5
6* What is Gemini? 6* What is Gemini?
7 7
8[[https://gemini.circumlunar.space/][Gemini]] is an internet protocol 8[[https://gemini.circumlunar.space/][Gemini]] is an internet protocol introduced in June 2019 as an alternative to the
9introduced in June 2019 as an alternative to HTTP(S) or Gopher. In 9Hypertext Transfer Protocol (HTTP) or Gopher. In layman's terms, it's an
10layman's terms, it's an alternative way to browse sites (called 10alternative way to browse sites (called capsules) that requires a special
11capsules) that requires a special browser. Since Gemini is not 11browser. Since Gemini is not standardized as an internet standard, normal web
12standardized as an internet standard, normal web browsers won't be able 12browsers won't be able to load a Gemini capsule. Instead, you'll need to use [[https://gemini.circumlunar.space/clients.html][a
13to load a Gemini capsule. Instead, you'll need to use 13Gemini-specific browser]].
14[[https://gemini.circumlunar.space/clients.html][a Gemini-specific 14
15browser]]. 15The content found within a Gemini page is called [[https://gemini.circumlunar.space/docs/cheatsheet.gmi][Gemtext]] and is /extremely/
16 16basic (on purpose). Gemini only processes the text, no media content like
17The content found within a Gemini page is called 17images. However, you're able to style 3 levels of headings, regular text, links
18[[https://gemini.circumlunar.space/docs/cheatsheet.gmi][Gemtext]] and is 18(which will display on their own line), quotes, and an unordered list.
19/extremely/ basic (on purpose). Gemini only processes the text, no media
20content like images. However, you're able to style 3 levels of headings,
21regular text, links (which will display on their own line), quotes, and
22an unordered list.
23 19
24Here's a complete listing of valid Gemtext: 20Here's a complete listing of valid Gemtext:
25 21
@@ -44,78 +40,72 @@ My List:
44 40
45*** Free Option 41*** Free Option
46 42
47There are probably numerous websites that allow you to create your 43There are probably numerous websites that allow you to create your personal
48personal Gemini capsule, but I'm going to focus on the two sites that I 44Gemini capsule, but I'm going to focus on the two sites that I have personally
49have personally tested. The first option below, Midnight Pub, allows you 45tested. The first option below, Midnight Pub, allows you to create/edit any
50to create/edit any Gemini files you want in your account. This is 46Gemini files you want in your account. This is essentially a graphical option
51essentially a GUI option with a built-in text box for editing. The 47with a built-in text box for editing. The second option below, Sourcehut, allows
52second option below, Sourcehut, allows you to use a Git repository and 48you to use a Git repository and automatic build process to deploy your personal
53automatic build process to deploy your personal Gemini capsule every 49Gemini capsule every time you push a commit.
54time you push a commit.
55 50
56** Midnight Pub - Beginner Friendly 51** Midnight Pub - Beginner Friendly
57 52
58[[https://midnight.pub/][Midnight Pub]] is a small, virtual community 53[[https://midnight.pub/][Midnight Pub]] is a small, virtual community meant to reflect the atmosphere of
59meant to reflect the atmosphere of wandering into a small alley pub. The 54wandering into a small alley pub. The site is built in Gemtext and has a
60site is built in Gemtext and has a server-side process to convert 55server-side process to convert Gemtext to HTML if someone loads the site in an
61Gemtext to HTML if someone loads the site in an HTTP(S) browser. 56HTTP(S) browser.
62 57
63To create an account, you'll need to email the owner of the website to 58To create an account, you'll need to email the owner of the website to obtain a
64obtain a key. You can find their email on the Midnight Pub homepage. 59key. You can find their email on the Midnight Pub homepage. Once registered,
65Once registered, head to [[https://midnight.pub/account][your account]] 60head to [[https://midnight.pub/account][your account]] and select [[https://midnight.pub/site][manage site]]. This is the screen where you can
66and select [[https://midnight.pub/site][manage site]]. This is the 61upload or create any files to be displayed on the internet.
67screen where you can upload or create any files to be displayed on the
68internet.
69 62
70For example, I've created both an HTML file and a Gemini file. Remember 63For example, I've created both a Hypertext Markup Language (HTML) file and a
71that Gemini is automatically converted to HTML on the Pub, so you don't 64Gemini file. Remember that Gemini is automatically converted to HTML on the Pub,
72need an HTML version. For example, I created an HTML version to add in 65so you don't need an HTML version. For example, I created an HTML version to add
73some extra styling. 66in some extra styling.
74 67
75All you need to do is create a page like =index.gmi= and use your Gemini 68All you need to do is create a page like =index.gmi= and use your Gemini browser
76browser to head over to your-username.midnight.pub to see the result. 69to head over to your-username.midnight.pub to see the result.
77 70
78That's all there is to it! Easy enough, right? Let's check out a more 71That's all there is to it! Easy enough, right? Let's check out a more advanced
79advanced version in the next section. 72version in the next section.
80 73
81* Paid Option 74* Paid Option
82 75
83As of 2021, Sourcehut has decided to require users to have a paid 76As of 2021, Sourcehut has decided to require users to have a paid account in
84account in order to utilize their automated build system. For now, paid 77order to utilize their automated build system. For now, paid accounts can be as
85accounts can be as low as $2/month. 78low as $2/month.
86 79
87** Sourcehut 80** Sourcehut
88 81
89[[https://sourcehut.org/][Sourcehut]] is a collection of software 82[[https://sourcehut.org/][Sourcehut]] is a collection of software development tools, but mostly surrounds
90development tools, but mostly surrounds their hosted Git repository 83their hosted Git repository service. Simply put, it's a minimal and more private
91service. Simply put, it's a minimal and more private alternative to 84alternative to services like GitHub.
92services like GitHub.
93 85
94This walkthrough is more advanced and involves things like Git, SSH, the 86This walkthrough is more advanced and involves things like Git, SSH, the command
95command line. If you don't think you know enough to do this, check out 87line. If you don't think you know enough to do this, check out my walkthrough on
96my walkthrough on creating a Gemini capsule for the Midnight Pub 88creating a Gemini capsule for the Midnight Pub instead.
97instead.
98 89
99The first thing you'll need to do is create an SSH key pair, if you 90The first thing you'll need to do is create an SSH key pair, if you don't
100don't already have one on your system. Once created, grab the contents 91already have one on your system. Once created, grab the contents of =id_rsa.pub=
101of =id_rsa.pub= and add it to your Sourcehut account settings - this 92and add it to your Sourcehut account settings - this will allow you to push and
102will allow you to push and pull code changes without using a 93pull code changes without using a username/password.
103username/password.
104 94
105#+begin_src sh 95#+begin_src sh
106ssh keygen 96ssh keygen
107#+end_src 97#+end_src
108 98
109Next up, let's create a repository with the proper name so that the 99Next up, let's create a repository with the proper name so that the Sourcehut
110Sourcehut build system will know we want them to host a website for us. 100build system will know we want them to host a website for us. Use the following
111Use the following format exactly: 101format exactly:
112 102
113#+begin_src sh 103#+begin_src sh
114mkdir your-username.srht.site && cd your-username.srht.site 104mkdir your-username.srht.site && cd your-username.srht.site
115#+end_src 105#+end_src
116 106
117Now that we've created the repo, let's initialize Git and add the proper 107Now that we've created the repo, let's initialize Git and add the proper remote
118remote URL. 108URL.
119 109
120#+begin_src sh 110#+begin_src sh
121git init 111git init
@@ -125,14 +115,14 @@ git init
125git remote add origin git@git.sr.ht:~your-username/your-username.srht.site 115git remote add origin git@git.sr.ht:~your-username/your-username.srht.site
126#+end_src 116#+end_src
127 117
128Now that our repository is set up and configured, we will need to create 118Now that our repository is set up and configured, we will need to create at
129at least two files: 119least two files:
130 120
131- =index.gmi= 121- =index.gmi=
132- =.build.yml= 122- =.build.yml=
133 123
134For your =.build.yml= file, use the following content and be sure to 124For your =.build.yml= file, use the following content and be sure to update the
135update the =site= line with your username! 125=site= line with your username!
136 126
137#+begin_src yaml 127#+begin_src yaml
138image: alpine/latest 128image: alpine/latest
@@ -147,11 +137,11 @@ tasks:
147 acurl -f https://pages.sr.ht/publish/$site -Fcontent=@site.tar.gz -Fprotocol=GEMINI 137 acurl -f https://pages.sr.ht/publish/$site -Fcontent=@site.tar.gz -Fprotocol=GEMINI
148#+end_src 138#+end_src
149 139
150For the =index.gmi= file, put whatever you want in there and save it. 140For the =index.gmi= file, put whatever you want in there and save it. You could
151You could even just copy and paste the Gemtext cheatsheet. 141even just copy and paste the Gemtext cheatsheet.
152 142
153If you want to serve both HTML and Gemini files from this repository, 143If you want to serve both HTML and Gemini files from this repository, just add a
154just add a second command to the =upload= section: 144second command to the =upload= section:
155 145
156#+begin_src yaml 146#+begin_src yaml
157- upload: | 147- upload: |
@@ -165,9 +155,9 @@ Lastly, commit your changes and push them to the remote repo.
165git add .; git commit -m "initial commit"; git push --set-upstream origin HEAD 155git add .; git commit -m "initial commit"; git push --set-upstream origin HEAD
166#+end_src 156#+end_src
167 157
168If you've successfully created the files with the proper format, you'll 158If you've successfully created the files with the proper format, you'll see the
169see the terminal print a message that lets you know where the automatic 159terminal print a message that lets you know where the automatic build is taking
170build is taking place. For example, here's what the terminal tells me: 160place. For example, here's what the terminal tells me:
171 161
172#+begin_src sh 162#+begin_src sh
173remote: Build started: 163remote: Build started:
content/blog/2021-03-28-vaporwave-vs-outrun.org +62 −74
@@ -5,15 +5,14 @@
5 5
6* Overview 6* Overview
7 7
8When it comes to an aesthetic that originated primarily online, there 8When it comes to an aesthetic that originated primarily online, there tends to
9tends to be a lot of confusion around what falls into each specific 9be a lot of confusion around what falls into each specific genre. This post
10genre. This post discusses Vaporwave and Outrun, which have become 10discusses Vaporwave and Outrun, which have become almost synonymous in the minds
11almost synonymous in the minds of those online who aren't hardcore into 11of those online who aren't hardcore into these genres of media. More
12these genres of media. More specifically, Outrun is largely an unknown 12specifically, Outrun is largely an unknown term while all aesthetics in these
13term while all aesthetics in these two genres are usually attributed to 13two genres are usually attributed to Vaporwave. For example, take a look at the
14Vaporwave. For example, take a look at the image search results for 14image search results for Vaporwave: the results include *a lot* of Outrun-themed
15Vaporwave: the results include *a lot* of Outrun-themed images. You'll 15images. You'll find a similar trend almost everywhere.
16find a similar trend almost everywhere.
17 16
18#+caption: Vaporwave Search Results 17#+caption: Vaporwave Search Results
19[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/vaporwave-search-results.webp]] 18[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/vaporwave-search-results.webp]]
@@ -23,102 +22,91 @@ find a similar trend almost everywhere.
23#+caption: Macintosh Plus Album Cover 22#+caption: Macintosh Plus Album Cover
24[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/macintosh-plus.webp]] 23[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/macintosh-plus.webp]]
25 24
26Okay, so what is Vaporwave? I'm going to just copy-and-paste some 25Okay, so what is Vaporwave? I'm going to just copy-and-paste some general info
27general info from the Wikipedia article on 26from the Wikipedia article on [[https://en.wikipedia.org/wiki/Vaporwave][Vaporwave]], so that I'm not repeating everything
28[[https://en.wikipedia.org/wiki/Vaporwave][Vaporwave]], so that I'm not 27you can already search for online:
29repeating everything you can already search for online:
30 28
31#+begin_quote 29#+begin_quote
32Vaporwave is a microgenre of electronic music, a visual art style, and 30Vaporwave is a microgenre of electronic music, a visual art style, and an
33an Internet meme that emerged in the early 2010s. It is defined partly 31Internet meme that emerged in the early 2010s. It is defined partly by its
34by its slowed-down, chopped and screwed samples of smooth jazz, 32slowed-down, chopped and screwed samples of smooth jazz, elevator, R&B, and
35elevator, R&B, and lounge music from the 1980s and 1990s. The 33lounge music from the 1980s and 1990s. The surrounding subculture is sometimes
36surrounding subculture is sometimes associated with an ambiguous or 34associated with an ambiguous or satirical take on consumer capitalism and pop
37satirical take on consumer capitalism and pop culture, and tends to be 35culture, and tends to be characterized by a nostalgic or surrealist engagement
38characterized by a nostalgic or surrealist engagement with the popular 36with the popular entertainment, technology and advertising of previous decades.
39entertainment, technology and advertising of previous decades. Visually, 37Visually, it incorporates early Internet imagery, late 1990s web design, glitch
40it incorporates early Internet imagery, late 1990s web design, glitch 38art, anime, 3D-rendered objects, and cyberpunk tropes in its cover artwork and
41art, anime, 3D-rendered objects, and cyberpunk tropes in its cover 39music videos.
42artwork and music videos.
43#+end_quote 40#+end_quote
44 41
45This is an excellent summary, and it helps address my point here: there 42This is an excellent summary, and it helps address my point here: there are
46are specific aspects that make Vaporwave unique: 43specific aspects that make Vaporwave unique:
47 44
48** Time Frame 45** Time Frame
49 46
50The time frame for references, logos, etc. focuses mostly on the 1990s 47The time frame for references, logos, etc. focuses mostly on the 1990s in
51in Vaporwave. You'll see old school Pepsi logos, Microsoft 95 screens, 48Vaporwave. You'll see old school Pepsi logos, Microsoft 95 screens, tropical
52tropical plants, classic marble sculptures, and many references from 49plants, classic marble sculptures, and many references from Japan's influence in
53Japan's influence in the 90s. 50the 90s.
54 51
55** Art 52** Art
56 53
57The color scheme is generally a soft, light palette that uses pastel 54The color scheme is generally a soft, light palette that uses pastel colors. The
58colors. The backdrop will often be in a light-pink or teal blue. 55backdrop will often be in a light-pink or teal blue.
59 56
60** Music 57** Music
61 58
62The musical genre of Vaporwave incorporates soft tunes, lounge music, 59The musical genre of Vaporwave incorporates soft tunes, lounge music, and sound
63and sound effects that will make the listener reminisce of the 90s. The 60effects that will make the listener reminisce of the 90s. The sounds of the
64sounds of the genre are generally slower-paced and calming. The major 61genre are generally slower-paced and calming. The major breakthrough artist for
65breakthrough artist for Vaporwave was 62Vaporwave was [[https://en.wikipedia.org/wiki/Vektroid][Macintosh Plus]], who released the album [[https://archive.org/details/MACINTOSHPLUS-FLORALSHOPPE_complete][Floral Shoppe]] in 2011.
66[[https://en.wikipedia.org/wiki/Vektroid][Macintosh Plus]], who released 63Another more recent example is the artist [[https://sadbert.bandcamp.com/][sadbert]], whose latest album
67the album 64incorporates the upbeat tones of the 1999 Dilbert television series.
68[[https://archive.org/details/MACINTOSHPLUS-FLORALSHOPPE_complete][Floral 65
69Shoppe]] in 2011. Another more recent example is the artist 66Notice that Vaporwave doesn't include things like racing cars, futuristic
70[[https://sadbert.bandcamp.com/][sadbert]], whose latest album 67technology, chrome, or the deep orange/purple color scheme. Vaporwave is a focus
71incorporates the upbeat tones of the 1999 Dilbert TV series. 68on the idyllic state of the world when technology was becoming common in
72 69households, a reality that we have already experienced. Focus on the most
73Notice that Vaporwave doesn't include things like racing cars, 70aesthetically-pleasing parts of that past is a large part of Vaporwave.
74futuristic technology, chrome, or the deep orange/purple color scheme.
75Vaporwave is a focus on the idyllic state of the world when technology
76was becoming common in households, a reality that we have already
77experienced. Focus on the most aesthetically-pleasing parts of that past
78is a large part of Vaporwave.
79 71
80* Outrun 72* Outrun
81 73
82#+caption: Outrun 74#+caption: Outrun
83[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/outrun.webp]] 75[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/outrun.webp]]
84 76
85Now, let's get to Outrun. This one is a little trickier since the genre 77Now, let's get to Outrun. This one is a little trickier since the genre has
86has largely been lumped under the Vaporwave title for so long. However, 78largely been lumped under the Vaporwave title for so long. However, it stems
87it stems from the [[https://en.wikipedia.org/wiki/Synthwave][Synthwave]] 79from the [[https://en.wikipedia.org/wiki/Synthwave][Synthwave]] music genre and is likely named after the 1986 racer game,
88music genre and is likely named after the 1986 racer game,
89[[https://en.wikipedia.org/wiki/Out_Run][Out Run]]. 80[[https://en.wikipedia.org/wiki/Out_Run][Out Run]].
90 81
91** Time Frame 82** Time Frame
92 83
93Outrun can be thought of as a retro-futuristic aesthetic born from the 84Outrun can be thought of as a retro-futuristic aesthetic born from the 1980s.
941980s.
95 85
96** Art 86** Art
97 87
98The color scheme uses a very dark color palette with the main colors 88The color scheme uses a very dark color palette with the main colors being deep
99being deep oranges, blues, and purples. Red edges are common around 89oranges, blues, and purples. Red edges are common around objects in Outrun art.
100objects in Outrun art. The background of the Outrun aesthetic is almost 90The background of the Outrun aesthetic is almost always a neon grid like you'd
101always a neon grid like you'd expect to see in Tron or a 1980s arcade 91expect to see in Tron or a 1980s arcade machine.
102machine.
103 92
104Classic sports cars, chrome robots, computer generated graphics and 93Classic sports cars, chrome robots, computer generated graphics and fonts, and
105fonts, and the occasional use of rain or palm trees can be found in 94the occasional use of rain or palm trees can be found in Outrun art.
106Outrun art.
107 95
108** Music 96** Music
109 97
110This aesthetic has a more aggressive and fast-paced style of music, 98This aesthetic has a more aggressive and fast-paced style of music, which tends
111which tends to match the subject of the art in this aesthetic. 99to match the subject of the art in this aesthetic.
112 100
113Outrun enthusiasts love what people in the 1980s thought the future 101Outrun enthusiasts love what people in the 1980s thought the future would look
114would look like. Take a look at a common video game discussed in Outrun 102like. Take a look at a common video game discussed in Outrun circles, Far Cry 3:
115circles, Far Cry 3: Blood Dragon: 103Blood Dragon:
116 104
117#+caption: Fry Cry 3: Blood Dragon 105#+caption: Fry Cry 3: Blood Dragon
118[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/far-cry.webp]] 106[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/far-cry.webp]]
119 107
120Another example that doesn't force the color scheme as hard as some 108Another example that doesn't force the color scheme as hard as some online art
121online art does is Kung Fury: 109does is Kung Fury:
122 110
123#+caption: Kung Fury 111#+caption: Kung Fury
124[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/kung-fury.webp]] 112[[https://img.cleberg.net/blog/20210328-vaporwave-vs-outrun/kung-fury.webp]]
@@ -128,7 +116,7 @@ online art does is Kung Fury:
128 116
129* Conclusion 117* Conclusion
130 118
131While Vaporwave and Outrun share similarities, they are two distinct 119While Vaporwave and Outrun share similarities, they are two distinct aesthetics
132aesthetics with many important distinctions. Someone who enjoys one may 120with many important distinctions. Someone who enjoys one may not necessarily
133not necessarily enjoy the other, so it's important to make sure we 121enjoy the other, so it's important to make sure we properly describe the
134properly describe the aesthetic we're looking for. 122aesthetic we're looking for.
content/blog/2021-03-30-vps-web-server.org +153 −178
@@ -3,108 +3,93 @@
3#+description: Instructional outline for setting up and maintaining a VPS environment configured for secure and scalable web hosting applications. 3#+description: Instructional outline for setting up and maintaining a VPS environment configured for secure and scalable web hosting applications.
4#+slug: vps-web-server 4#+slug: vps-web-server
5 5
6* Shared Hosting vs. VPS 6* Shared Hosting vs. VPS (Virtual Private Server)
7 7
8Choosing a place to host a website is one of the most confusing 8Choosing a place to host a website is one of the most confusing decisions for
9decisions for beginner web developers. Even for experienced web devs, 9beginner web developers. Even for experienced web devs, choosing between
10choosing between different forms of web hosting can be a daunting 10different forms of web hosting can be a daunting choice.
11choice. 11
12 12First, let's take a look at [[https://en.wikipedia.org/wiki/Shared_web_hosting_service][shared web hosting]]. Shared web hosting is a product
13First, let's take a look at 13where you are purchasing a small piece of a web server that is being shared
14[[https://en.wikipedia.org/wiki/Shared_web_hosting_service][shared web 14between many websites. As a result, the cost of shared hosting is extremely low.
15hosting]]. Shared web hosting is a product where you are purchasing a 15You won't have access to the server itself, which means you can't install your
16small piece of a web server that is being shared between many websites. 16own software on the server, such as Docker. Usually, you are simply allowed to
17As a result, the cost of shared hosting is extremely low. You won't have 17connect your domains to the server, set up domain security, and other small
18access to the server itself, which means you can't install your own 18utilities.
19software on the server, such as Docker. Usually, you are simply allowed 19
20to connect your domains to the server, set up domain security, and other 20In contrast, a [[https://en.wikipedia.org/wiki/Virtual_private_server][virtual private server]] (VPS) is a virtual machine that replicates
21small utilities. 21the environment of having a dedicated server to yourself. You are able to
22 22control the virtual server's host names, base file system, package manager, etc.
23In contrast, a 23Another great upside of a VPS is that since it's virtual, the company providing
24[[https://en.wikipedia.org/wiki/Virtual_private_server][virtual private 24the VPS can dynamically increase the disk size, RAM size, or number of CPUs at
25server]] (VPS) is a virtual machine that replicates the environment of 25any time. However, the virtual server is still physically located on a server
26having a dedicated server to yourself. You are able to control the 26that is shared between multiple virtual servers.
27virtual server's host names, base file system, package manager, etc. 27
28Another great upside of a VPS is that since it's virtual, the company 28The choice between shared hosting and VPS mostly depends on your skill level
29providing the VPS can dynamically increase the disk size, RAM size, or 29with system administration. If you're comforting working on a server that is
30number of CPUs at any time. However, the virtual server is still 30mostly left up to you (or you're willing to learn), then a VPS is usually a
31physically located on a server that is shared between multiple virtual 31better option. However, shared hosting is a fantastic option for people who
32servers. 32don't want to have to learn how to manage their server.
33
34The choice between shared hosting and VPS mostly depends on your skill
35level with system administration. If you're comforting working on a
36server that is mostly left up to you (or you're willing to learn), then
37a VPS is usually a better option. However, shared hosting is a fantastic
38option for people who don't want to have to learn how to manage their
39server.
40 33
41* My Situation 34* My Situation
42 35
43I had used shared hosting for approximately 5 years before trying my 36I had used shared hosting for approximately 5 years before trying my first VPS.
44first VPS. I manage a homelab and have had success running a server and 37I manage a homelab and have had success running a server and performing typical
45performing typical sysadmin duties, but I was still hesitant to get a 38sysadmin duties, but I was still hesitant to get a VPS. One fear was that I
46VPS. One fear was that I always struggled to properly set up the 39always struggled to properly set up the networking part of a server - DNS and
47networking part of a server - DNS and hostname configurations were not 40hostname configurations were not my friend.
48my friend. 41
49 42As a little bit of background, I originally used [[https://www.siteground.com][Siteground]] for my initially
50As a little bit of background, I originally used 43shared hosting and stayed on that platform for at least a year. However, the
51[[https://www.siteground.com][Siteground]] for my initially shared 44user interface (UI) was clunky, and I didn't like how they handled certain
52hosting and stayed on that platform for at least a year. However, the UI 45technical aspects, so I switched to [[https://www.namecheap.com][Namecheap]]. Namecheap was great because it is
53was clunky, and I didn't like how they handled certain technical 46the service I primarily use for purchasing domain names, which made it
54aspects, so I switched to [[https://www.namecheap.com][Namecheap]]. 47incredibly easy to link them to my hosting service. However, it was still
55Namecheap was great because it is the service I primarily use for 48mediocre shared hosting, and Namecheap is notorious for not letting you use
56purchasing domain names, which made it incredibly easy to link them to 49[[https://letsencrypt.org][Let's Encrypt]] to obtain free SSL (Secure Socket Layer)/TLS (Transport Layer
57my hosting service. However, it was still mediocre shared hosting, and 50Security) certificates; Namecheap wants to make you purchase certificates
58Namecheap is notorious for not letting you use 51through their store.
59[[https://letsencrypt.org][Let's Encrypt]] to obtain free SSL/TLS 52
60certificates; Namecheap wants to make you purchase certificates through 53Finally, I settled down with [[https://www.iwebfusion.net][iWebFusion]] for about the last year of my shared
61their store. 54hosting. This service was pretty great, came with free SSL/TLS, and I never had
62 55any complaints.
63Finally, I settled down with [[https://www.iwebfusion.net][iWebFusion]] 56
64for about the last year of my shared hosting. This service was pretty 57However, I finally grew tired of not being able to install software on my own
65great, came with free SSL/TLS, and I never had any complaints. 58web server. I wanted to be able to try out things like [[https://postmill.xyz][Postmill]] or [[https://matrix.org][Matrix]]. This
66 59is possible with a VPS, so I decided to grab a new domain name to try it out.
67However, I finally grew tired of not being able to install software on
68my own web server. I wanted to be able to try out things like
69[[https://postmill.xyz][Postmill]] or [[https://matrix.org][Matrix]].
70This is possible with a VPS, so I decided to grab a new domain name to
71try it out.
72 60
73* Getting Started: Buying a VPS 61* Getting Started: Buying a VPS
74 62
75The first step to moving over to a VPS is (you guessed it): finding a 63The first step to moving over to a VPS is (you guessed it): finding a VPS
76VPS provider. For my VPSs, I use [[https://1984hosting.com][1984]] and 64provider. For my VPSs, I use [[https://1984hosting.com][1984]] and prefer their services much more than any
77prefer their services much more than any alternative, due to their 65alternative, due to their location (Iceland), their [[https://1984hosting.com/GDPR/][privacy policy]], their
78location (Iceland), their [[https://1984hosting.com/GDPR/][privacy 66respect for GDPR, and the ability to remain anonymous if you pay in Bitcoin or
79policy]], their respect for GDPR, and the ability to remain anonymous if 67Monero.
80you pay in Bitcoin or Monero.
81 68
82[[https://njal.la][Njalla]] is another good, privacy-oriented option for 69[[https://njal.la][Njalla]] is another good, privacy-oriented option for VPS services.
83VPS services.
84 70
85You'll have to decide what specifications you want on your VPS. For me, 71You'll have to decide what specifications you want on your VPS. For me, I only
86I only build and deploy low-resource HTML, PHP, and Python websites. 72build and deploy low-resource HTML, PHP, and Python websites. This means I can
87This means I can survive on the smallest VPS: 1 CPU, 1GB of RAM, and 73survive on the smallest VPS: 1 CPU, 1GB of RAM, and 25GB SSD for $5.00 per
8825GB SSD for $5.00 per month. 74month.
89 75
90As noted above, the great thing about a VPS is you can request your 76As noted above, the great thing about a VPS is you can request your provider to
91provider to increase the resources at any time. 77increase the resources at any time.
92 78
93* Configuring DNS Settings 79* Configuring DNS Settings
94 80
95Okay, so now let's get into some actual work that has to be done to get 81Okay, so now let's get into some actual work that has to be done to get content
96content moved from a shared host to a VPS. At this point, I'm assuming 82moved from a shared host to a VPS. At this point, I'm assuming you have a shared
97you have a shared host with website content that you can still access, 83host with website content that you can still access, and you've purchased a new
98and you've purchased a new VPS and can SSH into that server. 84VPS and can SSH into that server.
99 85
100The first change is minor, but it should be done immediately in order to 86The first change is minor, but it should be done immediately in order to get
101get things moving: DNS settings. Go to wherever your DNS settings are 87things moving: DNS settings. Go to wherever your DNS settings are handled. If
102handled. If your shared host also managed your DNS settings, you'll need 88your shared host also managed your DNS settings, you'll need to first move that
103to first move that DNS over to your new VPS provider. For me, I route my 89DNS over to your new VPS provider. For me, I route my DNS through [[https://www.gandi.net][Gandi]].
104DNS through [[https://www.gandi.net][Gandi]].
105 90
106Once you know where your DNS settings are, go ahead and update the =A= 91Once you know where your DNS settings are, go ahead and update the =A= records
107records to match the public IP address of your VPS. For example: 92to match the public IP address of your VPS. For example:
108 93
109#+begin_src txt 94#+begin_src txt
110A example.com xxx.xxx.xxx.xxx 95A example.com xxx.xxx.xxx.xxx
@@ -112,36 +97,35 @@ A subdomain xxx.xxx.xxx.xxx
112CNAME www example.com. 97CNAME www example.com.
113#+end_src 98#+end_src
114 99
115If you have any other records that require updates, such as MX or TXT 100If you have any other records that require updates, such as MX or TXT records
116records for a mail server, be sure to update those accordingly. 101for a mail server, be sure to update those accordingly. Personally, I don't host
117Personally, I don't host my own mail server. I route all mail on my 102my own mail server. I route all mail on my custom domains to [[https://www.migadu.com][Migadu]]. Hosting
118custom domains to [[https://www.migadu.com][Migadu]]. Hosting your own 103your own email server can become complex quickly and is not for beginners.
119email server can become complex quickly and is not for beginners.
120 104
121DNS changes can take up to 48 hours to propagate, so be sure to give it 105DNS changes can take up to 48 hours to propagate, so be sure to give it some
122some time before assuming you've made an error. 106time before assuming you've made an error.
123 107
124* Server Updates and Packages 108* Server Updates and Packages
125 109
126Now that the DNS settings have been changed, let's set up our server 110Now that the DNS settings have been changed, let's set up our server while we
127while we wait for the DNS to propagate. First up is to ssh into your 111wait for the DNS to propagate. First up is to ssh into your server. If you've
128server. If you've signed up with a service like DigitalOcean, you can 112signed up with a service like DigitalOcean, you can add your SSH key to your
129add your SSH key to your account and to your VPS droplet so that you 113account and to your VPS droplet so that you don't need a password in order to
130don't need a password in order to SSH. 114SSH.
131 115
132#+begin_src sh 116#+begin_src sh
133ssh root@xxx.xxx.xxx.xxx 117ssh root@xxx.xxx.xxx.xxx
134#+end_src 118#+end_src
135 119
136The VPS that is used in this blog post runs Ubuntu 20.04 with an Apache 120The VPS that is used in this blog post runs Ubuntu 20.04 with an Apache web
137web server. If you're working on a different operating system (OS) or 121server. If you're working on a different operating system (OS) or want a
138want a different web server, such as Nginx, you'll have to use different 122different web server, such as Nginx, you'll have to use different commands to
139commands to set it up. 123set it up.
140 124
141First, let's update and upgrade our server. 125First, let's update and upgrade our server.
142 126
143*NOTE:* Since we have logged in to the server as =root= for now, we 127*NOTE:* Since we have logged in to the server as =root= for now, we don't need
144don't need to use the =sudo= modifier before our commands. 128to use the =sudo= modifier before our commands.
145 129
146#+begin_src sh 130#+begin_src sh
147apt update && apt upgrade -y 131apt update && apt upgrade -y
@@ -149,11 +133,11 @@ apt update && apt upgrade -y
149 133
150* Create A User Account 134* Create A User Account
151 135
152While being able to use =root= can be beneficial at times, you shouldn't 136While being able to use =root= can be beneficial at times, you shouldn't use
153use =root= unless you have to. 137=root= unless you have to.
154 138
155So let's set up a new user in our system. The =-m= option below tells 139So let's set up a new user in our system. The =-m= option below tells the OS to
156the OS to create a home directory for the new user. 140create a home directory for the new user.
157 141
158#+begin_src sh 142#+begin_src sh
159adduser USERNAME 143adduser USERNAME
@@ -165,40 +149,40 @@ Now, create a password for that user.
165passwd USERNAME 149passwd USERNAME
166#+end_src 150#+end_src
167 151
168Finally, add the user to the sudoers file, so they can perform 152Finally, add the user to the sudoers file, so they can perform privileged
169priveleged commands. 153commands.
170 154
171#+begin_src sh 155#+begin_src sh
172usermod -a -G sudo USERNAME 156usermod -a -G sudo USERNAME
173#+end_src 157#+end_src
174 158
175If you are using SSH keys and not passwords, you'll need to copy your 159If you are using SSH (secure shell protocol) keys and not passwords, you'll need
176SSH key from your local machine to the VPS. If you haven't disabled 160to copy your SSH key from your local machine to the VPS. If you haven't disabled
177password-based SSH yet, the easiest way to do this is =ssh-copy-id= from 161password-based SSH yet, the easiest way to do this is =ssh-copy-id= from your
178your local computer (not from the VPS): 162local computer (not from the VPS):
179 163
180#+begin_src sh 164#+begin_src sh
181ssh-copy-id testuser@xxx.xxx.xxx.xxx 165ssh-copy-id testuser@xxx.xxx.xxx.xxx
182#+end_src 166#+end_src
183 167
184If you've disabled password-based SSH, you'll need to manually copy your 168If you've disabled password-based SSH, you'll need to manually copy your SSH key
185SSH key into the =~/.ssh/authorized_keys= file. 169into the =~/.ssh/authorized_keys= file.
186 170
187* Install Software 171* Install Software
188 172
189Our goal here is to host a web server, so the next step is to install 173Our goal here is to host a web server, so the next step is to install the Apache
190the Apache web server and any other packages we need. 174web server and any other packages we need.
191 175
192From this point on, I will be logged in as a user (not =root=) and will 176From this point on, I will be logged in as a user (not =root=) and will need to
193need to use the =sudo= modifier for most commands. 177use the =sudo= modifier for most commands.
194 178
195#+begin_src sh 179#+begin_src sh
196sudo apt update; sudo apt upgrade -y; sudo apt autoremove -y 180sudo apt update; sudo apt upgrade -y; sudo apt autoremove -y
197sudo apt install apache2 181sudo apt install apache2
198#+end_src 182#+end_src
199 183
200If you need other language support, such as PHP, you'll need to install 184If you need other language support, such as PHP, you'll need to install that
201that too. 185too.
202 186
203#+begin_src sh 187#+begin_src sh
204sudo apt install libapache2-mod-php php-dom 188sudo apt install libapache2-mod-php php-dom
@@ -208,19 +192,18 @@ sudo systemctl restart apache2
208 192
209* Website Files & Folders 193* Website Files & Folders
210 194
211Next up is to create the directories for the domain(s) we want to be 195Next up is to create the directories for the domain(s) we want to be hosted on
212hosted on this web server. 196this web server.
213 197
214#+begin_src sh 198#+begin_src sh
215cd /var/www 199cd /var/www
216sudo mkdir example.com 200sudo mkdir example.com
217#+end_src 201#+end_src
218 202
219We have a folder for =example.com= now, so let's add an =index.html= 203We have a folder for =example.com= now, so let's add an =index.html= file and
220file and put it within a specific =public_html= folder. You don't need 204put it within a specific =public_html= folder. You don't need this =public_html=
221this =public_html= if you don't want it, but it helps with organizing 205if you don't want it, but it helps with organizing items related to
222items related to =example.com= that you don't want to publish to the 206=example.com= that you don't want to publish to the internet.
223internet.
224 207
225#+begin_src sh 208#+begin_src sh
226cd example.com 209cd example.com
@@ -228,8 +211,8 @@ sudo mkdir public_html && cd public_html
228sudo nano index.html 211sudo nano index.html
229#+end_src 212#+end_src
230 213
231You can put anything you want in this =index.html= file. If you can't 214You can put anything you want in this =index.html= file. If you can't think of
232think of anything, paste this in there: 215anything, paste this in there:
233 216
234#+begin_src html 217#+begin_src html
235<!DOCTYPE html> 218<!DOCTYPE html>
@@ -245,9 +228,8 @@ think of anything, paste this in there:
245</html> 228</html>
246#+end_src 229#+end_src
247 230
248If you want something to be served at =example.com/page01/file.txt=, 231If you want something to be served at =example.com/page01/file.txt=, you'll have
249you'll have to create the =page01= directory under the =example.com= 232to create the =page01= directory under the =example.com= directory. For example:
250directory. For example:
251 233
252#+begin_src sh 234#+begin_src sh
253cd /var/www/example.com/public_html 235cd /var/www/example.com/public_html
@@ -257,9 +239,9 @@ sudo nano file.txt
257 239
258* Apache Configuration 240* Apache Configuration
259 241
260Now, let's set up the files that will tell the server where to find the 242Now, let's set up the files that will tell the server where to find the files
261files for =example.com=. We will copy the default configuration file and 243for =example.com=. We will copy the default configuration file and create our
262create our own. 244own.
263 245
264#+begin_src sh 246#+begin_src sh
265cd /etc/apache2/sites-available 247cd /etc/apache2/sites-available
@@ -267,9 +249,8 @@ sudo cp 000-default.conf example.com.conf
267sudo nano example.com.conf 249sudo nano example.com.conf
268#+end_src 250#+end_src
269 251
270This configuration file will have a few default lines, but you'll need 252This configuration file will have a few default lines, but you'll need to edit
271to edit it to look similar to this (settings may change based on your 253it to look similar to this (settings may change based on your personal needs):
272personal needs):
273 254
274#+begin_src config 255#+begin_src config
275<VirtualHost *:80> 256<VirtualHost *:80>
@@ -291,31 +272,30 @@ sudo a2dissite 000-default.conf
291sudo systemctl reload apache2 272sudo systemctl reload apache2
292#+end_src 273#+end_src
293 274
294You can always run a test to make sure no errors or warnings are found 275You can always run a test to make sure no errors or warnings are found in your
295in your configuration files. 276configuration files.
296 277
297#+begin_src sh 278#+begin_src sh
298sudo apache2ctl configtest 279sudo apache2ctl configtest
299#+end_src 280#+end_src
300 281
301Now, restart the web server entirely. After this, you should be able to 282Now, restart the web server entirely. After this, you should be able to browse
302browse to =http://example.com= and see the HTML content you provided 283to =http://example.com= and see the HTML (hypertext markup language) content you
303earlier. Note that SSL/TLS has not been enabled yet, so you won't be 284provided earlier. Note that SSL/TLS has not been enabled yet, so you won't be
304able to use the secure version yet (=https://example.com=). 285able to use the secure version yet (=https://example.com=).
305 286
306#+begin_src sh 287#+begin_src sh
307sudo systemctl restart apache2 288sudo systemctl restart apache2
308#+end_src 289#+end_src
309 290
310You can repeat this for as many websites as you need. Just create the 291You can repeat this for as many websites as you need. Just create the domain
311domain folders in =/var/www/=, add the configuration file, enable the 292folders in =/var/www/=, add the configuration file, enable the configuration,
312configuration, and restart =apache2=. 293and restart =apache2=.
313 294
314* SSL/TLS Certificates: Serve Websites Over HTTPS 295* SSL/TLS Certificates: Serve Websites Over HTTPS
315 296
316In order to serve secure content, you'll need to obtain SSL/TLS 297In order to serve secure content, you'll need to obtain SSL/TLS certificates.
317certificates. Luckily, there's a free tool called 298Luckily, there's a free tool called [[https://certbot.eff.org][Certbot]] that helps us with the process.
318[[https://certbot.eff.org][Certbot]] that helps us with the process.
319 299
320The first step is to install =snapd= and =core= for Ubuntu. 300The first step is to install =snapd= and =core= for Ubuntu.
321 301
@@ -340,10 +320,10 @@ sudo ln -s /snap/bin/certbot /usr/bin/certbot
340 320
341Finally, you can run =certbot= one of two ways: 321Finally, you can run =certbot= one of two ways:
342 322
3431. run it and let it alter your Apache configuration files automatically 3231. run it and let it alter your Apache configuration files automatically to
344 to enable HTTPS redirects. 324 enable HTTPS (Hypertext Transport Protocol) redirects.
3452. run it and only allow it to create certificates. You'll need to 3252. run it and only allow it to create certificates. You'll need to manually
346 manually alter the config files to enable HTTPS redirects. 326 alter the config files to enable HTTPS redirects.
347 327
348Run certbot and allow automatic config changes: 328Run certbot and allow automatic config changes:
349 329
@@ -358,11 +338,10 @@ files:
358sudo certbot certonly --apache 338sudo certbot certonly --apache
359#+end_src 339#+end_src
360 340
361The Certbot packages on your system come with a cron job or systemd 341The Certbot packages on your system come with a =cron= job or =systemd= timer
362timer that will renew your certificates automatically before they 342that will renew your certificates automatically before they expire. You will not
363expire. You will not need to run Certbot again unless you change your 343need to run Certbot again unless you change your configuration. You can test
364configuration. You can test automatic renewal for your certificates by 344automatic renewal for your certificates by running this command:
365running this command:
366 345
367#+begin_src sh 346#+begin_src sh
368sudo certbot renew --dry-run 347sudo certbot renew --dry-run
@@ -373,13 +352,11 @@ Now, test your domains by going to =https://example.com=.
373* Firewall Security 352* Firewall Security
374 353
375To enable better security on your server, you'll need to enable a basic 354To enable better security on your server, you'll need to enable a basic
376firewall. For Ubuntu, we'll use 355firewall. For Ubuntu, we'll use [[https://cleberg.net/blog/ufw.html][the uncomplicated firewall]].
377[[../secure-your-network-with-the-uncomplicated-firewall/][the
378uncomplicated firewall]].
379 356
380Now, add the following rules to the firewall allow SSH, Apache, and 357Now, add the following rules to the firewall allow SSH, Apache, and HTTP(S)
381HTTP(S) connections. If you need to, you can enable different ports for 358connections. If you need to, you can enable different ports for specific
382specifics applications, SFTP, etc. 359applications.
383 360
384#+begin_src sh 361#+begin_src sh
385sudo ufw default deny incoming 362sudo ufw default deny incoming
@@ -397,15 +374,13 @@ sudo ufw enable
397 374
398* Troubleshooting 375* Troubleshooting
399 376
400If you run into any issues during your VPS set-up, be sure to walk back 377If you run into any issues during your VPS set-up, be sure to walk back through
401through your actions and make sure you didn't miss any steps. 378your actions and make sure you didn't miss any steps.
402 379
403Many websites have fantastic guides to setting up various web servers. 380Many websites have fantastic guides to setting up various web servers. This is
404This is one of the areas 381one of the areas [[https://www.digitalocean.com/community/tutorials][where DigitalOcean shines]]. For simpler or more Linux-oriented
405[[https://www.digitalocean.com/community/tutorials][where DigitalOcean 382questions, I suggest using [Linuxize] ([[https://linuxize.com]]).
406shines]]. For simpler or more Linux-oriented questions, I suggest using
407[Linuxize] ([[https://linuxize.com]]).
408 383
409If you're getting certain errors (e.g. =500 Internal Server Error=) and 384If you're getting certain errors (e.g. =500 Internal Server Error=) and need to
410need to debug locally, you can view the =access.log= and =error.log= 385debug locally, you can view the =access.log= and =error.log= files in the
411files in the =/var/log/apache/= directory. 386=/var/log/apache/= directory.
content/blog/2021-04-17-gemini-server.org +33 −38
@@ -5,28 +5,26 @@
5 5
6* Similar Article Available 6* Similar Article Available
7 7
8To read more about Gemini and ways to test out this new protocol without 8To read more about Gemini and ways to test out this new protocol without your
9your own server, see my previous post 9own server, see my previous post [[../launching-a-gemini-capsule/][Launching a Gemini Capsule]].
10[[../launching-a-gemini-capsule/][Launching a Gemini Capsule]].
11 10
12* Preparation 11* Preparation
13 12
14This guide assumes you have access to a server accessible to the world 13This guide assumes you have access to a server accessible to the world through a
15through a public IP address and that you own a domain name used for this 14public IP (internet protocol) address and that you own a domain name used for
16Gemini capsule. 15this Gemini capsule.
17 16
18* Getting Started with Agate 17* Getting Started with Agate
19 18
20We are going to use [[https://github.com/mbrubeck/agate][Agate]] for 19We are going to use [[https://github.com/mbrubeck/agate][Agate]] for this tutorial. This is a basic Gemini server
21this tutorial. This is a basic Gemini server written in Rust. It takes 20written in Rust. It takes very little time and maintenance to get it running.
22very little time and maintenance to get it running.
23 21
24* Install Dependencies 22* Install Dependencies
25 23
26First, you will need to install the Rust package for your system. On 24First, you will need to install the Rust package for your system. On Ubuntu, use
27Ubuntu, use the following commands (remember to use =sudo= if you are 25the following commands (remember to use =sudo= if you are not the root user).
28not the root user). The Rust installation will give you options to 26The Rust installation will give you options to customize the installation; I
29customize the installation; I used the default installation options. 27used the default installation options.
30 28
31#+begin_src sh 29#+begin_src sh
32sudo apt update && sudo apt upgrade -y 30sudo apt update && sudo apt upgrade -y
@@ -54,8 +52,8 @@ cargo install agate
54 52
55* Create Symlinks 53* Create Symlinks
56 54
57Once Cargo has finished installing all the required packages, symlink 55Once Cargo has finished installing all the required packages, create a symbolic
58the executable to your $PATH. 56link to the executable to your $PATH.
59 57
60#+begin_src sh 58#+begin_src sh
61sudo ln -s $HOME/.cargo/bin/agate /usr/local/bin/agate 59sudo ln -s $HOME/.cargo/bin/agate /usr/local/bin/agate
@@ -63,8 +61,8 @@ sudo ln -s $HOME/.cargo/bin/agate /usr/local/bin/agate
63 61
64* Using Agate's Built-In Installation Tool 62* Using Agate's Built-In Installation Tool
65 63
66If you're running Ubuntu or Debian, use the Debian installation script 64If you're running Ubuntu or Debian, use the Debian installation script found in
67found in Agate's GitHub repository, under the =tools/debian= folder. 65Agate's GitHub repository, under the =tools/debian= folder.
68 66
69#+begin_src sh 67#+begin_src sh
70git clone https://github.com/mbrubeck/agate 68git clone https://github.com/mbrubeck/agate
@@ -74,11 +72,11 @@ sudo ./install.sh
74 72
75* Configure the Gemini Service 73* Configure the Gemini Service
76 74
77We have a little more to do, but since this script tries to immediately 75We have a little more to do, but since this script tries to immediately run the
78run the service, it will likely fail with an exit code. Let's add our 76service, it will likely fail with an exit code. Let's add our finishing touches.
79finishing touches. Edit the following file and replace the hostname with 77Edit the following file and replace the hostname with your desired URL (uniform
80your desired URL. You can also change the directory where content will 78resource locator). You can also change the directory where content will be
81be served. 79served.
82 80
83#+begin_src sh 81#+begin_src sh
84sudo nano /etc/systemd/system/gemini.service 82sudo nano /etc/systemd/system/gemini.service
@@ -97,8 +95,8 @@ WorkingDirectory=/var/gemini/
97ExecStart=agate --hostname gemini.example.com --lang en 95ExecStart=agate --hostname gemini.example.com --lang en
98#+end_src 96#+end_src
99 97
100Since we've altered the systemd configuration files, we have to reload 98Since we've altered the systemd configuration files, we have to reload the
101the daemon. Let's do that, restart our service, and check its status. 99daemon. Let's do that, restart our service, and check its status.
102 100
103#+begin_src sh 101#+begin_src sh
104sudo systemctl daemon-reload 102sudo systemctl daemon-reload
@@ -108,8 +106,8 @@ sudo systemctl status gemini.service
108 106
109* Fixing Systemd Errors 107* Fixing Systemd Errors
110 108
111If you're still getting errors, the installation process may not have 109If you're still getting errors, the installation process may not have properly
112properly enabled the gemini service. Fix it with the following commands. 110enabled the gemini service. Fix it with the following commands.
113 111
114#+begin_src sh 112#+begin_src sh
115sudo systemctl enable gemini.service 113sudo systemctl enable gemini.service
@@ -119,9 +117,9 @@ sudo systemctl status gemini.service
119 117
120* Firewall Rules 118* Firewall Rules
121 119
122Great! Our server is now functional and running. The first consideration 120Great! Our server is now functional and running. The first consideration now is
123now is that you need to be able to access port 1965 on the server. If 121that you need to be able to access port 1965 on the server. If you have a
124you have a firewall enabled, you'll need to open that port up. 122firewall enabled, you'll need to open that port up.
125 123
126#+begin_src sh 124#+begin_src sh
127sudo ufw allow 1965 125sudo ufw allow 1965
@@ -131,21 +129,18 @@ sudo ufw reload
131* Creating Content 129* Creating Content
132 130
133Let's create the Gemini capsule. Note that wherever you set the 131Let's create the Gemini capsule. Note that wherever you set the
134WorkingDirectory variable to earlier, Agate will expect you to put your 132=WorkingDirectory= variable to earlier, Agate will expect you to put your Gemini
135Gemini capsule contents in a sub-folder called "content." So, I place my 133capsule contents in a sub-folder called =content=. So, I place my files in
136files in "/var/gmi/content." I'm going to create that folder now and put 134=/var/gmi/content=. I'm going to create that folder now and put a file in there.
137a file in there.
138 135
139#+begin_src sh 136#+begin_src sh
140sudo mkdir /var/gemini/content 137sudo mkdir /var/gemini/content
141sudo nano /var/gemini/content/index.gmi 138sudo nano /var/gemini/content/index.gmi
142#+end_src 139#+end_src
143 140
144You can put whatever you want in the "index.gmi" file, just make sure 141You can put whatever you want in the =index.gmi= file, just make sure it's valid
145it's valid Gemtext. 142Gemtext.
146 143
147* The Results 144* The Results
148 145
149To view the results, you can use a Gemini browser, such as 146To view the results, you can use a Gemini browser, such as [[https://gmi.skyjake.fi/lagrange/][Lagrange]] or [[https://github.com/makeworld-the-better-one/amfora][amfora]].
150[[https://gmi.skyjake.fi/lagrange/][Lagrange]] or
151[[https://github.com/makeworld-the-better-one/amfora][amfora]].
content/blog/2021-04-23-php-comment-system.org +83 −94
@@ -5,84 +5,79 @@
5 5
6* The Terrible-ness of Commenting Systems 6* The Terrible-ness of Commenting Systems
7 7
8The current state of affairs regarding interactive comment systems is, 8The current state of affairs regarding interactive comment systems is, well,
9well, terrible. It is especially awful if you're a privacy conscious 9terrible. It is especially awful if you're a privacy conscious person who does
10person who does not generally load third-party scripts or frames on the 10not generally load third-party scripts or frames on the websites you visit.
11websites you visit.
12 11
13Even further, many comment systems are charging exorbitant fees for 12Even further, many comment systems are charging exorbitant fees for something
14something that should be standard. 13that should be standard.
15 14
16Of course, there are some really terrible options: 15Of course, there are some really terrible options:
17 16
18- Facebook Comments 17- Facebook Comments
19- Discourse 18- Discourse
20 19
21There are some options that are better but still use too many scripts, 20There are some options that are better but still use too many scripts, frames,
22frames, or social integrations on your web page that could impact some 21or social integrations on your web page that could impact some users:
23users:
24 22
25- Disqus 23- Disqus
26- Isso 24- Isso
27- Remark42 25- Remark42
28 26
29Lastly, I looked into a few unique ways of generating blog comments, 27Lastly, I looked into a few unique ways of generating blog comments, such as
30such as using Twitter threads or GitHub issues to automatically post 28using Twitter threads or GitHub issues to automatically post issues. However,
31issues. However, these both rely on external third-party sites that I 29these both rely on external third-party sites that I don't currently use.
32don't currently use.
33 30
34* Stay Static with Server-Side Comments 31* Stay Static with Server-Side Comments
35 32
36The main issue for my personal use-case is that my blog is completely, 33The main issue for my personal use-case is that my blog is completely, 100%
37100% static. I use PHP on the back-end but website visitors only see 34static. I use PHP on the back-end but website visitors only see HTML (Hypertext
38HTML and a single CSS file. No external javascript and no embedded 35Markup Language) and a single CSS (Cascading Style Sheets) file. No external
39frames. 36JavaScript and no embedded frames.
40 37
41So, how do we keep a site static and still allow users to interact with 38So, how do we keep a site static and still allow users to interact with blog
42blog posts? The key actually pretty simple - I'm already using PHP, so 39posts? The key actually pretty simple - I'm already using PHP, so why not rely
43why not rely on the classic HTML =<form>= and a PHP script to save the 40on the classic HTML =<form>= and a PHP script to save the comments somewhere? As
44comments somewhere? As it turns out, this was a perfect solution for me. 41it turns out, this was a perfect solution for me.
45 42
46The second issue for my personal use-case is that I am trying to keep 43The second issue for my personal use-case is that I am trying to keep the
47the contents of my website accessible over time, as described by 44contents of my website accessible over time, as described by [cite/t:@brandur],
48[cite/t:@brandur], in his post entitled 45in his post entitled [[https://brandur.org/fragments/graceful-degradation-time][Blog with Markdown + Git, and degrade gracefully through
49[[https://brandur.org/fragments/graceful-degradation-time][Blog with 46time]] .
50Markdown + Git, and degrade gracefully through time]] .
51 47
52This means I cannot rely on a database for comments, since I do not rely 48This means I cannot rely on a database for comments, since I do not rely on a
53on a database for any other part of my websites. 49database for any other part of my websites.
54 50
55I blog in plain Markdown files, commit all articles to Git, and ensure 51I blog in plain Markdown files, commit all articles to Git, and ensure that
56that future readers will be able to see the source data long after I'm 52future readers will be able to see the source data long after I'm gone, or the
57gone, or the website has gone offline. However, I still haven't 53website has gone offline. However, I still haven't committed any images served
58committed any images served on my blog to Git, as I'm not entirely sold 54on my blog to Git, as I'm not entirely sold on Git LFS (large file storage)
59on Git LFS yet - for now, images can be found at 55yet - for now, images can be found at [[https://img.cleberg.net][img.cleberg.net]].
60[[https://img.cleberg.net][img.cleberg.net]].
61 56
62Saving my comments back to the Git repository ensures that another 57Saving my comments back to the Git repository ensures that another aspect of my
63aspect of my site will degrade gracefully. 58site will degrade gracefully.
64 59
65* Create a Comment Form 60* Create a Comment Form
66 61
67Okay, let's get started. The first step is to create an HTML form that 62Okay, let's get started. The first step is to create an HTML form that users can
68users can see and utilize to submit comments. This is fairly easy and 63see and utilize to submit comments. This is fairly easy and can be changed
69can be changed depending on your personal preferences. 64depending on your personal preferences.
70 65
71Take a look at the code block below for the form I currently use. Note 66Take a look at the code block below for the form I currently use. Note that
72that =<current-url>= is replaced automatically in PHP with the current 67=<current-url>= is replaced automatically in PHP with the current post's URL
73post's URL, so that my PHP script used later will know which blog post 68(uniform resource locator), so that my PHP script used later will know which
74the comment is related to. 69blog post the comment is related to.
75 70
76The form contains the following structure: 71The form contains the following structure:
77 72
781. =<form>= - This is the form and will determine which PHP script to 731. =<form>= - This is the form and will determine which PHP script to send the
79 send the comment to. 74 comment to.
802. =<section hidden>= - This section is hidden from the user and is used 752. =<section hidden>= - This section is hidden from the user and is used to
81 to ensure that we know which blog post sent the comment. 76 ensure that we know which blog post sent the comment.
823. =<section>= Display Name (Optional) - Used to accept a display name, 773. =<section>= Display Name (Optional) - Used to accept a display name, if
83 if entered. 78 entered.
844. =<section>= Comment (Required) - Used to accept the user's full 794. =<section>= Comment (Required) - Used to accept the user's full comment.
85 comment. Markdown is allowed. 80 Markdown is allowed.
865. =<button>= - A button to submit the form. 815. =<button>= - A button to submit the form.
87 82
88#+begin_src html 83#+begin_src html
@@ -129,25 +124,25 @@ The form contains the following structure:
129 124
130* Handle Comments via POST 125* Handle Comments via POST
131 126
132Now that we have a form and can submit comments, we need to create a PHP 127Now that we have a form and can submit comments, we need to create a PHP script
133script so that the server can fetch the comment data and save it. Make 128so that the server can fetch the comment data and save it. Make sure your PHP
134sure your PHP script name matches the name you entered in the =action= 129script name matches the name you entered in the =action= field in your form.
135field in your form.
136 130
137See the code block below for the contents of my =comment.php= script. We 131See the code block below for the contents of my =comment.php= script. We perform
138perform the following tasks in this script: 132the following tasks in this script:
139 133
1401. Grab the POST data from the HTML form. 1341. Grab the POST data from the HTML form.
1412. Sanitize the comment data with =htmlentities=. 1352. Sanitize the comment data with =htmlentities=.
1423. Set the display name to =Anonymous= if it was left blank. 1363. Set the display name to =Anonymous= if it was left blank.
1434. Create a PHP object that combines all of this data. 1374. Create a PHP object that combines all of this data.
1445. Check if our destination file =comments.json= exists. 1385. Check if our destination file =comments.json= exists.
1456. If so, convert the PHP object to JSON and save it to the file. 1396. If so, convert the PHP object to JSON (JavaScript Object Notation) and save
1467. If the =comments.json= file does not exist, the script will exit with 140 it to the file.
147 an error. You can alter this to ensure it creates the script, but my 1417. If the =comments.json= file does not exist, the script will exit with an
148 source code includes the file by default, so it will always exist. 142 error. You can alter this to ensure it creates the script, but my source code
1498. Finally, send the user back to the =#comments= section of the blog 143 includes the file by default, so it will always exist.
150 post they just read. 1448. Finally, send the user back to the =#comments= section of the blog post they
145 just read.
151 146
152#+begin_src php 147#+begin_src php
153// Get the content sent from the comment form 148// Get the content sent from the comment form
@@ -186,9 +181,9 @@ if (file_exists($file_name)) {
186header('Location: ' . $post_url . '#comments'); 181header('Location: ' . $post_url . '#comments');
187#+end_src 182#+end_src
188 183
189If you're using Apache, make sure the =www-data= user on your server has 184If you're using Apache, make sure the =www-data= user on your server has the
190the correct permissions to your website directory or else it will not be 185correct permissions to your website directory or else it will not be able to
191able to write to =comments.json=. 186write to =comments.json=.
192 187
193#+begin_src sh 188#+begin_src sh
194chgrp -R www-data /path/to/website/ 189chgrp -R www-data /path/to/website/
@@ -197,18 +192,15 @@ chmod -R g+w comments.json
197 192
198* Display User Comments 193* Display User Comments
199 194
200Now that we can submit comments, and they are saved to the 195Now that we can submit comments, and they are saved to the =comments.json= file,
201=comments.json= file, let's make sure we can show those comments in each 196let's make sure we can show those comments in each blog post.
202blog post.
203 197
204The code block below shows the function I use to decode my 198The code block below shows the function I use to decode my =comments.json= file,
205=comments.json= file, check if the comments apply to the current post, 199check if the comments apply to the current post, and then display them.
206and then display them.
207 200
208This piece of code should *really* be inside a function (or at least in 201This piece of code should *really* be inside a function (or at least in an
209an organized PHP workflow). Don't just copy-and-paste and expect it to 202organized PHP workflow). Don't just copy-and-paste and expect it to work. You
210work. You need to at least supply a =$query= variable depending on the 203need to at least supply a =$query= variable depending on the page visited.
211page visited.
212 204
213#+begin_src php 205#+begin_src php
214$query = 'your-blog-post.html'; 206$query = 'your-blog-post.html';
@@ -246,27 +238,24 @@ echo $comment_section;
246 238
247* Bonus: Create a 'Recent Comments' Page 239* Bonus: Create a 'Recent Comments' Page
248 240
249Finally, the last part of my current system is to create a Recent 241Finally, the last part of my current system is to create a Recent Comments page
250Comments page so that I can easily check-in on my blog and moderate any 242so that I can easily check-in on my blog and moderate any spam. As an
251spam. As an alternative, you could use PHP's =mail()= function to email 243alternative, you could use PHP's =mail()= function to email you for each blog
252you for each blog comment. 244comment.
253 245
254The code to do this is literally the same code as the previous section, 246The code to do this is literally the same code as the previous section, I just
255I just make sure it is printed when someone visits 247make sure it is printed when someone visits =https://example.com/comments/=.
256=https://example.com/comments/=.
257 248
258* Possible Enhancements 249* Possible Enhancements
259 250
260This comment system is by no means a fully-developed system. I have 251This comment system is by no means a fully-developed system. I have noted a few
261noted a few possible enhancements here that I may implement in the 252possible enhancements here that I may implement in the future:
262future:
263 253
264- Create a secure moderator page with user authentication at 254- Create a secure moderator page with user authentication at
265 =https://blog.example.com/mod/=. This page could have the option to 255 =https://blog.example.com/mod/=. This page could have the option to edit or
266 edit or delete any comment found in =comments.json=. 256 delete any comment found in =comments.json=.
267- Create a temporary file, such as =pending_comments.json=, that will 257- Create a temporary file, such as =pending_comments.json=, that will store
268 store newly-submitted comments and won't display on blog posts until 258 newly-submitted comments and won't display on blog posts until approved by a
269 approved by a moderator. 259 moderator.
270- Create a =/modlog/= page with a chronological log, showing which 260- Create a =/modlog/= page with a chronological log, showing which moderator
271 moderator approved which comments and why certain comments were 261 approved which comments and why certain comments were rejected.
272 rejected.
content/blog/2021-04-28-photography.org +39 −47
@@ -6,66 +6,58 @@
6* Why Photography? 6* Why Photography?
7 7
8I've often wondered why photography is as enticing as it is. You can see 8I've often wondered why photography is as enticing as it is. You can see
9billions of people around the world taking photographs every single 9billions of people around the world taking photographs every single moment of
10moment of the day. New technology often boasts about their photographic 10the day. New technology often boasts about their photographic capabilities,
11capabilities, especially smartphones. I would even assume that we live 11especially smartphones. I would even assume that we live in a world where there
12in a world where there is never a moment in which a photograph is not 12is never a moment in which a photograph is not being taken somewhere on Earth.
13being taken somewhere on Earth.
14 13
15As for myself, I would simply say that I enjoy preserving a memory in 14As for myself, I would simply say that I enjoy preserving a memory in physical
16physical (or digital) form. I've never had the best memory when it comes 15(or digital) form. I've never had the best memory when it comes to recalling
17to recalling details of places and people gone by, so it helps to have a 16details of places and people gone by, so it helps to have a frame of reference
18frame of reference lying around. 17lying around.
19 18
20Regardless of the reason, I think most people would agree that you 19Regardless of the reason, I think most people would agree that you simply cannot
21simply cannot have too many hobbies. 20have too many hobbies.
22 21
23* Older Cameras 22* Older Cameras
24 23
25I started playing around with the idea of photography when my family 24I started playing around with the idea of photography when my family purchased a
26purchased a Fujifilm camera for family-specific events. I don't recall 25Fujifilm camera for family-specific events. I don't recall the specific model,
27the specific model, but I do recall it was a point-and-shoot camera 26but I do recall it was a point-and-shoot camera without an interchangeable lens.
28without an interchangeable lens. However, it was of great value to 27However, it was of great value to someone, like myself, who couldn't afford any
29someone, like myself, who couldn't afford any other camera. I took about 28other camera. I took about 10,000 shots with that camera over a 3-5 year span.
3010,000 shots with that camera over a 3-5 year span. Most notably, all of 29Most notably, all of my trips to California were documented through this camera.
31my trips to California were documented through this camera.
32 30
33When possible, I would borrow my sister's camera, which is a Sony 31When possible, I would borrow my sister's camera, which is a Sony SLT-A58. This
34SLT-A58. This camera was great and allowed for some of my best early 32camera was great and allowed for some of my best early shots, especially those
35shots, especially those taken in Utah's and Nevada's parks. 33taken in Utah's and Nevada's parks.
36 34
37* My Current Kit 35* My Current Kit
38 36
39I've finally come to a point in my life where I have the disposable 37I've finally come to a point in my life where I have the disposable income to
40income to invest in a solid photography kit. I played around with the 38invest in a solid photography kit. I played around with the idea of a lot of
41idea of a lot of different cameras, different types, new vs used, etc. 39different cameras, different types, new vs used, etc. Finally, I settled on the
42Finally, I settled on the 40[[https://en.wikipedia.org/wiki/Sony_%CE%B17_III][Sony α7 III]]. This camera is mirror-less and uses a full-frame image sensor at 24
43[[https://en.wikipedia.org/wiki/Sony_%CE%B17_III][Sony α7 III]]. This 41megapixels. I don't create large prints, and I am mostly focused on preserving
44camera is mirror-less and uses a full-frame image sensor at 24 42memories in high quality for the next 5-10 years with this camera, so the
45megapixels. I don't create large prints, and I am mostly focused on 43specifications here are just perfect for me.
46preserving memories in high quality for the next 5-10 years with this
47camera, so the specifications here are just perfect for me.
48 44
49For lenses, I decided to buy two lenses that could carry me through most 45For lenses, I decided to buy two lenses that could carry me through most
50situations: 46situations:
51 47
52- [[https://electronics.sony.com/imaging/lenses/full-frame-e-mount/p/sel2470z][Vario-Tessar 48- [[https://electronics.sony.com/imaging/lenses/full-frame-e-mount/p/sel2470z][Vario-Tessar T** FE 24-70 mm F4 ZA OSS]]
53 T** FE 24-70 mm F4 ZA OSS]] 49- [[https://www.tamron-usa.com/product/lenses/a047.html][Tamron 70-300mm f4.5-6.3 Di III RXD]]
54- [[https://www.tamron-usa.com/product/lenses/a047.html][Tamron 70-300mm
55 f4.5-6.3 Di III RXD]]
56 50
57In addition, I grabbed a couple 51In addition, I grabbed a couple [[https://www.promaster.com/Product/6725][HGX Prime 67mm]] protection filters for the
58[[https://www.promaster.com/Product/6725][HGX Prime 67mm]] protection 52lenses.
59filters for the lenses.
60 53
61As I delve further into photography and pick up more skills, I will most 54As I delve further into photography and pick up more skills, I will most likely
62likely go back and grab a lens with a higher f-stop value, such as 55go back and grab a lens with a higher f-stop value, such as f/1.8. I toyed with
63f/1.8. I toyed with the idea of grabbing a 50 mm at =f/1.8=, but decided 56the idea of grabbing a 50 mm at =f/1.8=, but decided to keep things in a
64to keep things in a reasonable price range instead. 57reasonable price range instead.
65 58
66Finally, I made sure to buy a photography-specific backpack with a rain 59Finally, I made sure to buy a photography-specific backpack with a rain guard,
67guard, and the zipper on the back panel, to protect the equipment while 60and the zipper on the back panel, to protect the equipment while wearing the
68wearing the bag. If you've ever had to haul around a DSLR (or camera of 61bag. If you've ever had to haul around a DSLR (digital single-lens reflex)
69similar heft) in a bag that only has a shoulder strap, you'll know the 62camera in a bag that only has a shoulder strap, you'll know the pain it can
70pain it can cause. Putting all my equipment in a backpack was an easy 63cause. Putting all my equipment in a backpack was an easy decision.
71decision.
content/blog/2021-05-30-changing-git-authors.org +8 −8
@@ -5,12 +5,12 @@
5 5
6* Changing Git Author/Email Based on Previously Committed Email 6* Changing Git Author/Email Based on Previously Committed Email
7 7
8Here's the dilemma: You've been committing changes to your git 8Here's the dilemma: You've been committing changes to your Git repository with
9repository with an incorrect name or email (or multiple repositories), 9an incorrect name or email (or multiple repositories), and now you want to fix
10and now you want to fix it. Luckily, there's a semi-reliable way to fix 10it. Luckily, there's a semi-reliable way to fix that. While I have never
11that. While I have never experienced issues with this method, some 11experienced issues with this method, some people have warned that it can mess
12people have warned that it can mess with historical hashes and integrity 12with historical hashes and integrity of commits, so use this method only if
13of commits, so use this method only if you're okay accepting that risk. 13you're okay accepting that risk.
14 14
15Okay, let's create the bash script: 15Okay, let's create the bash script:
16 16
@@ -18,8 +18,8 @@ Okay, let's create the bash script:
18nano change_git_authors.sh 18nano change_git_authors.sh
19#+end_src 19#+end_src
20 20
21The following information can be pasted directly into your bash script. 21The following information can be pasted directly into your bash script. The only
22The only changes you need to make are to the following variables: 22changes you need to make are to the following variables:
23 23
24- =OLD_EMAIL= 24- =OLD_EMAIL=
25- =CORRECT_NAME= 25- =CORRECT_NAME=
content/blog/2021-07-15-delete-gitlab-repos.org +19 −22
@@ -5,31 +5,29 @@
5 5
6* Background 6* Background
7 7
8Have you ever used GitLab to host your source code, moved to a different 8Have you ever used GitLab to host your source code, moved to a different host,
9host, and wanted to delete everything from your GitLab account? Well, 9and wanted to delete everything from your GitLab account? Well, this post covers
10this post covers any scenario where you would want to delete all 10any scenario where you would want to delete all repositories from your GitLab
11repositories from your GitLab account. 11account.
12 12
13For me, I currently maintain around 30 repositories and don't like to 13For me, I currently maintain around 30 repositories and don't like to manually
14manually delete them whenever I switch host. GitHub has a few different 14delete them whenever I switch host. GitHub has a few different tools online to
15tools online to delete all repositories for you, but I have not found 15delete all repositories for you, but I have not found anything similar for
16anything similar for GitLab, so I needed an alternative solution. 16GitLab, so I needed an alternative solution.
17 17
18* Use a Python Script 18* Use a Python Script
19 19
20** Requirements 20** Requirements
21 21
22Before we look at the script, make sure you know your GitLab username. 22Before we look at the script, make sure you know your GitLab username. Next,
23Next, [[https://gitlab.com/-/profile/personal_access_tokens][create an 23[[https://gitlab.com/-/profile/personal_access_tokens][create an authorization token]] so that the Python script can delete your
24authorization token]] so that the Python script can delete your 24repositories. Don't lose this token or else you'll need to create a new one.
25repositories. Don't lose this token or else you'll need to create a new
26one.
27 25
28** Create the Script 26** Create the Script
29 27
30To run a Python script, you must first create it. Open a terminal and 28To run a Python script, you must first create it. Open a terminal and enter the
31enter the following commands in whichever directory you prefer to store 29following commands in whichever directory you prefer to store the script. You
32the script. You can do the same things in a file manager if you prefer. 30can do the same things in a file manager if you prefer.
33 31
34#+begin_src sh 32#+begin_src sh
35mkdir delete-gitlab 33mkdir delete-gitlab
@@ -101,13 +99,12 @@ if __name__ == "__main__":
101 main() 99 main()
102#+end_src 100#+end_src
103 101
104Now that you have the proper information, replace ={user-id}= with your 102Now that you have the proper information, replace ={user-id}= with your GitLab
105GitLab username and ={auth-token}= with the authorization token you 103username and ={auth-token}= with the authorization token you created earlier.
106created earlier.
107 104
108Finally, simply run the script and watch the output. You can also use 105Finally, simply run the script and watch the output. You can also use PyCharm
109PyCharm Community Edition to edit and run the Python script if you don't 106Community Edition to edit and run the Python script if you don't want to work in
110want to work in a terminal. 107a terminal.
111 108
112#+begin_src sh 109#+begin_src sh
113python3 main.py 110python3 main.py
content/blog/2021-08-25-audit-sampling.org +98 −101
@@ -6,44 +6,40 @@
6* Introduction 6* Introduction
7 7
8For anyone who is familiar with internal auditing, external auditing, or 8For anyone who is familiar with internal auditing, external auditing, or
9consulting, you will understand how tedious audit testing can become 9consulting, you will understand how tedious audit testing can become when you
10when you are required to test large swaths of data. When we cannot 10are required to test large swaths of data. When we cannot establish an automated
11establish an automated means of testing an entire population, we 11means of testing an entire population, we generate samples to represent the
12generate samples to represent the population of data. This helps ensure 12population of data. This helps ensure we can have a small enough data pool to
13we can have a small enough data pool to test and that our results still 13test and that our results still represent the population.
14represent the population. 14
15 15However, sampling data within the world of audit still seems to confuse quite a
16However, sampling data within the world of audit still seems to confuse 16lot of people. While some audit-focused tools have introduced sampling
17quite a lot of people. While some audit-focused tools have introduced 17functionality (e.g. Wdesk), many audit departments and firms cannot use software
18sampling functionality (e.g. Wdesk), many audit departments and firms 18like this due to certain constraints, such as the team's budget or knowledge.
19cannot use software like this due to certain constraints, such as the 19Here is where this article comes in: we're going to use [[https://www.python.org][Python]], a free and
20team's budget or knowledge. Here is where this article comes in: we're 20open-source programming language, to generate random samples from a dataset in
21going to use [[https://www.python.org][Python]], a free and open-source 21order to suffice numerous audit situations.
22programming language, to generate random samples from a dataset in order
23to suffice numerous audit situations.
24 22
25* Audit Requirements for Sampling 23* Audit Requirements for Sampling
26 24
27Before we get into the details of how to sample with Python, I want to 25Before we get into the details of how to sample with Python, I want to make sure
28make sure I discuss the different requirements that auditors may have of 26I discuss the different requirements that auditors may have of samples used
29samples used within their projects. 27within their projects.
30 28
31** Randomness 29** Randomness
32 30
33First, let's discuss randomness. When testing out new technology to help 31First, let's discuss randomness. When testing out new technology to help assist
34assist with audit sampling, you need to understand exactly how your 32with audit sampling, you need to understand exactly how your samples are being
35samples are being generated. For example, if the underlying function is 33generated. For example, if the underlying function is just picking every 57th
36just picking every 57th element from a list, that's not truly random; 34element from a list, that's not truly random; it's a systematic form of
37it's a systematic form of sampling. Luckily, since Python is 35sampling. Luckily, since Python is open-source, we have access to its codebase.
38open-source, we have access to its codebase. Through this blog post, I 36Through this blog post, I will be using the [[https://pandas.pydata.org][pandas]] module in order to generate
39will be using the [[https://pandas.pydata.org][pandas]] module in order 37the random samples. More specifically, I will be using the
40to generate the random samples. More specifically, I will be using the 38[[https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sample.html][pandas.DataFrame.sample]] function provided by Pandas.
41[[https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sample.html][pandas.DataFrame.sample]] 39
42function provided by Pandas. 40Now that you know what you're using, you can always check out the code behind
43 41=pandas.DataFrame.sample=. This function does a lot of work, but we really only
44Now that you know what you're using, you can always check out the code 42care about the following snippets of code:
45behind =pandas.DataFrame.sample=. This function does a lot of work, but
46we really only care about the following snippets of code:
47 43
48#+begin_src python 44#+begin_src python
49# Process random_state argument 45# Process random_state argument
@@ -59,61 +55,62 @@ result.index = ibase.default_index(len(result))
59return result 55return result
60#+end_src 56#+end_src
61 57
62The block of code above shows you that if you assign a =random_state= 58The block of code above shows you that if you assign a =random_state= argument
63argument when you run the function, that will be used as a seed number 59when you run the function, that will be used as a seed number in the random
64in the random generation and will allow you to reproduce a sample, given 60generation and will allow you to reproduce a sample, given that nothing else
65that nothing else changes. This is critical to the posterity of audit 61changes. This is critical to the posterity of audit work. After all, how can you
66work. After all, how can you say your audit process is adequately 62say your audit process is adequately documented if the next person can't run the
67documented if the next person can't run the code and get the same 63code and get the same sample? The final piece here on randomness is to look at
68sample? The final piece here on randomness is to look at the 64the [[https://docs.python.org/3/library/random.html#random.choice][choice]] function used above. This is the crux of the generation and can also
69[[https://docs.python.org/3/library/random.html#random.choice][choice]] 65be examined for more detailed analysis on its reliability. As far as auditing
70function used above. This is the crux of the generation and can also be 66goes, we will trust that these functions are mathematically random.
71examined for more detailed analysis on its reliability. As far as
72auditing goes, we will trust that these functions are mathematically
73random.
74 67
75** Sample Sizes 68** Sample Sizes
76 69
77As mentioned in the intro, sampling is only an effective method of 70As mentioned in the intro, sampling is only an effective method of auditing when
78auditing when it truly represents the entire population. While some 71it truly represents the entire population. While some audit departments or firms
79audit departments or firms may consider certain judgmental sample sizes 72pmay consider certain judgmental sample sizes to be adequate, you may need to
80to be adequate, you may need to rely on statistically-significant 73rely on statistically-significant confidence levels of sample testing at certain
81confidence levels of sample testing at certain points. I will 74
82demonstrate both here. For statistically-significant confidence levels, 75points. I will demonstrate both here. For statistically-significant confidence
83most people will assume a 90% - 99% confidence level. In order to 76levels, most people will assume a 90% - 99% confidence level. In order to
84actually calculate the correct sample size, it is best to use 77actually calculate the correct sample size, it is best to use statistical tools
85statistical tools due to the tedious math work required. For example, 78due to the tedious math work required. For example, for a population of 1000,
86for a population of 1000, and a 90% confidence level that no more than 79and a 90% confidence level that no more than 5% of the items are nonconforming,
875% of the items are nonconforming, you would sample 45 items. 80you would sample 45 items.
88 81
89However, in my personal experience, many audit departments and firms do 82However, in my personal experience, many audit departments and firms do not use
90not use statistical sampling. Most people use a predetermined, often 83statistical sampling. Most people use a predetermined, often proprietary, table
91proprietary, table that will instruct auditors which sample sizes to 84that will instruct auditors which sample sizes to choose. This allows for
92choose. This allows for uniform testing and reduces overall workload. 85uniform testing and reduces overall workload. See the table below for a common
93See the table below for a common implementation of sample sizes: 86implementation of sample sizes:
94 87
95Control Frequency Sample Size - High Risk Sample Size - Low Risk 88| Control Frequency | Sample Size (High Risk) | Sample Size (Low Risk) |
96 89|-------------------+-------------------------+------------------------|
97-------------- 90| More Than Daily | 40 | 25 |
98 91| Daily | 40 | 25 |
99More Than Daily 40 25 Daily 40 25 Weekly 12 5 Monthly 5 3 Quarterly 2 2 92| Weekly | 12 | 5 |
100Semi-Annually 1 1 Annually 1 1 Ad-hoc 1 1 93| Monthly | 5 | 3 |
94| Quarterly | 2 | 2 |
95| Semi-Annually | 1 | 1 |
96| Annually | 1 | 1 |
97| Ad-hoc | 1 | 1 |
101 98
102*** Sampling with Python & Pandas 99*** Sampling with Python & Pandas
103 100
104In this section, I am going to cover a few basic audit situations that 101In this section, I am going to cover a few basic audit situations that require
105require sampling. While some situations may require more effort, the 102sampling. While some situations may require more effort, the syntax,
106syntax, organization, and intellect used remain largely the same. If 103organization, and intellect used remain largely the same. If you've never used
107you've never used Python before, note that lines starting with a '=#=' 104Python before, note that lines starting with a '=#=' symbol are called comments,
108symbol are called comments, and they will be skipped by Python. I highly 105and they will be skipped by Python. I highly recommend taking a quick tutorial
109recommend taking a quick tutorial online to understand the basics of 106online to understand the basics of Python if any of the code below is confusing
110Python if any of the code below is confusing to you. 107to you.
111 108
112** Simple Random Sample 109** Simple Random Sample
113 110
114First, let's look at a simple, random sample. The code block below will 111First, let's look at a simple, random sample. The code block below will import
115import the =pandas= module, load a data file, sample the data, and 112the =pandas= module, load a data file, sample the data, and export the sample to
116export the sample to a file. 113a file.
117 114
118#+begin_src python 115#+begin_src python
119# Import the Pandas module 116# Import the Pandas module
@@ -137,8 +134,8 @@ sample.to_excel(file_output)
137 134
138** Simple Random Sample: Using Multiple Input Files 135** Simple Random Sample: Using Multiple Input Files
139 136
140Now that we've created a simple sample, let's create a sample from 137Now that we've created a simple sample, let's create a sample from multiple
141multiple files. 138files.
142 139
143#+begin_src python 140#+begin_src python
144# Import the Pandas module 141# Import the Pandas module
@@ -171,9 +168,9 @@ sample.to_excel(file_output)
171 168
172** Stratified Random Sample 169** Stratified Random Sample
173 170
174Well, what if you need to sample distinct parts of a single file? For 171Well, what if you need to sample distinct parts of a single file? For example,
175example, let's write some code to separate our data by "Region" and 172let's write some code to separate our data by "Region" and sample those regions
176sample those regions independently. 173independently.
177 174
178#+begin_src python 175#+begin_src python
179# Import the Pandas module 176# Import the Pandas module
@@ -205,10 +202,10 @@ sample.to_excel(file_output)
205 202
206** Stratified Systematic Sample 203** Stratified Systematic Sample
207 204
208This next example is quite useful if you need audit coverage over a 205This next example is quite useful if you need audit coverage over a certain time
209certain time period. This code will generate samples for each month in 206period. This code will generate samples for each month in the data and combine
210the data and combine them all together at the end. Obviously, this code 207them all together at the end. Obviously, this code can be modified to stratify
211can be modified to stratify by something other than months, if needed. 208by something other than months, if needed.
212 209
213#+begin_src python 210#+begin_src python
214# Import the Pandas module 211# Import the Pandas module
@@ -254,17 +251,17 @@ sample.to_excel(file_output)
254 251
255*** Documenting the Results 252*** Documenting the Results
256 253
257Once you've generated a proper sample, there are a few things left to do 254Once you've generated a proper sample, there are a few things left to do in
258in order to properly ensure your process is reproducible. 255order to properly ensure your process is reproducible.
259 256
2601. Document the sample. Make sure the resulting file is readable and 2571. Document the sample. Make sure the resulting file is readable and includes
261 includes the documentation listed in the next bullet. 258 the documentation listed in the next bullet.
2622. Include documentation around the data source, extraction techniques, 2592. Include documentation around the data source, extraction techniques, any
263 any modifications made to the data, and be sure to include a copy of 260 modifications made to the data, and be sure to include a copy of the script
264 the script itself. 261 itself.
2653. Whenever possible, perform a completeness and accuracy test to ensure 2623. Whenever possible, perform a completeness and accuracy test to ensure your
266 your sample is coming from a complete and accurate population. To 263 sample is coming from a complete and accurate population. To ensure
267 ensure completeness, compare the record count from the data source to 264 completeness, compare the record count from the data source to the record
268 the record count loaded into Python. To ensure accuracy, test a small 265 count loaded into Python. To ensure accuracy, test a small sample against the
269 sample against the source data (e.g., test 5 sales against the 266 source data (e.g., test 5 sales against the database to see if the details
270 database to see if the details are accurate). 267 are accurate).
content/blog/2021-10-09-apache-redirect.org +14 −17
@@ -5,15 +5,13 @@
5 5
6* The Problem 6* The Problem
7 7
8After recently switching static site generators (SSG), my blog URLs 8After recently switching static site generators (SSG), my blog URLs (uniform
9changed with no option to preserve the classic =.html= extension at the 9resource locators) changed with no option to preserve the classic =.html=
10end of my blog post URLs. 10extension at the end of my blog post URLs.
11 11
12I really disliked using my old SSG ([[https://jekyllrb.com][Jekyll]]) 12I really disliked using my old SSG ([[https://jekyllrb.com][Jekyll]]) and prefer my new tool ([[https://www.getzola.org][Zola]]) much
13and prefer my new tool ([[https://www.getzola.org][Zola]]) much more, so 13more, so I was determined to figure out a way to get the proper redirect set up
14I was determined to figure out a way to get the proper redirect set up 14so that people who find my posts online aren't constantly met by 404 errors.
15so that people who find my posts online aren't constantly met by 404
16errors.
17 15
18* The Solution 16* The Solution
19 17
@@ -21,11 +19,10 @@ To solve this problem, I really needed to solve two pieces:
21 19
221. Redirect all blog post URL requests from =/blog/some-post.html= to 201. Redirect all blog post URL requests from =/blog/some-post.html= to
23 =/blog/some-post/=. 21 =/blog/some-post/=.
242. Ensure that no other =.html= files are redirected, such as 222. Ensure that no other =.html= files are redirected, such as =index.html=.
25 =index.html=.
26 23
27After /a lot/ of tweaking and testing, I believe I have finally found 24After /a lot/ of tweaking and testing, I believe I have finally found the
28the solution. The solution is shown below. 25solution. The solution is shown below.
29 26
30#+begin_src conf 27#+begin_src conf
31RewriteEngine On 28RewriteEngine On
@@ -38,8 +35,8 @@ following:
38 35
391. Turn on the RewriteEngine so that we can modify URLs. 361. Turn on the RewriteEngine so that we can modify URLs.
402. Ignore any =index.html= files from the rule we are about to specify. 372. Ignore any =index.html= files from the rule we are about to specify.
413. Find any =.html= files within the website directory and redirect it 383. Find any =.html= files within the website directory and redirect it to
42 to exclude the file extension. 39 exclude the file extension.
434. The final piece is adding the trailing slash (=/=) at the end of the 404. The final piece is adding the trailing slash (=/=) at the end of the URL -
44 URL - you'll notice that I don't have an Apache rule for that since 41 you'll notice that I don't have an Apache rule for that since Apache handles
45 Apache handles that automatically. 42 that automatically.
content/blog/2021-12-04-cisa.org +142 −156
@@ -6,200 +6,186 @@
6* What is the CISA? 6* What is the CISA?
7 7
8For those of you lucky enough not to be knee-deep in the world of IT/IS 8For those of you lucky enough not to be knee-deep in the world of IT/IS
9Auditing, [[https://www.isaca.org/credentialing/cisa][CISA]] stands for 9Auditing, the [[https://www.isaca.org/credentialing/cisa][CISA]] (Certified Information Systems Auditor) certification and
10Certified Information Systems Auditor. This certification and exam are 10exam are part of ISACA's suite of certifications. As I often explain it to
11part of ISACA's suite of certifications. As I often explain it to people 11people like my family, it basically means you're employed to use your knowledge
12like my family, it basically means you're employed to use your knowledge 12of information systems, regulations, common threats, risks, etc. in order to
13of information systems, regulations, common threats, risks, etc. in 13assess an organization's current control of their risk. If a risk isn't
14order to assess an organization's current control of their risk. If a 14controlled (and the company doesn't want to accept the risk), an IS auditor will
15risk isn't controlled (and the company doesn't want to accept the risk), 15suggest implementing a control to address that risk.
16an IS auditor will suggest implementing a control to address that risk. 16
17 17Now, the CISA certification itself is, in my opinion, the main certification for
18Now, the CISA certification itself is, in my opinion, the main 18this career. While certifications such as the CPA (Certified Public Accountant)
19certification for this career. While certifications such as the CPA or 19or CISSP (Certified Information Systems Security Professional) are beneficial,
20CISSP are beneficial, nothing matches the power of the CISA for an IS 20nothing matches the power of the CISA for an information systems (IS) auditor
21auditor when it comes to getting hired, getting a raise/bonus, or 21when it comes to getting hired, getting a raise/bonus, or earning respect in the
22earning respect in the field. 22field.
23 23
24However, to be honest, I am a skeptic of most certifications. I 24However, to be honest, I am a skeptic of most certifications. I understand the
25understand the value they hold in terms of how much you need to commit 25value they hold in terms of how much you need to commit to studying or learning
26to studying or learning on the job, as well as the market value for 26on the job, as well as the market value for certifications such as the CISA. But
27certifications such as the CISA. But I also have known some very 27I also have known some very +incompetent+ /less than stellar/ auditors who have
28+incompetent+ /less than stellar/ auditors who have CPAs, CISAs, CIAs, 28relevant certifications.
29etc. 29
30 30The same goes for most industries: if a person is good at studying, they can
31The same goes for most industries: if a person is good at studying, they 31earn the certification. However, that knowledge means nothing unless you're
32can earn the certification. However, that knowledge means nothing unless 32actually able to use it in real life and perform as expected of a certification
33you're actually able to use it in real life and perform as expected of a 33holder. The challenge comes when people are hired or connected strictly because
34certification holder. The challenge comes when people are hired or 34of their certifications or resume; you need to see a person work before you can
35connected strictly because of their certifications or resume; you need 35assume them having a CISA means they're better than someone without the CISA.
36to see a person work before you can assume them having a CISA means 36
37they're better than someone without the CISA. 37Okay, rant over. Certifications are generally accepted as a measuring stick of
38 38commitment and quality of an employee, so I am accepting it too.
39Okay, rant over. Certifications are generally accepted as a measuring
40stick of commitment and quality of an employee, so I am accepting it
41too.
42 39
43* Exam Content 40* Exam Content
44 41
45The CISA is broken down into five sections, each weighted with a 42The CISA is broken down into five sections, each weighted with a percentage of
46percentage of test questions that may appear. 43test questions that may appear.
47 44
48Since the exam contains 150 questions, here's how those sections break 45Since the exam contains 150 questions, here's how those sections break down:
49down:
50 46
51| Exam Section | Percentage of Exam | Questions | 47| Exam Section | Percentage of Exam | Questions |
52|---------------+--------------------+-----------| 48|---------------+--------------------+-----------|
53| 1 | 21% | 32 | 49| 1 | 21% | 32 |
54| 2 | 17% | 26 | 50| 2 | 17% | 26 |
55| 3 | 12% | 18 | 51| 3 | 12% | 18 |
56| 4 | 23% | 34 | 52| 4 | 23% | 34 |
57| 5 | 27% | 40 | 53| 5 | 27% | 40 |
58| *Grand Total* | *100%* | *150* | 54| *Grand Total* | *100%* | *150* |
59 55
60* My Studying Habits 56* My Studying Habits
61 57
62This part is a little hard for me to break down into specific detail due 58This part is a little hard for me to break down into specific detail due to the
63to the craziness of the last year. While I officially purchased my 59craziness of the last year. While I officially purchased my studying materials
64studying materials in December 2020 and opened them to "start studying" 60in December 2020 and opened them to "start studying" in January 2021, I really
65in January 2021, I really wasn't able to study much due to the demands 61wasn't able to study much due to the demands of my job and personal life.
66of my job and personal life.
67 62
68Let me approach this from a few different viewpoints. 63Let me approach this from a few different viewpoints.
69 64
70** Study Materials 65** Study Materials
71 66
72Let's start by discussing the study materials I purchased. I'll be 67Let's start by discussing the study materials I purchased. I'll be referring to
73referring to #1 as the CRM and #2 as the QAE. 68#1 as the CRM (CISA Review Manual) and #2 as the QAE (Questions, Answers &
74 69Explanations).
751. [[https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCbEAK][CISA 70
76 Review Manual, 27th Edition | Print]] 711. [[https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCbEAK][CISA Review Manual, 27th Edition | Print]]
772. [[https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCcEAK][CISA 722. [[https://store.isaca.org/s/store#/store/browse/detail/a2S4w000004KoCcEAK][CISA Review Questions, Answers & Explanations Manual, 12th Edition | Print]]
78 Review Questions, Answers & Explanations Manual, 12th Edition | 73
79 Print]] 74The CRM is an excellent source of information and could honestly be used as a
80 75reference for most IS auditors as a learning reference during their daily audit
81The CRM is an excellent source of information and could honestly be used 76responsibilities. However, it is *full* of information and can be overloading if
82as a reference for most IS auditors as a learning reference during their 77you're not good at filtering out useless information while studying.
83daily audit responsibilities. However, it is *full* of information and 78
84can be overloading if you're not good at filtering out useless 79The QAE is the real star of the show here. This book contains 1000 questions,
85information while studying. 80separated by exam section, and a practice exam. My only complaint about the QAE
86 81is that each question is immediately followed with the correct answer and
87The QAE is the real star of the show here. This book contains 1000 82explanations below it, which means I had to use something to constantly cover
88questions, separated by exam section, and a practice exam. My only 83the answers while I was studying.
89complaint about the QAE is that each question is immediately followed 84
90with the correct answer and explanations below it, which means I had to 85I didn't use the online database version of the QAE, but I've heard that it's
91use something to constantly cover the answers while I was studying. 86easier to use than the printed book. However, it is more expensive ($299
92 87database vs $129 book) which might be important if you're paying for materials
93I didn't use the online database version of the QAE, but I've heard that 88yourself.
94it's easier to use than the printed book. However, it is more expensive 89
95($299 database vs $129 book) which might be important if you're paying 90In terms of question difficulty, I felt that the QAE was a good representation
96for materials yourself. 91of the actual exam. I've seen a lot of people online say it wasn't accurate to
97 92the exam or that it was much easier/harder, but I disagree with all of those.
98In terms of question difficulty, I felt that the QAE was a good 93The exam was fairly similar to the QAE, just focusing on whichever topics they
99representation of the actual exam. I've seen a lot of people online say 94chose for my version of the exam.
100it wasn't accurate to the exam or that it was much easier/harder, but I 95
101disagree with all of those. The exam was fairly similar to the QAE, just 96If you understand the concepts, skim the CRM (and read in-depth on topics you
102focusing on whichever topics they chose for my version of the exam. 97struggle with), and use the QAE to continue practicing exam-like questions, you
103 98should be fine. I didn't use any online courses, videos, etc. - the ISACA
104If you understand the concepts, skim the CRM (and read in-depth on 99materials are more than enough.
105topics you struggle with), and use the QAE to continue practicing
106exam-like questions, you should be fine. I didn't use any online
107courses, videos, etc. - the ISACA materials are more than enough.
108 100
109** Studying Process 101** Studying Process
110 102
111While I was able to briefly read through sections 1 and 2 in early 2021, 103While I was able to briefly read through sections 1 and 2 in early 2021, I had
112I had to stop and take a break from February/March to September. I 104to stop and take a break from February/March to September. I switched jobs in
113switched jobs in September, which allowed me a lot more free time to 105September, which allowed me a lot more free time to study.
114study.
115 106
116In September, I studied sections 3-5, took notes, and did a quick review 107In September, I studied sections 3-5, took notes, and did a quick review of the
117of the section topics. Once I felt comfortable with my notes, I took a 108section topics. Once I felt comfortable with my notes, I took a practice exam
118practice exam from the QAE manual and scored 70% (105/150). 109from the QAE manual and scored 70% (105/150).
119 110
120Here's a breakdown of my initial practice exam: 111Here's a breakdown of my initial practice exam:
121 112
122| Exam Section | Incorrect | Correct | Grand Total | Percent | 113| Exam Section | Incorrect | Correct | Grand Total | Percent |
123|---------------+-----------+---------+-------------+---------| 114|---------------+-----------+---------+-------------+---------|
124| 1 | 8 | 25 | 33 | 76% | 115| 1 | 8 | 25 | 33 | 76% |
125| 2 | 5 | 20 | 25 | 80% | 116| 2 | 5 | 20 | 25 | 80% |
126| 3 | 6 | 12 | 18 | 67% | 117| 3 | 6 | 12 | 18 | 67% |
127| 4 | 10 | 23 | 33 | 70% | 118| 4 | 10 | 23 | 33 | 70% |
128| 5 | 16 | 25 | 41 | 61% | 119| 5 | 16 | 25 | 41 | 61% |
129| *Grand Total* | *45* | *105* | *150* | *70%* | 120| *Grand Total* | *45* | *105* | *150* | *70%* |
130 121
131As I expected, my toughest sections were related to project management, 122As I expected, my toughest sections were related to project management,
132development, implementation, and security. 123development, implementation, and security.
133 124
134This just leaves October and November. For these months, I tried to 125This just leaves October and November. For these months, I tried to practice
135practice every few days, doing 10 questions for each section, until the 126every few days, doing 10 questions for each section, until the exam. This came
136exam. This came out to 13 practice sessions, ~140 questions per section, 127out to 13 practice sessions, ~140 questions per section, and ~700 questions
137and ~700 questions total. 128total.
138 129
139While some practice sessions were worse and some were better, the final 130While some practice sessions were worse and some were better, the final results
140results were similar to my practice exam results. As you can see below, 131were similar to my practice exam results. As you can see below, my averages were
141my averages were slightly worse than my practice exam. However, I got in 132slightly worse than my practice exam. However, I got in over 700 questions of
142over 700 questions of practice and, most importantly, /I read through 133practice and, most importantly, /I read through the explanations every time I
143the explanations every time I answered incorrectly and learned from my 134answered incorrectly and learned from my mistakes/.
144mistakes/.
145 135
146| Exam Section | Incorrect | Correct | Grand Total | Percent | 136| Exam Section | Incorrect | Correct | Grand Total | Percent |
147|---------------+-----------+---------+-------------+---------| 137|---------------+-----------+---------+-------------+---------|
148| 1 | 33 | 108 | 141 | 77% | 138| 1 | 33 | 108 | 141 | 77% |
149| 2 | 33 | 109 | 142 | 77% | 139| 2 | 33 | 109 | 142 | 77% |
150| 3 | 55 | 89 | 144 | 62% | 140| 3 | 55 | 89 | 144 | 62% |
151| 4 | 52 | 88 | 140 | 63% | 141| 4 | 52 | 88 | 140 | 63% |
152| 5 | 55 | 85 | 140 | 61% | 142| 5 | 55 | 85 | 140 | 61% |
153| *Grand Total* | *228* | *479* | *707* | *68%* | 143| *Grand Total* | *228* | *479* | *707* | *68%* |
154 144
155* Results 145* Results
156 146
157Now, how do the practice scores reflect my actual results? After all, 147Now, how do the practice scores reflect my actual results? After all, it's hard
158it's hard to tell how good a practice regimen is unless you see how it 148to tell how good a practice regimen is unless you see how it turns out.
159turns out.
160 149
161| Exam Section | Section Name | Score | 150| Exam Section | Section Name | Score |
162|--------------+------------------------------------------------------------------+-------| 151|--------------+------------------------------------------------------------------+-------|
163| 1 | Information Systems Auditing Process | 678 | 152| 1 | Information Systems Auditing Process | 678 |
164| 2 | Governance and Management of IT | 590 | 153| 2 | Governance and Management of IT | 590 |
165| 3 | Information Systems Acquisition, Development, and Implementation | 721 | 154| 3 | Information Systems Acquisition, Development, and Implementation | 721 |
166| 4 | Information Systems Operations and Business Resilience | 643 | 155| 4 | Information Systems Operations and Business Resilience | 643 |
167| 5 | Protection of Information Assets | 511 | 156| 5 | Protection of Information Assets | 511 |
168 157
169Now, in order to pass the CISA, you need at least 450 on a sliding scale 158Now, in order to pass the CISA, you need at least 450 on a sliding scale of
170of 200-800. Personally, I really have no clue what an average CISA score 159200-800. Personally, I really have no clue what an average CISA score is. After
171is. After a /very/ brief look online, I can see that the high end is 160a /very/ brief look online, I can see that the high end is usually in the low
172usually in the low 700s. In addition, only about 50-60% of people pass 161700s. In addition, only about 50-60% of people pass the exam.
173the exam. 162
174 163Given this information, I feel great about my scores. 616 may not be phenomenal,
175Given this information, I feel great about my scores. 616 may not be 164and I wish I had done better on sections 2 & 5, but my practicing seems to have
176phenomenal, and I wish I had done better on sections 2 & 5, but my 165worked very well overall.
177practicing seems to have worked very well overall. 166
178 167However, the practice results do not conform to the actual results. Section 2
179However, the practice results do not conform to the actual results. 168was one of my highest practice sections and was my second-lowest score in the
180Section 2 was one of my highest practice sections and was my 169exam. Conversely, section 3 was my second-lowest practice section and turned out
181second-lowest score in the exam. Conversely, section 3 was my 170to be my highest actual score!
182second-lowest practice section and turned out to be my highest actual 171
183score! 172After reflecting, it is obvious that if you have any background on the CISA
184 173topics at all, the most important part of studying is doing practice questions.
185After reflecting, it is obvious that if you have any background on the 174You really need to understand how to read the questions critically and pick the
186CISA topics at all, the most important part of studying is doing 175best answer.
187practice questions. You really need to understand how to read the
188questions critically and pick the best answer.
189 176
190* Looking Forward 177* Looking Forward
191 178
192I am extremely happy that I was finally able to pass the CISA. Looking 179I am extremely happy that I was finally able to pass the CISA. Looking to the
193to the future, I'm not sure what's next in terms of professional 180future, I'm not sure what's next in terms of professional learning. My current
194learning. My current company offers internal learning courses, so I will 181company offers internal learning courses, so I will most likely focus on that if
195most likely focus on that if I need to gain more knowledge in certain 182I need to gain more knowledge in certain areas.
196areas. 183
197 184To be fair, even if you pass the CISA, it's hard to become an expert on any
198To be fair, even if you pass the CISA, it's hard to become an expert on 185specific topic found within. My career may take me in a different direction, and
199any specific topic found within. My career may take me in a different 186I might need to focus more on security or networking certifications (or possibly
200direction, and I might need to focus more on security or networking 187building a better analysis/visualization portfolio if I want to go into data
201certifications (or possibly building a better analysis/visualization 188analysis/science).
202portfolio if I want to go into data analysis/science).
203 189
204All I know is that I am content at the moment and extremely proud of my 190All I know is that I am content at the moment and extremely proud of my
205accomplishment. 191accomplishment.