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