Commit 3d70db647d

3d70db647d43bb449ada73b56f98248a560befee

parent: 972b15ecc9

Unsigned

cmc <hello@cleberg.net> · 2024-09-02 03:03 UTC

format 2024 blog posts

Layout: unified · split

content/blog/2024-01-08-dont-say-hello.org +16 −16
@@ -3,25 +3,25 @@
33#+description:
44#+slug: dont-say-hello
55
6I recently came back from a winter break and have started working
7again... only to immediately run into the dilemma of people sending me
8cliffhanger messages again.
6I recently came back from a winter break and have started working again... only
7to immediately run into the dilemma of people sending me cliffhanger messages
8again.
99
1010* No Hello
1111
12A year or two ago, I discovered [[https://nohello.net/en/][no hello]]
13and have thought about it often since then. I've even sent it to a few
14people since then (who wouldn't take offense to it).
12A year or two ago, I discovered [[https://nohello.net/en/][no hello]] and have thought about it often since
13then. I've even sent it to a few people since then (who wouldn't take offense to
14it).
1515
16I work in a fast-paced environment where efficiency is extremely
17valuable. Therefore, I have always held a deep displeasure for
18conversations where people start with "Hello" and then.
16I work in a fast-paced environment where efficiency is extremely valuable.
17Therefore, I have always held a deep displeasure for conversations where people
18start with "Hello" and then.
1919
20I searched back through my work messages and found that I received ~50
21messages from ~10 people last year from people that contained "hi",
22"hey", or "hello" and did not contain any indication of the purpose of
23the conversation. I also noticed that a few of the users were
24responsible for the large majority of the cliffhangers.
20I searched back through my work messages and found that I received ~50 messages
21from ~10 people last year from people that contained "hi", "hey", or "hello" and
22did not contain any indication of the purpose of the conversation. I also
23noticed that a few of the users were responsible for the large majority of the
24cliffhangers.
2525
26There's no real point to this post, just a desparate request for people
27to please stop doing this.
26There's no real point to this post, just a desparate request for people to
27please stop doing this.
content/blog/2024-01-09-macos-customization.org +52 −68
@@ -3,73 +3,65 @@
33#+description:
44#+slug: macos-customization
55
6I have been using macOS more than Linux lately, so I wrote this post to
7describe some simple options to customize macOS beyond the normal
8built-in settings menu.
6I have been using macOS more than Linux lately, so I wrote this post to describe
7some simple options to customize macOS beyond the normal built-in settings menu.
98
10While not all-encompassing, the options below should be a good start for
11anyone looking to dive down the rabbit hole.
9While not all-encompassing, the options below should be a good start for anyone
10looking to dive down the rabbit hole.
1211
1312* Basics
1413
1514** Package Management
1615
17To install a lot of software on macOS, you will need
18[[https://brew.sh/][Homebrew]]. You can use their installation script to
19get started. Simply open the =Terminal= application and paste the
20following snippet:
16To install a lot of software on macOS, you will need [[https://brew.sh/][Homebrew]]. You can use their
17installation script to get started. Simply open the =Terminal= application and
18paste the following snippet:
2119
2220#+begin_src sh
2321/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
2422#+end_src
2523
26This will allow you to easily install and manage applications and other
27software easily through the =brew= command.
24This will allow you to easily install and manage applications and other software
25easily through the =brew= command.
2826
2927** Terminal
3028
31If you're serious about customizing your macOS system, I highly
32recommend installing a terminal emulator that you like and if you're not
33comfortable on the command line yet, start learning. A lot of
34customization options require you to edit hidden files, which is easiest
35in a terminal.
29If you're serious about customizing your macOS system, I highly recommend
30installing a terminal emulator that you like and if you're not comfortable on
31the command line yet, start learning. A lot of customization options require you
32to edit hidden files, which is easiest in a terminal.
3633
37There are options like iTerm2, Kitty, Alacritty, Hyper, Warp, or the
38built-in Terminal app.
34There are options like iTerm2, Kitty, Alacritty, Hyper, Warp, or the built-in
35Terminal app.
3936
40I use [[https://iterm2.com/][iTerm2]], which can be installed with
41Homebrew:
37I use [[https://iterm2.com/][iTerm2]], which can be installed with Homebrew:
4238
4339#+begin_src sh
4440brew install iterm2
4541#+end_src
4642
47To install color schemes, such as the Dracula scheme, you visit
48[[https://iterm2colorschemes.com/][iTerm Themes]] and follow their
49installation instructions to install any of the themes.
43To install color schemes, such as the Dracula scheme, you visit [[https://iterm2colorschemes.com/][iTerm Themes]] and
44follow their installation instructions to install any of the themes.
5045
5146* Desktop
5247
5348** Window Management
5449
55[[https://github.com/koekeishiya/yabai][yabai]] is a tiling window
56manager for macOS. While other window managers exist, I found that most
57of them struggled to create logical layouts and to allow me to easily
58move windows around the screen.
50[[https://github.com/koekeishiya/yabai][yabai]] is a tiling window manager for macOS. While other window managers exist, I
51found that most of them struggled to create logical layouts and to allow me to
52easily move windows around the screen.
5953
60Some advanced settings for yabai are only available if partially disable
61System Integrity Protection (SIP). However, I chose not to do this and
62it hasn't affected my basic usage of yabai at all.
54Some advanced settings for yabai are only available if partially disable System
55Integrity Protection (SIP). However, I chose not to do this and it hasn't
56affected my basic usage of yabai at all.
6357
64Refer to the
65[[https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)][yabai
66wiki]] for installation instructions. You will need to ensure that yabai
67is allowed to access the accessibility and screen recording APIs.
58Refer to the [[https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)][yabai wiki]] for installation instructions. You will need to ensure
59that yabai is allowed to access the accessibility and screen recording APIs.
6860
6961** Keyboard Shortcuts
7062
71[[https://github.com/koekeishiya/skhd][skhd]] is a simple hotkey daemon
72that allows you to define hotkeys in a file for usage on your system.
63[[https://github.com/koekeishiya/skhd][skhd]] is a simple hotkey daemon that allows you to define hotkeys in a file for
64usage on your system.
7365
7466Installation is simple:
7567
@@ -78,8 +70,8 @@ brew install koekeishiya/formulae/skhd
7870skhd --start-service
7971#+end_src
8072
81After installation, be sure to allow =skhd= access to the accessibility
82API in the macOS privacy settings.
73After installation, be sure to allow =skhd= access to the accessibility API in
74the macOS privacy settings.
8375
8476You can configure your hotkeys in the =~/.config/skhd/skhdrc= file:
8577
@@ -99,53 +91,45 @@ cmd + shift - return : /Applications/LibreWolf.app/Contents/MacOS/librewolf
9991
10092** Widgets
10193
102[[https://github.com/felixhageloh/uebersicht/][uebersicht]] is a handy
103desktop-based widget tool with a plethora of community-made widgets
104available in the [[https://tracesof.net/uebersicht-widgets/][widgets
105gallery]]. You can also write your own widgets with this tool.
94[[https://github.com/felixhageloh/uebersicht/][uebersicht]] is a handy desktop-based widget tool with a plethora of
95community-made widgets available in the [[https://tracesof.net/uebersicht-widgets/][widgets gallery]]. You can also write your
96own widgets with this tool.
10697
107To install, simply download the latest release from the
108[[https://tracesof.net/uebersicht/][uebersicht website]] and copy it to
109the Applications folder.
98To install, simply download the latest release from the [[https://tracesof.net/uebersicht/][uebersicht website]] and
99copy it to the Applications folder.
110100
111See below for an example of the
112[[https://tracesof.net/uebersicht-widgets/#Mond][Mond]] widget in
113action.
101See below for an example of the [[https://tracesof.net/uebersicht-widgets/#Mond][Mond]] widget in action.
114102
115103** Status Bar
116104
117[[https://github.com/FelixKratz/SketchyBar][SketchyBar]] is a
118customizable replacement for the macOS status or menu bar.
105[[https://github.com/FelixKratz/SketchyBar][SketchyBar]] is a customizable replacement for the macOS status or menu bar.
119106
120You can browse a discussion where various users shared their
121[[https://github.com/FelixKratz/SketchyBar/discussions/47?sort=top][configurations]]
122for inspiration or to copy their dotfiles.
107You can browse a discussion where various users shared their [[https://github.com/FelixKratz/SketchyBar/discussions/47?sort=top][configurations]] for
108inspiration or to copy their dotfiles.
123109
124110** Dock
125111
126The easiest way to customize the dock is to install
127[[https://ubarapp.com/][uBar]], which uses a Windows-like menu bar as
128the default style.
112The easiest way to customize the dock is to install [[https://ubarapp.com/][uBar]], which uses a
113Windows-like menu bar as the default style.
129114
130However, the built-in macOS dock cannot be disabled and can only be set
131to "always hidden". This can be annoying as it will pop out any time
132your mouse cursor passes closely to the dock edge of the screen. Because
133of this, I simply use the built-in dock instead of customizing it with
134third-party software.
115However, the built-in macOS dock cannot be disabled and can only be set to
116"always hidden". This can be annoying as it will pop out any time your mouse
117cursor passes closely to the dock edge of the screen. Because of this, I simply
118use the built-in dock instead of customizing it with third-party software.
135119
136120Regardless, see below for the default installation style of uBar.
137121
138122** Application Icons
139123
140You can also customize the icon of any application in macOS, which will
141show up in Finder, the Dock, Launchpad, search results, etc. I recommend
142using [[https://macosicons.com/][macOSicons]] to download icons you
143want, and then apply them by following this process.
124You can also customize the icon of any application in macOS, which will show up
125in Finder, the Dock, Launchpad, search results, etc. I recommend using
126[[https://macosicons.com/][macOSicons]] to download icons you want, and then apply them by following this
127process.
144128
1451291. Open the Finder application.
1461302. Navigate to the =Applications= folder.
1471313. Right-click an application of your choice, and select =Get Info=.
1484. Drag the image you downloaded on top of the application's icon at the
149 top of information window (you will see a green "plus" symbol when
150 you're hovering over it).
1324. Drag the image you downloaded on top of the application's icon at the top of
133 information window (you will see a green "plus" symbol when you're hovering
134 over it).
1511355. Release the new icon on top of the old icon and it will update!
content/blog/2024-01-13-local-llm.org +43 −51
@@ -5,11 +5,10 @@
55
66* Requirements
77
8I've recently started playing with large language models (LLMs), mostly
9in the popular chatbot form, as part of my job and have decided to see
10if there's a consistent and reliable way to interact with these models
11on Apple devices without sacrificing privacy or requiring in-depth
12technical setup.
8I've recently started playing with large language models (LLMs), mostly in the
9popular chatbot form, as part of my job and have decided to see if there's a
10consistent and reliable way to interact with these models on Apple devices
11without sacrificing privacy or requiring in-depth technical setup.
1312
1413My requirements for this test:
1514
@@ -18,12 +17,12 @@ My requirements for this test:
1817- Minimal required configuration
1918- Preferably pre-built, but a simple build process is acceptable
2019
21I tested a handful of apps and have summarized my favorite (so far) for
22macOS and iOS below.
20I tested a handful of apps and have summarized my favorite (so far) for macOS
21and iOS below.
2322
2423#+begin_quote
25TL;DR - Here are the two that met my requirements and I have found the
26easiest to install and use so far:
24TL;DR - Here are the two that met my requirements and I have found the easiest
25to install and use so far:
2726#+end_quote
2827
2928- macOS: [[https://ollama.ai/][Ollama]]
@@ -31,13 +30,12 @@ easiest to install and use so far:
3130
3231* macOS
3332
34[[https://ollama.ai/][Ollama]] is a simple Go application for macOS and
35Linux that can run various LLMs locally.
33[[https://ollama.ai/][Ollama]] is a simple Go application for macOS and Linux that can run various LLMs
34locally.
3635
37For macOS, you can download the pplication on the
38[[https://ollama.ai/download/mac][Ollama download page]] and install it
39by unzipping the =Ollama.app= file and moving it to the =Applications=
40folder.
36For macOS, you can download the pplication on the [[https://ollama.ai/download/mac][Ollama download page]] and
37install it by unzipping the =Ollama.app= file and moving it to the
38=Applications= folder.
4139
4240If you prefer the command line, you can run these commands after the
4341download finished:
@@ -48,49 +46,43 @@ unzip Ollama-darwin.zip && \
4846mv ~/Downloads/Ollama.app /Applications/
4947#+end_src
5048
51After running the app, the app will ask you to open a terminal and run
52the default =llama2= model, which will open an interactive chat session
53in the terminal. You can startfully using the application at this point.
49After running the app, the app will ask you to open a terminal and run the
50default =llama2= model, which will open an interactive chat session in the
51terminal. You can startfully using the application at this point.
5452
55If you don't want to use the default =llama2= model, you can download
56and run additional models found on the
57[[https://ollama.ai/library][Models]] page.
53If you don't want to use the default =llama2= model, you can download and run
54additional models found on the [[https://ollama.ai/library][Models]] page.
5855
5956To see the information for the currently-used model, you can run the
6057=/show info= command in the chat.
6158
6259** Community Integrations
6360
64I highly recommend browsing the
65[[https://github.com/jmorganca/ollama#community-integrations][Community
66Integrations]] section of the project to see how you would prefer to
67extend Ollama beyond a simple command-line interface. There are options
68for APIs, browser UIs, advanced terminal configurations, and more.
61I highly recommend browsing the [[https://github.com/jmorganca/ollama#community-integrations][Community Integrations]] section of the project to
62see how you would prefer to extend Ollama beyond a simple command-line
63interface. There are options for APIs, browser UIs, advanced terminal
64configurations, and more.
6965
7066* iOS
7167
72While there are a handful of decent macOS options, it was quite
73difficult to find an iOS app that offered an open source platform
74without an extensive configuration and building process. I found LLM
75Farm to be decent enough in quality to sit at the top of my list -
76however, it's definitely not user friendly enough for me to consider
77using it on a daily basis.
78
79[[https://llmfarm.site/][LLM Farm]] is available on TestFlight, so
80there's no manual build process required. However, you can view the
81[[https://github.com/guinmoon/LLMFarm][LLMFarm repository]] if you wish.
82
83The caveat is that you will have to manually download the model files
84from the links in the
85[[https://github.com/guinmoon/LLMFarm/blob/main/models.md][models.md]]
86file to your iPhone to use the app - there's currently no option in the
87app to reach out and grab the latest version of any supported model.
88
89Once you have a file downloaded, you simply create a new chat and select
90the downloaded model file and ensure the inference matches the
91requirement in the =models.md= file.
92
93[[https://github.com/AugustDev/enchanted][Enchanted]] is also an iOS for
94private AI models, but it requires a public-facing Ollama API, which did
95not meet my "on device requirement." Nonetheless, it's an interesting
96looking app and I will likely set it up to test soon.
68While there are a handful of decent macOS options, it was quite difficult to
69find an iOS app that offered an open source platform without an extensive
70configuration and building process. I found LLM Farm to be decent enough in
71quality to sit at the top of my list - however, it's definitely not user
72friendly enough for me to consider using it on a daily basis.
73
74[[https://llmfarm.site/][LLM Farm]] is available on TestFlight, so there's no manual build process
75required. However, you can view the [[https://github.com/guinmoon/LLMFarm][LLMFarm repository]] if you wish.
76
77The caveat is that you will have to manually download the model files from the
78links in the [[https://github.com/guinmoon/LLMFarm/blob/main/models.md][models.md]] file to your iPhone to use the app - there's currently no
79option in the app to reach out and grab the latest version of any supported
80model.
81
82Once you have a file downloaded, you simply create a new chat and select the
83downloaded model file and ensure the inference matches the requirement in the
84=models.md= file.
85
86[[https://github.com/AugustDev/enchanted][Enchanted]] is also an iOS for private AI models, but it requires a public-facing
87Ollama API, which did not meet my "on device requirement." Nonetheless, it's an
88interesting looking app and I will likely set it up to test soon.
content/blog/2024-01-26-audit-dashboard.org +59 −64
@@ -3,9 +3,9 @@
33#+description:
44#+slug: audit-dashboard
55
6Alteryx and Power BI are powerful tools that can help turn your
7old-school audit trackers into interactive tools that provide useful
8insights and potential action plans.
6Alteryx and Power BI are powerful tools that can help turn your old-school audit
7trackers into interactive tools that provide useful insights and potential
8action plans.
99
1010With these tools, we are going to build a dashboard that can effectively
1111communicate project status.
@@ -15,30 +15,28 @@ communicate project status.
1515This project assumes the following:
1616
1717- You have access to Alteryx Designer and Power BI Desktop.
18 - If you only have Power BI Desktop, you may need to perform some
19 analysis in Power BI instead of Alteryx.
20- Your data is in a format that can be imported into Alteryx and/or
21 Power BI.
18 - If you only have Power BI Desktop, you may need to perform some analysis in
19 Power BI instead of Alteryx.
20- Your data is in a format that can be imported into Alteryx and/or Power BI.
2221- You have a basic understanding of data types and visualization.
2322
2423* Alteryx: Data Preparation & Analysis
2524
2625** Import Data
2726
28With Alteryx, importing data is easy with the use of the =Input Data=
29tool. Simply drag this tool onto the canvas from the =In/Out= tab in the
30Ribbon to create it as a node.
27With Alteryx, importing data is easy with the use of the =Input Data= tool.
28Simply drag this tool onto the canvas from the =In/Out= tab in the Ribbon to
29create it as a node.
3130
32You can choose the File Format manually or simply connect to your
33file/database and let Alteryx determine the format for you. For this
34example, we will be importing an Excel file and changing the
35=Start Data Import on Line= variable to =2=.
31You can choose the File Format manually or simply connect to your file/database
32and let Alteryx determine the format for you. For this example, we will be
33importing an Excel file and changing the =Start Data Import on Line= variable to
34=2=.
3635
3736** Transform Data
3837
39Next, let's replace null data and remove whitespace to clean up our
40data. We can do this with the =Data Cleansing= tool in the =Preparation=
41tab in the Ribbon.
38Next, let's replace null data and remove whitespace to clean up our data. We can
39do this with the =Data Cleansing= tool in the =Preparation= tab in the Ribbon.
4240
4341Ensure that the following options are enabled:
4442
@@ -48,49 +46,48 @@ Ensure that the following options are enabled:
4846- Remove Unwanted Characters
4947 - Leading and Trailing Whitespace
5048
51For our next step, we will transform the date fields from strings to
52datetime format. Add a =Datetime= tool for each field you want to
53transform - in the example below, I am using the tool twice for the
54"Started On" and "Submitted On" fields.
49For our next step, we will transform the date fields from strings to datetime
50format. Add a =Datetime= tool for each field you want to transform - in the
51example below, I am using the tool twice for the "Started On" and "Submitted On"
52fields.
5553
56Now that the dates are in the correct format, let's perform a
57calculation based on those fields. Start by adding a =Filter= tool,
58naming a new Output Column, and pasting the formula below into it (the
59two fields used in this formula must match the output of the =Datetime=
60tools above):
54Now that the dates are in the correct format, let's perform a calculation based
55on those fields. Start by adding a =Filter= tool, naming a new Output Column,
56and pasting the formula below into it (the two fields used in this formula must
57match the output of the =Datetime= tools above):
6158
62``=txt DateTimeDiff([SubmittedOn_Out],[StartedOn_Out], "days")=
59```txt
60DateTimeDiff([SubmittedOn_Out],[StartedOn_Out], "days")
61```
6362
6463** Export Data
6564
66Finalize the process by exporting the transformed data set to a new
67file, for use in the following visualization step.
65Finalize the process by exporting the transformed data set to a new file, for
66use in the following visualization step.
6867
6968* Power BI: Data Visualization
7069
7170** Import Data
7271
73To start, open the Power BI Desktop application. Upon first use, Power
74BI will ask if you want to open an existing dashboard or import new
75data.
72To start, open the Power BI Desktop application. Upon first use, Power BI will
73ask if you want to open an existing dashboard or import new data.
7674
77As we are creating our first dashboard, let's import our data. In my
78example below, I'm importing data from the "Tracker" sheet of the Excel
79file I'm using for this project.
75As we are creating our first dashboard, let's import our data. In my example
76below, I'm importing data from the "Tracker" sheet of the Excel file I'm using
77for this project.
8078
81During this process, I also imported the export from the Alteryx
82workflow above. Therefore, we have two different files available for use
83in our dashboard.
79During this process, I also imported the export from the Alteryx workflow above.
80Therefore, we have two different files available for use in our dashboard.
8481
8582** Add Visuals
8683
87To create the dashboard, you will need to follow the list instructions
88below and format as needed.
84To create the dashboard, you will need to follow the list instructions below and
85format as needed.
8986
9087Instructions to create the visuals above:
9188
92- =Text Box=: Explain the name and purpose of the dashboard. You can
93 also add images and logos at the top of the dashboard.
89- =Text Box=: Explain the name and purpose of the dashboard. You can also add
90 images and logos at the top of the dashboard.
9491- =Donut Chart=: Overall status of the project.
9592 - =Legend=: Status
9693 - =Values=: Count of Status
@@ -111,13 +108,12 @@ Instructions to create the visuals above:
111108
112109** Format the Dashboard
113110
114You can choose a theme in the View tab of the Ribbon. You can even
115browse for custom JSON files that define themes, such as ones found
116online or custom ones created by your organization.
111You can choose a theme in the View tab of the Ribbon. You can even browse for
112custom JSON files that define themes, such as ones found online or custom ones
113created by your organization.
117114
118For each visual, you can click the =Format= button in the
119=Visualizations= side pane and explore the options. You can custom
120options such as:
115For each visual, you can click the =Format= button in the =Visualizations= side
116pane and explore the options. You can custom options such as:
121117
122118- Visual
123119 - Legend
@@ -132,22 +128,21 @@ options such as:
132128 - Tooltips
133129 - Alt text
134130
135You can always look online for inspiration when trying to decide how
136best to organize and style your dashboard.
131You can always look online for inspiration when trying to decide how best to
132organize and style your dashboard.
137133
138134* Sharing the Results
139135
140Generally, you have a few different options for sharing your dashboards
141with others:
142
1431. Export the dashboard as a PDF in the file menu of Power BI. This will
144 export all tabs and visuals as they are set when the export button is
145 pressed. You will lose all interactivity with this option.
1462. Send the full Power BI file to those you wish to share the dashboard.
147 This will retain all settings and interactivity. However, you will
148 also need to send the source files if they need to refresh the
149 dashboard and you will need to re-send the files if you make updates.
1503. Store the dashboard in a synced location, such as a shared drive or
151 Microsoft Teams. Depending on how a user configures their local
152 Windows paths, the data source paths may not be compatible for all
153 users with such a setup.
136Generally, you have a few different options for sharing your dashboards with
137others:
138
1391. Export the dashboard as a PDF in the file menu of Power BI. This will export
140 all tabs and visuals as they are set when the export button is pressed. You
141 will lose all interactivity with this option.
1422. Send the full Power BI file to those you wish to share the dashboard. This
143 will retain all settings and interactivity. However, you will also need to
144 send the source files if they need to refresh the dashboard and you will need
145 to re-send the files if you make updates.
1463. Store the dashboard in a synced location, such as a shared drive or Microsoft
147 Teams. Depending on how a user configures their local Windows paths, the data
148 source paths may not be compatible for all users with such a setup.
content/blog/2024-01-27-tableau-dashboard.org +42 −47
@@ -3,14 +3,12 @@
33#+description:
44#+slug: tableau-dashboard
55
6In this project, I am going to show you how to use Tableau Public for
7free to create simple dashboards.
6In this project, I am going to show you how to use Tableau Public for free to
7create simple dashboards.
88
9I will be creating simple visuals from an Omaha crime data set and
10combining them to create the dashboard below. You can view this
11dashboard interactively online here:
12[[https://public.tableau.com/app/profile/c.c7042/viz/OmahaCrimeData2015-2023/OmahaCrimeData2015-2023#1][Omaha
13Crime Data (2015 - 2023)]].
9I will be creating simple visuals from an Omaha crime data set and combining
10them to create the dashboard below. You can view this dashboard interactively
11online here: [[https://public.tableau.com/app/profile/c.c7042/viz/OmahaCrimeData2015-2023/OmahaCrimeData2015-2023#1][Omaha Crime Data (2015 - 2023)]].
1412
1513#+caption: Tableau Dashboard
1614[[https://img.cleberg.net/blog/20240127-tableau-dashboard/dashboard.png]]
@@ -18,18 +16,17 @@ Crime Data (2015 - 2023)]].
1816* Gather the Data
1917
2018You can download incident data from the Omaha Police Department on their
21[[https://police.cityofomaha.org/crime-information/incident-data-download][Incident
22Data Download]] page. They currently have files for the years 2015
19[[https://police.cityofomaha.org/crime-information/incident-data-download][Incident Data Download]] page. They currently have files for the years 2015
2320through 2023.
2421
2522Each file will be downloaded as a CSV file, approximately 3 MB - 8 MB.
2623
2724* Clean and Transform the Data
2825
29I have used Python to combine the files into a single CSV file, as well
30as adding a custom =datetime= column. You could do this step in any
31software you prefer, but I prefer Python as its free, easy to use, and
32has a plethora of support resources online.
26I have used Python to combine the files into a single CSV file, as well as
27adding a custom =datetime= column. You could do this step in any software you
28prefer, but I prefer Python as its free, easy to use, and has a plethora of
29support resources online.
3330
3431Start by opening a terminal, navigating to your Downloads directory, and
3532creating a python script.
@@ -76,38 +73,37 @@ Once pasted, save and close the file. You can execute the file like so:
7673python3 data_processing.py
7774#+end_src
7875
79After this, you should have a combined data file that contains all
80incidents between 2015 and 2023. Mine was approximately 55 MB.
76After this, you should have a combined data file that contains all incidents
77between 2015 and 2023. Mine was approximately 55 MB.
8178
8279* Tableau Public
8380
84[[https://public.tableau.com/][Tableau Public]] is a free-to-use web
85application that allows you to create visualizations by uploading data
86sources. Note that there's no way to keep the data and visualizations
87private, so don't upload anything private.
81[[https://public.tableau.com/][Tableau Public]] is a free-to-use web application that allows you to create
82visualizations by uploading data sources. Note that there's no way to keep the
83data and visualizations private, so don't upload anything private.
8884
89After creating an account, you can click the =Create= > =Web Authoring=
90link to create your first visualization.
85After creating an account, you can click the =Create= > =Web Authoring= link to
86create your first visualization.
9187
9288** Upload the Data
9389
94Once you've opened your first project, Tableau will ask you to connect
95to your data. For this project, click the =Upload from computer= button
96and select the CSV file previously combined in the step above.
90Once you've opened your first project, Tableau will ask you to connect to your
91data. For this project, click the =Upload from computer= button and select the
92CSV file previously combined in the step above.
9793
98Once connected, you can refresh the preview of the data with the
99=Refresh Data Source= button in the toolbar.
94Once connected, you can refresh the preview of the data with the =Refresh Data
95Source= button in the toolbar.
10096
101If you need to edit any of the data types, column names, etc., you can
102do so now. Once complete, generate an extract so that you can start
103creating visualizations.
97If you need to edit any of the data types, column names, etc., you can do so
98now. Once complete, generate an extract so that you can start creating
99visualizations.
104100
105101** Create Visualizations
106102
107103To start, create a worksheet in the toolbar at the bottom of the screen.
108104
109Within this screen, select a column from the =Data= side bar on the left
110and drag it into the =Columns= or =Rows= area of the canvas.
105Within this screen, select a column from the =Data= side bar on the left and
106drag it into the =Columns= or =Rows= area of the canvas.
111107
112108See below for the map visualization. You can recreate this by adding the
113109following fields:
@@ -119,30 +115,29 @@ following fields:
119115 - Datetime
120116- =Filters=: Datetime
121117
122You can repeat this process for each visualization you want to create.
123Explore your options by dragging data fields to different areas and by
124opening the field options to explore what operations can be performed on
125different data types (e.g., average, count, etc.).
118You can repeat this process for each visualization you want to create. Explore
119your options by dragging data fields to different areas and by opening the field
120options to explore what operations can be performed on different data types
121(e.g., average, count, etc.).
126122
127123** Create Dashboard
128124
129To create a dashboard, click the button on the toolbar at the bottom of
130the screen. Within the dashboard, drag each sheet from the left side bar
131onto the dashboard canvas.
125To create a dashboard, click the button on the toolbar at the bottom of the
126screen. Within the dashboard, drag each sheet from the left side bar onto the
127dashboard canvas.
132128
133129** Formatting
134130
135You can explore a ton of different formatting options throughout the
136worksheets and dashboard. Specifically for maps, you can alter the map
137layers, background, and visible features through the =Map= menu in the
138top file menu of the editing screen.
131You can explore a ton of different formatting options throughout the worksheets
132and dashboard. Specifically for maps, you can alter the map layers, background,
133and visible features through the =Map= menu in the top file menu of the editing
134screen.
139135
140In the finished dashboard below, I opted for a dark mode with a map that
141showed county lines and city names.
136In the finished dashboard below, I opted for a dark mode with a map that showed
137county lines and city names.
142138
143There's a ton of other options available to be used in a dashboard like
144this, but this project shows a quick preview of what you can do in
145Tableau Public.
139There's a ton of other options available to be used in a dashboard like this,
140but this project shows a quick preview of what you can do in Tableau Public.
146141
147142#+caption: Tableau Dashboard
148143[[https://img.cleberg.net/blog/20240127-tableau-dashboard/dashboard.png]]
content/blog/2024-02-06-zfs.org +54 −68
@@ -6,14 +6,11 @@
66This post details the process I used to create ZFS pools, datasets, and
77snapshots on Ubuntu Server.
88
9I found the following pages very helpful while going through this
10process:
9I found the following pages very helpful while going through this process:
1110
12- [[https://ubuntu.com/tutorials/setup-zfs-storage-pool][Setup a ZFS
13 storage pool]]
11- [[https://ubuntu.com/tutorials/setup-zfs-storage-pool][Setup a ZFS storage pool]]
1412- [[https://wiki.ubuntu.com/Kernel/Reference/ZFS][Kernel/Reference/ZFS]]
15- [[https://blog.victormendonca.com/2020/11/03/zfs-for-dummies/][ZFS for
16 Dummies]]
13- [[https://blog.victormendonca.com/2020/11/03/zfs-for-dummies/][ZFS for Dummies]]
1714
1815* Installation
1916
@@ -23,8 +20,7 @@ To start, I installed the ZFS package with the following command:
2320sudo apt install zfsutils-linux
2421#+end_src
2522
26Once installed, you can check the version to see if it installed
27correctly.
23Once installed, you can check the version to see if it installed correctly.
2824
2925#+begin_src sh
3026> zsf --version
@@ -37,9 +33,9 @@ zfs-kmod-2.1.5-1ubuntu6~22.04.1
3733
3834Now that ZFS is installed, we can create and configure the pool.
3935
40You have various options for configuring ZFS pools that all come
41different pros and cons. I suggest visiting the links at the top of this
42post or searching online for the best configuration for your use-case.
36You have various options for configuring ZFS pools that all come different pros
37and cons. I suggest visiting the links at the top of this post or searching
38online for the best configuration for your use-case.
4339
4440- Striped VDEVs (Raid0)
4541- Mirrored VDEVs (Raid1)
@@ -49,20 +45,20 @@ post or searching online for the best configuration for your use-case.
4945- RAIDz3
5046- Nested RAIDz (Raid50, Raid60)
5147
52I will be using Raid10 in this guide. However, the majority of the steps
53are the same regardless of your chosen pool configuration.
48I will be using Raid10 in this guide. However, the majority of the steps are the
49same regardless of your chosen pool configuration.
5450
5551** Creating the Pool
5652
57To start, let's list the disks available to use. You can use =fdisk=
58command to see all available disks.
53To start, let's list the disks available to use. You can use =fdisk= command to
54see all available disks.
5955
6056#+begin_src sh
6157sudo fdisk -l
6258#+end_src
6359
64Or, if you currently have them mounted, you can use the =df= command to
65view your disks.
60Or, if you currently have them mounted, you can use the =df= command to view
61your disks.
6662
6763#+begin_src sh
6864> sudo df -h
@@ -77,17 +73,16 @@ Filesystem Size Used Avail Use% Mounted on
7773/dev/sdf1 7.3T 28K 6.9T 1% /mnt/red-04
7874#+end_src
7975
80If you're going to use mounted disks, make sure to umount them before
81creating the pool.
76If you're going to use mounted disks, make sure to umount them before creating
77the pool.
8278
8379#+begin_src sh
8480sudo umount /dev/sda1
8581sudo umount /dev/sdb1
8682#+end_src
8783
88Now that I've identified the disks I want to use and have them
89unmounted, let's create the pool. For this example, I will call it
90=tank=.
84Now that I've identified the disks I want to use and have them unmounted, let's
85create the pool. For this example, I will call it =tank=.
9186
9287#+begin_src sh
9388sudo zpool create -f -m /mnt/pool tank mirror /dev/sda /dev/sdb
@@ -119,8 +114,8 @@ config:
119114errors: No known data errors
120115#+end_src
121116
122We can also look at the mounted filesystem to see where the pool is
123mounted and some quick stats.
117We can also look at the mounted filesystem to see where the pool is mounted and
118some quick stats.
124119
125120#+begin_src sh
126121> df -h
@@ -132,28 +127,25 @@ tank 7.2T 128K 7.2T 1% /tank
132127
133128** Expanding the Pool
134129
135If you want to expand this pool, you will need to add a new VDEV to the
136pool. Since I am using 2 disks per VDEV, I will need to add a new 2-disk
137VDEV to the existing =tank= pool.
130If you want to expand this pool, you will need to add a new VDEV to the pool.
131Since I am using 2 disks per VDEV, I will need to add a new 2-disk VDEV to the
132existing =tank= pool.
138133
139134#+begin_src sh
140135sudo zpool add tank mirror /dev/sdX /dev/sdY
141136#+end_src
142137
143If you're adding disks of different sizes, you'll need to use the =-f=
144flag. Keep in mind that the max size will be limited to the smallest
145disk added.
138If you're adding disks of different sizes, you'll need to use the =-f= flag.
139Keep in mind that the max size will be limited to the smallest disk added.
146140
147141#+begin_src sh
148142sudo zpool add -f tank mirror /dev/sdX /dev/sdY
149143#+end_src
150144
151I added two 8TB hard drives and this process took around 10 seconds to
152complete.
145I added two 8TB hard drives and this process took around 10 seconds to complete.
153146
154When viewing the pool again, you can see that the pool has now doubled
155in size. We have 14.3 TB useable space and the same space used for
156mirroring.
147When viewing the pool again, you can see that the pool has now doubled in size.
148We have 14.3 TB useable space and the same space used for mirroring.
157149
158150#+begin_src sh
159151> zfs list
@@ -166,8 +158,8 @@ tank/media 96K 14.3T 96K /tank/media
166158
167159*** Converting Disks
168160
169Some disks, such as NTFS-formatted drives, will need to be partitioned
170and formatted prior to being added to the pool.
161Some disks, such as NTFS-formatted drives, will need to be partitioned and
162formatted prior to being added to the pool.
171163
172164Start by identifying the disks you want to format and add to the pool.
173165
@@ -178,8 +170,8 @@ sudo fdisk -l | grep /dev
178170I am going to format my =/dev/sdc= and =/dev/sdd= disks with the =fdisk=
179171command.
180172
181See below for instructions on how to use =fdisk=. Here's what I did to
182create basic Linux formatted disks:
173See below for instructions on how to use =fdisk=. Here's what I did to create
174basic Linux formatted disks:
183175
184176- =g= : Create GPT partition table
185177- =n= : Create a new partition, hit Enter for all default options
@@ -191,13 +183,12 @@ I repeated this process for both disks.
191183#+begin_src sh
192184> sudo fdisk /dev/sdc
193185
194Welcome to fdisk (util-linux 2.37.2).
195Changes will remain in memory only, until you decide to write them.
196Be careful before using the write command.
186Welcome to fdisk (util-linux 2.37.2). Changes will remain in memory only, until
187you decide to write them. Be careful before using the write command.
197188
198This disk is currently in use - repartitioning is probably a bad idea.
199It's recommended to umount all file systems, and swapoff all swap
200partitions on this disk.
189This disk is currently in use - repartitioning is probably a bad idea. It's
190recommended to umount all file systems, and swapoff all swap partitions on this
191disk.
201192
202193
203194Command (m for help): m
@@ -243,9 +234,9 @@ sudo zpool add tank mirror /dev/sdc /dev/sdd
243234#+end_src
244235
245236When we list the pool again, we can see that our size is now updated to
246approximately 22TB. This represents my hard drives totalling 45.6TB when
247shown with =fdisk -l=, with a Raid10 configuration using 22TB for
248mirroring and 22TB of useable space.
237approximately 22TB. This represents my hard drives totalling 45.6TB when shown
238with =fdisk -l=, with a Raid10 configuration using 22TB for mirroring and 22TB
239of useable space.
249240
250241#+begin_src sh
251242> zfs list
@@ -258,17 +249,15 @@ tank/media 145GT 21.7T 96K /tank/media
258249
259250** Creating Datasets
260251
261According to
262[[https://docs.oracle.com/cd/E18752_01/html/819-5461/ftyue.html][ZFS
263Terminology]], a =dataset= can refer to “clones, file systems,
252According to [[https://docs.oracle.com/cd/E18752_01/html/819-5461/ftyue.html][ZFS Terminology]], a =dataset= can refer to “clones, file systems,
264253snapshots, and volumes.
265254
266For this guide, I will use the =dataset= term to refer to file systems
267created under a pool.
255For this guide, I will use the =dataset= term to refer to file systems created
256under a pool.
268257
269Within my =tank= pool, I am going to create some datasets to help
270organize my files. This will give me location to store data rather than
271simply dumping everything at the =/tank/= location.
258Within my =tank= pool, I am going to create some datasets to help organize my
259files. This will give me location to store data rather than simply dumping
260everything at the =/tank/= location.
272261
273262#+begin_src sh
274263sudo zfs create tank/cloud
@@ -288,9 +277,9 @@ tank/media 96K 7.14T 96K /tank/media
288277
289278** Creating Snapshots
290279
291Next, let's create our first snapshot. We can do this by calling the
292=snapshot= command and give it an output name. I will be throwing the
293current date and time into my example.
280Next, let's create our first snapshot. We can do this by calling the =snapshot=
281command and give it an output name. I will be throwing the current date and time
282into my example.
294283
295284#+begin_src sh
296285sudo zfs snapshot tank@$(date '+%Y-%m-%d_%H-%M')
@@ -321,13 +310,10 @@ no datasets available
321310
322311* My Thoughts on ZFS So Far
323312
324- I sacrificed 25TB to be able to mirror my data, but I feel more
325 comfortable with the potential to save my data by quickly replacing a
326 disk if I need to.
313- I sacrificed 25TB to be able to mirror my data, but I feel more comfortable
314 with the potential to save my data by quickly replacing a disk if I need to.
327315- The set-up was surprisingly easy and fast.
328- Disk I/O is fast as well. I was worried that the data transfer speeds
329 would be slower due to the RAID configuration.
330- Media streaming and transcoding has seen no noticeable drop in
331 performance.
332- My only limitation really is the number of HDD bays in my server HDD
333 cage.
316- Disk I/O is fast as well. I was worried that the data transfer speeds would be
317 slower due to the RAID configuration.
318- Media streaming and transcoding has seen no noticeable drop in performance.
319- My only limitation really is the number of HDD bays in my server HDD cage.
content/blog/2024-02-13-ubuntu-emergency-mode.org +21 −22
@@ -5,12 +5,12 @@
55
66* The Problem
77
8I recently [[../zfs/][migrated my hard drives to a ZFS pool]] and found
9myself stuck in Ubuntu's emergency mode after the first reboot I
10performed after creating the ZFS pool.
8I recently [[../zfs/][migrated my hard drives to a ZFS pool]] and found myself stuck in
9Ubuntu's emergency mode after the first reboot I performed after creating the
10ZFS pool.
1111
12My server was stuck in the boot process and showed the following error
13on the screen:
12My server was stuck in the boot process and showed the following error on the
13screen:
1414
1515#+begin_src txt
1616You are in emergency mode.
@@ -19,34 +19,33 @@ After logging in, type "journalctl -xb" to view system logs,
1919or ^D to try again to boot into default mode".
2020#+end_src
2121
22After rebooting the server and watching the logs scroll on a monitor, I
23noticed the root cause was related to a very long search for certain
24drives. I kept seeing errors like this:
22After rebooting the server and watching the logs scroll on a monitor, I noticed
23the root cause was related to a very long search for certain drives. I kept
24seeing errors like this:
2525
2626#+begin_src txt
2727[ TIME ] Timed out waiting of device dev-disk-by/[disk-uuid]
2828#+end_src
2929
30I realized that I had not removed the =/etc/fstab= references that asked
31Ubuntu to mount two disks on boot, but I had recently changed those
32disks to be part of my ZFS pool instead. Therefore, Ubuntu was trying to
33identify and mount a disk that was not available.
30I realized that I had not removed the =/etc/fstab= references that asked Ubuntu
31to mount two disks on boot, but I had recently changed those disks to be part of
32my ZFS pool instead. Therefore, Ubuntu was trying to identify and mount a disk
33that was not available.
3434
3535Now that we have an idea of the issue, let's move to solution.
3636
3737* The Solution
3838
39In order to fix the issue, I waited until I was allowed to type the root
40user's password, and then I executed the following command:
39In order to fix the issue, I waited until I was allowed to type the root user's
40password, and then I executed the following command:
4141
4242#+begin_src sh
4343nano /etc/fstab
4444#+end_src
4545
46Within the =fstab= file, I needed to comment/remove the following lines
47at the bottom of the file. You can comment-out a line by prepending a
48=#= symbol at the beginning of the line. You can also delete the line
49entirely.
46Within the =fstab= file, I needed to comment/remove the following lines at the
47bottom of the file. You can comment-out a line by prepending a =#= symbol at the
48beginning of the line. You can also delete the line entirely.
5049
5150#+begin_src conf
5251# What it looked like when running into the issue:
@@ -58,8 +57,8 @@ UUID=E69867E59867B32B /mnt/white-02 ntfs-3g uid=1000,gid=1000 0 0
5857# UUID=E69867E59867B32B /mnt/white-02 ntfs-3g uid=1000,gid=1000 0 0
5958#+end_src
6059
61Once removing the lines above from the =/etc/fstab= file, save and exit
62the file by hitting the =Ctrl= + =x= key combo.
60Once removing the lines above from the =/etc/fstab= file, save and exit the file
61by hitting the =Ctrl= + =x= key combo.
6362
6463You can now hit =Ctrl= + =D= to continue, or reboot:
6564
@@ -67,5 +66,5 @@ You can now hit =Ctrl= + =D= to continue, or reboot:
6766systemctl reboot
6867#+end_src
6968
70Once rebooted, I was able to watch the machine boot properly and launch
71to the TTY login screen without errors!
69Once rebooted, I was able to watch the machine boot properly and launch to the
70TTY login screen without errors!
content/blog/2024-02-21-self-hosting-otter-wiki.org +17 −20
@@ -5,14 +5,14 @@
55
66* An Otter Wiki
77
8[[https://otterwiki.com/][An Otter Wiki]] is an easy to use wiki
9software that takes almost no effort to set up and maintain.
8[[https://otterwiki.com/][An Otter Wiki]] is an easy to use wiki software that takes almost no effort to set
9up and maintain.
1010
1111* Installation
1212
1313To install An Otter Wiki, I'm going to use Docker Compose to create the
14container and then use Nginx as a reverse proxy to allow external access
15via a subdomain I own.
14container and then use Nginx as a reverse proxy to allow external access via a
15subdomain I own.
1616
1717** Docker Compose
1818
@@ -22,16 +22,14 @@ Start by creating a directory for the container's files.
2222mkdir ~/otterwiki
2323#+end_src
2424
25Next, create the =docker-compose.yml= file to define the container's
26parameters.
25Next, create the =docker-compose.yml= file to define the container's parameters.
2726
2827#+begin_src sh
2928nano ~/otterwiki/docker-compose.yml
3029#+end_src
3130
3231Within the file, paste the following content. You can read the project's
33documentation if you want to further override or customize the
34container.
32documentation if you want to further override or customize the container.
3533
3634#+begin_src conf
3735version: '3'
@@ -54,22 +52,22 @@ cd ~/otterwiki
5452sudo docker-compose up -d
5553#+end_src
5654
57The container is now available at =localhost:8337=. Next, we will use
58Nginx to serve this app externally.
55The container is now available at =localhost:8337=. Next, we will use Nginx to
56serve this app externally.
5957
6058** Nginx
6159
62To access the app externally, let's set up a reverse proxy. I'll start
63by creating the Nginx configuration file for my wiki.
60To access the app externally, let's set up a reverse proxy. I'll start by
61creating the Nginx configuration file for my wiki.
6462
6563#+begin_src sh
6664sudo nano /etc/nginx/sites-available/wiki
6765#+end_src
6866
69Within the file, I have saved the following content. This assumes you
70already have a TLS/SSL cert to use with this subdomain. If not, simply
71remove the =ssl_*= variables, remove the =80= server block, and change
72the =443= server block to =80= to serve the app without SSL.
67Within the file, I have saved the following content. This assumes you already
68have a TLS/SSL cert to use with this subdomain. If not, simply remove the
69=ssl_*= variables, remove the =80= server block, and change the =443= server
70block to =80= to serve the app without SSL.
7371
7472#+begin_src conf
7573server {
@@ -107,15 +105,14 @@ server {
107105}
108106#+end_src
109107
110Save and close the configuration file. On Nginx, we need to symlink the
111file to enable it.
108Save and close the configuration file. On Nginx, we need to symlink the file to
109enable it.
112110
113111#+begin_src sh
114112sudo ln -s /etc/nginx/sites-available/wiki /etc/nginx/sites-enabled/wiki
115113#+end_src
116114
117Once enabled, restart the Nginx server to start serving the app
118externally.
115Once enabled, restart the Nginx server to start serving the app externally.
119116
120117#+begin_src sh
121118sudo systemctl restart nginx.service
content/blog/2024-03-13-doom-emacs.org +92 −113
@@ -5,9 +5,9 @@
55
66** Screenshots
77
8These screenshots are showing a project opened with projectile, a
9treemacs side pane open with the project contents, multiple buffers
10tiled next to each other, and the help pane open at the bottomm.
8These screenshots are showing a project opened with projectile, a treemacs side
9pane open with the project contents, multiple buffers tiled next to each other,
10and the help pane open at the bottomm.
1111
1212The themes are =doom-homage-white= and =doom-homage-black=.
1313
@@ -19,44 +19,35 @@ The themes are =doom-homage-white= and =doom-homage-black=.
1919
2020** Getting Started
2121
22I have been switching back and forth between
23[[https://en.wikipedia.org/wiki/Markdown][markdown]] and
24[[https://en.wikipedia.org/wiki/Org-mode][org-mode]] recently for my
25personal note taking, wiki, and even this blog. As a result, I have been
26stumbling further into the world of Emacs and found myself at a point
27where I now prefer to do most of my basic editing within Emacs.
22I have been switching back and forth between [[https://en.wikipedia.org/wiki/Markdown][markdown]] and [[https://en.wikipedia.org/wiki/Org-mode][org-mode]] recently for
23my personal note taking, wiki, and even this blog. As a result, I have been
24stumbling further into the world of Emacs and found myself at a point where I
25now prefer to do most of my basic editing within Emacs.
2826
2927I'll leave the markdown vs. org-mode debate for another post, but I love
30org-mode's extensibility and interactive nature within Emacs, but it
31becomes very unwieldy in any other client implementation of org-mode -
32especially on iOS. On the flip side, markdown is limited in
33functionality and fractured into different standards, but it's simple
34and popular enough that there are a plethora of great clients to choose
35from that will get the job done.
28org-mode's extensibility and interactive nature within Emacs, but it becomes
29very unwieldy in any other client implementation of org-mode - especially on
30iOS. On the flip side, markdown is limited in functionality and fractured into
31different standards, but it's simple and popular enough that there are a
32plethora of great clients to choose from that will get the job done.
3633
37For now, I want to focus on how I have been using Emacs and some of the
38things that would have helped me learn it faster had I known where to
39start.
34For now, I want to focus on how I have been using Emacs and some of the things
35that would have helped me learn it faster had I known where to start.
4036
4137*** Installation
4238
43This post focuses on [[https://github.com/doomemacs/doomemacs][Doom
44Emacs]], which is an Emacs framework that provides an alternative
45experience to the vanilla [[https://www.gnu.org/software/emacs/][GNU
46Emacs]].
39This post focuses on [[https://github.com/doomemacs/doomemacs][Doom Emacs]], which is an Emacs framework that provides an
40alternative experience to the vanilla [[https://www.gnu.org/software/emacs/][GNU Emacs]].
4741
48The
49[[https://github.com/doomemacs/doomemacs/blob/master/docs/getting_started.org][Getting
50Start Guide]] has an extremely detailed walkthrough of installation for
51all systems, so please refer to that guide for up-to-date instructions.
42The [[https://github.com/doomemacs/doomemacs/blob/master/docs/getting_started.org][Getting Start Guide]] has an extremely detailed walkthrough of installation
43for all systems, so please refer to that guide for up-to-date instructions.
5244
5345I chose to install on macOS, using the Homebrew option with the
5446=railwaycat/emacsmacport= version of Emacs.
5547
56Once the program is installed, you can run the program by typing =emacs=
57in a terminal. If you installed a version of Emacs that supports both a
58GUI and TUI, you will have to run =emacs -nw= to get the TUI instead of
59the default GUI.
48Once the program is installed, you can run the program by typing =emacs= in a
49terminal. If you installed a version of Emacs that supports both a GUI and TUI,
50you will have to run =emacs -nw= to get the TUI instead of the default GUI.
6051
6152*** Configuration
6253
@@ -65,13 +56,12 @@ Once installed, you can configure Doom by editing the files within the
6556
66571. =config.el= - Personal configuration file
67582. =custom.el= - Custom set variables
683. =init.el= - Doom modules and load order, must run =doom sync= after
69 modifying
704. =packages.el= - Declare packages to install in this file, then run
71 =doom sync= to install
593. =init.el= - Doom modules and load order, must run =doom sync= after modifying
604. =packages.el= - Declare packages to install in this file, then run =doom
61 sync= to install
7262
73I only needed a few customizations for my configuration, so I'll list
74them below.
63I only needed a few customizations for my configuration, so I'll list them
64below.
7565
7666#+begin_src lisp
7767;; ~/.doom.d/config.el
@@ -145,30 +135,28 @@ them below.
145135 (default +bindings +smartparens))
146136#+end_src
147137
148If you're editing these files within Doom directly, remember to run
149=SPC h r r= to reload the configuration. Also remember to run
150=doom sync= for any changes to the =init.el= or =packages.el= files.
138If you're editing these files within Doom directly, remember to run =SPC h r r=
139to reload the configuration. Also remember to run =doom sync= for any changes to
140the =init.el= or =packages.el= files.
151141
152142** Basic Functionality
153143
154I kept a cheat sheet note open at first with all of the basic functions
155typed out, copied as I went through the tutorial. After a little while,
156I no longer needed it. I highly recommend writing down the most
157applicable shortcuts for your preferred functionality and refer back to
158it until you've memorized it.
159
160Memorizing the shortcuts will differ based on the type of Emacs
161framework being used. Personally, migrating from vanilla Emacs to Doom
162Emacs simplified everything by a large factor and instantly enabled me
163to start working on my projects, eliminating most of the hurdles I was
164running into. The vanilla emacs hotkeys became obnoxious and I actually
165stopped using Emacs entirely for about a month before trying Doom.
166
167For me, the first logical step is to interact with the local filesystem.
168To do this, I needed to know how to open directories, open files, save
169files, discard changes, close files, and switch between open files. Here
170are some example shortcuts I've written down in order to accomplish
171file-based actions.
144I kept a cheat sheet note open at first with all of the basic functions typed
145out, copied as I went through the tutorial. After a little while, I no longer
146needed it. I highly recommend writing down the most applicable shortcuts for
147your preferred functionality and refer back to it until you've memorized it.
148
149Memorizing the shortcuts will differ based on the type of Emacs framework being
150used. Personally, migrating from vanilla Emacs to Doom Emacs simplified
151everything by a large factor and instantly enabled me to start working on my
152projects, eliminating most of the hurdles I was running into. The vanilla emacs
153hotkeys became obnoxious and I actually stopped using Emacs entirely for about a
154month before trying Doom.
155
156For me, the first logical step is to interact with the local filesystem. To do
157this, I needed to know how to open directories, open files, save files, discard
158changes, close files, and switch between open files. Here are some example
159shortcuts I've written down in order to accomplish file-based actions.
172160
173161| Doom Hotkey | Emacs Hotkey | Description |
174162|-----------------+---------------+----------------------------------------|
@@ -181,30 +169,28 @@ file-based actions.
181169| =SPC b k= | =C-x k= | Kill current buffer |
182170| =SPC w h/j/k/l= | =C-x o=[fn:2] | Move left/down/up/right to next buffer |
183171
184In general, when in Doom, you can press =SPC= and wait a second for the
185help pane to appear with all available hotkey options. For example, you
186can press =SPC=, wait for the help pane, and then select a key such as
187=g= to enter the git help pane and explore further command options.
172In general, when in Doom, you can press =SPC= and wait a second for the help
173pane to appear with all available hotkey options. For example, you can press
174=SPC=, wait for the help pane, and then select a key such as =g= to enter the
175git help pane and explore further command options.
188176
189177** Editing
190178
191Next in my process is to dive into editing for any languages I'm
192currently using. In this post, I will just cover Markdown and Org-Mode
193but I have also been slowly adoping some Python and general web dev
194tools as well.
179Next in my process is to dive into editing for any languages I'm currently
180using. In this post, I will just cover Markdown and Org-Mode but I have also
181been slowly adoping some Python and general web dev tools as well.
195182
196183*** Markdown
197184
198185#+caption: Markdown Preview
199186[[https://img.cleberg.net/blog/20240314-doom-emacs/markdown.png]]
200187
201Markdown is fairly simple as the syntax is limited, so just make sure
202the =~/.doom.d/init.el= includes the =markdown= declaration in the
203=:lang= section.
188Markdown is fairly simple as the syntax is limited, so just make sure the
189=~/.doom.d/init.el= includes the =markdown= declaration in the =:lang= section.
204190
205This package includes the following hotkey menus. The insert and toggle
206menu expands further, allowing you to insert various markdown elements
207and toggle things like link hiding.
191This package includes the following hotkey menus. The insert and toggle menu
192expands further, allowing you to insert various markdown elements and toggle
193things like link hiding.
208194
209195| Doom Hotkey | Function |
210196|------------------------------+--------------------------|
@@ -221,14 +207,12 @@ and toggle things like link hiding.
221207#+caption: Org-Mode Preview
222208[[https://img.cleberg.net/blog/20240314-doom-emacs/org.png]]
223209
224Similar to the markdown section above, ensure that the
225=~/.doom.d/init.el= includes the =org= declaration in the =:lang=
226section.
210Similar to the markdown section above, ensure that the =~/.doom.d/init.el=
211includes the =org= declaration in the =:lang= section.
227212
228There are a few hot keys, but a quick search with =SPC : org= shows that
229there are 865 possible org-related functions you can run. I won't
230possibly be able to list them all, so I will simply cover a few of the
231basic commands I use myself.
213There are a few hot keys, but a quick search with =SPC : org= shows that there
214are 865 possible org-related functions you can run. I won't possibly be able to
215list them all, so I will simply cover a few of the basic commands I use myself.
232216
233217| Doom Hotkey | Function |
234218|----------------+---------------------------------------|
@@ -246,32 +230,28 @@ basic commands I use myself.
246230
2472311. Org-Publish
248232
249 Org includes a
250 [[https://orgmode.org/manual/Publishing.html][publishing management
251 system]] by default that allows you to export org files to Org,
252 iCalendar, HTML, LaTex, Markdown, ODT, and Plain Text. Most of these
253 can be exported into another buffer and opened, or simply to an
254 external file.
233 Org includes a [[https://orgmode.org/manual/Publishing.html][publishing management system]] by default that allows you to
234 export org files to Org, iCalendar, HTML, LaTex, Markdown, ODT, and Plain
235 Text. Most of these can be exported into another buffer and opened, or simply
236 to an external file.
255237
256 While inside an org file, simply run =SPC m e= or
257 =M-x org-export-dispatch= to open the export menu. This menu will
258 show all options and ask you to select an option. If you want to
259 export to HTML, simply press =h= and then =H= (As HTML buffer), =h=
260 (As HTML file), or =o= (As HTML file and open).
238 While inside an org file, simply run =SPC m e= or =M-x org-export-dispatch=
239 to open the export menu. This menu will show all options and ask you to
240 select an option. If you want to export to HTML, simply press =h= and then
241 =H= (As HTML buffer), =h= (As HTML file), or =o= (As HTML file and open).
261242
2622432. Projects
263244
264 Some publishing options are easier with a defined project in Emacs.
265 To create a project within Emacs, I use two methods:
245 Some publishing options are easier with a defined project in Emacs. To create
246 a project within Emacs, I use two methods:
266247
267 1. Add the project via the projectile command =SPC p a=. Does not
268 always work for me.
248 1. Add the project via the projectile command =SPC p a=. Does not always work
249 for me.
269250 2. Add an empty =.projectile= file in the project root.
270251
271 Once a project has been created, you can create custom publishing
272 actions within your =~/.doom.d/config.el= file. For example, here's a
273 test project I created to try and convert this blog to org-mode
274 recently.
252 Once a project has been created, you can create custom publishing actions
253 within your =~/.doom.d/config.el= file. For example, here's a test project I
254 created to try and convert this blog to org-mode recently.
275255
276256 #+begin_src lisp
277257 ;; org-publish
@@ -342,19 +322,18 @@ basic commands I use myself.
342322
343323** General Thoughts
344324
345I have enjoyed Doom Emacs (far more than GNU Emacs) and will likely
346continue to use it as my main editor for the time being. Org-Mode is
347certainly the largest factor here, as I far prefer it over Markdown due
348to its inherent features and detailed markup options. However, working
349with org-mode on iOS has been a pain and I will have to see if there's
350an easier way to resolve those issues or if going back to separate
351Markdown, Reminders, and Calendar apps is easier to work with than an
352all-in-one org solution.
353
354[fn:1] Doom's evil-window functionality is a bit different from GNU
355 Emacs, but you can always switch to the "other" buffer with
356 =C-x o= or =C-x b= to get a list of buffers to select.
357
358[fn:2] Doom's evil-window functionality is a bit different from GNU
359 Emacs, but you can always switch to the "other" buffer with
360 =C-x o= or =C-x b= to get a list of buffers to select.
325I have enjoyed Doom Emacs (far more than GNU Emacs) and will likely continue to
326use it as my main editor for the time being. Org-Mode is certainly the largest
327factor here, as I far prefer it over Markdown due to its inherent features and
328detailed markup options. However, working with org-mode on iOS has been a pain
329and I will have to see if there's an easier way to resolve those issues or if
330going back to separate Markdown, Reminders, and Calendar apps is easier to work
331with than an all-in-one org solution.
332
333[fn:1] Doom's evil-window functionality is a bit different from GNU Emacs, but
334 you can always switch to the "other" buffer with =C-x o= or =C-x b= to
335 get a list of buffers to select.
336
337[fn:2] Doom's evil-window functionality is a bit different from GNU Emacs, but
338 you can always switch to the "other" buffer with =C-x o= or =C-x b= to
339 get a list of buffers to select.
content/blog/2024-03-15-self-hosting-ddns-updater.org +41 −52
@@ -6,25 +6,21 @@
66#+caption: DDNS Updater Web View
77[[https://img.cleberg.net/blog/20240315-ddns-updater/ddns.png]]
88
9[[https://github.com/qdm12/ddns-updater][DDNS Updater]] is a program to
10keep DNS A and/or AAAA records updated for multiple DNS providers.
9[[https://github.com/qdm12/ddns-updater][DDNS Updater]] is a program to keep DNS A and/or AAAA records updated for multiple
10DNS providers.
1111
12If you've read any of my other posts, you'll notice that I have been
13searching for and using a few different DDNS updating solutions for
14years. You'll also notice that I love any projects that offer a Docker
15Compose solution.
12If you've read any of my other posts, you'll notice that I have been searching
13for and using a few different DDNS updating solutions for years. You'll also
14notice that I love any projects that offer a Docker Compose solution.
1615
1716Luckily, DDNS Upater fits both of these preferences.
1817
1918** Installation
2019
21To get started, always make sure to review the project's
22[[https://github.com/qdm12/ddns-updater/blob/master/README.md][README]].
23I'll be documenting my steps below, but they may have changed by the
24time you read this.
20To get started, always make sure to review the project's [[https://github.com/qdm12/ddns-updater/blob/master/README.md][README]]. I'll be
21documenting my steps below, but they may have changed by the time you read this.
2522
26The first step is to set up the directories and files required for the
27project.
23The first step is to set up the directories and files required for the project.
2824
2925#+begin_src sh
3026mkdir ~/ddns-updater
@@ -34,43 +30,36 @@ touch ~/ddns-updater/data/config.json
3430
3531*** Configuration
3632
37The main configuration you need to update is the =data/config.json=
38file. There is a large list of supported providers in the README, but
39I'm going to use Cloudflare in this example.
33The main configuration you need to update is the =data/config.json= file. There
34is a large list of supported providers in the README, but I'm going to use
35Cloudflare in this example.
4036
4137#+begin_src sh
4238nano ~/ddns-updater/data/config.json
4339#+end_src
4440
45When setting up the configuration for Cloudflare, you'll need the
46following:
41When setting up the configuration for Cloudflare, you'll need the following:
4742
4843- Required Parameters
49 - ="zone_identifier"= is the Zone ID of your site from the domain
50 overview page
51 - ="host"= is your host and can be ="@"=, a subdomain or the wildcard
52 ="*"=. See
53 [[https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949][this
54 issue comment for context]].
55 - ="ttl"= integer value for record TTL in seconds (specify 1 for
56 automatic)
57 - One of the following
58 ([[https://developers.cloudflare.com/fundamentals/api/get-started/][how
59 to find API keys]]):
44 - ="zone_identifier"= is the Zone ID of your site from the domain overview
45 page
46 - ="host"= is your host and can be ="@"=, a subdomain or the wildcard ="*"=.
47 See [[https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949][this issue comment for context]].
48 - ="ttl"= integer value for record TTL in seconds (specify 1 for automatic)
49 - One of the following ([[https://developers.cloudflare.com/fundamentals/api/get-started/][how to find API keys]]):
6050 - Email ="email"= and Global API Key ="key"=
6151 - User service key ="user_service_key"=
62 - API Token ="token"=, configured with DNS edit permissions for your
63 DNS name's zone
52 - API Token ="token"=, configured with DNS edit permissions for your DNS
53 name's zone
6454- Optional Parameters
65 - ="proxied"= can be set to =true= to use the proxy services of
66 Cloudflare
67 - ="ip_version"= can be =ipv4= (A records), or =ipv6= (AAAA records)
68 or =ipv4 or ipv6= (update one of the two, depending on the public
69 ip found). It defaults to =ipv4 or ipv6=.
70 - ="ipv6_suffix"= is the IPv6 interface identifier suffix to use. It
71 can be for example =0:0:0:0:72ad:8fbb:a54e:bedd/64=. If left empty,
72 it defaults to no suffix and the raw public IPv6 address obtained is
73 used in the record updating.
55 - ="proxied"= can be set to =true= to use the proxy services of Cloudflare
56 - ="ip_version"= can be =ipv4= (A records), or =ipv6= (AAAA records) or =ipv4
57 or ipv6= (update one of the two, depending on the public ip found). It
58 defaults to =ipv4 or ipv6=.
59 - ="ipv6_suffix"= is the IPv6 interface identifier suffix to use. It can be
60 for example =0:0:0:0:72ad:8fbb:a54e:bedd/64=. If left empty, it defaults to
61 no suffix and the raw public IPv6 address obtained is used in the record
62 updating.
7463
7564#+begin_src conf
7665{
@@ -90,8 +79,8 @@ following:
9079}
9180#+end_src
9281
93Once you have configured the provider of your choice, correct the file
94and directory permissions and ownership.
82Once you have configured the provider of your choice, correct the file and
83directory permissions and ownership.
9584
9685#+begin_src sh
9786cd ~/ddns_updater
@@ -105,8 +94,8 @@ chmod 400 data/config.json
10594
10695*** Docker Compose
10796
108After creating the project structure, let's create the
109=docker-compose.yml= file.
97After creating the project structure, let's create the =docker-compose.yml=
98file.
11099
111100#+begin_src sh
112101nano ~/ddns_-pdater/docker-compose.yml
@@ -150,22 +139,22 @@ services:
150139 restart: always
151140#+end_src
152141
153After configuring your preferences in the =docker-compose.yml=, launch
154the container.
142After configuring your preferences in the =docker-compose.yml=, launch the
143container.
155144
156145#+begin_src sh
157146cd ~/ddns-updater
158147sudo docker-compose up -d
159148#+end_src
160149
161If you've launched this on your local machine, you can launch
162=localhost:8097= in your browser to see the results.
150If you've launched this on your local machine, you can launch =localhost:8097=
151in your browser to see the results.
163152
164153*** Nginx Reverse Proxy
165154
166If you launched this service on a server, other machine, or just want to
167access it remotely via a domain name, you can use Nginx as a reverse
168proxy to expose the service publicly.
155If you launched this service on a server, other machine, or just want to access
156it remotely via a domain name, you can use Nginx as a reverse proxy to expose
157the service publicly.
169158
170159Start by creating the Nginx configuration file.
171160
@@ -193,8 +182,8 @@ server {
193182}
194183#+end_src
195184
196Here's a full example that uses my Authelia authentication service to
197require authentication before someone can access the web page.
185Here's a full example that uses my Authelia authentication service to require
186authentication before someone can access the web page.
198187
199188#+begin_src conf
200189server {
content/blog/2024-03-29-org-blog.org +56 −67
@@ -3,48 +3,41 @@
33#+description:
44#+slug: org-blog
55
6First and foremost, apologies to those who subscribe via RSS as I know
7that my feed duplicated itself when I moved this blog over to org-mode
8last night.
6First and foremost, apologies to those who subscribe via RSS as I know that my
7feed duplicated itself when I moved this blog over to org-mode last night.
98
10This post focuses specifically on the configuration and tools I use to
11blog from Emacs with Org-Mode and does not focus on Emacs or Org-Mode
12themselves. Refer to the post I wrote about
13[[https://cleberg.net/blog/doom-emacs-org-mode.html][Doom Emacs & Org-Mode]] for
14more information about my base Emacs configuration.
9This post focuses specifically on the configuration and tools I use to blog from
10Emacs with Org-Mode and does not focus on Emacs or Org-Mode themselves. Refer to
11the post I wrote about [[https://cleberg.net/blog/doom-emacs-org-mode.html][Doom Emacs & Org-Mode]] for more information about my base
12Emacs configuration.
1513
1614* Weblorg
1715
18The first step in blogging with Org-Mode is to choose a method to
19convert the source files to HTML and publish them. The Worg site
20maintains a nice list of
21[[https://orgmode.org/worg/org-blog-wiki.html][Blogs and Wikis with
22Org]], but the tools are inevitably different and opinionated, so you'll
23need to find what works for you.
24
25I tried using Jekyll, Hugo, ox-hugo, Nikola, Blorg, org-static-blog, and
26the native org-publish functions before finally settling on Weblorg. For
27one reason or another, the other solutions were a drastic step down from
28my previous workflow that used [[https://www.getzola.org/][Zola]] with
29Markdown content.
30
31[[https://github.com/emacs-love/weblorg][Weblorg]] is a static site
32generator for [[https://orgmode.org/][org-mode]], built for use within
33[[https://www.gnu.org/software/emacs/][Emacs]]. Since it's written in
34Emacs Lisp, there's no need to install other languages or frameworks to
35get started. More than that, you can write in any editor you please and
36simply invoke the Emacs build process with the =--script= parameter
16The first step in blogging with Org-Mode is to choose a method to convert the
17source files to HTML and publish them. The Worg site maintains a nice list of
18[[https://orgmode.org/worg/org-blog-wiki.html][Blogs and Wikis with Org]], but the tools are inevitably different and
19opinionated, so you'll need to find what works for you.
20
21I tried using Jekyll, Hugo, ox-hugo, Nikola, Blorg, org-static-blog, and the
22native org-publish functions before finally settling on Weblorg. For one reason
23or another, the other solutions were a drastic step down from my previous
24workflow that used [[https://www.getzola.org/][Zola]] with Markdown content.
25
26[[https://github.com/emacs-love/weblorg][Weblorg]] is a static site generator for [[https://orgmode.org/][org-mode]], built for use within [[https://www.gnu.org/software/emacs/][Emacs]].
27Since it's written in Emacs Lisp, there's no need to install other languages or
28frameworks to get started. More than that, you can write in any editor you
29please and simply invoke the Emacs build process with the =--script= parameter
3730instead of requiring you to blog inside Emacs.
3831
3932** Installation
4033
41The [[https://emacs.love/weblorg/doc/index.html][Getting Started]] page
42details broad installation requirements. I am using Doom Emacs on macOS,
43which requires you to add the package to the =~/.doom.d/packages.el=
44file and configure the =publish.el= file slightly differently.
34The [[https://emacs.love/weblorg/doc/index.html][Getting Started]] page details broad installation requirements. I am using
35Doom Emacs on macOS, which requires you to add the package to the
36=~/.doom.d/packages.el= file and configure the =publish.el= file slightly
37differently.
4538
46To start, add the =htmlize= and =weblorg= packages to Doom, sync the
47changes, and reload.
39To start, add the =htmlize= and =weblorg= packages to Doom, sync the changes,
40and reload.
4841
4942#+begin_src sh
5043nano ~/.doom.d/packages.el
@@ -63,18 +56,17 @@ Either re-open Emacs or hit =SPC h r r= to reload the changes.
6356
6457** Configuration
6558
66Now that I've installed weblorg, I need to configure the project. I'll
67start by navigating to my site's source code and creating a =publish.el=
68file.
59Now that I've installed weblorg, I need to configure the project. I'll start by
60navigating to my site's source code and creating a =publish.el= file.
6961
7062#+begin_src sh
7163cd ~/Source/cleberg.net && nano publish.el
7264#+end_src
7365
74Since I'm using Doom, Emacs will not automatically load the packages I
75need later in the build process. To compensate, my =publish.el= file
76needs to explicitly tell Emacs where Doom stores the =htmlize=,
77=weblorg=, and =templatel= packages.
66Since I'm using Doom, Emacs will not automatically load the packages I need
67later in the build process. To compensate, my =publish.el= file needs to
68explicitly tell Emacs where Doom stores the =htmlize=, =weblorg=, and
69=templatel= packages.
7870
7971#+begin_src lisp
8072;; explicity load packages since I'm using Doom Emacs
@@ -184,12 +176,10 @@ needs to explicitly tell Emacs where Doom stores the =htmlize=,
184176** Structure
185177
186178The project structure for weblorg is highly customizable and the main
187restriction is that the =publish.el= file must point to the correct
188paths.
179restriction is that the =publish.el= file must point to the correct paths.
189180
190For my blog, I prefer to keep the blog content out of the top-level
191directory. This results in the following structure (shortened for
192brevity):
181For my blog, I prefer to keep the blog content out of the top-level directory.
182This results in the following structure (shortened for brevity):
193183
194184#+begin_src txt
195185.build/
@@ -217,17 +207,17 @@ build.sh
217207publish.el
218208#+end_src
219209
220This is simply my preferred structure and you can alter it to fit your
221needs. The key here really is that you can customize at will, as long as
222the =publish.el= file matches.
210This is simply my preferred structure and you can alter it to fit your needs.
211The key here really is that you can customize at will, as long as the
212=publish.el= file matches.
223213
224214** Build & Deploy
225215
226Once you're content with the status of the project, you're ready to
227build and deploy the blog.
216Once you're content with the status of the project, you're ready to build and
217deploy the blog.
228218
229My process utilizes a =build.sh= script that combines the steps I take
230every time.
219My process utilizes a =build.sh= script that combines the steps I take every
220time.
231221
232222#+begin_src sh
233223touch build.sh && chmod +x build.sh && nano build.sh
@@ -235,16 +225,16 @@ touch build.sh && chmod +x build.sh && nano build.sh
235225
236226Within this script, I do the following:
237227
2381. Remove any files within the =.build= directory that I use to store
239 published files.
2402. Set the environment variable to =prod= to ensure the =base_url=
241 matches my configuration in =publish.el=.
2281. Remove any files within the =.build= directory that I use to store published
229 files.
2302. Set the environment variable to =prod= to ensure the =base_url= matches my
231 configuration in =publish.el=.
2422323. Build the site with Emacs & =publish.el=.
2432334. Use =scp= to copy files to my site's public directory on my server.
244234
245235#+begin_src sh
246rm -rf .build/* && \
247ENV=prod emacs --script publish.el && \
236rm -rf .build/* && \
237ENV=prod emacs--script publish.el && \
248238scp -r .build/* ubuntu:/var/www/cleberg.net/
249239#+end_src
250240
@@ -252,13 +242,12 @@ scp -r .build/* ubuntu:/var/www/cleberg.net/
252242
253243My only current complaints are:
254244
2551. Errors messages are not helpful. It takes work to determine what the
256 error is and where it's coming from. I generally have to sit and
257 watch the build process to see the file that weblorg pubslishes right
258 before the error occurred.
2592. The build process re-builds every single file on each run, which
260 takes a long time for a blog of my size. See below for the last time
261 I measured.
2451. Errors messages are not helpful. It takes work to determine what the error is
246 and where it's coming from. I generally have to sit and watch the build
247 process to see the file that weblorg pubslishes right before the error
248 occurred.
2492. The build process re-builds every single file on each run, which takes a long
250 time for a blog of my size. See below for the last time I measured.
262251
263252#+begin_src sh
264253> time ./build.sh
@@ -266,5 +255,5 @@ My only current complaints are:
266255./build.sh 35.46s user 0.59s system 85% cpu 41.965 total
267256#+end_src
268257
269Overall, I have thoroughly enjoyed using weblog and will continue to use
270it going forward until I find something better.
258Overall, I have thoroughly enjoyed using weblog and will continue to use it
259going forward until I find something better.
content/blog/2024-04-06-convert-onenote-to-markdown.org +41 −47
@@ -3,54 +3,49 @@
33#+description:
44#+slug: convert-onenote-to-markdown
55
6If you're looking to convert your OneNote content to another format,
7such as Markdown or Org-Mode, you're in luck. I use a solution that
8doesn't require other programs, such as Evernote or Notion. Personally,
9I used this solution on a managed corporate laptop that doesn't allow
10installation of other programs like these.
6If you're looking to convert your OneNote content to another format, such as
7Markdown or Org-Mode, you're in luck. I use a solution that doesn't require
8other programs, such as Evernote or Notion. Personally, I used this solution on
9a managed corporate laptop that doesn't allow installation of other programs
10like these.
1111
1212This solution uses OneNote and Pandoc on Windows 10.
1313
1414* Export OneNote Content to Word
1515
16To start, export any pages or tabs from OneNote to the Word format
17(=.docx=):
16To start, export any pages or tabs from OneNote to the Word format (=.docx=):
1817
19181. Open OneNote desktop.
20192. Select =File= and then =Export=.
21203. Select the scope of content to export, such as =Tab= or =Page=.
224. Name and save the file in an easy to remember location. I recommend
23 your Downloads or Desktop folder.
214. Name and save the file in an easy to remember location. I recommend your
22 Downloads or Desktop folder.
2423
2524See below for a visual walkthrough of the export process.
2625
2726* Download Pandoc
2827
29Start by downloading Pandoc from their
30[[https://github.com/jgm/pandoc/releases][GitHub releases]] page. I
31cannot install =.msi= files on my corporate laptop, so I downloaded the
32=pandoc-3.1.12.3-windows-x86_64.zip= file, which contains a simple
33=.exe= file that you do not need to install - you will simply run it
34from the command line below.
28Start by downloading Pandoc from their [[https://github.com/jgm/pandoc/releases][GitHub releases]] page. I cannot install
29=.msi= files on my corporate laptop, so I downloaded the
30=pandoc-3.1.12.3-windows-x86_64.zip= file, which contains a simple =.exe= file
31that you do not need to install - you will simply run it from the command line
32below.
3533
36Once downloaded, unzip the archive and move the =pandoc.exe= file to the
37same folder where your Word documents were saved above. If you prefer,
38you can move this file to an easier location, such as
39=C:\Users\youruser\Downloads=.
34Once downloaded, unzip the archive and move the =pandoc.exe= file to the same
35folder where your Word documents were saved above. If you prefer, you can move
36this file to an easier location, such as =C:\Users\youruser\Downloads=.
4037
4138* Convert Word to Markdown
4239
43In this example, I will be converting the Word documents to Markdown,
44but Pandoc supports
45[[https://github.com/jgm/pandoc?tab=readme-ov-file#the-universal-markup-converter][a
46ton of different formats for conversion]]. Choose the format you prefer
40In this example, I will be converting the Word documents to Markdown, but Pandoc
41supports [[https://github.com/jgm/pandoc?tab=readme-ov-file#the-universal-markup-converter][a ton of different formats for conversion]]. Choose the format you prefer
4742and then modify the following commands as needed.
4843
49To perform the conversion, open the Command Prompt. If you can't find
50it, open the start menu and search for it.
44To perform the conversion, open the Command Prompt. If you can't find it, open
45the start menu and search for it.
5146
52Within the command prompt, navigate to the directory where you stored
53the =pandoc.exe= file and the Word documents.
47Within the command prompt, navigate to the directory where you stored the
48=pandoc.exe= file and the Word documents.
5449
5550#+begin_src ps1
5651cd "C:\Users\yourusername\Downloads"
@@ -63,9 +58,9 @@ command.
6358dir
6459#+end_src
6560
66Once you have verified that you have the command prompt open in the
67correct directory with the =pandoc.exe= and the Word documents, you can
68run the following loop to convert all Word documents to Markdown.
61Once you have verified that you have the command prompt open in the correct
62directory with the =pandoc.exe= and the Word documents, you can run the
63following loop to convert all Word documents to Markdown.
6964
7065#+begin_src ps1
7166for %f in (*.docx) do (pandoc.exe --extract-media=. --wrap=preserve "%f" -o "%f.md")
@@ -73,25 +68,24 @@ for %f in (*.docx) do (pandoc.exe --extract-media=. --wrap=preserve "%f" -o "%f.
7368
7469This loop will perform the following actions:
7570
761. Find all documents matching the pattern =*.docx=, which means all
77 Word documents ending with that file extension.
711. Find all documents matching the pattern =*.docx=, which means all Word
72 documents ending with that file extension.
78732. Iterate through all files found in step 1.
79743. For each file, perform the pandoc command.
804. Within the pandoc command, =--extract-media= saves all media found in
81 the files to the current folder, with pandoc automatically creating a
82 =media= subfolder to hold all images.
835. Within the pandoc command, =--wrap=preserve= will attempt to prseerve
84 the wrapping from the source document.
856. Within the pandoc command, the final step is to specify the output
86 path with =-o=. This option adds the =.md= file extension to
87 recognize the output files as Markdown files.
88
89If you want to export to another format, simply specify the
90=-f==/=--from== and =-t==/=--to== options.
91
92For example, you can convert the Word document to org-mode. You can also
93convert to one format and subsequently convert to other formats as
94needed.
754. Within the pandoc command, =--extract-media= saves all media found in the
76 files to the current folder, with pandoc automatically creating a =media=
77 subfolder to hold all images.
785. Within the pandoc command, =--wrap=preserve= will attempt to prseerve the
79 wrapping from the source document.
806. Within the pandoc command, the final step is to specify the output path with
81 =-o=. This option adds the =.md= file extension to recognize the output files
82 as Markdown files.
83
84If you want to export to another format, simply specify the =-f==/=--from== and
85=-t==/=--to== options.
86
87For example, you can convert the Word document to org-mode. You can also convert
88to one format and subsequently convert to other formats as needed.
9589
9690#+begin_src ps1
9791pandoc.exe -f docx -t org file.docx
content/blog/2024-04-08-docker-local-web-server.org +35 −38
@@ -3,43 +3,42 @@
33#+description:
44#+slug: docker-local-web-server
55
6When developing websites locally, I often use a simple Python web server
7to observe the changes.
6When developing websites locally, I often use a simple Python web server to
7observe the changes.
88
99#+begin_src sh
1010python3 -m http.server
1111#+end_src
1212
13However, this approach has its limitations. For example, this approach
14does not enable logging or access controls. You also need to customize
15=SimpleHTTPServer= if you have advanced needs from your web server.
13However, this approach has its limitations. For example, this approach does not
14enable logging or access controls. You also need to customize =SimpleHTTPServer=
15if you have advanced needs from your web server.
1616
17So, I went to find an alternative that is almost as easy and far more
18extensible and found Docker Desktop to be a suitable replacement.
17So, I went to find an alternative that is almost as easy and far more extensible
18and found Docker Desktop to be a suitable replacement.
1919
2020* Docker Desktop
2121
2222** Installation
2323
24[[https://www.docker.com/products/docker-desktop/][Docker Desktop]] is a
25desktop GUI for the phenomenal Docker container software. This allows
26you to manage containers, images, volumes, environments, and extensions
27via an easy-to-use GUI.
24[[https://www.docker.com/products/docker-desktop/][Docker Desktop]] is a desktop GUI for the phenomenal Docker container software.
25This allows you to manage containers, images, volumes, environments, and
26extensions via an easy-to-use GUI.
2827
2928To install, open the link above and click the =Download= button for your
30platform. I'm going through this process on an M2 Macbook, so I
31downloaded the Mac - Apple Chip version.
29platform. I'm going through this process on an M2 Macbook, so I downloaded the
30Mac - Apple Chip version.
3231
33Open the installer and follow the installation process until the
34application finishes the installation process.
32Open the installer and follow the installation process until the application
33finishes the installation process.
3534
3635#+caption: Docker Desktop on macOS
3736[[https://img.cleberg.net/blog/20240408-docker-local-web-server/docker-desktop.png]]
3837
3938** Creating an Nginx Container
4039
41I prefer to use the command line to create containers, so the following
42commands will be input via the terminal.
40I prefer to use the command line to create containers, so the following commands
41will be input via the terminal.
4342
4443The following command will create a container, using the =nginx= image:
4544
@@ -61,20 +60,20 @@ You can navigate to [[http://localhost:8000]] to see the resulting page.
6160
6261** Customizing the Nginx Container
6362
64Now that I have a container running the Nginx web server, I need to link
65some volumes so that I can modify the site configuration and provide the
66web files to serve.
63Now that I have a container running the Nginx web server, I need to link some
64volumes so that I can modify the site configuration and provide the web files to
65serve.
6766
6867Let's start with the new command, which adds two volumes:
6968
701. =<your_content>:/usr/share/nginx/html=: This is the directory where
71 you will provide the web pages for the server to serve.
691. =<your_content>:/usr/share/nginx/html=: This is the directory where you will
70 provide the web pages for the server to serve.
72712. =<your_config>:/etc/nginx/conf.d/default.conf=: This is the Nginx
7372 configuration file for your site.
7473
75To see the updates, you can delete the previous container in the GUI or
76run =docker stop web= to stop the container. Once stopped, you can run
77the new =docker run= command below.
74To see the updates, you can delete the previous container in the GUI or run
75=docker stop web= to stop the container. Once stopped, you can run the new
76=docker run= command below.
7877
7978#+begin_src sh
8079docker run -it -d -p 8000:80 --name web -v ~/Source/cleberg.net/.build:/usr/share/nginx/html -v ~/Source/cleberg.net/nginx-config.conf:/etc/nginx/conf.d/default.conf nginx
@@ -107,16 +106,15 @@ server {
107106
108107* Customizing Deployment Actions
109108
110I am currently blogging with [[https://emacs.love/weblorg/][weblorg]],
111which uses a custom =publish.el= file to build the static site. Within
112this file, I have configured my deployment process to check for the
113=ENV= variable in thesh and if it's set to =prod=, the script will set
114the base URLs to =https://cleberg.net=. If not, it sets the base URLs to
115=localhost:8000= (which matches the port used in the container above).
109I am currently blogging with [[https://emacs.love/weblorg/][weblorg]], which uses a custom =publish.el= file to
110build the static site. Within this file, I have configured my deployment process
111to check for the =ENV= variable in thesh and if it's set to =prod=, the script
112will set the base URLs to =https://cleberg.net=. If not, it sets the base URLs
113to =localhost:8000= (which matches the port used in the container above).
116114
117Therefore, I have modified my =build.sh= script to build with
118=localhost= URLs if =ENV= is not set to =prod=. It also prevents the
119build process from sending the built files to the production web server.
115Therefore, I have modified my =build.sh= script to build with =localhost= URLs
116if =ENV= is not set to =prod=. It also prevents the build process from sending
117the built files to the production web server.
120118
121119#+begin_src sh
122120#!/bin/bash
@@ -133,7 +131,6 @@ else
133131fi
134132#+end_src
135133
136You can modify the container in numerous ways and this approach allows
137you to create complex scenarios for your web development purposes. I
138highly recommend switching over to a container-based approach for
139simple, local web development.
134You can modify the container in numerous ways and this approach allows you to
135create complex scenarios for your web development purposes. I highly recommend
136switching over to a container-based approach for simple, local web development.
content/blog/2024-04-18-mu4e.org +36 −42
@@ -3,20 +3,18 @@
33#+description:
44#+slug: mu4e
55
6This post was heavily inspired by
7[[https://macowners.club/posts/email-emacs-mu4e-macos/][Email setup in
8Emacs with Mu4e on macOS]], but with my own tweaks for a single-account
9configuration and some Doom-specific configurations.
6This post was heavily inspired by [[https://macowners.club/posts/email-emacs-mu4e-macos/][Email setup in Emacs with Mu4e on macOS]], but
7with my own tweaks for a single-account configuration and some Doom-specific
8configurations.
109
1110* Overview
1211
13[[https://github.com/emacsmirror/mu4e][Mu4e]] is an Emacs-based email
14client based on [[https://www.djcbsoftware.nl/code/mu/][mu]], an indexer
15that stores email in the Maildir format.
12[[https://github.com/emacsmirror/mu4e][Mu4e]] is an Emacs-based email client based on [[https://www.djcbsoftware.nl/code/mu/][mu]], an indexer that stores email in
13the Maildir format.
1614
17This blog post covers the installation of Mu4e in Doom Emacs on macOS.
18This guide should be very similar to GNU Emacs and Linux-based systems,
19with a few tweaks required in the various configuration files.
15This blog post covers the installation of Mu4e in Doom Emacs on macOS. This
16guide should be very similar to GNU Emacs and Linux-based systems, with a few
17tweaks required in the various configuration files.
2018
2119* Installation
2220
@@ -34,21 +32,21 @@ mkdir ~/.maildir/certificates # used to store system root certificates
3432
3533*** Store Email Account Passwords in macOS Keychain
3634
37Next, I will be using the macOS Keychain to store my email account
38passwords using the command below.
35Next, I will be using the macOS Keychain to store my email account passwords
36using the command below.
3937
4038#+begin_src sh
4139security add-generic-password -s mu4e-example -a you@example.com -w
4240#+end_src
4341
4442This will prompt you to input your password twice to confirm. Keep the
45=mu4e-example= name in mind, as you will need to reference it later in
46the IMAP and SMTP configuration files.
43=mu4e-example= name in mind, as you will need to reference it later in the IMAP
44and SMTP configuration files.
4745
4846*** Store Root Certificates
4947
50In order to use IMAP and SMTP, we need to provide certificates to the
51local services. We will use the macOS defaults for this.
48In order to use IMAP and SMTP, we need to provide certificates to the local
49services. We will use the macOS defaults for this.
5250
53511. Open =Keychain Access.app=.
54522. Select =System Roots= in the sidebar.
@@ -58,8 +56,8 @@ local services. We will use the macOS defaults for this.
5856
5957*** Install Dependencies
6058
61Install =mbsync= (via =isync=) to fetch emails via IMAP, =mu= to index
62emails, and =msmtp= to send emails via SMTP.
59Install =mbsync= (via =isync=) to fetch emails via IMAP, =mu= to index emails,
60and =msmtp= to send emails via SMTP.
6361
6462#+begin_src sh
6563brew install mu isync msmtp
@@ -73,8 +71,8 @@ Within Doom Emacs, we can install Mu4e by enabling the package.
7371nano ~/.doom.d/init.el
7472#+end_src
7573
76In this file, uncomment the =mu4e= line within the =:email= section. You
77can also enable the =+org= and =+gmail= options if you prefer.
74In this file, uncomment the =mu4e= line within the =:email= section. You can
75also enable the =+org= and =+gmail= options if you prefer.
7876
7977#+begin_src lisp
8078(doom! :input
@@ -88,9 +86,9 @@ can also enable the =+org= and =+gmail= options if you prefer.
8886
8987* Configuration
9088
91As an overall suggestion, I create the following configuration files in
92the =~/.maildir= directory and using symlinks to their proper locations
93so that I can backup and restore these files easily.
89As an overall suggestion, I create the following configuration files in the
90=~/.maildir= directory and using symlinks to their proper locations so that I
91can backup and restore these files easily.
9492
9593#+begin_src sh
9694touch ~/.maildir/.mbsyncrc && \
@@ -99,14 +97,13 @@ ln -s /Users/username/.maildir/.mbsyncrc /Users/username/.mbsyncrc && \
9997ln -s /Users/username/.maildir/.msmtprc /Users/username/.msmtprc
10098#+end_src
10199
102You can also create these files in your home directory and skip the
103symlinking process above.
100You can also create these files in your home directory and skip the symlinking
101process above.
104102
105103** IMAP
106104
107Next, let's configure =mbsync= in the file created above. Paste the
108following information and customize it to match your mail provider's
109information.
105Next, let's configure =mbsync= in the file created above. Paste the following
106information and customize it to match your mail provider's information.
110107
111108#+begin_src sh
112109nano ~/.maildir/.mbsyncrc
@@ -142,9 +139,8 @@ SyncState *
142139
143140** SMTP
144141
145Next, let's configured =msmtprc= in the file created above. Paste the
146following information and customize it to match your mail provider's
147information.
142Next, let's configured =msmtprc= in the file created above. Paste the following
143information and customize it to match your mail provider's information.
148144
149145#+begin_src sh
150146nano ~/.maildir/.msmtprc
@@ -176,8 +172,8 @@ account default : startmail
176172
177173** Doom Emacs
178174
179Finally, we need to configure Doom Emacs to use the proper packages and
180set some variables and functions.
175Finally, we need to configure Doom Emacs to use the proper packages and set some
176variables and functions.
181177
182178#+begin_src sh
183179nano ~/.doom.d/config.el
@@ -275,14 +271,12 @@ Be sure to sync Doom to update the current configurations.
275271doom sync
276272#+end_src
277273
278If you have Doom open, execute =SPC h r r= to reload the new
279configurations.
274If you have Doom open, execute =SPC h r r= to reload the new configurations.
280275
281276* Initial Sync
282277
283Once you have configured all of the relevant files, you can perform an
284initial sync. Note that you can perform syncing within Mu4e itself after
285this.
278Once you have configured all of the relevant files, you can perform an initial
279sync. Note that you can perform syncing within Mu4e itself after this.
286280
287281#+begin_src sh
288282mbsync -aV
@@ -299,11 +293,11 @@ The emails will now to be ready to use!
299293
300294* Screenshots
301295
302You can now launch Doom and open Mu4e with =SPC o m=. You can also
303explore the Mu4e options with =SPC : mu4e=.
296You can now launch Doom and open Mu4e with =SPC o m=. You can also explore the
297Mu4e options with =SPC : mu4e=.
304298
305The home page shows various options and metadata about the account
306you've opened.
299The home page shows various options and metadata about the account you've
300opened.
307301
308302#+caption: Mu4e Home Page
309303[[https://img.cleberg.net/blog/20240418-mu4e/mu4e.png]]
content/blog/2024-05-03-ubuntu-on-macos.org +38 −42
@@ -3,24 +3,24 @@
33#+description: Learn how to run Linux machines as applications on macOS with minimal hassle.
44#+slug: ubuntu-on-macos
55
6Being a macOS user who previously used Linux for many years, I often
7find myself searching for alternatives to the Linux-native tools and
8methods that I had become used to over the years.
6Being a macOS user who previously used Linux for many years, I often find myself
7searching for alternatives to the Linux-native tools and methods that I had
8become used to over the years.
99
10Luckily, there's an option to simply use Linux directly on your macOS
11device without having to boot the whole device into Linux or having to
12SSH into another Linux machine.
10Luckily, there's an option to simply use Linux directly on your macOS device
11without having to boot the whole device into Linux or having to SSH into another
12Linux machine.
1313
14In this post, I use [[https://orbstack.dev/][OrbStack]] to create an
15Ubuntu Linux machine to take advantage of the Linux system.
14In this post, I use [[https://orbstack.dev/][OrbStack]] to create an Ubuntu Linux machine to take advantage
15of the Linux system.
1616
1717** Installing OrbStack
1818
19OrbStack has a [[https://orbstack.dev/download][download page]] if you
20prefer to use =*.dmg= files to install applications.
19OrbStack has a [[https://orbstack.dev/download][download page]] if you prefer to use =*.dmg= files to install
20applications.
2121
22Personally, I prefer to install everything through Homebrew. For
23OrbStack, run the following to install the application via Homebrew:
22Personally, I prefer to install everything through Homebrew. For OrbStack, run
23the following to install the application via Homebrew:
2424
2525#+begin_src sh
2626brew install orbstack
@@ -28,72 +28,68 @@ brew install orbstack
2828
2929** Creating a Linux Machine
3030
31Once installed, you can launch OrbStack and create a Linux machine in a
32matter of seconds. The creation dialog defaults to Ubuntu.
31Once installed, you can launch OrbStack and create a Linux machine in a matter
32of seconds. The creation dialog defaults to Ubuntu.
3333
3434#+caption: OrbStack's Linux Machine Creation Page
3535[[https://img.cleberg.net/blog/20240503-ubuntu-on-macos/create.png]]
3636
3737** Launching the Machine
3838
39Once created, the dialog will close and you will be presented with your
40new list of machines. Simply double-click on a machine to run it.
39Once created, the dialog will close and you will be presented with your new list
40of machines. Simply double-click on a machine to run it.
4141
42When you run the machine for the first time, it may warn you that a
43program is attempting to run a shell script. You can choose to manually
44inspect this shell script via the provided path if you wish. When you're
45comfortable with the script, you can toggle the
46=Suppress this message permanently= button and click OK to run the
47machine.
42When you run the machine for the first time, it may warn you that a program is
43attempting to run a shell script. You can choose to manually inspect this shell
44script via the provided path if you wish. When you're comfortable with the
45script, you can toggle the =Suppress this message permanently= button and click
46OK to run the machine.
4847
4948#+begin_quote
5049*Quick Tip*!
5150
52You will always be able to launch the OrbStack application and control
53the machine via the Machines page, but you can also use the OrbStack
54icon in the macOS menu bar to quickly control the machine without
55launching OrbStack itself.
51You will always be able to launch the OrbStack application and control the
52machine via the Machines page, but you can also use the OrbStack icon in the
53macOS menu bar to quickly control the machine without launching OrbStack itself.
5654#+end_quote
5755
5856** Working in Linux
5957
60Once successful, OrbStack will launch your default terminal and log you
61into the Linux machine you created above.
58Once successful, OrbStack will launch your default terminal and log you into the
59Linux machine you created above.
6260
63In the example below, we can see that the machine is using
64=Linux ubuntu 6.9.6= and operates similar to a fresh Ubuntu install on
65bare metal.
61In the example below, we can see that the machine is using =Linux ubuntu 6.9.6=
62and operates similar to a fresh Ubuntu install on bare metal.
6663
6764#+caption: Ubuntu CLI
6865[[https://img.cleberg.net/blog/20240503-ubuntu-on-macos/cli.png]]
6966
70You can also click the machine's folder icon in OrbStack to open the
71machine's file system within macOS's native Files app. Within Files, you
72can double-click to open any files and they will open in the macOS
73defaults for those file types (e.g., TextEdit).
67You can also click the machine's folder icon in OrbStack to open the machine's
68file system within macOS's native Files app. Within Files, you can double-click
69to open any files and they will open in the macOS defaults for those file types
70(e.g., TextEdit).
7471
7572#+caption: Ubuntu Files
7673[[https://img.cleberg.net/blog/20240503-ubuntu-on-macos/files.png]]
7774
78Here's an example of opening the =test.md= file in the screenshot above,
79which defaults to opening in Xcode on my system.
75Here's an example of opening the =test.md= file in the screenshot above, which
76defaults to opening in Xcode on my system.
8077
8178#+caption: Ubuntu Files
8279[[https://img.cleberg.net/blog/20240503-ubuntu-on-macos/xcode.png]]
8380
8481*** Test Examples
8582
86As a quick example of the system, I installed =neofetch=, switched to
87the =zsh= shell, and ran a few common commands.
83As a quick example of the system, I installed =neofetch=, switched to the =zsh=
84shell, and ran a few common commands.
8885
8986#+caption: Test Examples
9087[[https://img.cleberg.net/blog/20240503-ubuntu-on-macos/test.png]]
9188
9289** Thoughts
9390
94The installation, creation, and launch processes are seamless and
95provide an easy way to test or use Linux on macOS with little to no
96hassle.
91The installation, creation, and launch processes are seamless and provide an
92easy way to test or use Linux on macOS with little to no hassle.
9793
9894The shell and file integrations are incredibly snappy and I have not
9995experienced any lag so far. Further, being able to open files in the
content/blog/2024-06-19-deprecated-trusted-gpg-fix.org +33 −35
@@ -5,8 +5,8 @@
55
66** System Warning
77
8When running an update on an Ubuntu system, you may have run into a
9system warning that looks like the example below.
8When running an update on an Ubuntu system, you may have run into a system
9warning that looks like the example below.
1010
1111#+begin_src txt
1212W: https://dl.yarnpkg.com/debian/dists/stable/InRelease: Key is stored in legacy
@@ -14,34 +14,33 @@ trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in
1414apt-key(8) for details.
1515#+end_src
1616
17While this example references the =yarn= package, the warning message is
18the same for any repository using the deprecated =trusted.gpg= key ring.
17While this example references the =yarn= package, the warning message is the
18same for any repository using the deprecated =trusted.gpg= key ring.
1919
20The issue arises from managing keys with the =apt-key= command, which
21utilizes the =/etc/apt/trusted.gpg= file by default. Instead, Ubuntu has
22moved to managing key rings with individual =.gpg= files in the
23=/etc/apt/trusted.gpg.d/= directory.
20The issue arises from managing keys with the =apt-key= command, which utilizes
21the =/etc/apt/trusted.gpg= file by default. Instead, Ubuntu has moved to
22managing key rings with individual =.gpg= files in the =/etc/apt/trusted.gpg.d/=
23directory.
2424
25To fix this issue, let's check to see which keys are using the
26=trusted.gpg= key ring and move them into their own dedicated key ring.
25To fix this issue, let's check to see which keys are using the =trusted.gpg= key
26ring and move them into their own dedicated key ring.
2727
2828** Finding All Keys in the Keyring
2929
30Let's start by simply listing the keys used by the =apt= commands. To do
31this, run the following command.
30Let's start by simply listing the keys used by the =apt= commands. To do this,
31run the following command.
3232
3333#+begin_src sh
3434sudo apt-key list
3535#+end_src
3636
3737This command will show an output similar to the one below. You may see
38additional keys in the =/etc/apt/trusted.gpg.d/= directory - this is
39where we will be moving any keys currently found in the =trusted.gpg=
40key ring.
38additional keys in the =/etc/apt/trusted.gpg.d/= directory - this is where we
39will be moving any keys currently found in the =trusted.gpg= key ring.
4140
42In the below example, we can see that this system has four different GPG
43keys stored within the =trusted.gpg= key ring. Let's go ahead and move
44them into their own files.
41In the below example, we can see that this system has four different GPG keys
42stored within the =trusted.gpg= key ring. Let's go ahead and move them into
43their own files.
4544
4645#+begin_src txt
4746Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead
@@ -73,24 +72,24 @@ uid [ unknown] nginx signing key <signing-key-3@nginx.com>
7372
7473*** Exporting Keys to New Files
7574
76Now that we know the keys, we will need to move them into their own key
77ring. We can do this by copying the last eight (8) characters from the
78key's signature and exporting it from this key ring into its own.
75Now that we know the keys, we will need to move them into their own key ring. We
76can do this by copying the last eight (8) characters from the key's signature
77and exporting it from this key ring into its own.
7978
80Using the yarn example from the beginning, here's the command to move
81this key into its own key ring.
79Using the yarn example from the beginning, here's the command to move this key
80into its own key ring.
8281
8382#+begin_src sh
8483sudo apt-key export 86E50310 | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/yarn.gpg
8584#+end_src
8685
87You can repeat this process for any other keys, such as the =nginx= keys
88in the example above.
86You can repeat this process for any other keys, such as the =nginx= keys in the
87example above.
8988
9089*** Cleaning Up
9190
92If you run =sudo apt-key list= again, you should see the keys within
93their own key rings:
91If you run =sudo apt-key list= again, you should see the keys within their own
92key rings:
9493
9594#+begin_src txt
9695/etc/apt/trusted.gpg.d/nginx-archive-keyring.gpg
@@ -117,17 +116,16 @@ sub rsa4096 2019-01-02 [S] [expires: 2026-01-23]
117116sub rsa4096 2019-01-11 [S] [expires: 2026-01-23]
118117#+end_src
119118
120Once you have verified that the keys are valid and stored in their own
121key rings, you can archive the =trusted.gpg= file and run a system
122update to test the new files.
119Once you have verified that the keys are valid and stored in their own key
120rings, you can archive the =trusted.gpg= file and run a system update to test
121the new files.
123122
124123#+begin_src sh
125124sudo mv /etc/apt/trusted.gpg /etc/apt/trusted.gpg.bkp
126125sudo apt update
127126#+end_src
128127
129Once you've verified that updates work as expected and that the keys are
130working as intended, you can delete the =.bkp= file created above. If
131you're storing keys that are not easily re-attainable, I suggest keeping
132the =.bkp= file stored in a safe location until you are positive that
133you no longer need it.
128Once you've verified that updates work as expected and that the keys are working
129as intended, you can delete the =.bkp= file created above. If you're storing
130keys that are not easily re-attainable, I suggest keeping the =.bkp= file stored
131in a safe location until you are positive that you no longer need it.
content/blog/2024-07-11-emacs-on-ipad.org +24 −28
@@ -5,25 +5,23 @@
55#+slug: emacs-on-ipad
66
77
8This post describes the process to install and use Emacs on the iPad Air
913-inch (M2). The iPad used in this post is running iPadOS 17.6.
8This post describes the process to install and use Emacs on the iPad Air 13-inch
9(M2). The iPad used in this post is running iPadOS 17.6.
1010
1111** Shell Application
1212
13In order to use Emacs on an iPad, you will need a terminal emulator
14application. I recommend
15[[https://apps.apple.com/us/app/ish-shell/id1436902243][iSH]], since it
16runs a version of Alpine Linux within the app itself and will allow you
17to install packages that you need.
13In order to use Emacs on an iPad, you will need a terminal emulator application.
14I recommend [[https://apps.apple.com/us/app/ish-shell/id1436902243][iSH]], since it runs a version of Alpine Linux within the app itself
15and will allow you to install packages that you need.
1816
1917#+caption: iSH Application
2018[[https://img.cleberg.net/blog/20240711-emacs-on-ipad/ish.png]]
2119
2220** Require Packages
2321
24I started by adding the required packages directly within iSH. Emacs
25should install dependencies by default, but I include a few other
26packages that I use in my terminal as well.
22I started by adding the required packages directly within iSH. Emacs should
23install dependencies by default, but I include a few other packages that I use
24in my terminal as well.
2725
2826#+begin_src sh
2927apk add emacs ripgrep fd findutils
@@ -34,39 +32,37 @@ apk add emacs ripgrep fd findutils
3432
3533** Emacs
3634
37Once this is complete, you should be able to run Emacs natively on your
38iPad. It's effective, but can be slow at times.
35Once this is complete, you should be able to run Emacs natively on your iPad.
36It's effective, but can be slow at times.
3937
40I attempted to also install Doom Emacs, which technically worked, but
41was so incredibly slow and buggy that I was not even able to take
42screenshots. Someone smarter than me could likely get it to work with a
43little tinkering.
38I attempted to also install Doom Emacs, which technically worked, but was so
39incredibly slow and buggy that I was not even able to take screenshots. Someone
40smarter than me could likely get it to work with a little tinkering.
4441
4542#+caption: Emacs
4643[[https://img.cleberg.net/blog/20240711-emacs-on-ipad/emacs.png]]
4744
4845*** MELPA
4946
50You also have to remember to hook up MELPA yourself in the =.emacs= file
51to be able to search through their 5700+ packages instead of just ELPA
52packages. If you don't, you will only have access to ELPA packages like
53the ones below.
47You also have to remember to hook up MELPA yourself in the =.emacs= file to be
48able to search through their 5700+ packages instead of just ELPA packages. If
49you don't, you will only have access to ELPA packages like the ones below.
5450
5551#+caption: package-install
5652[[https://img.cleberg.net/blog/20240711-emacs-on-ipad/melpa.png]]
5753
58Once you have MELPA, you can install packages like the =dashboard=
59package shown below.
54Once you have MELPA, you can install packages like the =dashboard= package shown
55below.
6056
6157#+caption: emacs-dashboard
6258[[https://img.cleberg.net/blog/20240711-emacs-on-ipad/dashboard.png]]
6359
6460*** Speed
6561
66While Emacs will run on my iPad, it's not perfect. The largest issue on
67my iPad is speed - loading Emacs takes 6-7 seconds and installing the
68=magit= package took 129 seconds.
62While Emacs will run on my iPad, it's not perfect. The largest issue on my iPad
63is speed - loading Emacs takes 6-7 seconds and installing the =magit= package
64took 129 seconds.
6965
70I haven't played around enough to optimize loading times and poke around
71to see why the network requests take so long, but it's a big enough
72issue that I wouldn't see casual Emacs users dealing with the lag.
66I haven't played around enough to optimize loading times and poke around to see
67why the network requests take so long, but it's a big enough issue that I
68wouldn't see casual Emacs users dealing with the lag.