convert existing posts to pageBundles

This commit is contained in:
John Bowdre 2021-12-20 22:43:57 -06:00
parent eda0f921b9
commit 8231a47c34
399 changed files with 403 additions and 401 deletions

View file

@ -1,8 +1,8 @@
---
series: Projects
date: "2018-09-26T08:34:30Z"
thumbnail: images/posts-2020/i0UKdXleC.png
usePageBundles: false
thumbnail: i0UKdXleC.png
usePageBundles: true
tags:
- docker
- linux
@ -10,7 +10,7 @@ tags:
title: BitWarden password manager self-hosted on free Google Cloud instance
---
![Bitwarden login](/images/posts-2020/i0UKdXleC.png)
![Bitwarden login](i0UKdXleC.png)
A friend mentioned the [BitWarden](https://bitwarden.com/) password manager to me yesterday and I had to confess that I'd never heard of it. I started researching it and was impressed by what I found: it's free, [open-source](https://github.com/bitwarden), feature-packed, fully cross-platform (with Windows/Linux/MacOS desktop clients, Android/iOS mobile apps, and browser extensions for Chrome/Firefox/Opera/Safari/Edge/etc), and even offers a self-hosted option.

View file

Before

Width:  |  Height:  |  Size: 552 KiB

After

Width:  |  Height:  |  Size: 552 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View file

@ -1,8 +1,8 @@
---
date: "2020-09-14T08:34:30Z"
thumbnail: /images/posts-2020/qDTXt1jp3.png
featureImage: /images/posts-2020/qDTXt1jp3.png
usePageBundles: false
thumbnail: qDTXt1jp3.png
featureImage: qDTXt1jp3.png
usePageBundles: true
tags:
- linux
- chromeos
@ -18,12 +18,12 @@ That's a pretty sweet setup, but I still needed a way to convert STL 3D models i
Enter "Crostini," Chrome OS's [Linux (Beta) feature](https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md). It consists of a hardened Linux VM named `termina` which runs (by default) a Debian Buster LXD container named `penguin` (though you can spin up just about any container for which you can find an [image](https://us.images.linuxcontainers.org/)) and some fancy plumbing to let Chrome OS and Linux interact in specific clearly-defined ways. It's a brilliant balance between offering the flexibility of Linux while preserving Chrome OS's industry-leading security posture.
![Neofetch in the Crostini terminal](/images/posts-2020/lhTnVwCO3.png)
![Neofetch in the Crostini terminal](lhTnVwCO3.png)
There are plenty of great guides (like [this one](https://www.computerworld.com/article/3314739/linux-apps-on-chrome-os-an-easy-to-follow-guide.html)) on how to get started with Linux on Chrome OS so I won't rehash those steps here.
One additional step you will probably want to take is make sure that your Chromebook is configured to enable hyperthreading, as it may have [hyperthreading disabled by default](https://support.google.com/chromebook/answer/9340236). Just plug `chrome://flags/#scheduler-configuration` into Chrome's address bar, set it to `Enables Hyper-Threading on relevant CPUs`, and then click the button to restart your Chromebook. You'll thank me later.
![Enabling hyperthreading](/images/posts-2020/LHax6lAwh.png)
![Enabling hyperthreading](LHax6lAwh.png)
### The Software
I settled on using [FreeCAD](https://www.freecadweb.org/) for parametric modeling and [Ultimaker Cura](https://ultimaker.com/software/ultimaker-cura) for my GCODE slicer, but unfortunately getting them working cleanly wasn't entirely straightforward.
@ -65,7 +65,7 @@ Comment[de_DE]=Feature-basierter parametrischer Modellierer
MimeType=application/x-extension-fcstd
```
That's it! Get on with your 3D-modeling bad self.
![FreeCAD](/images/posts-2020/qDTXt1jp3.png)
![FreeCAD](qDTXt1jp3.png)
Now that you've got a model, be sure to [export it as an STL mesh](https://wiki.freecadweb.org/Export_to_STL_or_OBJ) so you can import it into your slicer.
#### Ultimaker Cura
@ -85,12 +85,12 @@ $ sudo apt update && sudo apt install menulibre
$ menulibre
```
Just plug in the relevant details (you can grab the appropriate icon [here](https://github.com/Ultimaker/Cura/blob/master/icons/cura-128.png)), hit the filing cabinet Save icon, and you should then be able to search for Cura from the Chrome OS launcher.
![Using menulibre to create the launcher shortcut](/images/posts-2020/VTISYOKHO.png)
![Using menulibre to create the launcher shortcut](VTISYOKHO.png)
![Ultimaker Cura](/images/posts-2020/f8nRJcyI6.png)
![Ultimaker Cura](f8nRJcyI6.png)
From there, just import the STL mesh, configure the appropriate settings, slice, and save the resulting GCODE. You can then just upload the GCODE straight to The Spaghetti Detective and kick off the print.
![Successful print, designed and sliced on Chrome OS!](/images/posts-2020/2g57odtq2.jpeg)
![Successful print, designed and sliced on Chrome OS!](2g57odtq2.jpeg)
Nice!

View file

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 180 KiB

View file

Before

Width:  |  Height:  |  Size: 664 KiB

After

Width:  |  Height:  |  Size: 664 KiB

View file

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

View file

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 173 KiB

View file

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View file

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 347 KiB

After

Width:  |  Height:  |  Size: 347 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View file

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 218 KiB

View file

@ -1,8 +1,8 @@
---
series: Tips
date: "2020-09-24T08:34:30Z"
thumbnail: images/posts-2020/fmLDUWjia.png
usePageBundles: false
thumbnail: fmLDUWjia.png
usePageBundles: true
tags:
- chrome
title: Abusing Chrome's Custom Search Engines for Fun and Profit
@ -12,25 +12,25 @@ Do you (like me) find yourself frequently searching for information within the s
### The basics
Point your browser to `chrome://settings/searchEngines` to see which sites are registered as Custom Search Engines:
![Custom search engines list](/images/posts-2020/RuIrsHDqC.png)
![Custom search engines list](RuIrsHDqC.png)
Each of these search engine entries has three parts: a name ("Search engine"), a Keyword, and a Query URL. The "Search engine" title is just what will appear in the Omnibox when the search engine gets triggered, the Keyword is what you'll type in the Omnibox to trigger it, and the Query URL tells Chrome how to handle the search. All you have to do is type the keyword, hit your Tab key to activate the search, input your query, and hit Enter:
![Using a custom search engine](/images/posts-2020/o_o7rt4pA.gif)
![Using a custom search engine](o_o7rt4pA.gif)
For sites which register themselves automatically, the keyword is often set to something like `domain.tld` so it might make sense to assign it as something shorter or more descriptive.
The Query URL is basically just what appears in the address bar when you search the site directly, with `%s` placed where your query text would normally go. You can view these details for a given search entry by tapping the three-dot menu button and selecting "Edit", and you can manually create new entries by hitting that big friendly "Add" button:
![Editing a search engine](/images/posts-2020/fmLDUWjia.png)
![Editing a search engine](fmLDUWjia.png)
By searching the site directly, you might find that it supports additional search filters which get appended to the URL:
![Discovering search filters](/images/posts-2020/iHsYd7lbw.png)
![Discovering search filters](iHsYd7lbw.png)
You can add those filters to the Query URL to further customize your Custom Search Engine:
![Adding filters to a custom search](/images/posts-2020/EBkQTGmNb.png)
![Adding filters to a custom search](EBkQTGmNb.png)
I spend a lot of my free time helping out on Google's support forums as a part of their [Product Experts program](https://productexperts.withgoogle.com/what-it-is), and I often need to quickly look up a Help Center article or previous forum discussion to assist users. I created a set of Custom Search Engines to make that easier:
![Google Help Center search engines](/images/posts-2020/630ix7uVw.png)
![Pixel Buds Help search](/images/posts-2020/V3qLmfi50.png)
![Google Help Center search engines](630ix7uVw.png)
![Pixel Buds Help search](V3qLmfi50.png)
------
@ -39,21 +39,21 @@ Even if the site doesn't have a built-in native search, you can leverage Google'
```
http://google.com/search?q=%s&sitesearch=man7.org%2Flinux%2Fman-pages
```
![man search](/images/posts-2020/EkmgtRYN4.png)
![Searching man](/images/posts-2020/YKADY8YQR.gif)
![man search](EkmgtRYN4.png)
![Searching man](YKADY8YQR.gif)
------
### Speak foreign to me
This works for pretty much any site which parses the URL to render certain content. I use this for getting words/phrases instantly translated:
![Google Translate search](/images/posts-2020/ELly_F6x6.png)
![Translating German with search!](/images/posts-2020/1LDP5zxCU.gif)
![Google Translate search](ELly_F6x6.png)
![Translating German with search!](1LDP5zxCU.gif)
------
### Shorter shortcuts
Your Query URL doesn't even need to include a query at all! You can use the Custom Search Engines as a sort of hyper-fast shortcut to pages you visit frequently. If I create a new entry with the Keyword `searchax` and `abusing-chromes-custom-search-engines-for-fun-and-profit` as the query URL, I can quickly open to this page by typing `searchax[tab][enter]`:
![Custom search shortener](/images/posts-2020/YilNCaHil.png)
![Custom search shortener](YilNCaHil.png)
I use that trick pretty regularly for getting back to vCenter appliance management interfaces without having to type out the full FQDN and port number and all that.
@ -65,7 +65,7 @@ You can do some other creative stuff too, like speedily accessing a temporary sc
data:text/html;charset=utf-8, <title>Scratchpad</title><style>body {padding: 5%; font-size: 1.5em; font-family: Arial; }"></style><link rel="shortcut icon" href="https://ssl.gstatic.com/docs/documents/images/kix-favicon6.ico"/><body OnLoad='document.body.focus();' contenteditable spellcheck="true" >
```
And give it a nice short keyword - like the single letter 's':
![My own scratchpad!](/images/posts-2020/h6dUCApdV.gif)
![My own scratchpad!](h6dUCApdV.gif)
------

View file

Before

Width:  |  Height:  |  Size: 334 KiB

After

Width:  |  Height:  |  Size: 334 KiB

View file

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View file

@ -1,7 +1,7 @@
---
date: "2020-09-22T08:34:30Z"
thumbnail: images/posts-2020/8p-PSHx1R.png
usePageBundles: false
thumbnail: 8p-PSHx1R.png
usePageBundles: true
tags:
- docker
- windows
@ -71,12 +71,12 @@ Run the installer, and make sure to tick the box for installing the WSL2 engine.
#### Step Three: Configure Docker Desktop
Launch Docker Desktop from the Start menu, and you should be presented with this friendly prompt:
![Great news! We're supported.](/images/posts-2020/lY2FTflbK.png)
![Great news! We're supported.](lY2FTflbK.png)
Hit that big friendly "gimme WSL2" button. Then open the Docker Settings from the system tray, and make sure that **General > Use the WSL 2 based engine** is enabled. Now navigate to **Resources > WSL Integration**, confirm that **Enable integration with my default WSL distro** is enabled as well. Smash the "Apply & Restart" button if you've made any changes.
### Test it!
Fire up a WSL session and confirm that everything is working with `docker run hello-world`:
![Hello, world!](/images/posts-2020/8p-PSHx1R.png)
![Hello, world!](8p-PSHx1R.png)
It's beautiful!

View file

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View file

@ -1,7 +1,7 @@
---
series: Tips
date: "2020-09-13T08:34:30Z"
usePageBundles: false
usePageBundles: true
tags:
- linux
- shell

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -1,8 +1,8 @@
---
series: Scripts
date: "2020-09-16T08:34:30Z"
thumbnail: images/posts-2020/LJOcy2oqc.png
usePageBundles: false
thumbnail: LJOcy2oqc.png
usePageBundles: true
tags:
- vmware
- powercli
@ -13,7 +13,7 @@ I manage a large VMware environment spanning several individual vCenters, and I
I can, and here's how I do it.
![Logging in to multiple vCenters](/images/posts-2020/LJOcy2oqc.png)
![Logging in to multiple vCenters](LJOcy2oqc.png)
### The Script
The following Powershell script will let you define a list of vCenters to be accessed, securely store your credentials for each vCenter, log in to every vCenter with a single command, and also close the connections when they're no longer needed. It's also a great starting point for any other custom functions you'd like to incorporate into your PowerCLI sessions.

View file

@ -1,7 +1,7 @@
---
date: "2020-10-07T08:34:30Z"
thumbnail: images/posts-2020/MnmMuA0HC.png
usePageBundles: false
thumbnail: MnmMuA0HC.png
usePageBundles: true
tags:
- windows
- linux
@ -22,7 +22,7 @@ The instructions worked well for me so I won't rehash them all here. When it cam
All I need to do now is execute `sudo ./wsl-vpnkit` and leave that running in the background when I need to use WSL while connected to the corporate VPN.
![Successful connection via wsl-vpnkit](/images/posts-2020/MnmMuA0HC.png)
![Successful connection via wsl-vpnkit](MnmMuA0HC.png)
Whew! Okay, back to work.

View file

@ -2,8 +2,8 @@
series: Projects
date: "2020-10-27T08:34:30Z"
lastmod: "2021-05-20"
thumbnail: images/posts-2020/XtmaR9Z0J.png
usePageBundles: false
thumbnail: XtmaR9Z0J.png
usePageBundles: true
tags:
- chromeos
- linux
@ -16,7 +16,7 @@ featured: true
I've [written in the past](/3d-modeling-and-printing-on-chrome-os) about the Linux setup I've been using on my Pixel Slate. My Slate's keyboard stopped working over the weekend, though, and there don't seem to be any replacements (either Google or Brydge) to be found. And then I saw that [Walmart had the 64GB Lenovo Chromebook Duet temporarily marked down](https://twitter.com/johndotbowdre/status/1320733614426988544) to a mere $200 - just slightly more than the Slate's *keyboard* originally cost. So I jumped on that deal, and the little Chromeblet showed up today.
![Aww, it's so cute!](/images/posts-2020/kULHPeDuc.jpeg)
![Aww, it's so cute!](kULHPeDuc.jpeg)
I'll be putting the Duet through the paces in the coming days to see if/how it can replace my now-tablet-only Slate, but first things first: I need Linux. And this may be a little bit different than the setup on the Slate since the Duet's Mediatek processor uses the aarch64/arm64 architecture instead of amd64. (And while I'm writing these steps specific to the Duet, the same steps should work on basically any arm64 Chromebook.)
@ -24,16 +24,16 @@ So journey with me as I get this little guy set up!
### Installing Linux
This part is dead simple. Just head into **Settings > Linux (Beta)** and hit the **Turn on** button:
![It doesn't take much to get Linux turned on](/images/posts-2020/oLso9Wyzj.png)
![It doesn't take much to get Linux turned on](oLso9Wyzj.png)
Click **Next**, review the options for username and initial disk size (which can be easily increased later so there's no real need to change it right now), and then select **Install**:
![Selecting username and storage allocation](/images/posts-2020/ACUKsohq6.png)
![Selecting username and storage allocation](ACUKsohq6.png)
It takes just a few minutes to download and initialize the `termina` VM and then create the default `penguin` container:
![Installing...](/images/posts-2020/2LTaCEdWH.png)
![Installing...](2LTaCEdWH.png)
You're ready to roll once the Terminal opens and gives you a prompt:
![Hello, Penguin!](/images/posts-2020/0-h1flLZs.png)
![Hello, Penguin!](0-h1flLZs.png)
Your first action should be to go ahead and install any patches:
```shell
@ -57,7 +57,7 @@ Review it if you'd like (and you should! *Always* review code before running it!
sh install.sh
```
When asked if you'd like to change your default shell to `zsh` now, **say no**. This is because it will prompt for your password, but you probably don't have a password set on your brand-new Linux (Beta) account and that just makes things complicated. We'll clear this up later, but for now just check out that slick new prompt:
![Oh my!](/images/posts-2020/8q-WT0AyC.png)
![Oh my!](8q-WT0AyC.png)
Oh My Zsh is pretty handy because you can easily enable [additional plugins](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins) to make your prompt behave exactly the way you want it to. Let's spruce it up even more with the [powerlevel10k theme](https://github.com/romkatv/powerlevel10k)!
```shell
@ -72,11 +72,11 @@ We'll need to launch another instance of `zsh` for the theme change to take effe
sudo chsh -s /bin/zsh [username]
```
Now close out the terminal and open it again, and you should be met by the powerlevel10k configurator which will walk you through getting things set up:
![pwerlevel10k configurator](/images/posts-2020/K1ScSuWcg.png)
![pwerlevel10k configurator](K1ScSuWcg.png)
This theme is crazy-configurable, but fortunately the configurator wizard does a great job of helping you choose the options that work best for you.
I pick the Classic prompt style, Unicode character set, Dark prompt color, 24-hour time, Angled separators, Sharp prompt heads, Flat prompt tails, 2-line prompt height, Dotted prompt connection, Right prompt frame, Sparse prompt spacing, Fluent prompt flow, Enabled transient prompt, Verbose instant prompt, and (finally) Yes to apply the changes.
![New P10k prompt](/images/posts-2021/08/20210804_p10k_prompt.png)
![New P10k prompt](20210804_p10k_prompt.png)
Looking good!
### Visual Studio Code
@ -86,15 +86,15 @@ curl -L https://aka.ms/linux-arm64-deb > code_arm64.deb
sudo apt install ./code_arm64.deb
```
VS Code should automatically appear in the Chromebook's Launcher, or you can use it to open a file directly with `code [filename]`:
![VS Code editing my .zshrc file](/images/posts-2020/XtmaR9Z0J.png)
![VS Code editing my .zshrc file](XtmaR9Z0J.png)
Nice!
### Android platform tools (adb and fastboot)
I sometimes don't want to wait for my Pixel to get updated naturally, so I love using `adb sideload` to manually update my phones. Here's what it takes to set that up. Installing adb is as simple as `sudo apt install adb`. To use it, enable the USB Debugging Developer Option on your phone, and then connect the phone to the Chromebook. You'll get a prompt to connect the phone to Linux:
![Connecting a phone to Linux](/images/posts-2020/MkGu29HKl.png)
![Connecting a phone to Linux](MkGu29HKl.png)
Once you connect the phone to Linux, check the phone to approve the debugging connection. You can then issue `adb devices` to verify the phone is connected:
![Verifying the ADB connection](/images/posts-2020/a0uqHkJiC.png)
![Verifying the ADB connection](a0uqHkJiC.png)
*I've since realized that the platform-tools (adb/fastboot) available in the repos are much older than what are required for flashing a factory image or sideloading an OTA image to a modern Pixel phone. This'll do fine for installing APKs either to your Chromebook or your phone, but I had to pull out my trusty Pixelbook to flash GrapheneOS to my Pixel 4a.*
@ -111,11 +111,11 @@ sudo chmod +x /opt/microsoft/powershell/7/pwsh
sudo ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh
```
You can then just run `pwsh`:
![Powershell, in Linux, on Chrome OS](/images/posts-2020/QRP4iyLnu.png)
![Powershell, in Linux, on Chrome OS](QRP4iyLnu.png)
That was the hard part. To install PowerCLI into your new Powershell environment, just run `Install-Module -Name VMware.PowerCLI` at the `PS >` prompt, and accept the warning about installing a module from an untrusted repository.
I'm planning to use PowerCLI against my homelab without trusted SSL certificates so (note to self) I need to run `Set-PowerCLIConfiguration -InvalidCertificateAction Ignore` before I try to connect.
![PowerCLI connected to my vCenter](/images/posts-2020/YaFNJJG_c.png)
![PowerCLI connected to my vCenter](YaFNJJG_c.png)
Woot!
@ -147,12 +147,12 @@ And finally update the package cache and install `docker` and its friends:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
```
![I put a container in your container](/images/posts-2020/k2uiYi5e8.png)
![I put a container in your container](k2uiYi5e8.png)
Xzibit would be proud!
### 3D printing utilities
Just like [last time](/3d-modeling-and-printing-on-chrome-os), I'll want to be sure I can do light 3D part design and slicing on this Chromebook. Once again, I can install FreeCAD with `sudo apt install freecad`, and this time I didn't have to implement any workarounds for graphical issues:
![FreeCAD](/images/posts-2020/q1inyuUOb.png)
![FreeCAD](q1inyuUOb.png)
Unfortunately, though, I haven't found a slicer application compiled with support for aarch64/arm64. There's a *much* older version of Cura available in the default Debian repos but it crashes upon launch. Neither Cura nor PrusaSlicer (or the Slic3r upstream) offer arm64 releases.
@ -174,7 +174,7 @@ conda install -c conda-forge notebook
You can then launch the notebook with `jupyter notebook` and it will automatically open up in a Chrome OS browser tab:
![To Jupyter and beyond!](/images/posts-2020/U5E556eXf.png)
![To Jupyter and beyond!](U5E556eXf.png)
Cool! Now I just need to learn what I'm doing with Jupyter - but at least I don't have an excuse about "my laptop won't run it".

View file

Before

Width:  |  Height:  |  Size: 730 KiB

After

Width:  |  Height:  |  Size: 730 KiB

View file

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 229 KiB

View file

Before

Width:  |  Height:  |  Size: 401 KiB

After

Width:  |  Height:  |  Size: 401 KiB

View file

Before

Width:  |  Height:  |  Size: 478 KiB

After

Width:  |  Height:  |  Size: 478 KiB

View file

@ -2,8 +2,8 @@
series: Projects
date: "2020-11-24T08:34:30Z"
lastmod: "2021-03-12"
thumbnail: images/posts-2020/Ki7jo65t3.png
usePageBundles: false
thumbnail: Ki7jo65t3.png
usePageBundles: true
tags:
- android
- automation
@ -16,7 +16,7 @@ title: Auto-connect to ProtonVPN on untrusted WiFi with Tasker [Update!]
I recently shared how I use [Tasker and Home Assistant to keep my phone from charging past 80%](/safeguard-your-androids-battery-with-tasker-home-assistant). Today, I'm going to share the setup I use to automatically connect my phone to a VPN on networks I *don't* control.
![Tasker + OpenVPN](/images/posts-2020/Ki7jo65t3.png)
![Tasker + OpenVPN](Ki7jo65t3.png)
### Background
Android has an option to [set a VPN as Always-On](https://support.google.com/android/answer/9089766#always-on_VPN) so for maximum security I could just use that. I'm not *overly* concerned (yet?) with my internet traffic being intercepted upstream of my ISP, though, and often need to connect to other devices on my home network without passing through a VPN (or introducing split-tunnel complexity). But I do want to be sure that my traffic is protected whenever I'm connected to a WiFi network controlled by someone else.
@ -45,7 +45,7 @@ You can find instructions for configuring the OpenVPN client to work with Proton
- **Country configs** connect to a random VPN node in your target country
- **Standard server configs** let you choose the specific VPN node to use
- **Free server configs** connect you to one of the VPN nodes available in the free tier
![Client config download page](/images/posts-2020/vdIG0jHmk.png)
![Client config download page](vdIG0jHmk.png)
Feel free to download more than one if you'd like to have different profiles available within the OpenVPN app.
@ -56,7 +56,7 @@ ProtonVPN automatically generates a set of user credentials to use with a third-
### Configuring OpenVPN for Android
Now what you've got the config file(s) and your client credentials, it's time to actually configure that client.
![OpenVPN connection list](/images/posts-2020/9WdA6HRch.png)
![OpenVPN connection list](9WdA6HRch.png)
1. Launch the OpenVPN for Android app and tap the little 'downvote-in-a-box' "Import" icon.
2. Browse to wherever you saved the `.ovpn` config files and select the one you'd like to use.
@ -69,7 +69,7 @@ Success!
I don't like to have a bunch of persistent notification icons hanging around (and Android already shows a persistent status icon when a VPN connection is active). If you're like me, long-press the OpenVPN notification and tap the gear icon. Then tap on the **Connection statistics** category and activate the **Minimized** slider. The notification will still appear, but it will collapse to the bottom of your notification stack and you won't get bugged by the icon.
![Notification settings](/images/posts-2020/WWuHwVvrk.png)
![Notification settings](WWuHwVvrk.png)
### Tasker profiles
Open up Tasker and get ready to automate! We're going to wind up with at least two new Tasker profiles so (depending on how many you already have) you might want to create a new project by long-pressing the Home icon at the bottom-left of the screen and selecting the **Add** option. I chose to group all my VPN-related profiles in a project named (oh-so-creatively) "VPN". Totally your call though.
@ -146,7 +146,7 @@ A1: Variable Clear [ Name:%TRUSTED_WIFI Pattern Matching:Off Local Variables Onl
#### OpenVPN Connect app configuration
After installing and launching the official [OpenVPN Connect app](https://play.google.com/store/apps/details?id=net.openvpn.openvpn), tap the "+" button at the bottom right to create a new profile. Swipe over to the "File" tab and import the `*.ovpn` file you downloaded from ProtonVPN. Paste in the username, tick the "Save password" box, and paste in the password as well. I also chose to rename the profile to something a little bit more memorable - you'll need this name later. From there, hit the "Add" button and then go ahead and tap on your profile to test the connection.
![Creating a profile in OpenVPN Connect](/images/posts-2020/KjGOX8Yiv.png)
![Creating a profile in OpenVPN Connect](KjGOX8Yiv.png)
#### Tasker profiles
Go ahead and create the [Trusted Wifi profile](#trusted-wifi) as described above.

View file

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View file

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

View file

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View file

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

View file

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 157 KiB

View file

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View file

@ -1,8 +1,8 @@
---
series: Projects
date: "2020-11-14T08:34:30Z"
thumbnail: images/posts-2020/aeIOr8w6k.png
usePageBundles: false
thumbnail: aeIOr8w6k.png
usePageBundles: true
tags:
- android
- tasker
@ -13,7 +13,7 @@ title: Safeguard your Android's battery with Tasker + Home Assistant
A few months ago, I started using the [AccuBattery app](https://play.google.com/store/apps/details?id=com.digibites.accubattery) to keep a closer eye on how I'd been charging my phones. The app has a handy feature that notifies you once the battery level reaches a certain threshold so you can pull the phone off the charger and extend the lithium battery's service life, and it even offers an estimate for what that impact might be. For instance, right now the app indicates that charging my Pixel 5 from 51% to 100% would cause 0.92 wear cycles, while stopping the charge at 80% would impose just 0.17 cycles.
![AccuBattery screenshot](/images/posts-2020/aeIOr8w6k.png)
![AccuBattery screenshot](aeIOr8w6k.png)
But that depends on me being near my phone and conscious so I can take action when the notification goes off. That's often a big assumption to make - and, frankly, I'm lazy.
@ -29,17 +29,17 @@ I'm not going to go through how to install Home Assistant on the Pi or how to co
### The Recipe
1. Plug the Wemo into a wall outlet, and plug a phone charger into the Wemo. Add the Belkin Wemo integration in Home Assistant, and configure the device and entity. I named mine `switchy`. Make a note of the Entity ID: `switch.switchy`. We'll need that later.
![The new entity in HA](/images/posts-2020/Gu5I3LUep.png)
![The new entity in HA](Gu5I3LUep.png)
2. Either point your phone's browser to your [Home Assistant instance's local URL](http://homeassistant.local:8123/), or use the [Home Assistant app](https://play.google.com/store/apps/details?id=io.homeassistant.companion.android) to access it. Tap your username at the bottom of the menu and scroll all the way down to the Long-Lived Access Tokens section. Tap to create a new token. It doesn't matter what you name it, but be sure to copy to token data once it is generated since you won't be able to display it again.
3. Install the [Home Assistant Plug-In for Tasker](https://play.google.com/store/apps/details?id=com.markadamson.taskerplugin.homeassistant). Open Tasker, create a new Task called 'ChargeOff', and set the action to `Plugin > Home Assistant Plug-in for Tasker > Call Service`. Tap the pencil icon to edit the configuration, and then tap the plus sign to add a new server. Give it whatever name you like, and then enter your Home Assistant's IP address for the Base URL, followed by the port number `8123`. For example, `http://192.168.1.99:8123`. Paste in the Long-Lived Access Token you generated earlier. Go on and hit the Test Server button to make sure you got it right. It'll wind up looking something like this:
![Configuring the HA connection in Tasker](/images/posts-2020/8Jg4zgrgB.png)
![Configuring the HA connection in Tasker](8Jg4zgrgB.png)
For the Service field, you need to tell HA what you want it to do. We want it to turn off a switch so enter `switch.turn_off`. We'll use the Service Data field to tell it which switch, in JSON format:
```json
{"entity_id": "switch.switchy"}
```
Tap Test Service to make sure it works - and verify that the switch does indeed turn off.
![Creating and testing the service](/images/posts-2020/U3LfmEJ_7.png)
![Creating and testing the service](U3LfmEJ_7.png)
4. Hard part is over. Now we just need to set up a profile in Tasker to fire our new task. I named mine 'Charge Limiter'. I started with `State > Power > Battery Level` and set it to trigger between 81-100%., and also added `State > Power > Source: Any` so it will only be active while charging. I also only want this to trigger while my phone is charging at home, so I added `State > Net > Wifi Connected` and then specified my home SSID. Link this profile to the Task you created earlier, and never worry about overcharging your phone again.
![Tasker profile to kill power above 80%](/images/posts-2020/h7tl6facr.png)
![Tasker profile to kill power above 80%](h7tl6facr.png)
You can use a similar Task to turn the switch back on at a set time - or you could configure that automation directly in Home Assistant. I added an action to turn on the switch to my Google Assistant bedtime routine and that works quite well for my needs.

View file

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View file

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View file

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View file

Before

Width:  |  Height:  |  Size: 1 MiB

After

Width:  |  Height:  |  Size: 1 MiB

View file

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,7 +1,7 @@
---
date: "2020-11-06T08:34:30Z"
thumbnail: images/posts-2020/P-x5qEg_9.jpeg
usePageBundles: false
thumbnail: P-x5qEg_9.jpeg
usePageBundles: true
tags:
- chromeos
title: 'Showdown: Lenovo Chromebook Duet vs. Google Pixel Slate'
@ -9,7 +9,7 @@ title: 'Showdown: Lenovo Chromebook Duet vs. Google Pixel Slate'
Okay, okay, this isn't actually going to be a comparison review between the two wildly-mismatched-but-also-kind-of-similar [Chromeblets](https://www.reddit.com/r/chromeos/comments/bp1nwo/branding/), but rather a (hopefully) brief summary of my experience moving from an $800 Pixel Slate + $200 Google keyboard to a Lenovo Chromebook Duet I picked up on sale for just $200.
![A Tale of Two Chromeblets](/images/posts-2020/P-x5qEg_9.jpeg)
![A Tale of Two Chromeblets](P-x5qEg_9.jpeg)
### Background
Up until last week, I'd been using the Slate as my primary personal computing device for the previous 20 months or so, mainly in laptop mode (as opposed to tablet mode). I do a lot of casual web browsing, and I spend a significant portion of my free time helping other users on Google's product support forums as a part of the [Google Product Experts program](https://productexperts.withgoogle.com/what-it-is). I also work a lot with the [Chrome OS Linux (Beta) environment](/setting-up-linux-on-a-new-lenovo-chromebook-duet-bonus-arm64-complications), but I avoid Android apps as much as I can. And I also used the Slate for a bit of Stadia gaming when I wasn't near a Chromecast.
@ -20,32 +20,32 @@ I was pretty happy with the Slate, but its expensive keyboard stopped working re
### Size
When you put these machines side by side, the first difference that jumps out is the size disparity. The 12.3" Pixel Slate is positively massive next to the 10.1" Lenovo Duet.
![Big 'un and little 'un](/images/posts-2020/gVj7d_2Nu.jpeg)
![Big 'un and little 'un](gVj7d_2Nu.jpeg)
The Duet is physically smaller so the display itself is of course smaller. I had a brief moment of panic when I first logged in and the setup wizard completely filled the screen. Dialing Chrome OS's display scaling down to 80% strikes a good balance for me between fonts being legible while still displaying enough content to be worthwhile. It can get a bit tight when you've got windows docked side-by-side but I'm getting by okay.
Of course, the smaller size of the Duet also makes it work better as a tablet in my mind. It's comfortable enough to hold with one hand while you interact with the other, whereas the Slate always felt a little too big for that to me.
![One-handing the Duet](/images/posts-2020/qne9SybLi.jpeg)
![One-handing the Duet](qne9SybLi.jpeg)
### Keyboard
A far more impactful size difference is the keyboards though. The Duet keyboard gets a bit cramped, particularly over toward the right side (you know, those pesky braces and semicolons that are *never* needed when coding):
![The Duet's keyboard is MUCH smaller](/images/posts-2020/CBziPHD8A.jpeg)
![The Duet's keyboard is MUCH smaller](CBziPHD8A.jpeg)
Getting used to typing on this significantly smaller keyboard has been the biggest adjustment so far. The pad on my pinky finger is wider than the last few keys at the right edge of the keyboard so I've struggled with accurately hitting the correct `[` or `]`, and also with smacking Return (and inevitably sending a malformed chat message) when trying to insert an apostrophe. I feel like I'm slowly getting the hang of it, but like I said, it's been an adjustment.
### Cover
![Cover up!](/images/posts-2020/yiCW6XZbF.jpeg)
![Cover up!](yiCW6XZbF.jpeg)
The Pixel Slate's keyboard + folio cover is a single (floppy) piece. The keyboard connects to contacts on the bottom edge of the Slate, and magnets hold it in place. The rear cover then folds and sticks to the back of the Slate with magnets to prop up the tablet in different angles. The magnet setup means you can smoothly transition it through varying levels of tilt, which is pretty nice. But being a single piece means the keyboard might get in the way if you're trying to use it as just a propped-up tablet. And the extra folding in the back takes up a bit of space so the Slate may not work well as a laptop on your actual lap.
![Duet's fabric cover](/images/posts-2020/9_Ze3zyBk.jpeg)
![Duet's fabric cover](9_Ze3zyBk.jpeg)
The Duet's rear cover has a fabric finish kind of similar to the cases Google offers for their phones, and it provides a great texture for holding the tablet. It sticks to the back of the Duet through the magic of magnets, and the lower half of it folds out to create a really sturdy kickstand. And it's completely separate from the keyboard which is great for when you're using the Duet as a tablet (either handheld or propped up for watching a movie or gaming with Stadia).
![Duet kickstand](/images/posts-2020/nWRu2TB8i.jpeg)
![Duet kickstand](nWRu2TB8i.jpeg)
And this little kickstand can go *low*, much lower than the Slate. This makes it perfect for my late-night Stadia sessions while sitting in bed. I definitely prefer this approach compared to what Google did with the Pixel Slate.
![The Duet handily wins this limbo competition](/images/posts-2020/BAf7knBk5.jpeg)
![The Duet handily wins this limbo competition](BAf7knBk5.jpeg)
### Performance
The Duet does struggle a bit here. It's basically got a [smartphone processor](https://www.notebookcheck.net/Mediatek-Helio-P60T-Processor-Benchmarks-and-Specs.470711.0.html) and half the RAM of the Slate. Switching between windows and tabs sometimes takes an extra moment or two to catch up (particularly if said tab has been silently suspended in the background). Similarly, working with Linux apps is just a bit slower than you'd like it to be. Still, I've spent a bit more than a week now with the Duet as my go-to computer and it's never really been slow enough to bother me.

View file

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View file

Before

Width:  |  Height:  |  Size: 701 KiB

After

Width:  |  Height:  |  Size: 701 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View file

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View file

@ -1,8 +1,8 @@
---
series: Tips
date: "2020-12-23T08:34:30Z"
thumbnail: images/posts-2020/-lp1-DGiM.png
usePageBundles: false
thumbnail: -lp1-DGiM.png
usePageBundles: true
tags:
- chromeos
title: Burn an ISO to USB with the Chromebook Recovery Utility
@ -17,17 +17,17 @@ Normally that tool is used to creating bootable media to [reinstall Chrome OS on
1. Install the [Chromebook Recovery Utility](https://chrome.google.com/webstore/detail/chromebook-recovery-utili/pocpnlppkickgojjlmhdmidojbmbodfm).
2. Download the ISO you intend to use.
3. Rename the file to append `.bin` on the end, after the `.iso` bit:
![My renamed ISO for installing ESXi](/images/posts-2020/uoTjgtbN1.png)
![My renamed ISO for installing ESXi](uoTjgtbN1.png)
4. Plug in the USB drive you're going to sacrifice for this effort - remember that ALL data on the drive will be erased.
5. Open the recovery utility, click on the gear icon at the top right, and select the *Use local image* option:
![The CRU menu](/images/posts-2020/vdTpW9t7Q.png)
![The CRU menu](vdTpW9t7Q.png)
6. Browse to and select the `*.iso.bin` file.
7. Choose the USB drive, and click *Continue*.
![Selecting the drive](/images/posts-2020/p_Ieqsw4p.png)
![Selecting the drive](p_Ieqsw4p.png)
8. Click *Create now* to start the writing!
![Writing the image](/images/posts-2020/lhw5EEqSD.png)
![Writing the image](lhw5EEqSD.png)
9. All done! It probably won't work great for actually recovering your Chromebook but will do wonders for installing ESXi (or whatever) on another computer!
![Success!](/images/posts-2020/-lp1-DGiM.png)
![Success!](-lp1-DGiM.png)
You can also use the CRU to make a bootable USB from a `.zip` archive containing a single `.img` file, such as those commonly used to distribute [Raspberry Pi images](https://www.raspberrypi.org/documentation/installation/installing-images/chromeos.md).

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View file

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View file

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View file

@ -1,8 +1,8 @@
---
series: Tips
date: "2021-01-30T08:34:30Z"
thumbnail: images/posts-2020/XTaU9VDy8.png
usePageBundles: false
thumbnail: XTaU9VDy8.png
usePageBundles: true
tags:
- vmware
title: 'PSA: halt replication before snapshotting linked vCenters'
@ -13,7 +13,7 @@ It's a good idea to take a snapshot of your virtual appliances before applying a
*(Yes, that's a lesson I learned the hard way - and warnings about that are tragically hard to come by from what I've seen. So I'm sharing my notes so that you can avoid making the same mistake.)*
![Viewing replication status of linked vCenters](/images/posts-2020/XTaU9VDy8.png)
![Viewing replication status of linked vCenters](XTaU9VDy8.png)
Take these steps when you need to snapshot linked vCenters to avoid breaking replication:

View file

Before

Width:  |  Height:  |  Size: 533 KiB

After

Width:  |  Height:  |  Size: 533 KiB

View file

Before

Width:  |  Height:  |  Size: 542 KiB

After

Width:  |  Height:  |  Size: 542 KiB

View file

Before

Width:  |  Height:  |  Size: 917 KiB

After

Width:  |  Height:  |  Size: 917 KiB

View file

Before

Width:  |  Height:  |  Size: 275 KiB

After

Width:  |  Height:  |  Size: 275 KiB

View file

Before

Width:  |  Height:  |  Size: 498 KiB

After

Width:  |  Height:  |  Size: 498 KiB

View file

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 185 KiB

View file

Before

Width:  |  Height:  |  Size: 752 KiB

After

Width:  |  Height:  |  Size: 752 KiB

View file

Before

Width:  |  Height:  |  Size: 245 KiB

After

Width:  |  Height:  |  Size: 245 KiB

View file

Before

Width:  |  Height:  |  Size: 766 KiB

After

Width:  |  Height:  |  Size: 766 KiB

View file

Before

Width:  |  Height:  |  Size: 744 KiB

After

Width:  |  Height:  |  Size: 744 KiB

View file

Before

Width:  |  Height:  |  Size: 654 KiB

After

Width:  |  Height:  |  Size: 654 KiB

View file

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View file

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View file

@ -1,8 +1,8 @@
---
series: vRA8
date: "2021-02-22T08:34:30Z"
thumbnail: images/posts-2020/7_QI-Ti8g.png
usePageBundles: false
thumbnail: 7_QI-Ti8g.png
usePageBundles: true
tags:
- python
- rest
@ -100,34 +100,34 @@ Now would also be a good time to go ahead and enable cron jobs so that phpIPAM w
Okay, let's now move on to the phpIPAM web-based UI to continue the setup. After logging in at `https://ipam.lab.bowdre.net/`, I clicked on the red **Administration** menu at the right side and selected **phpIPAM Settings**. Under the **Site Settings** section, I enabled the *Prettify links* option, and under the **Feature Settings** section I toggled on the *API* component. I then hit *Save* at the bottom of the page to apply the changes.
Next, I went to the **Users** item on the left-hand menu to create a new user account which will be used by vRA. I named it `vra`, set a password for the account, and made it a member of the `Operators` group, but didn't grant any special module access.
![Creating vRA service account in phpIPAM](/images/posts-2020/DiqyOlf5S.png)
![Creating vRA service account in phpIPAM](/images/posts-2020/QoxVKC11t.png)
![Creating vRA service account in phpIPAM](DiqyOlf5S.png)
![Creating vRA service account in phpIPAM](QoxVKC11t.png)
The last step in configuring API access is to create an API key. This is done by clicking the **API** item on that left side menu and then selecting *Create API key*. I gave it the app ID `vra`, granted Read/Write permissions, and set the *App Security* option to "SSL with User token".
![Generating the API key](/images/posts-2020/-aPGJhSvz.png)
![Generating the API key](-aPGJhSvz.png)
Once we get things going, our API calls will authenticate with the username and password to get a token and bind that to the app ID.
### Step 2: Configuring phpIPAM subnets
Our fancy new IPAM solution is ready to go - except for the whole bit about managing IPs. We need to tell it about the network segments we'd like it to manage. phpIPAM uses "Sections" to group subnets together, so we start by creating a new Section at **Administration > IP related management > Sections**. I named my new section `Lab`, and pretty much left all the default options. Be sure that the `Operators` group has read/write access to this section and the subnets we're going to create inside it!
![Creating a section to hold the subnets](/images/posts-2020/6yo39lXI7.png)
![Creating a section to hold the subnets](6yo39lXI7.png)
We should also go ahead and create a Nameserver set so that phpIPAM will be able to tell its clients (vRA) what server(s) to use for DNS. Do this at **Administration > IP related management > Nameservers**. I created a new entry called `Lab` and pointed it at my internal DNS server, `192.168.1.5`.
![Designating the nameserver](/images/posts-2020/pDsEh18bx.png)
![Designating the nameserver](pDsEh18bx.png)
Okay, we're finally ready to start entering our subnets at **Administration > IP related management > Subnets**. For each one, I entered the Subnet in CIDR format, gave it a useful description, and associated it with my `Lab` section. I expanded the *VLAN* dropdown and used the *Add new VLAN* option to enter the corresponding VLAN information, and also selected the Nameserver I had just created.
![Entering the first subnet](/images/posts-2020/-PHf9oUyM.png)
![Entering the first subnet](-PHf9oUyM.png)
I also enabled the options *Mark as pool*, *Check hosts status*, *Discover new hosts*, and *Resolve DNS names*.
![Subnet options](/images/posts-2020/SR7oD0jsG.png)
![Subnet options](SR7oD0jsG.png)
I then used the *Scan subnets for new hosts* button to run a discovery scan against the new subnet.
![Scanning for new hosts](/images/posts-2020/4WQ8HWJ2N.png)
![Scanning for new hosts](4WQ8HWJ2N.png)
The scan only found a single host, `172.16.20.1`, which is the subnet's gateway address hosted by the Vyos router. I used the pencil icon to edit the IP and mark it as the gateway:
![Identifying the gateway](/images/posts-2020/2otDJvqRP.png)
![Identifying the gateway](2otDJvqRP.png)
phpIPAM now knows the network address, mask, gateway, VLAN, and DNS configuration for this subnet - all things that will be useful for clients seeking an address. I then repeated these steps for the remaining subnets.
![More subnets!](/images/posts-2020/09RIXJc12.png)
![More subnets!](09RIXJc12.png)
Now for the *real* fun!
@ -351,10 +351,10 @@ try:
You can view the full code [here](https://github.com/jbowdre/phpIPAM-for-vRA8/blob/main/src/main/python/validate_endpoint/source.py).
After completing each operation, run `mvn package -PcollectDependencies -Duser.id=${UID}` to build again, and then import the package to vRA again. This time, you'll see the new "API App ID" field on the form:
![Validating the new IPAM endpoint](/images/posts-2020/bpx8iKUHF.png)
![Validating the new IPAM endpoint](bpx8iKUHF.png)
Confirm that everything worked correctly by hopping over to the **Extensibility** tab, selecting **Action Runs** on the left, and changing the **User Runs** filter to say *Integration Runs*.
![Extensibility action runs](/images/posts-2020/e4PTJxfqH.png)
![Extensibility action runs](e4PTJxfqH.png)
Select the newest `phpIPAM_ValidateEndpoint` action and make sure it has a happy green *Completed* status. You can also review the Inputs to make sure they look like what you expected:
```json
{
@ -503,7 +503,7 @@ vRA runs the `phpIPAM_GetIPRanges` action about every ten minutes so keep checki
Note that it *did not* pick up my "Home Network" range since it wasn't set to be a pool.
We can also navigate to **Infrastructure > Networks > IP Ranges** to view them in all their glory:
![Reviewing the discovered IP ranges](/images/posts-2020/7_QI-Ti8g.png)
![Reviewing the discovered IP ranges](7_QI-Ti8g.png)
You can then follow [these instructions](https://docs.vmware.com/en/vRealize-Automation/8.3/Using-and-Managing-Cloud-Assembly/GUID-410899CA-1B02-4507-96AD-DFE622D2DD47.html) to associate the external IP ranges with networks available for vRA deployments.
@ -637,7 +637,7 @@ The full `allocate_ip` code is [here](https://github.com/jbowdre/phpIPAM-for-vRA
[2021-02-22 01:31:41,790] [INFO] - Successfully reserved ['172.16.40.2'] for BOW-VLTST-XXX41.
```
You can also check for a reserved address in phpIPAM:
![The reserved address in phpIPAM](/images/posts-2020/3BQnEd0bY.png)
![The reserved address in phpIPAM](3BQnEd0bY.png)
Almost done!

View file

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 378 KiB

View file

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

View file

Before

Width:  |  Height:  |  Size: 759 KiB

After

Width:  |  Height:  |  Size: 759 KiB

View file

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View file

@ -1,8 +1,8 @@
---
series: Tips
date: "2021-02-18T08:34:30Z"
thumbnail: images/posts-2020/PPZu_UOGO.png
usePageBundles: false
thumbnail: PPZu_UOGO.png
usePageBundles: true
tags:
- logs
- vmware
@ -11,21 +11,21 @@ toc: false
---
I recently ran into a peculiar issue after upgrading my vRealize Automation homelab to the new 8.3 release, and the error message displayed in the UI didn't give me a whole lot of information to work with:
![Unfortunately my 'Essential Googling The Error Message' O'RLY book was no help with making the bad words go away](/images/posts-2020/IL29_Shlg.png)
![Unfortunately my 'Essential Googling The Error Message' O'RLY book was no help with making the bad words go away](IL29_Shlg.png)
I connected to the vRA appliance to try to find the relevant log excerpt, but [doing so isn't all that straightforward](https://www.stevenbright.com/2020/01/vmware-vrealize-automation-8-0-logs/#:~:text=Access%20Logs%20from%20the%20CLI) given the containerized nature of the services.
So instead I used the `vracli log-bundle` command to generate a bundle of all relevant logs, and I then transferred the resulting (2.2GB!) `log-bundle.tar` to my workstation for further investigation. I expanded the tar and ran `tree -P '*.log'` to get a quick idea of what I've got to deal with:
![That's a lot of logs!](/images/posts-2020/wAa9KjBHO.png)
![That's a lot of logs!](wAa9KjBHO.png)
Ugh. Even if I knew which logs I wanted to look at (and I don't) it would take ages to dig through all of this. There's got to be a better way.
And there is! Visual Studio Code lets you open an entire directory tree in the editor:
![Directory opened in VS Code](/images/posts-2020/SBKtJ8K1p.png)
![Directory opened in VS Code](SBKtJ8K1p.png)
You can then "Find in Files" with `Ctrl`+`Shift`+`F`, and VS Code will *very* quickly search through all the files to find what you're looking for:
![Searching all files](/images/posts-2020/PPZu_UOGO.png)
![Searching all files](PPZu_UOGO.png)
You can also click the "Open in editor" link at the top of the search results to open the matching snippets in a single view:
![All the matching strings together](/images/posts-2020/kJ_l7gPD2.png)
![All the matching strings together](kJ_l7gPD2.png)
Adjusting the number at the far top right of that view will dynamically tweak how many context lines are included with each line containing the search term.

View file

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View file

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 493 KiB

View file

Before

Width:  |  Height:  |  Size: 364 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Some files were not shown because too many files have changed in this diff Show more