Re-enable pygments and add copy-code button

This commit is contained in:
Dave Gallant
2023-12-17 18:53:46 -05:00
parent e7fc123bfe
commit bbf6a152e0
89 changed files with 1449 additions and 940 deletions

View File

@@ -7,7 +7,9 @@
font-weight: 600; font-weight: 600;
} }
h2:hover a, h3:hover a, h4:hover a { h2:hover a,
h3:hover a,
h4:hover a {
visibility: visible; visibility: visible;
text-decoration: none; text-decoration: none;
} }

View File

@@ -4,8 +4,8 @@ languageCode: en-us
googleAnalytics: G-V8WJDERTX9 googleAnalytics: G-V8WJDERTX9
copyright: Dave Gallant copyright: Dave Gallant
preserveTaxonomyNames: true preserveTaxonomyNames: true
pygmentsstyle: "monokai" pygmentsstyle: nord
pygmentscodefences: false pygmentscodefences: true
pygmentscodefencesguesssyntax: true pygmentscodefencesguesssyntax: true
theme: theme:
- archie - archie

View File

@@ -29,7 +29,6 @@ flowchartDiagrams:
sequenceDiagrams: sequenceDiagrams:
enable: false enable: false
options: "" options: ""
--- ---
<!--more--> <!--more-->
@@ -48,9 +47,9 @@ This [gist](https://gist.github.com/triangletodd/02f595cd4c0dc9aac5f7763ca226418
There is an issue on Kubernetes regarding swap [here](https://github.com/kubernetes/kubernetes/issues/53533). There claims to be support for swap in 1.22, but for now let's disable it: There is an issue on Kubernetes regarding swap [here](https://github.com/kubernetes/kubernetes/issues/53533). There claims to be support for swap in 1.22, but for now let's disable it:
``` ```shell
sysctl vm.swappiness=0 sudo sysctl vm.swappiness=0
swapoff -a sudo swapoff -a
``` ```
It might be worth experimenting with swap enabled in the future to see how that might affect performance. It might be worth experimenting with swap enabled in the future to see how that might affect performance.
@@ -59,7 +58,7 @@ It might be worth experimenting with swap enabled in the future to see how that
To avoid IP Forwarding issues with Traefik, run the following on the host: To avoid IP Forwarding issues with Traefik, run the following on the host:
```sh ```shell
sudo sysctl net.ipv4.ip_forward=1 sudo sysctl net.ipv4.ip_forward=1
sudo sysctl net.ipv6.conf.all.forwarding=1 sudo sysctl net.ipv6.conf.all.forwarding=1
sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
@@ -81,7 +80,7 @@ Now back on the host run `pct list` to determine what VMID it was given.
Open `/etc/pve/lxc/$VMID.conf` and append: Open `/etc/pve/lxc/$VMID.conf` and append:
```sh ```
lxc.apparmor.profile: unconfined lxc.apparmor.profile: unconfined
lxc.cap.drop: lxc.cap.drop:
lxc.mount.auto: "proc:rw sys:rw" lxc.mount.auto: "proc:rw sys:rw"
@@ -92,6 +91,7 @@ All of the above configurations are described in the [manpages](https://linuxcon
Notice that `cgroup2` is used since Proxmox VE 7.0 has switched to a [pure cgroupv2 environment](https://pve.proxmox.com/pve-docs/chapter-pct.html#pct_cgroup). Notice that `cgroup2` is used since Proxmox VE 7.0 has switched to a [pure cgroupv2 environment](https://pve.proxmox.com/pve-docs/chapter-pct.html#pct_cgroup).
Thankfully cgroup v2 support has been supported in k3s with these contributions: Thankfully cgroup v2 support has been supported in k3s with these contributions:
- https://github.com/k3s-io/k3s/pull/2584 - https://github.com/k3s-io/k3s/pull/2584
- https://github.com/k3s-io/k3s/pull/2844 - https://github.com/k3s-io/k3s/pull/2844
@@ -99,7 +99,7 @@ Thankfully cgroup v2 support has been supported in k3s with these contributions:
From within the container, run: From within the container, run:
```sh ```shell
echo '#!/bin/sh -e echo '#!/bin/sh -e
ln -s /dev/console /dev/kmsg ln -s /dev/console /dev/kmsg
mount --make-rshared /' > /etc/rc.local mount --make-rshared /' > /etc/rc.local
@@ -113,7 +113,7 @@ One of the simplest ways to install K3s on a remote host is to use [k3sup](https
Ensure that you supply a valid `CONTAINER_IP` and choose the `k3s-version` you prefer. Ensure that you supply a valid `CONTAINER_IP` and choose the `k3s-version` you prefer.
As of 2021/11, it is still defaulting to the 1.19 channel, so I overrode it to 1.22 for cgroup v2 support. See the published releases [here](https://github.com/k3s-io/k3s/releases). As of 2021/11, it is still defaulting to the 1.19 channel, so I overrode it to 1.22 for cgroup v2 support. See the published releases [here](https://github.com/k3s-io/k3s/releases).
```sh ```shell
ssh-copy-id root@$CONTAINER_IP ssh-copy-id root@$CONTAINER_IP
k3sup install --ip $CONTAINER_IP --user root --k3s-version v1.22.3+k3s1 k3sup install --ip $CONTAINER_IP --user root --k3s-version v1.22.3+k3s1
``` ```
@@ -124,7 +124,6 @@ If all goes well, you should see a path to the `kubeconfig` generated. I moved t
Installing K3s in LXC on Proxmox works with a few tweaks to the default configuration. I later followed the Tekton's [Getting Started](https://tekton.dev/docs/getting-started/) guide and was able to deploy it in a few commands. Installing K3s in LXC on Proxmox works with a few tweaks to the default configuration. I later followed the Tekton's [Getting Started](https://tekton.dev/docs/getting-started/) guide and was able to deploy it in a few commands.
```console ```console
$ kubectl get all --namespace tekton-pipelines $ kubectl get all --namespace tekton-pipelines
NAME READY STATUS RESTARTS AGE NAME READY STATUS RESTARTS AGE

View File

@@ -56,13 +56,13 @@ A few days ago, yewtu.be went down briefly, and that motivated me enough to self
The quickest way to get invidious up is with docker-compose as mentioned in the [docs](https://docs.invidious.io/installation/). The quickest way to get invidious up is with docker-compose as mentioned in the [docs](https://docs.invidious.io/installation/).
I made a few modifications (such as pinning the container's tag), and ended up with: I made a few modifications, and ended up with:
```yaml ```yaml
version: "3" version: "3"
services: services:
invidious: invidious:
image: quay.io/invidious/invidious:5160d8bae39dc5cc5d51abee90571a03c08d0f2b image: quay.io/invidious/invidious
restart: unless-stopped restart: unless-stopped
ports: ports:
- "0.0.0.0:3000:3000" - "0.0.0.0:3000:3000"

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
@@ -92,6 +92,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -121,6 +123,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -23,8 +23,8 @@ Feel free to reach out at me@davegallant.ca."/>
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -71,7 +71,7 @@ Feel free to reach out at me@davegallant.ca."/>
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -94,6 +94,8 @@ Feel free to reach out at me@davegallant.ca."/>
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<main> <main>
@@ -145,6 +147,7 @@ Feel free to reach out at me@davegallant.ca."/>
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -109,93 +115,81 @@ As of right now, the latest AUR is <code>4.2.2-1</code>.</p>
<p>These steps highlight how to get it working with <code>Python3.8</code> by making a 1 line modification to AppGate source code.</p> <p>These steps highlight how to get it working with <code>Python3.8</code> by making a 1 line modification to AppGate source code.</p>
<h1 id="packaging">Packaging</h1> <h1 id="packaging">Packaging</h1>
<p>We already know the community package is currently out of date, so let&rsquo;s clone it:</p> <p>We already know the community package is currently out of date, so let&rsquo;s clone it:</p>
<pre><code class="language-shell">git clone https://aur.archlinux.org/appgate-sdp.git <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git clone https://aur.archlinux.org/appgate-sdp.git
cd appgate-sdp </span></span><span style="display:flex;"><span><span style="color:#81a1c1">cd</span> appgate-sdp
</code></pre> </span></span></code></pre></div><p>You&rsquo;ll likely notice that the version is not what we want, so let&rsquo;s modify the <code>PKGBUILD</code> to the following:</p>
<p>You&rsquo;ll likely notice that the version is not what we want, so let&rsquo;s modify the <code>PKGBUILD</code> to the following:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#616e87;font-style:italic"># Maintainer: Pawel Mosakowski &lt;pawel at mosakowski dot net&gt;</span>
<pre><code class="language-shell"># Maintainer: Pawel Mosakowski &lt;pawel at mosakowski dot net&gt; </span></span><span style="display:flex;"><span>pkgname<span style="color:#81a1c1">=</span>appgate-sdp
pkgname=appgate-sdp </span></span><span style="display:flex;"><span>conflicts<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#39;appgate-sdp-headless&#39;</span><span style="color:#81a1c1">)</span>
conflicts=('appgate-sdp-headless') </span></span><span style="display:flex;"><span>pkgver<span style="color:#81a1c1">=</span>4.3.2
pkgver=4.3.2 </span></span><span style="display:flex;"><span>_download_pkgver<span style="color:#81a1c1">=</span>4.3
_download_pkgver=4.3 </span></span><span style="display:flex;"><span>pkgrel<span style="color:#81a1c1">=</span><span style="color:#b48ead">1</span>
pkgrel=1 </span></span><span style="display:flex;"><span>epoch<span style="color:#81a1c1">=</span>
epoch= </span></span><span style="display:flex;"><span>pkgdesc<span style="color:#81a1c1">=</span><span style="color:#a3be8c">&#34;Software Defined Perimeter - GUI client&#34;</span>
pkgdesc=&quot;Software Defined Perimeter - GUI client&quot; </span></span><span style="display:flex;"><span>arch<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#39;x86_64&#39;</span><span style="color:#81a1c1">)</span>
arch=('x86_64') </span></span><span style="display:flex;"><span>url<span style="color:#81a1c1">=</span><span style="color:#a3be8c">&#34;https://www.cyxtera.com/essential-defense/appgate-sdp/support&#34;</span>
url=&quot;https://www.cyxtera.com/essential-defense/appgate-sdp/support&quot; </span></span><span style="display:flex;"><span>license<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#39;custom&#39;</span><span style="color:#81a1c1">)</span>
license=('custom') </span></span><span style="display:flex;"><span><span style="color:#616e87;font-style:italic"># dependecies calculated by namcap</span>
# dependecies calculated by namcap </span></span><span style="display:flex;"><span>depends<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#39;gconf&#39;</span> <span style="color:#a3be8c">&#39;libsecret&#39;</span> <span style="color:#a3be8c">&#39;gtk3&#39;</span> <span style="color:#a3be8c">&#39;python&#39;</span> <span style="color:#a3be8c">&#39;nss&#39;</span> <span style="color:#a3be8c">&#39;libxss&#39;</span> <span style="color:#a3be8c">&#39;nodejs&#39;</span> <span style="color:#a3be8c">&#39;dnsmasq&#39;</span><span style="color:#81a1c1">)</span>
depends=('gconf' 'libsecret' 'gtk3' 'python' 'nss' 'libxss' 'nodejs' 'dnsmasq') </span></span><span style="display:flex;"><span>source<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#34;https://sdpdownloads.cyxtera.com/AppGate-SDP-</span><span style="color:#a3be8c">${</span>_download_pkgver<span style="color:#a3be8c">}</span><span style="color:#a3be8c">/clients/</span><span style="color:#a3be8c">${</span>pkgname<span style="color:#a3be8c">}</span><span style="color:#a3be8c">_</span><span style="color:#a3be8c">${</span>pkgver<span style="color:#a3be8c">}</span><span style="color:#a3be8c">_amd64.deb&#34;</span>
source=(&quot;https://sdpdownloads.cyxtera.com/AppGate-SDP-${_download_pkgver}/clients/${pkgname}_${pkgver}_amd64.deb&quot; </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;appgatedriver.service&#34;</span><span style="color:#81a1c1">)</span>
&quot;appgatedriver.service&quot;) </span></span><span style="display:flex;"><span>options<span style="color:#81a1c1">=(</span>staticlibs<span style="color:#81a1c1">)</span>
options=(staticlibs) </span></span><span style="display:flex;"><span>prepare<span style="color:#81a1c1">()</span> <span style="color:#81a1c1">{</span>
prepare() { </span></span><span style="display:flex;"><span> tar -xf data.tar.xz
tar -xf data.tar.xz </span></span><span style="display:flex;"><span><span style="color:#81a1c1">}</span>
} </span></span><span style="display:flex;"><span>package<span style="color:#81a1c1">()</span> <span style="color:#81a1c1">{</span>
package() { </span></span><span style="display:flex;"><span> cp -dpr <span style="color:#a3be8c">&#34;</span><span style="color:#a3be8c">${</span>srcdir<span style="color:#a3be8c">}</span><span style="color:#a3be8c">&#34;</span>/<span style="color:#81a1c1">{</span>etc,lib,opt,usr<span style="color:#81a1c1">}</span> <span style="color:#a3be8c">&#34;</span><span style="color:#a3be8c">${</span>pkgdir<span style="color:#a3be8c">}</span><span style="color:#a3be8c">&#34;</span>
cp -dpr &quot;${srcdir}&quot;/{etc,lib,opt,usr} &quot;${pkgdir}&quot; </span></span><span style="display:flex;"><span> mv -v <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/lib/systemd/system&#34;</span> <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/lib/systemd/&#34;</span>
mv -v &quot;$pkgdir/lib/systemd/system&quot; &quot;$pkgdir/usr/lib/systemd/&quot; </span></span><span style="display:flex;"><span> rm -vrf <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/lib&#34;</span>
rm -vrf &quot;$pkgdir/lib&quot; </span></span><span style="display:flex;"><span> cp -v <span style="color:#a3be8c">&#34;</span>$srcdir<span style="color:#a3be8c">/appgatedriver.service&#34;</span> <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/lib/systemd/system/appgatedriver.service&#34;</span>
cp -v &quot;$srcdir/appgatedriver.service&quot; &quot;$pkgdir/usr/lib/systemd/system/appgatedriver.service&quot; </span></span><span style="display:flex;"><span> mkdir -vp <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/licenses/appgate-sdp&#34;</span>
mkdir -vp &quot;$pkgdir/usr/share/licenses/appgate-sdp&quot; </span></span><span style="display:flex;"><span> cp -v <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/doc/appgate/copyright&#34;</span> <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/licenses/appgate-sdp&#34;</span>
cp -v &quot;$pkgdir/usr/share/doc/appgate/copyright&quot; &quot;$pkgdir/usr/share/licenses/appgate-sdp&quot; </span></span><span style="display:flex;"><span> cp -v <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/doc/appgate/LICENSE.github&#34;</span> <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/licenses/appgate-sdp&#34;</span>
cp -v &quot;$pkgdir/usr/share/doc/appgate/LICENSE.github&quot; &quot;$pkgdir/usr/share/licenses/appgate-sdp&quot; </span></span><span style="display:flex;"><span> cp -v <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/doc/appgate/LICENSES.chromium.html.bz2&#34;</span> <span style="color:#a3be8c">&#34;</span>$pkgdir<span style="color:#a3be8c">/usr/share/licenses/appgate-sdp&#34;</span>
cp -v &quot;$pkgdir/usr/share/doc/appgate/LICENSES.chromium.html.bz2&quot; &quot;$pkgdir/usr/share/licenses/appgate-sdp&quot; </span></span><span style="display:flex;"><span><span style="color:#81a1c1">}</span>
} </span></span><span style="display:flex;"><span>md5sums<span style="color:#81a1c1">=(</span><span style="color:#a3be8c">&#39;17101aac7623c06d5fbb95f50cf3dbdc&#39;</span>
md5sums=('17101aac7623c06d5fbb95f50cf3dbdc' </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#39;002644116e20b2d79fdb36b7677ab4cf&#39;</span><span style="color:#81a1c1">)</span>
'002644116e20b2d79fdb36b7677ab4cf') </span></span></code></pre></div><p>Let&rsquo;s first make sure we have some dependencies. If you do not have <a href="https://github.com/Jguer/yay">yay</a>, check it out.</p>
<div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>yay -S dnsmasq gconf
</code></pre> </span></span></code></pre></div><p>Now, let&rsquo;s install it:</p>
<p>Let&rsquo;s first make sure we have some dependencies. If you do not have <a href="https://github.com/Jguer/yay">yay</a>, check it out.</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>makepkg -si
<pre><code class="language-shell">yay -S dnsmasq gconf </span></span></code></pre></div><h1 id="running-the-client">Running the client</h1>
</code></pre>
<p>Now, let&rsquo;s install it:</p>
<pre><code class="language-shell">makepkg -si
</code></pre>
<h1 id="running-the-client">Running the client</h1>
<p>Ok, let&rsquo;s run the client by executing <code>appgate</code>.</p> <p>Ok, let&rsquo;s run the client by executing <code>appgate</code>.</p>
<p>It complains about not being able to connect.</p> <p>It complains about not being able to connect.</p>
<p>Easy fix:</p> <p>Easy fix:</p>
<pre><code class="language-shell">sudo systemctl start appgatedriver.service <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo systemctl start appgatedriver.service
</code></pre> </span></span></code></pre></div><p>Now we should be connected&hellip; but DNS is not working?</p>
<p>Now we should be connected&hellip; but DNS is not working?</p>
<h1 id="fixing-the-dns">Fixing the DNS</h1> <h1 id="fixing-the-dns">Fixing the DNS</h1>
<p>Running <code>resolvectl</code> should display that something is not right.</p> <p>Running <code>resolvectl</code> should display that something is not right.</p>
<p>Why is the DNS not being set by appgate?</p> <p>Why is the DNS not being set by appgate?</p>
<pre><code class="language-shell">$ head -3 /opt/appgate/linux/set_dns <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ head -3 /opt/appgate/linux/set_dns
#!/usr/bin/env python3 </span></span><span style="display:flex;"><span><span style="color:#616e87;font-style:italic">#!/usr/bin/env python3</span>
''' </span></span><span style="display:flex;"><span><span style="color:#a3be8c">&#39;&#39;</span><span style="color:#bf616a">&#39;</span>
This is used to set and unset the DNS. </span></span><span style="display:flex;"><span>This is used to <span style="color:#81a1c1">set</span> and <span style="color:#81a1c1">unset</span> the DNS.
</code></pre> </span></span></code></pre></div><p>It seems like python3 is required for the DNS setting to happen.
<p>It seems like python3 is required for the DNS setting to happen.
Let&rsquo;s try to run it.</p> Let&rsquo;s try to run it.</p>
<pre><code class="language-shell">$ sudo /opt/appgate/linux/set_dns <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo /opt/appgate/linux/set_dns
/opt/appgate/linux/set_dns:88: SyntaxWarning: &quot;is&quot; with a literal. Did you mean &quot;==&quot;? </span></span><span style="display:flex;"><span>/opt/appgate/linux/set_dns:88: SyntaxWarning: <span style="color:#a3be8c">&#34;is&#34;</span> with a literal. Did you mean <span style="color:#a3be8c">&#34;==&#34;</span>?
servers = [( socket.AF_INET if x.version is 4 else socket.AF_INET6, map(int, x.packed)) for x in servers] </span></span><span style="display:flex;"><span> servers <span style="color:#81a1c1">=</span> <span style="color:#81a1c1">[(</span> socket.AF_INET <span style="color:#81a1c1;font-weight:bold">if</span> x.version is <span style="color:#b48ead">4</span> <span style="color:#81a1c1;font-weight:bold">else</span> socket.AF_INET6, map<span style="color:#81a1c1">(</span>int, x.packed<span style="color:#81a1c1">))</span> <span style="color:#81a1c1;font-weight:bold">for</span> x in servers<span style="color:#81a1c1">]</span>
Traceback (most recent call last): </span></span><span style="display:flex;"><span>Traceback <span style="color:#81a1c1">(</span>most recent call last<span style="color:#81a1c1">)</span>:
File &quot;/opt/appgate/linux/set_dns&quot;, line 30, in &lt;module&gt; </span></span><span style="display:flex;"><span> File <span style="color:#a3be8c">&#34;/opt/appgate/linux/set_dns&#34;</span>, line 30, in &lt;module&gt;
import dbus </span></span><span style="display:flex;"><span> import dbus
ModuleNotFoundError: No module named 'dbus' </span></span><span style="display:flex;"><span>ModuleNotFoundError: No module named <span style="color:#a3be8c">&#39;dbus&#39;</span>
</code></pre> </span></span></code></pre></div><p>Ok, let&rsquo;s install it:</p>
<p>Ok, let&rsquo;s install it:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo python3.8 -m pip install dbus-python
<pre><code class="language-shell">$ sudo python3.8 -m pip install dbus-python </span></span></code></pre></div><p>Will it work now? Not yet. There&rsquo;s another issue:</p>
</code></pre> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo /opt/appgate/linux/set_dns
<p>Will it work now? Not yet. There&rsquo;s another issue:</p> </span></span><span style="display:flex;"><span>/opt/appgate/linux/set_dns:88: SyntaxWarning: <span style="color:#a3be8c">&#34;is&#34;</span> with a literal. Did you mean <span style="color:#a3be8c">&#34;==&#34;</span>?
<pre><code class="language-shell">$ sudo /opt/appgate/linux/set_dns </span></span><span style="display:flex;"><span> servers <span style="color:#81a1c1">=</span> <span style="color:#81a1c1">[(</span> socket.AF_INET <span style="color:#81a1c1;font-weight:bold">if</span> x.version is <span style="color:#b48ead">4</span> <span style="color:#81a1c1;font-weight:bold">else</span> socket.AF_INET6, map<span style="color:#81a1c1">(</span>int, x.packed<span style="color:#81a1c1">))</span> <span style="color:#81a1c1;font-weight:bold">for</span> x in servers<span style="color:#81a1c1">]</span>
/opt/appgate/linux/set_dns:88: SyntaxWarning: &quot;is&quot; with a literal. Did you mean &quot;==&quot;? </span></span><span style="display:flex;"><span>module <span style="color:#a3be8c">&#39;platform&#39;</span> has no attribute <span style="color:#a3be8c">&#39;linux_distribution&#39;</span>
servers = [( socket.AF_INET if x.version is 4 else socket.AF_INET6, map(int, x.packed)) for x in servers] </span></span></code></pre></div><p>This is a breaking change in Python3.8.</p>
module 'platform' has no attribute 'linux_distribution'
</code></pre>
<p>This is a breaking change in Python3.8.</p>
<p>So what is calling <code>platform.linux_distribution</code>?</p> <p>So what is calling <code>platform.linux_distribution</code>?</p>
<p>Let&rsquo;s search for it:</p> <p>Let&rsquo;s search for it:</p>
<pre><code class="language-shell">$ sudo grep -r 'linux_distribution' /opt/appgate/linux/ <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo grep -r <span style="color:#a3be8c">&#39;linux_distribution&#39;</span> /opt/appgate/linux/
/opt/appgate/linux/nm.py: if platform.linux_distribution()[0] != 'Fedora': </span></span><span style="display:flex;"><span>/opt/appgate/linux/nm.py: <span style="color:#81a1c1;font-weight:bold">if</span> platform.linux_distribution<span style="color:#81a1c1">()[</span>0<span style="color:#81a1c1">]</span> !<span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#39;Fedora&#39;</span>:
</code></pre> </span></span></code></pre></div><p>Aha! So this is in the local AppGate source code. This should be an easy fix. Let&rsquo;s just replace this line with:</p>
<p>Aha! So this is in the local AppGate source code. This should be an easy fix. Let&rsquo;s just replace this line with:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#81a1c1;font-weight:bold">if</span> <span style="color:#81a1c1;font-weight:bold">True</span><span style="color:#eceff4">:</span> <span style="color:#616e87;font-style:italic"># Since we are not using Fedora :)</span>
<pre><code class="language-python">if True: # Since we are not using Fedora :) </span></span></code></pre></div><h1 id="wrapping-up">Wrapping up</h1>
</code></pre>
<h1 id="wrapping-up">Wrapping up</h1>
<p>It turns out there are <a href="https://docs.python.org/3.7/library/platform.html#platform.linux_distribution">breaking changes</a> in Python3.8.</p> <p>It turns out there are <a href="https://docs.python.org/3.7/library/platform.html#platform.linux_distribution">breaking changes</a> in Python3.8.</p>
<p>The docs say <code>Deprecated since version 3.5, will be removed in version 3.8: See alternative like the distro package.</code></p> <p>The docs say <code>Deprecated since version 3.5, will be removed in version 3.8: See alternative like the distro package.</code></p>
<p>I suppose this highlights one of the caveats of relying upon the system&rsquo;s python, rather than having an isolated, dedicated environment for all dependencies.</p></section> <p>I suppose this highlights one of the caveats of relying upon the system&rsquo;s python, rather than having an isolated, dedicated environment for all dependencies.</p></section>
@@ -271,6 +265,9 @@ module 'platform' has no attribute 'linux_distribution'
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<main> <main>
@@ -221,6 +223,7 @@ Containers have much less overhead in terms of boot time and storage allocation.
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -107,10 +113,9 @@
<h2 id="what-is-home-manager">What is home-manager?<a href="#what-is-home-manager" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="what-is-home-manager">What is home-manager?<a href="#what-is-home-manager" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>Before understanding home-manager, it is worth briefly discussing what nix is. <a href="https://nixos.org/">nix</a> is a package manager that originally spawned from a <a href="https://edolstra.github.io/pubs/phd-thesis.pdf">PhD thesis</a>. Unlike other package managers, it uses symbolic links to keep track of the currently installed packages, keeping around the old ones in case you may want to rollback.</p> <p>Before understanding home-manager, it is worth briefly discussing what nix is. <a href="https://nixos.org/">nix</a> is a package manager that originally spawned from a <a href="https://edolstra.github.io/pubs/phd-thesis.pdf">PhD thesis</a>. Unlike other package managers, it uses symbolic links to keep track of the currently installed packages, keeping around the old ones in case you may want to rollback.</p>
<p>For example, I have used nix to install the package <a href="https://search.nixos.org/packages?channel=unstable&amp;show=bind&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=bind">bind</a> which includes <code>dig</code>. You can see that it is available on multiple platforms. The absolute path of <code>dig</code> can be found by running:</p> <p>For example, I have used nix to install the package <a href="https://search.nixos.org/packages?channel=unstable&amp;show=bind&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=bind">bind</a> which includes <code>dig</code>. You can see that it is available on multiple platforms. The absolute path of <code>dig</code> can be found by running:</p>
<pre><code class="language-console">$ ls -lh $(which dig) <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> ls -lh <span style="color:#81a1c1;font-weight:bold">$(</span>which dig<span style="color:#81a1c1;font-weight:bold">)</span>
lrwxr-xr-x 73 root 31 Dec 1969 /run/current-system/sw/bin/dig -&gt; /nix/store/0r4qdyprljd3dki57jn6c6a8dh2rbg9g-bind-9.16.16-dnsutils/bin/dig </span></span><span style="display:flex;"><span>lrwxr-xr-x 73 root 31 Dec 1969 /run/current-system/sw/bin/dig -&gt; /nix/store/0r4qdyprljd3dki57jn6c6a8dh2rbg9g-bind-9.16.16-dnsutils/bin/dig
</code></pre> </span></span></code></pre></div><p>Notice that there is a hash included in the file path? This is a nix store path and is computed by the nix package manager. This <a href="https://nixos.org/guides/nix-pills/nix-store-paths.html">nix pill</a> does a good job explaining how this hash is computed. All of the nix pills are worth a read, if you are interested in learning more about nix itself. However, using home-manager does not require extensive knowledge of nix.</p>
<p>Notice that there is a hash included in the file path? This is a nix store path and is computed by the nix package manager. This <a href="https://nixos.org/guides/nix-pills/nix-store-paths.html">nix pill</a> does a good job explaining how this hash is computed. All of the nix pills are worth a read, if you are interested in learning more about nix itself. However, using home-manager does not require extensive knowledge of nix.</p>
<p>Part of the nix ecosystem includes <a href="https://github.com/NixOS/nixpkgs">nixpkgs</a>. Many popular tools can be found already packaged in this repository. As you can see with these <a href="https://repology.org/repositories/statistics/total">stats</a>, there is a large number of existing packages that are being maintained by the community. Contributing a new package is easy, and anyone can do it!</p> <p>Part of the nix ecosystem includes <a href="https://github.com/NixOS/nixpkgs">nixpkgs</a>. Many popular tools can be found already packaged in this repository. As you can see with these <a href="https://repology.org/repositories/statistics/total">stats</a>, there is a large number of existing packages that are being maintained by the community. Contributing a new package is easy, and anyone can do it!</p>
<p>home-manager leverages the nix package manager (and nixpkgs), as well the nix language so that you can declaratively define your system configuration. I store my <a href="https://github.com/davegallant/nix-config">nix-config</a> in git so that I can keep track of my packages and configurations, and retain a clean and informative git commit history so that I can understand what changed and why.</p> <p>home-manager leverages the nix package manager (and nixpkgs), as well the nix language so that you can declaratively define your system configuration. I store my <a href="https://github.com/davegallant/nix-config">nix-config</a> in git so that I can keep track of my packages and configurations, and retain a clean and informative git commit history so that I can understand what changed and why.</p>
<h2 id="setting-up-home-manager">Setting up home-manager<a href="#setting-up-home-manager" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="setting-up-home-manager">Setting up home-manager<a href="#setting-up-home-manager" class="hanchor" ariaLabel="Anchor">#</a></h2>
@@ -118,123 +123,119 @@ lrwxr-xr-x 73 root 31 Dec 1969 /run/current-system/sw/bin/dig -&gt; /nix/store/
<p>⚠️ If you run this on your main machine, make sure you backup your configuration files first. home-manager is pretty good about not overwriting existing configuration, but it is better to have a backup! Alternatively, you could test this out on a VM or cloud instance.</p> <p>⚠️ If you run this on your main machine, make sure you backup your configuration files first. home-manager is pretty good about not overwriting existing configuration, but it is better to have a backup! Alternatively, you could test this out on a VM or cloud instance.</p>
</blockquote> </blockquote>
<p>The first thing you should do is <a href="https://nixos.org/guides/install-nix.html">install nix</a>:</p> <p>The first thing you should do is <a href="https://nixos.org/guides/install-nix.html">install nix</a>:</p>
<pre><code class="language-shell">curl -L https://nixos.org/nix/install | sh <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>curl -L https://nixos.org/nix/install <span style="color:#eceff4">|</span> sh
</code></pre> </span></span></code></pre></div><p>It&rsquo;s generally not a good idea to curl and execute files from the internet (without verifying integrity), so you might want to download the install script first and take a look before executing it!</p>
<p>It&rsquo;s generally not a good idea to curl and execute files from the internet (without verifying integrity), so you might want to download the install script first and take a look before executing it!</p>
<p>Open up a new shell in your terminal and running <code>nix</code> <em>should</em> work. If not, run <code>. ~/.nix-profile/etc/profile.d/nix.sh</code></p> <p>Open up a new shell in your terminal and running <code>nix</code> <em>should</em> work. If not, run <code>. ~/.nix-profile/etc/profile.d/nix.sh</code></p>
<p>Now, <a href="https://github.com/nix-community/home-manager#installation">install home-manager</a>:</p> <p>Now, <a href="https://github.com/nix-community/home-manager#installation">install home-manager</a>:</p>
<pre><code class="language-shell">nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
nix-channel --update </span></span><span style="display:flex;"><span>nix-channel --update
nix-shell '&lt;home-manager&gt;' -A install </span></span><span style="display:flex;"><span>nix-shell <span style="color:#a3be8c">&#39;&lt;home-manager&gt;&#39;</span> -A install
</code></pre> </span></span></code></pre></div><p>You should see a wave of <code>/nix/store/*</code> paths being displayed on your screen.</p>
<p>You should see a wave of <code>/nix/store/*</code> paths being displayed on your screen.</p>
<p>Now, to start off with a basic configuration, open up <code>~/.config/nixpkgs/home.nix</code> in the editor of your choice and paste this in (you will want to change <code>userName</code> and <code>homeDirectory</code>):</p> <p>Now, to start off with a basic configuration, open up <code>~/.config/nixpkgs/home.nix</code> in the editor of your choice and paste this in (you will want to change <code>userName</code> and <code>homeDirectory</code>):</p>
<pre><code class="language-nix">{ config, pkgs, ... }: <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span><span style="color:#eceff4">{</span> config<span style="color:#81a1c1">,</span> pkgs<span style="color:#81a1c1">,</span> <span style="color:#81a1c1">...</span> <span style="color:#eceff4">}:</span>
</span></span><span style="display:flex;"><span>
{ </span></span><span style="display:flex;"><span><span style="color:#eceff4">{</span>
programs.home-manager.enable = true; </span></span><span style="display:flex;"><span> programs<span style="color:#81a1c1">.</span>home-manager<span style="color:#81a1c1">.</span>enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
</span></span><span style="display:flex;"><span>
home = { </span></span><span style="display:flex;"><span> home <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
username = &quot;dave&quot;; </span></span><span style="display:flex;"><span> username <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;dave&#34;</span><span style="color:#eceff4">;</span>
homeDirectory = &quot;/home/dave&quot;; </span></span><span style="display:flex;"><span> homeDirectory <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;/home/dave&#34;</span><span style="color:#eceff4">;</span>
stateVersion = &quot;21.11&quot;; </span></span><span style="display:flex;"><span> stateVersion <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;21.11&#34;</span><span style="color:#eceff4">;</span>
packages = with pkgs; [ </span></span><span style="display:flex;"><span> packages <span style="color:#81a1c1">=</span> <span style="color:#81a1c1;font-weight:bold">with</span> pkgs<span style="color:#eceff4">;</span> <span style="color:#eceff4">[</span>
bind </span></span><span style="display:flex;"><span> bind
exa </span></span><span style="display:flex;"><span> exa
fd </span></span><span style="display:flex;"><span> fd
ripgrep </span></span><span style="display:flex;"><span> ripgrep
]; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">];</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
programs = { </span></span><span style="display:flex;"><span> programs <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
</span></span><span style="display:flex;"><span>
git = { </span></span><span style="display:flex;"><span> git <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
enable = true; </span></span><span style="display:flex;"><span> enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
aliases = { </span></span><span style="display:flex;"><span> aliases <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
aa = &quot;add -A .&quot;; </span></span><span style="display:flex;"><span> aa <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;add -A .&#34;</span><span style="color:#eceff4">;</span>
br = &quot;branch&quot;; </span></span><span style="display:flex;"><span> br <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;branch&#34;</span><span style="color:#eceff4">;</span>
c = &quot;commit -S&quot;; </span></span><span style="display:flex;"><span> c <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;commit -S&#34;</span><span style="color:#eceff4">;</span>
ca = &quot;commit -S --amend&quot;; </span></span><span style="display:flex;"><span> ca <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;commit -S --amend&#34;</span><span style="color:#eceff4">;</span>
cb = &quot;checkout -b&quot;; </span></span><span style="display:flex;"><span> cb <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;checkout -b&#34;</span><span style="color:#eceff4">;</span>
co = &quot;checkout&quot;; </span></span><span style="display:flex;"><span> co <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;checkout&#34;</span><span style="color:#eceff4">;</span>
d = &quot;diff&quot;; </span></span><span style="display:flex;"><span> d <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;diff&#34;</span><span style="color:#eceff4">;</span>
l = </span></span><span style="display:flex;"><span> l <span style="color:#81a1c1">=</span>
&quot;log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit&quot;; </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;log --graph --pretty=format:&#39;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset&#39; --abbrev-commit&#34;</span><span style="color:#eceff4">;</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
delta = { </span></span><span style="display:flex;"><span> delta <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
enable = true; </span></span><span style="display:flex;"><span> enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
</span></span><span style="display:flex;"><span>
options = { </span></span><span style="display:flex;"><span> options <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
features = &quot;line-numbers decorations&quot;; </span></span><span style="display:flex;"><span> features <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;line-numbers decorations&#34;</span><span style="color:#eceff4">;</span>
whitespace-error-style = &quot;22 reverse&quot;; </span></span><span style="display:flex;"><span> whitespace-error-style <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;22 reverse&#34;</span><span style="color:#eceff4">;</span>
plus-style = &quot;green bold ul '#198214'&quot;; </span></span><span style="display:flex;"><span> plus-style <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;green bold ul &#39;#198214&#39;&#34;</span><span style="color:#eceff4">;</span>
decorations = { </span></span><span style="display:flex;"><span> decorations <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
commit-decoration-style = &quot;bold yellow box ul&quot;; </span></span><span style="display:flex;"><span> commit-decoration-style <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;bold yellow box ul&#34;</span><span style="color:#eceff4">;</span>
file-style = &quot;bold yellow ul&quot;; </span></span><span style="display:flex;"><span> file-style <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;bold yellow ul&#34;</span><span style="color:#eceff4">;</span>
file-decoration-style = &quot;none&quot;; </span></span><span style="display:flex;"><span> file-decoration-style <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;none&#34;</span><span style="color:#eceff4">;</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
extraConfig = { </span></span><span style="display:flex;"><span> extraConfig <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
push = { default = &quot;current&quot;; }; </span></span><span style="display:flex;"><span> push <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span> default <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;current&#34;</span><span style="color:#eceff4">;</span> <span style="color:#eceff4">};</span>
pull = { rebase = true; }; </span></span><span style="display:flex;"><span> pull <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span> rebase <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span> <span style="color:#eceff4">};</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
starship = { </span></span><span style="display:flex;"><span> starship <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
enable = true; </span></span><span style="display:flex;"><span> enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
enableZshIntegration = true; </span></span><span style="display:flex;"><span> enableZshIntegration <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
</span></span><span style="display:flex;"><span>
settings = { </span></span><span style="display:flex;"><span> settings <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
add_newline = false; </span></span><span style="display:flex;"><span> add_newline <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">false</span><span style="color:#eceff4">;</span>
scan_timeout = 10; </span></span><span style="display:flex;"><span> scan_timeout <span style="color:#81a1c1">=</span> <span style="color:#b48ead">10</span><span style="color:#eceff4">;</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
zsh = { </span></span><span style="display:flex;"><span> zsh <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
enable = true; </span></span><span style="display:flex;"><span> enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
enableAutosuggestions = true; </span></span><span style="display:flex;"><span> enableAutosuggestions <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
enableSyntaxHighlighting = true; </span></span><span style="display:flex;"><span> enableSyntaxHighlighting <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
history.size = 1000000; </span></span><span style="display:flex;"><span> history<span style="color:#81a1c1">.</span>size <span style="color:#81a1c1">=</span> <span style="color:#b48ead">1000000</span><span style="color:#eceff4">;</span>
</span></span><span style="display:flex;"><span>
localVariables = { </span></span><span style="display:flex;"><span> localVariables <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
CASE_SENSITIVE = &quot;true&quot;; </span></span><span style="display:flex;"><span> CASE_SENSITIVE <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;true&#34;</span><span style="color:#eceff4">;</span>
DISABLE_UNTRACKED_FILES_DIRTY = &quot;true&quot;; </span></span><span style="display:flex;"><span> DISABLE_UNTRACKED_FILES_DIRTY <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;true&#34;</span><span style="color:#eceff4">;</span>
RPROMPT = &quot;&quot;; # override because macOS defaults to filepath </span></span><span style="display:flex;"><span> RPROMPT <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;&#34;</span><span style="color:#eceff4">;</span> <span style="color:#616e87;font-style:italic"># override because macOS defaults to filepath</span>
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE = &quot;fg=#838383,underline&quot;; </span></span><span style="display:flex;"><span> ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;fg=#838383,underline&#34;</span><span style="color:#eceff4">;</span>
ZSH_DISABLE_COMPFIX = &quot;true&quot;; </span></span><span style="display:flex;"><span> ZSH_DISABLE_COMPFIX <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;true&#34;</span><span style="color:#eceff4">;</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
initExtra = '' </span></span><span style="display:flex;"><span> initExtra <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#39;&#39;
export PAGER=less </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c"> export PAGER=less
''; </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c"> &#39;&#39;</span><span style="color:#eceff4">;</span>
</span></span><span style="display:flex;"><span>
shellAliases = { </span></span><span style="display:flex;"><span> shellAliases <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
&quot;..&quot; = &quot;cd ..&quot;; </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;..&#34;</span> <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;cd ..&#34;</span><span style="color:#eceff4">;</span>
grep = &quot;rg --smart-case&quot;; </span></span><span style="display:flex;"><span> grep <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;rg --smart-case&#34;</span><span style="color:#eceff4">;</span>
ls = &quot;exa -la --git&quot;; </span></span><span style="display:flex;"><span> ls <span style="color:#81a1c1">=</span> <span style="color:#a3be8c">&#34;exa -la --git&#34;</span><span style="color:#eceff4">;</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
&quot;oh-my-zsh&quot; = { </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;oh-my-zsh&#34;</span> <span style="color:#81a1c1">=</span> <span style="color:#eceff4">{</span>
enable = true; </span></span><span style="display:flex;"><span> enable <span style="color:#81a1c1">=</span> <span style="color:#8fbcbb">true</span><span style="color:#eceff4">;</span>
plugins = [ </span></span><span style="display:flex;"><span> plugins <span style="color:#81a1c1">=</span> <span style="color:#eceff4">[</span>
&quot;gitfast&quot; </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;gitfast&#34;</span>
&quot;last-working-dir&quot; </span></span><span style="display:flex;"><span> <span style="color:#a3be8c">&#34;last-working-dir&#34;</span>
]; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">];</span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
</span></span><span style="display:flex;"><span>
}; </span></span><span style="display:flex;"><span> <span style="color:#eceff4">};</span>
} </span></span><span style="display:flex;"><span><span style="color:#eceff4">}</span>
</code></pre> </span></span></code></pre></div><p>Save the file and run:</p>
<p>Save the file and run:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>home-manager switch
<pre><code>home-manager switch </span></span></code></pre></div><p>You should see another wave of <code>/nix/store/*</code> paths. The new configuration should now be active.</p>
</code></pre>
<p>You should see another wave of <code>/nix/store/*</code> paths. The new configuration should now be active.</p>
<p>If you run <code>zsh</code>, you should see that you have <a href="https://starship.rs/">starship</a> and access to several other utils such as <code>rg</code>, <code>fd</code>, and <code>exa</code>.</p> <p>If you run <code>zsh</code>, you should see that you have <a href="https://starship.rs/">starship</a> and access to several other utils such as <code>rg</code>, <code>fd</code>, and <code>exa</code>.</p>
<p>This basic configuration above is also defining your <code>~/.config/git/config</code> and <code>.zshrc</code>. If you already have either of these files, home-manager will complain about them already existing.</p> <p>This basic configuration above is also defining your <code>~/.config/git/config</code> and <code>.zshrc</code>. If you already have either of these files, home-manager will complain about them already existing.</p>
<p>If you run <code>cat ~/.zshrc</code>, you will see the way these configuration files are generated.</p> <p>If you run <code>cat ~/.zshrc</code>, you will see the way these configuration files are generated.</p>
@@ -315,6 +316,9 @@ nix-shell '&lt;home-manager&gt;' -A install
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<main> <main>
@@ -179,6 +181,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -119,74 +125,65 @@
<p>I&rsquo;ve also observed that so far my 2019 16&quot; Macbook Pro hasn&rsquo;t sounded like a jet engine, although I haven&rsquo;t performed any disk-intensive operations yet.</p> <p>I&rsquo;ve also observed that so far my 2019 16&quot; Macbook Pro hasn&rsquo;t sounded like a jet engine, although I haven&rsquo;t performed any disk-intensive operations yet.</p>
<h3 id="installing-podman">Installing Podman<a href="#installing-podman" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="installing-podman">Installing Podman<a href="#installing-podman" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>Running Podman on macOS is more involved than on Linux, because the podman-machine must run Linux inside of a virtual machine. Fortunately, the installation is made simple with <a href="https://formulae.brew.sh/formula/podman">brew</a> (read <a href="https://podman.io/getting-started/installation#linux-distributions">this</a> if you&rsquo;re installing Podman on Linux):</p> <p>Running Podman on macOS is more involved than on Linux, because the podman-machine must run Linux inside of a virtual machine. Fortunately, the installation is made simple with <a href="https://formulae.brew.sh/formula/podman">brew</a> (read <a href="https://podman.io/getting-started/installation#linux-distributions">this</a> if you&rsquo;re installing Podman on Linux):</p>
<pre><code class="language-sh">brew install podman <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>brew install podman
</code></pre> </span></span></code></pre></div><p>The podman-machine must be started:</p>
<p>The podman-machine must be started:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#616e87;font-style:italic"># This is not necessary on Linux</span>
<pre><code class="language-sh"># This is not necessary on Linux </span></span><span style="display:flex;"><span>podman machine init
podman machine init </span></span><span style="display:flex;"><span>podman machine start
podman machine start </span></span></code></pre></div><h3 id="running-a-container">Running a container<a href="#running-a-container" class="hanchor" ariaLabel="Anchor">#</a></h3>
</code></pre>
<h3 id="running-a-container">Running a container<a href="#running-a-container" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>Let&rsquo;s try to pull an image:</p> <p>Let&rsquo;s try to pull an image:</p>
<pre><code class="language-console">$ podman pull alpine <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> podman pull alpine
Trying to pull docker.io/library/alpine:latest... </span></span><span style="display:flex;"><span>Trying to pull docker.io/library/alpine:latest...
Getting image source signatures </span></span><span style="display:flex;"><span>Getting image source signatures
Copying blob sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e </span></span><span style="display:flex;"><span>Copying blob sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e
Copying config sha256:14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab </span></span><span style="display:flex;"><span>Copying config sha256:14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab
Writing manifest to image destination </span></span><span style="display:flex;"><span>Writing manifest to image destination
Storing signatures </span></span><span style="display:flex;"><span>Storing signatures
14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab </span></span><span style="display:flex;"><span>14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab
</code></pre> </span></span></code></pre></div><blockquote>
<blockquote>
<p>If you&rsquo;re having an issue pulling images, you may need to remove <code>~/.docker/config.json</code> or remove the set of auths in the configuration as mentioned <a href="https://stackoverflow.com/a/69121873/1191286">here</a>.</p> <p>If you&rsquo;re having an issue pulling images, you may need to remove <code>~/.docker/config.json</code> or remove the set of auths in the configuration as mentioned <a href="https://stackoverflow.com/a/69121873/1191286">here</a>.</p>
</blockquote> </blockquote>
<p>and then run and exec into the container:</p> <p>and then run and exec into the container:</p>
<pre><code class="language-console">$ podman run --rm -ti alpine <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> podman run --rm -ti alpine
Error: error preparing container 99ace1ef8a78118e178372d91fd182e8166c399fbebe0f676af59fbf32ce205b for attach: error configuring network namespace for container 99ace1ef8a78118e178372d91fd182e8166c399fbebe0f676af59fbf32ce205b: error adding pod unruffled_bohr_unruffled_bohr to CNI network &quot;podman&quot;: unexpected end of JSON input </span></span><span style="display:flex;"><span>Error: error preparing container 99ace1ef8a78118e178372d91fd182e8166c399fbebe0f676af59fbf32ce205b for attach: error configuring network namespace for container 99ace1ef8a78118e178372d91fd182e8166c399fbebe0f676af59fbf32ce205b: error adding pod unruffled_bohr_unruffled_bohr to CNI network &#34;podman&#34;: unexpected end of JSON input
</code></pre> </span></span></code></pre></div><p>What does this error mean? A bit of searching lead to <a href="https://github.com/containers/podman/issues/11837">this github issue</a>.</p>
<p>What does this error mean? A bit of searching lead to <a href="https://github.com/containers/podman/issues/11837">this github issue</a>.</p>
<p>Until the fix is released, a workaround is to just specify a port (even when it&rsquo;s not needed):</p> <p>Until the fix is released, a workaround is to just specify a port (even when it&rsquo;s not needed):</p>
<pre><code class="language-sh">podman run -p 4242 --rm -ti alpine <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>podman run -p <span style="color:#b48ead">4242</span> --rm -ti alpine
</code></pre> </span></span></code></pre></div><p>If you&rsquo;re reading this from the future, there is a good chance specifying a port won&rsquo;t be needed.</p>
<p>If you&rsquo;re reading this from the future, there is a good chance specifying a port won&rsquo;t be needed.</p>
<p>Another example of running a container with Podman can be found in the <a href="https://jellyfin.org/docs/general/administration/installing.html#podman">Jellyfin Documentation</a>.</p> <p>Another example of running a container with Podman can be found in the <a href="https://jellyfin.org/docs/general/administration/installing.html#podman">Jellyfin Documentation</a>.</p>
<h3 id="aliasing-docker-with-podman">Aliasing docker with podman<a href="#aliasing-docker-with-podman" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="aliasing-docker-with-podman">Aliasing docker with podman<a href="#aliasing-docker-with-podman" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>Force of habit (or other scripts) may have you calling <code>docker</code>. To work around this:</p> <p>Force of habit (or other scripts) may have you calling <code>docker</code>. To work around this:</p>
<pre><code class="language-sh">alias docker=podman <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#81a1c1">alias</span> docker<span style="color:#81a1c1">=</span>podman
</code></pre> </span></span></code></pre></div><h3 id="podman-compose">podman-compose<a href="#podman-compose" class="hanchor" ariaLabel="Anchor">#</a></h3>
<h3 id="podman-compose">podman-compose<a href="#podman-compose" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>You may be wondering: what about docker-compose? Well, there <em>claims</em> to be a drop-in replacement for it: <a href="https://github.com/containers/podman-compose">podman-compose</a>.</p> <p>You may be wondering: what about docker-compose? Well, there <em>claims</em> to be a drop-in replacement for it: <a href="https://github.com/containers/podman-compose">podman-compose</a>.</p>
<pre><code class="language-sh">pip3 install --user podman-compose <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>pip3 install --user podman-compose
</code></pre> </span></span></code></pre></div><p>Now let&rsquo;s create a <code>docker-compose.yml</code> file to test:</p>
<p>Now let&rsquo;s create a <code>docker-compose.yml</code> file to test:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>cat <span style="color:#a3be8c">&lt;&lt; EOF &gt;&gt; docker-compose.yml
<pre><code class="language-sh">cat &lt;&lt; EOF &gt;&gt; docker-compose.yml </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c">version: &#39;2&#39;
version: '2' </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c">services:
services: </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c"> hello_world:
hello_world: </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c"> image: ubuntu
image: ubuntu </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c"> command: [/bin/echo, &#39;Hello world&#39;]
command: [/bin/echo, 'Hello world'] </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c">EOF</span>
EOF </span></span></code></pre></div><p>Now run:</p>
</code></pre> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> podman-compose up
<p>Now run:</p> </span></span><span style="display:flex;"><span>podman pod create --name=davegallant.github.io --share net
<pre><code class="language-console">$ podman-compose up </span></span><span style="display:flex;"><span>40d61dc6e95216c07d2b21cea6dcb30205bfcaf1260501fe652f05bddf7e595e
podman pod create --name=davegallant.github.io --share net </span></span><span style="display:flex;"><span>0
40d61dc6e95216c07d2b21cea6dcb30205bfcaf1260501fe652f05bddf7e595e </span></span><span style="display:flex;"><span>podman create --name=davegallant.github.io_hello_world_1 --pod=davegallant.github.io -l io.podman.compose.config-hash=123 -l io.podman.compose.project=davegallant.github.io -l io.podman.compose.version=0.0.1 -l com.docker.compose.container-number=1 -l com.docker.compose.service=hello_world --add-host hello_world:127.0.0.1 --add-host davegallant.github.io_hello_world_1:127.0.0.1 ubuntu /bin/echo Hello world
0 </span></span><span style="display:flex;"><span>Resolved &#34;ubuntu&#34; as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
podman create --name=davegallant.github.io_hello_world_1 --pod=davegallant.github.io -l io.podman.compose.config-hash=123 -l io.podman.compose.project=davegallant.github.io -l io.podman.compose.version=0.0.1 -l com.docker.compose.container-number=1 -l com.docker.compose.service=hello_world --add-host hello_world:127.0.0.1 --add-host davegallant.github.io_hello_world_1:127.0.0.1 ubuntu /bin/echo Hello world </span></span><span style="display:flex;"><span>Trying to pull docker.io/library/ubuntu:latest...
Resolved &quot;ubuntu&quot; as an alias (/etc/containers/registries.conf.d/000-shortnames.conf) </span></span><span style="display:flex;"><span>Getting image source signatures
Trying to pull docker.io/library/ubuntu:latest... </span></span><span style="display:flex;"><span>Copying blob sha256:f3ef4ff62e0da0ef761ec1c8a578f3035bef51043e53ae1b13a20b3e03726d17
Getting image source signatures </span></span><span style="display:flex;"><span>Copying blob sha256:f3ef4ff62e0da0ef761ec1c8a578f3035bef51043e53ae1b13a20b3e03726d17
Copying blob sha256:f3ef4ff62e0da0ef761ec1c8a578f3035bef51043e53ae1b13a20b3e03726d17 </span></span><span style="display:flex;"><span>Copying config sha256:597ce1600cf4ac5f449b66e75e840657bb53864434d6bd82f00b172544c32ee2
Copying blob sha256:f3ef4ff62e0da0ef761ec1c8a578f3035bef51043e53ae1b13a20b3e03726d17 </span></span><span style="display:flex;"><span>Writing manifest to image destination
Copying config sha256:597ce1600cf4ac5f449b66e75e840657bb53864434d6bd82f00b172544c32ee2 </span></span><span style="display:flex;"><span>Storing signatures
Writing manifest to image destination </span></span><span style="display:flex;"><span>1a68b2fed3fdf2037b7aef16d770f22929eec1d799219ce30541df7876918576
Storing signatures </span></span><span style="display:flex;"><span>0
1a68b2fed3fdf2037b7aef16d770f22929eec1d799219ce30541df7876918576 </span></span><span style="display:flex;"><span>podman start -a davegallant.github.io_hello_world_1
0 </span></span><span style="display:flex;"><span>Hello world
podman start -a davegallant.github.io_hello_world_1 </span></span></code></pre></div><p>This should more or less provide the same results you would come to expect with docker. The README does clearly state that podman-compose is under development.</p>
Hello world
</code></pre>
<p>This should more or less provide the same results you would come to expect with docker. The README does clearly state that podman-compose is under development.</p>
<h3 id="summary">Summary<a href="#summary" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="summary">Summary<a href="#summary" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>Installing Podman on macOS was not seamless, but it was manageable well within 30 minutes. I would recommend giving Podman a try to anyone who is unhappy with experiencing forced docker updates, or who is interested in using a more modern technology for running containers.</p> <p>Installing Podman on macOS was not seamless, but it was manageable well within 30 minutes. I would recommend giving Podman a try to anyone who is unhappy with experiencing forced docker updates, or who is interested in using a more modern technology for running containers.</p>
<p>One caveat to mention is that there isn&rsquo;t an official graphical user interface for Podman, but there is an <a href="https://github.com/containers/podman/issues/11494">open issue</a> considering one. If you rely heavily on Docker Desktop&rsquo;s UI, you may not be as interested in using podman yet.</p> <p>One caveat to mention is that there isn&rsquo;t an official graphical user interface for Podman, but there is an <a href="https://github.com/containers/podman/issues/11494">open issue</a> considering one. If you rely heavily on Docker Desktop&rsquo;s UI, you may not be as interested in using podman yet.</p>
@@ -266,6 +263,9 @@ Hello world
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -110,18 +116,16 @@
<p>This <a href="https://gist.github.com/triangletodd/02f595cd4c0dc9aac5f7763ca2264185">gist</a> contains snippets and discussion on how to deploy K3s in LXC on Proxmox. It mentions that <code>bridge-nf-call-iptables</code> should be loaded, but I did not understand the benefit of doing this.</p> <p>This <a href="https://gist.github.com/triangletodd/02f595cd4c0dc9aac5f7763ca2264185">gist</a> contains snippets and discussion on how to deploy K3s in LXC on Proxmox. It mentions that <code>bridge-nf-call-iptables</code> should be loaded, but I did not understand the benefit of doing this.</p>
<h2 id="disable-swap">Disable swap<a href="#disable-swap" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="disable-swap">Disable swap<a href="#disable-swap" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>There is an issue on Kubernetes regarding swap <a href="https://github.com/kubernetes/kubernetes/issues/53533">here</a>. There claims to be support for swap in 1.22, but for now let&rsquo;s disable it:</p> <p>There is an issue on Kubernetes regarding swap <a href="https://github.com/kubernetes/kubernetes/issues/53533">here</a>. There claims to be support for swap in 1.22, but for now let&rsquo;s disable it:</p>
<pre><code>sysctl vm.swappiness=0 <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo sysctl vm.swappiness<span style="color:#81a1c1">=</span><span style="color:#b48ead">0</span>
swapoff -a </span></span><span style="display:flex;"><span>sudo swapoff -a
</code></pre> </span></span></code></pre></div><p>It might be worth experimenting with swap enabled in the future to see how that might affect performance.</p>
<p>It might be worth experimenting with swap enabled in the future to see how that might affect performance.</p>
<h3 id="enable-ip-forwarding">Enable IP Forwarding<a href="#enable-ip-forwarding" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="enable-ip-forwarding">Enable IP Forwarding<a href="#enable-ip-forwarding" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>To avoid IP Forwarding issues with Traefik, run the following on the host:</p> <p>To avoid IP Forwarding issues with Traefik, run the following on the host:</p>
<pre><code class="language-sh">sudo sysctl net.ipv4.ip_forward=1 <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo sysctl net.ipv4.ip_forward<span style="color:#81a1c1">=</span><span style="color:#b48ead">1</span>
sudo sysctl net.ipv6.conf.all.forwarding=1 </span></span><span style="display:flex;"><span>sudo sysctl net.ipv6.conf.all.forwarding<span style="color:#81a1c1">=</span><span style="color:#b48ead">1</span>
sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf </span></span><span style="display:flex;"><span>sudo sed -i <span style="color:#a3be8c">&#39;s/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g&#39;</span> /etc/sysctl.conf
sudo sed -i 's/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/g' /etc/sysctl.conf </span></span><span style="display:flex;"><span>sudo sed -i <span style="color:#a3be8c">&#39;s/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/g&#39;</span> /etc/sysctl.conf
</code></pre> </span></span></code></pre></div><h2 id="create-lxc-container">Create LXC container<a href="#create-lxc-container" class="hanchor" ariaLabel="Anchor">#</a></h2>
<h2 id="create-lxc-container">Create LXC container<a href="#create-lxc-container" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>Create an LXC container in the Proxmox interface as you normally would. Remember to:</p> <p>Create an LXC container in the Proxmox interface as you normally would. Remember to:</p>
<ul> <ul>
<li>Uncheck <code>unprivileged container</code></li> <li>Uncheck <code>unprivileged container</code></li>
@@ -132,12 +136,11 @@ sudo sed -i 's/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/g'
<h3 id="modify-container-config">Modify container config<a href="#modify-container-config" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="modify-container-config">Modify container config<a href="#modify-container-config" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>Now back on the host run <code>pct list</code> to determine what VMID it was given.</p> <p>Now back on the host run <code>pct list</code> to determine what VMID it was given.</p>
<p>Open <code>/etc/pve/lxc/$VMID.conf</code> and append:</p> <p>Open <code>/etc/pve/lxc/$VMID.conf</code> and append:</p>
<pre><code class="language-sh">lxc.apparmor.profile: unconfined <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>lxc.apparmor.profile: unconfined
lxc.cap.drop: </span></span><span style="display:flex;"><span>lxc.cap.drop:
lxc.mount.auto: &quot;proc:rw sys:rw&quot; </span></span><span style="display:flex;"><span>lxc.mount.auto: &#34;proc:rw sys:rw&#34;
lxc.cgroup2.devices.allow: c 10:200 rwm </span></span><span style="display:flex;"><span>lxc.cgroup2.devices.allow: c 10:200 rwm
</code></pre> </span></span></code></pre></div><p>All of the above configurations are described in the <a href="https://linuxcontainers.org/lxc/manpages/man5/lxc.container.conf.5.html">manpages</a>.
<p>All of the above configurations are described in the <a href="https://linuxcontainers.org/lxc/manpages/man5/lxc.container.conf.5.html">manpages</a>.
Notice that <code>cgroup2</code> is used since Proxmox VE 7.0 has switched to a <a href="https://pve.proxmox.com/pve-docs/chapter-pct.html#pct_cgroup">pure cgroupv2 environment</a>.</p> Notice that <code>cgroup2</code> is used since Proxmox VE 7.0 has switched to a <a href="https://pve.proxmox.com/pve-docs/chapter-pct.html#pct_cgroup">pure cgroupv2 environment</a>.</p>
<p>Thankfully cgroup v2 support has been supported in k3s with these contributions:</p> <p>Thankfully cgroup v2 support has been supported in k3s with these contributions:</p>
<ul> <ul>
@@ -146,47 +149,44 @@ Notice that <code>cgroup2</code> is used since Proxmox VE 7.0 has switched to a
</ul> </ul>
<h2 id="enable-shared-host-mounts">Enable shared host mounts<a href="#enable-shared-host-mounts" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="enable-shared-host-mounts">Enable shared host mounts<a href="#enable-shared-host-mounts" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>From within the container, run:</p> <p>From within the container, run:</p>
<pre><code class="language-sh">echo '#!/bin/sh -e <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#81a1c1">echo</span> <span style="color:#a3be8c">&#39;#!/bin/sh -e
ln -s /dev/console /dev/kmsg </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c">ln -s /dev/console /dev/kmsg
mount --make-rshared /' &gt; /etc/rc.local </span></span></span><span style="display:flex;"><span><span style="color:#a3be8c">mount --make-rshared /&#39;</span> &gt; /etc/rc.local
chmod +x /etc/rc.local </span></span><span style="display:flex;"><span>chmod +x /etc/rc.local
reboot </span></span><span style="display:flex;"><span>reboot
</code></pre> </span></span></code></pre></div><h2 id="install-k3s">Install K3s<a href="#install-k3s" class="hanchor" ariaLabel="Anchor">#</a></h2>
<h2 id="install-k3s">Install K3s<a href="#install-k3s" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>One of the simplest ways to install K3s on a remote host is to use <a href="https://github.com/alexellis/k3sup">k3sup</a>. <p>One of the simplest ways to install K3s on a remote host is to use <a href="https://github.com/alexellis/k3sup">k3sup</a>.
Ensure that you supply a valid <code>CONTAINER_IP</code> and choose the <code>k3s-version</code> you prefer. Ensure that you supply a valid <code>CONTAINER_IP</code> and choose the <code>k3s-version</code> you prefer.
As of 2021/11, it is still defaulting to the 1.19 channel, so I overrode it to 1.22 for cgroup v2 support. See the published releases <a href="https://github.com/k3s-io/k3s/releases">here</a>.</p> As of 2021/11, it is still defaulting to the 1.19 channel, so I overrode it to 1.22 for cgroup v2 support. See the published releases <a href="https://github.com/k3s-io/k3s/releases">here</a>.</p>
<pre><code class="language-sh">ssh-copy-id root@$CONTAINER_IP <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>ssh-copy-id root@$CONTAINER_IP
k3sup install --ip $CONTAINER_IP --user root --k3s-version v1.22.3+k3s1 </span></span><span style="display:flex;"><span>k3sup install --ip $CONTAINER_IP --user root --k3s-version v1.22.3+k3s1
</code></pre> </span></span></code></pre></div><p>If all goes well, you should see a path to the <code>kubeconfig</code> generated. I moved this into <code>~/.kube/config</code> so that kubectl would read this by default.</p>
<p>If all goes well, you should see a path to the <code>kubeconfig</code> generated. I moved this into <code>~/.kube/config</code> so that kubectl would read this by default.</p>
<h2 id="wrapping-up">Wrapping up<a href="#wrapping-up" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="wrapping-up">Wrapping up<a href="#wrapping-up" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>Installing K3s in LXC on Proxmox works with a few tweaks to the default configuration. I later followed the Tekton&rsquo;s <a href="https://tekton.dev/docs/getting-started/">Getting Started</a> guide and was able to deploy it in a few commands.</p> <p>Installing K3s in LXC on Proxmox works with a few tweaks to the default configuration. I later followed the Tekton&rsquo;s <a href="https://tekton.dev/docs/getting-started/">Getting Started</a> guide and was able to deploy it in a few commands.</p>
<pre><code class="language-console">$ kubectl get all --namespace tekton-pipelines <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> kubectl get all --namespace tekton-pipelines
NAME READY STATUS RESTARTS AGE </span></span><span style="display:flex;"><span>NAME READY STATUS RESTARTS AGE
pod/tekton-pipelines-webhook-8566ff9b6b-6rnh8 1/1 Running 1 (50m ago) 12h </span></span><span style="display:flex;"><span>pod/tekton-pipelines-webhook-8566ff9b6b-6rnh8 1/1 Running 1 (50m ago) 12h
pod/tekton-dashboard-6bf858f977-qt4hr 1/1 Running 1 (50m ago) 11h </span></span><span style="display:flex;"><span>pod/tekton-dashboard-6bf858f977-qt4hr 1/1 Running 1 (50m ago) 11h
pod/tekton-pipelines-controller-69fd7498d8-f57m4 1/1 Running 1 (50m ago) 12h </span></span><span style="display:flex;"><span>pod/tekton-pipelines-controller-69fd7498d8-f57m4 1/1 Running 1 (50m ago) 12h
</span></span><span style="display:flex;"><span><span style="color:#bf616a">
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE </span></span></span><span style="display:flex;"><span><span style="color:#bf616a"></span>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tekton-pipelines-controller ClusterIP 10.43.44.245 &lt;none&gt; 9090/TCP,8080/TCP 12h </span></span><span style="display:flex;"><span>service/tekton-pipelines-controller ClusterIP 10.43.44.245 &lt;none&gt; 9090/TCP,8080/TCP 12h
service/tekton-pipelines-webhook ClusterIP 10.43.183.242 &lt;none&gt; 9090/TCP,8008/TCP,443/TCP,8080/TCP 12h </span></span><span style="display:flex;"><span>service/tekton-pipelines-webhook ClusterIP 10.43.183.242 &lt;none&gt; 9090/TCP,8008/TCP,443/TCP,8080/TCP 12h
service/tekton-dashboard ClusterIP 10.43.87.97 &lt;none&gt; 9097/TCP 11h </span></span><span style="display:flex;"><span>service/tekton-dashboard ClusterIP 10.43.87.97 &lt;none&gt; 9097/TCP 11h
</span></span><span style="display:flex;"><span><span style="color:#bf616a">
NAME READY UP-TO-DATE AVAILABLE AGE </span></span></span><span style="display:flex;"><span><span style="color:#bf616a"></span>NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/tekton-pipelines-webhook 1/1 1 1 12h </span></span><span style="display:flex;"><span>deployment.apps/tekton-pipelines-webhook 1/1 1 1 12h
deployment.apps/tekton-dashboard 1/1 1 1 11h </span></span><span style="display:flex;"><span>deployment.apps/tekton-dashboard 1/1 1 1 11h
deployment.apps/tekton-pipelines-controller 1/1 1 1 12h </span></span><span style="display:flex;"><span>deployment.apps/tekton-pipelines-controller 1/1 1 1 12h
</span></span><span style="display:flex;"><span><span style="color:#bf616a">
NAME DESIRED CURRENT READY AGE </span></span></span><span style="display:flex;"><span><span style="color:#bf616a"></span>NAME DESIRED CURRENT READY AGE
replicaset.apps/tekton-pipelines-webhook-8566ff9b6b 1 1 1 12h </span></span><span style="display:flex;"><span>replicaset.apps/tekton-pipelines-webhook-8566ff9b6b 1 1 1 12h
replicaset.apps/tekton-dashboard-6bf858f977 1 1 1 11h </span></span><span style="display:flex;"><span>replicaset.apps/tekton-dashboard-6bf858f977 1 1 1 11h
replicaset.apps/tekton-pipelines-controller-69fd7498d8 1 1 1 12h </span></span><span style="display:flex;"><span>replicaset.apps/tekton-pipelines-controller-69fd7498d8 1 1 1 12h
</span></span><span style="display:flex;"><span><span style="color:#bf616a">
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE </span></span></span><span style="display:flex;"><span><span style="color:#bf616a"></span>NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook Deployment/tekton-pipelines-webhook 9%/100% 1 5 1 12h </span></span><span style="display:flex;"><span>horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook Deployment/tekton-pipelines-webhook 9%/100% 1 5 1 12h
</code></pre> </span></span></code></pre></div><p>I made sure to install Tailscale in the container so that I can easily access K3s from anywhere.</p>
<p>I made sure to install Tailscale in the container so that I can easily access K3s from anywhere.</p>
<p>If I&rsquo;m feeling adventurous, I might experiment with <a href="https://rancher.com/docs/k3s/latest/en/advanced/#running-k3s-with-rootless-mode-experimental">K3s rootless</a>.</p></section> <p>If I&rsquo;m feeling adventurous, I might experiment with <a href="https://rancher.com/docs/k3s/latest/en/advanced/#running-k3s-with-rootless-mode-experimental">K3s rootless</a>.</p></section>
<script <script
@@ -262,6 +262,9 @@ horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook Deployment/tekton
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<main> <main>
@@ -199,6 +201,7 @@ Encrypting your shared volumes should also be done, since unfortunately <a href=
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<main> <main>
@@ -221,6 +223,7 @@ When setting up the machine, I mostly went with all of the defaults. Configurati
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -110,49 +116,48 @@
<p>A few days ago, yewtu.be went down briefly, and that motivated me enough to self-host invidious. There are several other hosted instances listed <a href="https://docs.invidious.io/instances/">here</a>, but being able to easily backup my own instance (including subscriptions and watch history) is more compelling in my case.</p> <p>A few days ago, yewtu.be went down briefly, and that motivated me enough to self-host invidious. There are several other hosted instances listed <a href="https://docs.invidious.io/instances/">here</a>, but being able to easily backup my own instance (including subscriptions and watch history) is more compelling in my case.</p>
<h3 id="hosting-invidious">Hosting invidious<a href="#hosting-invidious" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="hosting-invidious">Hosting invidious<a href="#hosting-invidious" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>The quickest way to get invidious up is with docker-compose as mentioned in the <a href="https://docs.invidious.io/installation/">docs</a>.</p> <p>The quickest way to get invidious up is with docker-compose as mentioned in the <a href="https://docs.invidious.io/installation/">docs</a>.</p>
<p>I made a few modifications (such as pinning the container&rsquo;s tag), and ended up with:</p> <p>I made a few modifications, and ended up with:</p>
<pre><code class="language-yaml">version: &quot;3&quot; <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">version</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;3&#34;</span>
services: </span></span><span style="display:flex;"><span><span style="color:#81a1c1">services</span><span style="color:#eceff4">:</span>
invidious: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">invidious</span><span style="color:#eceff4">:</span>
image: quay.io/invidious/invidious:5160d8bae39dc5cc5d51abee90571a03c08d0f2b </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> quay.io/invidious/invidious
restart: unless-stopped </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> unless-stopped
ports: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">ports</span><span style="color:#eceff4">:</span>
- &quot;0.0.0.0:3000:3000&quot; </span></span><span style="display:flex;"><span> - <span style="color:#a3be8c">&#34;0.0.0.0:3000:3000&#34;</span>
environment: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">environment</span><span style="color:#eceff4">:</span>
INVIDIOUS_CONFIG: | </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">INVIDIOUS_CONFIG</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">|</span><span style="color:#616e87">
db: </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> db:
dbname: invidious </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> dbname: invidious
user: kemal </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> user: kemal
password: kemal </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> password: kemal
host: invidious-db </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> host: invidious-db
port: 5432 </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> port: 5432
check_tables: true </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> check_tables: true</span>
healthcheck: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">healthcheck</span><span style="color:#eceff4">:</span>
test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">test</span><span style="color:#eceff4">:</span> wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1
interval: 30s </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">interval</span><span style="color:#eceff4">:</span> 30s
timeout: 5s </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">timeout</span><span style="color:#eceff4">:</span> 5s
retries: 2 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">retries</span><span style="color:#eceff4">:</span> <span style="color:#b48ead">2</span>
depends_on: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">depends_on</span><span style="color:#eceff4">:</span>
- invidious-db </span></span><span style="display:flex;"><span> - invidious-db
</span></span><span style="display:flex;"><span>
invidious-db: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">invidious-db</span><span style="color:#eceff4">:</span>
image: docker.io/library/postgres:14 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> docker.io/library/postgres:14
restart: unless-stopped </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> unless-stopped
volumes: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
- postgresdata:/var/lib/postgresql/data </span></span><span style="display:flex;"><span> - postgresdata:/var/lib/postgresql/data
- ./config/sql:/config/sql </span></span><span style="display:flex;"><span> - ./config/sql:/config/sql
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh </span></span><span style="display:flex;"><span> - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
environment: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">environment</span><span style="color:#eceff4">:</span>
POSTGRES_DB: invidious </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_DB</span><span style="color:#eceff4">:</span> invidious
POSTGRES_USER: kemal </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_USER</span><span style="color:#eceff4">:</span> kemal
POSTGRES_PASSWORD: kemal </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_PASSWORD</span><span style="color:#eceff4">:</span> kemal
healthcheck: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">healthcheck</span><span style="color:#eceff4">:</span>
test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB&quot;] </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">test</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">[</span><span style="color:#a3be8c">&#34;CMD-SHELL&#34;</span><span style="color:#eceff4">,</span> <span style="color:#a3be8c">&#34;pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB&#34;</span><span style="color:#eceff4">]</span>
</span></span><span style="display:flex;"><span>
volumes: </span></span><span style="display:flex;"><span><span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
postgresdata: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">postgresdata</span><span style="color:#eceff4">:</span>
</code></pre> </span></span></code></pre></div><p>After invidious was up and running, I installed <a href="https://tailscale.com/">Tailscale</a> on it to leverage its MagicDNS, and I&rsquo;m now able to access this instance from anywhere at <a href="http://invidious:3000/feed/subscriptions">http://invidious:3000/feed/subscriptions</a>.</p>
<p>After invidious was up and running, I installed <a href="https://tailscale.com/">Tailscale</a> on it to leverage its MagicDNS, and I&rsquo;m now able to access this instance from anywhere at <a href="http://invidious:3000/feed/subscriptions">http://invidious:3000/feed/subscriptions</a>.</p>
<h3 id="redirecting-youtube-links">Redirecting YouTube links<a href="#redirecting-youtube-links" class="hanchor" ariaLabel="Anchor">#</a></h3> <h3 id="redirecting-youtube-links">Redirecting YouTube links<a href="#redirecting-youtube-links" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>I figured it would be nice to redirect existing YouTube links that others send me, so that I could seamlessly watch the videos using invidious.</p> <p>I figured it would be nice to redirect existing YouTube links that others send me, so that I could seamlessly watch the videos using invidious.</p>
<p>I went looking for a way to redirect paths at the browser level. I found the lightweight proxy <a href="https://requestly.io/">requestly</a>, which can be used to modify http requests in my browser. I created the following rules:</p> <p>I went looking for a way to redirect paths at the browser level. I found the lightweight proxy <a href="https://requestly.io/">requestly</a>, which can be used to modify http requests in my browser. I created the following rules:</p>
@@ -239,6 +244,9 @@ volumes:
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -124,15 +130,14 @@ If this sounds more appealing, install <a href="https://github.com/antitree/krew
<p>It&rsquo;s possible to use this sort of proxy to connect to a private DB, but is it any simpler than using a virtual machine as a jumphost? It wasn&rsquo;t until I stumbled upon <a href="https://github.com/yokawasa/kubectl-plugin-socks5-proxy">kubectl-plugin-socks5-proxy</a> that I was convinced that using SOCKS could be made simple.</p> <p>It&rsquo;s possible to use this sort of proxy to connect to a private DB, but is it any simpler than using a virtual machine as a jumphost? It wasn&rsquo;t until I stumbled upon <a href="https://github.com/yokawasa/kubectl-plugin-socks5-proxy">kubectl-plugin-socks5-proxy</a> that I was convinced that using SOCKS could be made simple.</p>
<p>So how does it work? By installing the kubectl plugin and then running <code>kubectl socks5-proxy</code>, a SOCKS proxy server is spun up in a pod and then opens up port-forwarding session using kubectl.</p> <p>So how does it work? By installing the kubectl plugin and then running <code>kubectl socks5-proxy</code>, a SOCKS proxy server is spun up in a pod and then opens up port-forwarding session using kubectl.</p>
<p>As you can see below, this k8s plugin is wrapped up nicely:</p> <p>As you can see below, this k8s plugin is wrapped up nicely:</p>
<pre><code class="language-console">$ kubectl socks5-proxy <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span><span style="color:#4c566a;font-weight:bold">$</span> kubectl socks5-proxy
using: namespace=default </span></span><span style="display:flex;"><span>using: namespace=default
using: port=1080 </span></span><span style="display:flex;"><span>using: port=1080
using: name=davegallant-proxy </span></span><span style="display:flex;"><span>using: name=davegallant-proxy
using: image=serjs/go-socks5-proxy </span></span><span style="display:flex;"><span>using: image=serjs/go-socks5-proxy
Creating SOCKS5 Proxy (Pod)... </span></span><span style="display:flex;"><span>Creating SOCKS5 Proxy (Pod)...
pod/davegallant-proxy created </span></span><span style="display:flex;"><span>pod/davegallant-proxy created
</code></pre> </span></span></code></pre></div><p>With the above proxy connection open, it is possible to access both the DNS and private IPs accessible within the k8s cluster. In this case, I am able to access the private database, since there is network connectivity between the k8s cluster and the database.</p>
<p>With the above proxy connection open, it is possible to access both the DNS and private IPs accessible within the k8s cluster. In this case, I am able to access the private database, since there is network connectivity between the k8s cluster and the database.</p>
<h2 id="caveats-and-conclusion">Caveats and Conclusion<a href="#caveats-and-conclusion" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="caveats-and-conclusion">Caveats and Conclusion<a href="#caveats-and-conclusion" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>The above outlined solution makes some assumptions:</p> <p>The above outlined solution makes some assumptions:</p>
<ul> <ul>
@@ -232,6 +237,9 @@ pod/davegallant-proxy created
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -20,8 +20,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -68,7 +68,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -91,6 +91,12 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header> </header>
<main> <main>
@@ -122,68 +128,65 @@
</ul> </ul>
<p>My preferred approach to deploying code in a homelab environment is with docker compose. I have deployed this in a <a href="https://pve.proxmox.com/wiki/Linux_Container">proxmox lxc container</a> based on debian with a hostname <code>gitea</code>. This could be deployed in any environment and with any hostname (as long you updated the tailscale machine name to your preferred subdomain for magic dns).</p> <p>My preferred approach to deploying code in a homelab environment is with docker compose. I have deployed this in a <a href="https://pve.proxmox.com/wiki/Linux_Container">proxmox lxc container</a> based on debian with a hostname <code>gitea</code>. This could be deployed in any environment and with any hostname (as long you updated the tailscale machine name to your preferred subdomain for magic dns).</p>
<p>The <code>docker-compose.yaml</code> file looks like:</p> <p>The <code>docker-compose.yaml</code> file looks like:</p>
<pre><code class="language-yaml">version: &quot;3.7&quot; <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">version</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;3.7&#34;</span>
services: </span></span><span style="display:flex;"><span><span style="color:#81a1c1">services</span><span style="color:#eceff4">:</span>
gitea: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">gitea</span><span style="color:#eceff4">:</span>
image: gitea/gitea:1.21.1 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> gitea/gitea:1.21.1
container_name: gitea </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">container_name</span><span style="color:#eceff4">:</span> gitea
environment: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">environment</span><span style="color:#eceff4">:</span>
- USER_UID=1000 </span></span><span style="display:flex;"><span> - USER_UID=1000
- USER_GID=1000 </span></span><span style="display:flex;"><span> - USER_GID=1000
</span></span><span style="display:flex;"><span>
- GITEA__server__DOMAIN=gitea.my-tailnet-name.ts.net </span></span><span style="display:flex;"><span> - GITEA__server__DOMAIN=gitea.my-tailnet-name.ts.net
- GITEA__server__ROOT_URL=https://gitea.my-tailnet-name.ts.net </span></span><span style="display:flex;"><span> - GITEA__server__ROOT_URL=https://gitea.my-tailnet-name.ts.net
- GITEA__server__HTTP_ADDR=0.0.0.0 </span></span><span style="display:flex;"><span> - GITEA__server__HTTP_ADDR=0.0.0.0
- GITEA__server__LFS_JWT_SECRET=my-secret-jwt </span></span><span style="display:flex;"><span> - GITEA__server__LFS_JWT_SECRET=my-secret-jwt
restart: always </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> always
volumes: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
- ./data:/data </span></span><span style="display:flex;"><span> - ./data:/data
- /etc/timezone:/etc/timezone:ro </span></span><span style="display:flex;"><span> - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro </span></span><span style="display:flex;"><span> - /etc/localtime:/etc/localtime:ro
traefik: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">traefik</span><span style="color:#eceff4">:</span>
image: traefik:v3.0.0-beta4 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> traefik:v3.0.0-beta4
container_name: traefik </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">container_name</span><span style="color:#eceff4">:</span> traefik
security_opt: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">security_opt</span><span style="color:#eceff4">:</span>
- no-new-privileges:true </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1;font-weight:bold">no</span>-new-privileges:true
restart: unless-stopped </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> unless-stopped
ports: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">ports</span><span style="color:#eceff4">:</span>
- 80:80 </span></span><span style="display:flex;"><span> - <span style="color:#b48ead">80</span><span style="color:#eceff4">:</span><span style="color:#b48ead">80</span>
- 443:443 </span></span><span style="display:flex;"><span> - <span style="color:#b48ead">443</span><span style="color:#eceff4">:</span><span style="color:#b48ead">443</span>
volumes: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
- ./traefik/data/traefik.yaml:/traefik.yaml:ro </span></span><span style="display:flex;"><span> - ./traefik/data/traefik.yaml:/traefik.yaml:ro
- ./traefik/data/dynamic.yaml:/dynamic.yaml:ro </span></span><span style="display:flex;"><span> - ./traefik/data/dynamic.yaml:/dynamic.yaml:ro
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock </span></span><span style="display:flex;"><span> - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
</code></pre> </span></span></code></pre></div><p><code>traefik/data/traefik.yaml</code>:</p>
<p><code>traefik/data/traefik.yaml</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">entryPoints</span><span style="color:#eceff4">:</span>
<pre><code class="language-yaml">entryPoints: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">https</span><span style="color:#eceff4">:</span>
https: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">address</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;:443&#34;</span>
address: &quot;:443&quot; </span></span><span style="display:flex;"><span><span style="color:#81a1c1">providers</span><span style="color:#eceff4">:</span>
providers: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">file</span><span style="color:#eceff4">:</span>
file: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">filename</span><span style="color:#eceff4">:</span> dynamic.yaml
filename: dynamic.yaml </span></span><span style="display:flex;"><span><span style="color:#81a1c1">certificatesResolvers</span><span style="color:#eceff4">:</span>
certificatesResolvers: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">myresolver</span><span style="color:#eceff4">:</span>
myresolver: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">tailscale</span><span style="color:#eceff4">:</span> {}
tailscale: {} </span></span><span style="display:flex;"><span><span style="color:#81a1c1">log</span><span style="color:#eceff4">:</span>
log: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">level</span><span style="color:#eceff4">:</span> INFO
level: INFO </span></span></code></pre></div><p>and finally <code>traefik/data/dynamic/dynamic.yaml</code>:</p>
</code></pre> <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">http</span><span style="color:#eceff4">:</span>
<p>and finally <code>traefik/data/dynamic/dynamic.yaml</code>:</p> </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">routers</span><span style="color:#eceff4">:</span>
<pre><code class="language-yaml">http: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">gitea</span><span style="color:#eceff4">:</span>
routers: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">rule</span><span style="color:#eceff4">:</span> Host(`gitea.my-tailnet-name.ts.net`)
gitea: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">entrypoints</span><span style="color:#eceff4">:</span>
rule: Host(`gitea.my-tailnet-name.ts.net`) </span></span><span style="display:flex;"><span> - <span style="color:#a3be8c">&#34;https&#34;</span>
entrypoints: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">service</span><span style="color:#eceff4">:</span> gitea
- &quot;https&quot; </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">tls</span><span style="color:#eceff4">:</span>
service: gitea </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">certResolver</span><span style="color:#eceff4">:</span> myresolver
tls: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">services</span><span style="color:#eceff4">:</span>
certResolver: myresolver </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">gitea</span><span style="color:#eceff4">:</span>
services: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">loadBalancer</span><span style="color:#eceff4">:</span>
gitea: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">servers</span><span style="color:#eceff4">:</span>
loadBalancer: </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">url</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;http://gitea:3000&#34;</span>
servers: </span></span></code></pre></div><p>Something to consider is whether or not you want to use ssh with git. One method to get this to work with containers is to use <a href="https://docs.gitea.com/installation/install-with-docker#ssh-container-passthrough">ssh container passthrough</a>. I decided to keep it simple and not use ssh, since communicating over https is perfectly fine for my use case.</p>
- url: &quot;http://gitea:3000&quot;
</code></pre>
<p>Something to consider is whether or not you want to use ssh with git. One method to get this to work with containers is to use <a href="https://docs.gitea.com/installation/install-with-docker#ssh-container-passthrough">ssh container passthrough</a>. I decided to keep it simple and not use ssh, since communicating over https is perfectly fine for my use case.</p>
<p>After adding the above configuration, running <code>docker compose up -d</code> should be enough to get an instance up and running. It will be accessible at <a href="https://gitea.my-tailnet-name.ts.net">https://gitea.my-tailnet-name.ts.net</a> from within the tailnet.</p> <p>After adding the above configuration, running <code>docker compose up -d</code> should be enough to get an instance up and running. It will be accessible at <a href="https://gitea.my-tailnet-name.ts.net">https://gitea.my-tailnet-name.ts.net</a> from within the tailnet.</p>
<h2 id="connecting-a-runner">Connecting a Runner<a href="#connecting-a-runner" class="hanchor" ariaLabel="Anchor">#</a></h2> <h2 id="connecting-a-runner">Connecting a Runner<a href="#connecting-a-runner" class="hanchor" ariaLabel="Anchor">#</a></h2>
<p>I installed the runner by <a href="https://docs.gitea.com/usage/actions/quickstart#set-up-runner">following the docs</a>. I opted for installing it on a separate host (another lxc container) as recommended in the docs. I used the systemd unit file to ensure that the runner comes back online after system reboots. I installed tailscale on this act runner as well, so that it can have the same &ldquo;networking privileges&rdquo; as the main instance.</p> <p>I installed the runner by <a href="https://docs.gitea.com/usage/actions/quickstart#set-up-runner">following the docs</a>. I opted for installing it on a separate host (another lxc container) as recommended in the docs. I used the systemd unit file to ensure that the runner comes back online after system reboots. I installed tailscale on this act runner as well, so that it can have the same &ldquo;networking privileges&rdquo; as the main instance.</p>
@@ -193,64 +196,63 @@ log:
<p>Now it&rsquo;s time start running some automation. I used the <a href="https://docs.gitea.com/usage/actions/quickstart#use-actions">demo workflow</a> as a starting point to verify that the runner is executing workflows.</p> <p>Now it&rsquo;s time start running some automation. I used the <a href="https://docs.gitea.com/usage/actions/quickstart#use-actions">demo workflow</a> as a starting point to verify that the runner is executing workflows.</p>
<p>After this, I wanted to make sure that some of my existing workflows could be migrated over.</p> <p>After this, I wanted to make sure that some of my existing workflows could be migrated over.</p>
<p>The following workflow uses a matrix to run a job for several of my hosts using ansible playbooks that will do various tasks such as patching os updates and updating container images.</p> <p>The following workflow uses a matrix to run a job for several of my hosts using ansible playbooks that will do various tasks such as patching os updates and updating container images.</p>
<pre><code class="language-yaml">name: Run ansible <div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">name</span><span style="color:#eceff4">:</span> Run ansible
on: </span></span><span style="display:flex;"><span><span style="color:#81a1c1">on</span><span style="color:#eceff4">:</span>
push: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">push</span><span style="color:#eceff4">:</span>
schedule: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">schedule</span><span style="color:#eceff4">:</span>
- cron: &quot;0 */12 * * *&quot; </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">cron</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;0 */12 * * *&#34;</span>
</span></span><span style="display:flex;"><span>
jobs: </span></span><span style="display:flex;"><span><span style="color:#81a1c1">jobs</span><span style="color:#eceff4">:</span>
run-ansible-playbook: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">run-ansible-playbook</span><span style="color:#eceff4">:</span>
runs-on: ubuntu-latest </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">runs-on</span><span style="color:#eceff4">:</span> ubuntu-latest
strategy: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">strategy</span><span style="color:#eceff4">:</span>
matrix: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">matrix</span><span style="color:#eceff4">:</span>
host: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">host</span><span style="color:#eceff4">:</span>
- changedetection </span></span><span style="display:flex;"><span> - changedetection
- homelab </span></span><span style="display:flex;"><span> - homelab
- invidious </span></span><span style="display:flex;"><span> - invidious
- jackett </span></span><span style="display:flex;"><span> - jackett
- ladder </span></span><span style="display:flex;"><span> - ladder
- miniflux </span></span><span style="display:flex;"><span> - miniflux
- plex </span></span><span style="display:flex;"><span> - plex
- qbittorrent </span></span><span style="display:flex;"><span> - qbittorrent
- tailscale-exit-node </span></span><span style="display:flex;"><span> - tailscale-exit-node
- uptime-kuma </span></span><span style="display:flex;"><span> - uptime-kuma
steps: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">steps</span><span style="color:#eceff4">:</span>
- name: Check out repository code </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">name</span><span style="color:#eceff4">:</span> Check out repository code
uses: actions/checkout@v4 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">uses</span><span style="color:#eceff4">:</span> actions/checkout@v4
- name: Install ansible </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">name</span><span style="color:#eceff4">:</span> Install ansible
run: | </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">run</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">|</span><span style="color:#616e87">
apt update &amp;&amp; apt install ansible -y </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> apt update &amp;&amp; apt install ansible -y</span>
- name: Run playbook </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">name</span><span style="color:#eceff4">:</span> Run playbook
uses: dawidd6/action-ansible-playbook@v2 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">uses</span><span style="color:#eceff4">:</span> dawidd6/action-ansible-playbook@v2
with: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">with</span><span style="color:#eceff4">:</span>
playbook: playbooks/main.yml </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">playbook</span><span style="color:#eceff4">:</span> playbooks/main.yml
requirements: requirements.yml </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">requirements</span><span style="color:#eceff4">:</span> requirements.yml
key: ${{ secrets.SSH_PRIVATE_KEY}} </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">key</span><span style="color:#eceff4">:</span> ${{ secrets.SSH_PRIVATE_KEY}}
options: | </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">options</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">|</span><span style="color:#616e87">
--inventory inventory </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> --inventory inventory
--ssh-extra-args &quot;-o StrictHostKeyChecking=no&quot; </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> --ssh-extra-args &#34;-o StrictHostKeyChecking=no&#34;
--limit ${{ matrix.host }} </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> --limit ${{ matrix.host }}</span>
send-failure-notification: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">send-failure-notification</span><span style="color:#eceff4">:</span>
needs: run-ansible-playbook </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">needs</span><span style="color:#eceff4">:</span> run-ansible-playbook
runs-on: ubuntu-latest </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">runs-on</span><span style="color:#eceff4">:</span> ubuntu-latest
if: always() &amp;&amp; failure() </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">if</span><span style="color:#eceff4">:</span> always() &amp;&amp; failure()
steps: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">steps</span><span style="color:#eceff4">:</span>
- name: Send failure notification </span></span><span style="display:flex;"><span> - <span style="color:#81a1c1">name</span><span style="color:#eceff4">:</span> Send failure notification
uses: dawidd6/action-send-mail@v3 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">uses</span><span style="color:#eceff4">:</span> dawidd6/action-send-mail@v3
with: </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">with</span><span style="color:#eceff4">:</span>
server_address: smtp.gmail.com </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">server_address</span><span style="color:#eceff4">:</span> smtp.gmail.com
server_port: 465 </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">server_port</span><span style="color:#eceff4">:</span> <span style="color:#b48ead">465</span>
secure: true </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">secure</span><span style="color:#eceff4">:</span> <span style="color:#81a1c1;font-weight:bold">true</span>
username: myuser </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">username</span><span style="color:#eceff4">:</span> myuser
password: ${{ secrets.MAIL_PASSWORD }} </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">password</span><span style="color:#eceff4">:</span> ${{ secrets.MAIL_PASSWORD }}
subject: gitea job ${{github.repository}} failed! </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">subject</span><span style="color:#eceff4">:</span> gitea job ${{github.repository}} failed!
to: me@davegallant.ca </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">to</span><span style="color:#eceff4">:</span> me@davegallant.ca
from: Gitea </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">from</span><span style="color:#eceff4">:</span> Gitea
body: | </span></span><span style="display:flex;"><span> <span style="color:#81a1c1">body</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">|</span><span style="color:#616e87">
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }} </span></span></span><span style="display:flex;"><span><span style="color:#616e87"> ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}</span>
</code></pre> </span></span></code></pre></div><p>And voilà:</p>
<p>And voilà:</p>
<video controls preload="auto" width="100%" playsinline class="html-video"> <video controls preload="auto" width="100%" playsinline class="html-video">
<source src="/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/gitea-workflow.webm" type="video/webm"> <source src="/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/gitea-workflow.webm" type="video/webm">
<span>Your browser doesn't support embedded videos, but don't worry, you can <a href="/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/gitea-workflow.webm">download it</a> and watch it with your favorite video player!</span> <span>Your browser doesn't support embedded videos, but don't worry, you can <a href="/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/gitea-workflow.webm">download it</a> and watch it with your favorite video player!</span>
@@ -336,6 +338,9 @@ jobs:
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
<script src="/js/copy-code-button.js"></script>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<h1 class="page-title">All tags</h1> <h1 class="page-title">All tags</h1>
@@ -148,6 +150,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

1
public/css/copy-code-button.min.css vendored Normal file
View File

@@ -0,0 +1 @@
.highlight-wrapper{display:block}.highlight-wrapper .lntd pre{padding:0}.chroma .lntd pre{border:0 solid #ccc}.chroma .lntd:first-child{padding:7px 7px 7px 10px;margin:0}.chroma .lntd:last-child{padding:7px 10px 7px 7px;margin:0}.highlight{position:relative;z-index:0;padding:0;margin:40px 0 10px;border-radius:4px}.highlight>.chroma{position:static;z-index:1;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px;border-bottom-right-radius:4px;padding:10px}.copy-code-button{position:absolute;z-index:2;right:0;top:-29px;font-size:13px;font-weight:700;line-height:14px;letter-spacing:.5px;width:65px;color:#fff;background-color:#000;border:1.25px solid #232326;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0;white-space:nowrap;padding:6px 6px 7px;margin:0 0 0 1px;cursor:pointer;opacity:.6}.copy-code-button:hover,.copy-code-button:focus,.copy-code-button:active,.copy-code-button:active:hover{color:#222225;background-color:#b3b3b3;opacity:.8}.copyable-text-area{position:absolute;height:0;z-index:-1;opacity:.01}.chroma [data-lang]:before{position:absolute;z-index:0;top:-29px;left:0;content:attr(data-lang);font-size:13px;font-weight:700;color:#fff;background-color:#000;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:6px 6px 7px;line-height:14px;opacity:.6;position:absolute;letter-spacing:.5px;border:1.25px solid #232326;margin:0 0 0 1px}

View File

@@ -7,7 +7,9 @@
font-weight: 600; font-weight: 600;
} }
h2:hover a, h3:hover a, h4:hover a { h2:hover a,
h3:hover a,
h4:hover a {
visibility: visible; visibility: visible;
text-decoration: none; text-decoration: none;
} }

View File

@@ -111,49 +111,49 @@ a:hover {
color: var(--darkMaincolor); color: var(--darkMaincolor);
background-color: blue; background-color: blue;
} }
.highlight pre code[class=language-javaScript]::before, .highlight pre code[class="language-javaScript"]::before,
.highlight pre code[class="language-js"]::before { .highlight pre code[class="language-js"]::before {
content: "js"; content: "js";
background: #f7df1e; background: #f7df1e;
color: black; color: black;
} }
.highlight pre code[class*='language-yml']::before, .highlight pre code[class*="language-yml"]::before,
.highlight pre code[class*='language-yaml']::before { .highlight pre code[class*="language-yaml"]::before {
content: 'yaml'; content: "yaml";
background: #f71e6a; background: #f71e6a;
color: white; color: white;
} }
.highlight pre code[class*='language-shell']::before, .highlight pre code[class*="language-shell"]::before,
.highlight pre code[class*='language-bash']::before, .highlight pre code[class*="language-bash"]::before,
.highlight pre code[class*='language-sh']::before { .highlight pre code[class*="language-sh"]::before {
content: 'shell'; content: "shell";
background: rgb(118, 137, 118); background: rgb(118, 137, 118);
color:white color: white;
} }
.highlight pre code[class*='language-json']::before{ .highlight pre code[class*="language-json"]::before {
content: 'json'; content: "json";
background: dodgerblue; background: dodgerblue;
color: #000000 color: #000000;
} }
.highlight pre code[class*='language-python']::before, .highlight pre code[class*="language-python"]::before,
.highlight pre code[class*='language-py']::before { .highlight pre code[class*="language-py"]::before {
content: 'py'; content: "py";
background: blue; background: blue;
color: yellow ; color: yellow;
} }
.highlight pre code[class*='language-css']::before{ .highlight pre code[class*="language-css"]::before {
content: 'css'; content: "css";
background: cyan; background: cyan;
color: black ; color: black;
} }
.highlight pre code[class*='language-go']::before{ .highlight pre code[class*="language-go"]::before {
content: 'Go'; content: "Go";
background: cyan; background: cyan;
color: royalblue ; color: royalblue;
} }
.highlight pre code[class*='language-md']::before, .highlight pre code[class*="language-md"]::before,
.highlight pre code[class*='language-md']::before{ .highlight pre code[class*="language-md"]::before {
content: 'Markdown'; content: "Markdown";
background: royalblue; background: royalblue;
color: whitesmoke ; color: whitesmoke;
} }

View File

@@ -1,18 +1,18 @@
/* Markdown */ /* Markdown */
:root{ :root {
--maincolor: #a15bc2; --maincolor: #a15bc2;
--bordercl: #a15bc2; --bordercl: #a15bc2;
--callouctcolor:dodgerblue; --callouctcolor: dodgerblue;
--hovercolor: #a15bc2; --hovercolor: #a15bc2;
--darkMaincolor: #a15bc2; --darkMaincolor: #a15bc2;
} }
html { html {
color: #232333; color: #232333;
font-family: 'Roboto Mono', monospace; font-family: "Roboto Mono", monospace;
font-size: 18px; font-size: 18px;
line-height: 1.6em; line-height: 1.6em;
} }
body{ body {
display: block; display: block;
background-color: #f8f8f8; background-color: #f8f8f8;
margin: 8px; margin: 8px;
@@ -27,7 +27,7 @@ body{
} }
p { p {
font-family: 'Roboto Light', sans-serif; font-family: "Roboto Light", sans-serif;
line-height: 1.5; line-height: 1.5;
} }
@@ -50,8 +50,8 @@ a {
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
background-color: var(--hovercolor); background-color: var(--hovercolor);
color: #fff; color: #fff;
} }
ul { ul {
@@ -62,7 +62,7 @@ ul li {
text-indent: -2ch; text-indent: -2ch;
} }
ul > li::before { ul > li::before {
content: '* '; content: "* ";
font-weight: bold; font-weight: bold;
} }
@@ -95,13 +95,13 @@ figure h4 {
margin-bottom: 1em; margin-bottom: 1em;
} }
figure h4::before { figure h4::before {
content: ''; content: "";
} }
/* Code blocks */ /* Code blocks */
code { code {
background-color: #f1f1f1; background-color: #f1f1f1;
padding: 0em .0.1em; padding: 0em 0.1em;
} }
pre { pre {
@@ -145,17 +145,40 @@ header {
header .main { header .main {
font-size: 1.5rem; font-size: 1.5rem;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 1.2rem; font-size: 1.2rem;
margin-top: 2em; margin-top: 2em;
} }
h1::before { color: var(--maincolor); content: '# '; } h1::before {
h2::before { color: var(--maincolor); content: '## '; } color: var(--maincolor);
h3::before { color: var(--maincolor); content: '### '; } content: "# ";
h4::before { color: var(--maincolor); content: '#### '; } }
h5::before { color: var(--maincolor); content: '##### '; } h2::before {
h6::before { color: var(--maincolor); content: '###### '; } color: var(--maincolor);
content: "## ";
}
h3::before {
color: var(--maincolor);
content: "### ";
}
h4::before {
color: var(--maincolor);
content: "#### ";
}
h5::before {
color: var(--maincolor);
content: "##### ";
}
h6::before {
color: var(--maincolor);
content: "###### ";
}
.meta { .meta {
color: #999; color: #999;
@@ -198,7 +221,6 @@ article .title {
margin-bottom: 1em; margin-bottom: 1em;
} }
/* Callout */ /* Callout */
.callout { .callout {
background-color: var(--callouctcolor); background-color: var(--callouctcolor);
@@ -207,7 +229,7 @@ article .title {
} }
.callout p { .callout p {
font-family: 'IBM Plex Mono', monospace; font-family: "IBM Plex Mono", monospace;
margin: 0; margin: 0;
} }
@@ -221,32 +243,32 @@ article .title {
} }
.site-description { .site-description {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.tags li::before{ .tags li::before {
content: "- "; content: "- ";
} }
.tags a{ .tags a {
border-bottom: 3px solid var(--maincolor); border-bottom: 3px solid var(--maincolor);
} }
.tags a:hover{ .tags a:hover {
color:white; color: white;
background-color: var(--hovercolor); background-color: var(--hovercolor);
} }
svg{ svg {
max-height: 15px; max-height: 15px;
} }
.soc:hover{ .soc:hover {
color: white; color: white;
} }
.draft-label{ .draft-label {
color: var(--bordercl); color: var(--bordercl);
text-decoration: none; text-decoration: none;
padding: 2px 4px; padding: 2px 4px;
border-radius: 4px; border-radius: 4px;
margin-left: 6px; margin-left: 6px;
background-color: #f9f2f4; background-color: #f9f2f4;
} }
.highlight { .highlight {
position: relative; position: relative;
@@ -269,51 +291,51 @@ svg{
top: 0; top: 0;
} }
.highlight pre code[class=language-javaScript]::before, .highlight pre code[class="language-javaScript"]::before,
.highlight pre code[class="language-js"]::before { .highlight pre code[class="language-js"]::before {
content: "js"; content: "js";
background: #f7df1e; background: #f7df1e;
color: black; color: black;
} }
.highlight pre code[class*='language-yml']::before, .highlight pre code[class*="language-yml"]::before,
.highlight pre code[class*='language-yaml']::before { .highlight pre code[class*="language-yaml"]::before {
content: 'yaml'; content: "yaml";
background: #f71e6a; background: #f71e6a;
color: white; color: white;
} }
.highlight pre code[class*='language-shell']::before, .highlight pre code[class*="language-shell"]::before,
.highlight pre code[class*='language-bash']::before, .highlight pre code[class*="language-bash"]::before,
.highlight pre code[class*='language-sh']::before { .highlight pre code[class*="language-sh"]::before {
content: 'shell'; content: "shell";
background: green; background: green;
color:white color: white;
} }
.highlight pre code[class*='language-json']::before{ .highlight pre code[class*="language-json"]::before {
content: 'json'; content: "json";
background: dodgerblue; background: dodgerblue;
color: #000000 color: #000000;
} }
.highlight pre code[class*='language-python']::before, .highlight pre code[class*="language-python"]::before,
.highlight pre code[class*='language-py']::before { .highlight pre code[class*="language-py"]::before {
content: 'py'; content: "py";
background: blue; background: blue;
color: yellow ; color: yellow;
} }
.highlight pre code[class*='language-css']::before{ .highlight pre code[class*="language-css"]::before {
content: 'css'; content: "css";
background: cyan; background: cyan;
color: black ; color: black;
} }
.highlight pre code[class*='language-go']::before{ .highlight pre code[class*="language-go"]::before {
content: 'Go'; content: "Go";
background: cyan; background: cyan;
color: royalblue ; color: royalblue;
} }
.highlight pre code[class*='language-md']::before, .highlight pre code[class*="language-md"]::before,
.highlight pre code[class*='language-md']::before{ .highlight pre code[class*="language-md"]::before {
content: 'Markdown'; content: "Markdown";
background: royalblue; background: royalblue;
color: whitesmoke ; color: whitesmoke;
} }
/* table */ /* table */
@@ -322,13 +344,13 @@ table {
border-collapse: collapse; border-collapse: collapse;
} }
table th{ table th {
padding: 6px 13px; padding: 6px 13px;
border: 1px solid #dfe2e5; border: 1px solid #dfe2e5;
font-size: large; font-size: large;
} }
table td{ table td {
padding: 6px 13px; padding: 6px 13px;
border: 1px solid #dfe2e5; border: 1px solid #dfe2e5;
} }

View File

@@ -21,8 +21,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -69,7 +69,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
@@ -94,6 +94,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -238,6 +240,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -0,0 +1,58 @@
function createCopyButton(highlightDiv) {
const button = document.createElement("button");
button.className = "copy-code-button";
button.type = "button";
button.innerText = "Copy";
button.addEventListener("click", () =>
copyCodeToClipboard(button, highlightDiv)
);
highlightDiv.insertBefore(button, highlightDiv.firstChild);
const wrapper = document.createElement("div");
wrapper.className = "highlight-wrapper";
highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
wrapper.appendChild(highlightDiv);
}
document
.querySelectorAll(".highlight")
.forEach((highlightDiv) => createCopyButton(highlightDiv));
async function copyCodeToClipboard(button, highlightDiv) {
const codeToCopy = highlightDiv.querySelector(
"pre > code"
).innerText;
try {
var result = await navigator.permissions.query({ name: "clipboard-write" });
if (result.state == "granted" || result.state == "prompt") {
await navigator.clipboard.writeText(codeToCopy);
} else {
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
}
} catch (_) {
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
} finally {
button.blur();
button.innerText = "Copied!";
setTimeout(function () {
button.innerText = "Copy";
}, 2000);
}
}
function copyCodeBlockExecCommand(codeToCopy, highlightDiv) {
const textArea = document.createElement("textArea");
textArea.contentEditable = "true";
textArea.readOnly = "false";
textArea.className = "copyable-text-area";
textArea.value = codeToCopy;
highlightDiv.insertBefore(textArea, highlightDiv.firstChild);
const range = document.createRange();
range.selectNodeContents(textArea);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
textArea.setSelectionRange(0, 999999);
document.execCommand("copy");
highlightDiv.removeChild(textArea);
}

View File

View File

@@ -21,8 +21,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -69,7 +69,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
@@ -94,6 +94,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -148,6 +150,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -161,6 +163,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -143,6 +145,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -143,6 +145,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
<h1 class="page-title">All tags</h1> <h1 class="page-title">All tags</h1>
@@ -360,6 +362,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -143,6 +145,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -143,6 +145,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -149,6 +151,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -145,6 +147,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -19,8 +19,8 @@
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.b242ee667697ab3e792722deba86ca7575ca26cc470cedac147b7fd89e24b22f.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.0b62b6a8c9bc96baf3dd0b8690823918769e50f96220bad87969bb570d1febfe.css" disabled /> <link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
@@ -67,7 +67,7 @@
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css"> <link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head> </head>
<body> <body>
@@ -90,6 +90,8 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script> <script src="/js/themetoggle.js"></script>
</header> </header>
@@ -141,6 +143,7 @@
<div class="footer-info"> <div class="footer-info">
2023 Dave Gallant 2023 Dave Gallant
</div> </div>
</footer> </footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>

View File

@@ -0,0 +1,103 @@
.highlight-wrapper {
display: block;
}
/* Start: Turn off individual column border, margin, and padding when line numbers are showing */
.highlight-wrapper .lntd pre {
padding: 0;
}
.chroma .lntd pre {
border: 0px solid #ccc;
}
.chroma .lntd:first-child {
padding: 7px 7px 7px 10px;
margin: 0;
}
.chroma .lntd:last-child {
padding: 7px 10px 7px 7px;
margin: 0;
}
/* End: Turn off individual column border, margin, and padding when line numbers are showing */
.highlight {
position: relative;
z-index: 0;
padding: 0;
margin: 40px 0 10px 0;
border-radius: 4px;
}
.highlight > .chroma {
position: static;
z-index: 1;
border-top-left-radius: 0px;
border-top-right-radius: 0px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
}
.copy-code-button {
position: absolute;
z-index: 2;
right: 0;
top: -29px;
font-size: 13px;
font-weight: 700;
line-height: 14px;
letter-spacing: 0.5px;
width: 65px;
color: #ffffff;
background-color: #000000;
border: 1.25px solid #232326;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
white-space: nowrap;
padding: 6px 6px 7px 6px;
margin: 0 0 0 1px;
cursor: pointer;
opacity: 0.6;
}
.copy-code-button:hover,
.copy-code-button:focus,
.copy-code-button:active,
.copy-code-button:active:hover {
color: #222225;
background-color: #b3b3b3;
opacity: 0.8;
}
.copyable-text-area {
position: absolute;
height: 0;
z-index: -1;
opacity: 0.01;
}
.chroma [data-lang]:before {
position: absolute;
z-index: 0;
top: -29px;
left: 0;
content: attr(data-lang);
font-size: 13px;
font-weight: 700;
color: white;
background-color: black;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
padding: 6px 6px 7px 6px;
line-height: 14px;
opacity: 0.6;
position: absolute;
letter-spacing: 0.5px;
border: 1.25px solid #232326;
margin: 0 0 0 1px;
}

View File

@@ -111,49 +111,49 @@ a:hover {
color: var(--darkMaincolor); color: var(--darkMaincolor);
background-color: blue; background-color: blue;
} }
.highlight pre code[class=language-javaScript]::before, .highlight pre code[class="language-javaScript"]::before,
.highlight pre code[class="language-js"]::before { .highlight pre code[class="language-js"]::before {
content: "js"; content: "js";
background: #f7df1e; background: #f7df1e;
color: black; color: black;
} }
.highlight pre code[class*='language-yml']::before, .highlight pre code[class*="language-yml"]::before,
.highlight pre code[class*='language-yaml']::before { .highlight pre code[class*="language-yaml"]::before {
content: 'yaml'; content: "yaml";
background: #f71e6a; background: #f71e6a;
color: white; color: white;
} }
.highlight pre code[class*='language-shell']::before, .highlight pre code[class*="language-shell"]::before,
.highlight pre code[class*='language-bash']::before, .highlight pre code[class*="language-bash"]::before,
.highlight pre code[class*='language-sh']::before { .highlight pre code[class*="language-sh"]::before {
content: 'shell'; content: "shell";
background: rgb(118, 137, 118); background: rgb(118, 137, 118);
color:white color: white;
} }
.highlight pre code[class*='language-json']::before{ .highlight pre code[class*="language-json"]::before {
content: 'json'; content: "json";
background: dodgerblue; background: dodgerblue;
color: #000000 color: #000000;
} }
.highlight pre code[class*='language-python']::before, .highlight pre code[class*="language-python"]::before,
.highlight pre code[class*='language-py']::before { .highlight pre code[class*="language-py"]::before {
content: 'py'; content: "py";
background: blue; background: blue;
color: yellow ; color: yellow;
} }
.highlight pre code[class*='language-css']::before{ .highlight pre code[class*="language-css"]::before {
content: 'css'; content: "css";
background: cyan; background: cyan;
color: black ; color: black;
} }
.highlight pre code[class*='language-go']::before{ .highlight pre code[class*="language-go"]::before {
content: 'Go'; content: "Go";
background: cyan; background: cyan;
color: royalblue ; color: royalblue;
} }
.highlight pre code[class*='language-md']::before, .highlight pre code[class*="language-md"]::before,
.highlight pre code[class*='language-md']::before{ .highlight pre code[class*="language-md"]::before {
content: 'Markdown'; content: "Markdown";
background: royalblue; background: royalblue;
color: whitesmoke ; color: whitesmoke;
} }

View File

@@ -1,41 +1,57 @@
/* fira-sans-regular - latin */ /* fira-sans-regular - latin */
@font-face { @font-face {
font-display: swap; font-display: swap;
font-family: 'Fira Sans'; font-family: "Fira Sans";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: url('../fonts/fira-sans-v10-latin-regular.eot'); /* IE9 Compat Modes */ src: url("../fonts/fira-sans-v10-latin-regular.eot"); /* IE9 Compat Modes */
src: local('Fira Sans Regular'), local('FiraSans-Regular'), src: local("Fira Sans Regular"), local("FiraSans-Regular"),
url('../fonts/fira-sans-v10-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url("../fonts/fira-sans-v10-latin-regular.eot?#iefix")
url('../fonts/fira-sans-v10-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ format("embedded-opentype"),
url('../fonts/fira-sans-v10-latin-regular.woff') format('woff'), /* Modern Browsers */ /* IE6-IE8 */ url("../fonts/fira-sans-v10-latin-regular.woff2")
url('../fonts/fira-sans-v10-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ format("woff2"),
url('../fonts/fira-sans-v10-latin-regular.svg#FiraSans') format('svg'); /* Legacy iOS */ /* Super Modern Browsers */ url("../fonts/fira-sans-v10-latin-regular.woff")
format("woff"),
/* Modern Browsers */ url("../fonts/fira-sans-v10-latin-regular.ttf")
format("truetype"),
/* Safari, Android, iOS */
url("../fonts/fira-sans-v10-latin-regular.svg#FiraSans") format("svg"); /* Legacy iOS */
} }
/* roboto-mono-regular - latin */ /* roboto-mono-regular - latin */
@font-face { @font-face {
font-display: swap; font-display: swap;
font-family: 'Roboto Mono'; font-family: "Roboto Mono";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: url('../fonts/roboto-mono-v12-latin-regular.eot'); /* IE9 Compat Modes */ src: url("../fonts/roboto-mono-v12-latin-regular.eot"); /* IE9 Compat Modes */
src: url('../fonts/roboto-mono-v12-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ src: url("../fonts/roboto-mono-v12-latin-regular.eot?#iefix")
url('../fonts/roboto-mono-v12-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ format("embedded-opentype"),
url('../fonts/roboto-mono-v12-latin-regular.woff') format('woff'), /* Modern Browsers */ /* IE6-IE8 */ url("../fonts/roboto-mono-v12-latin-regular.woff2")
url('../fonts/roboto-mono-v12-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ format("woff2"),
url('../fonts/roboto-mono-v12-latin-regular.svg#RobotoMono') format('svg'); /* Legacy iOS */ /* Super Modern Browsers */
url("../fonts/roboto-mono-v12-latin-regular.woff") format("woff"),
/* Modern Browsers */ url("../fonts/roboto-mono-v12-latin-regular.ttf")
format("truetype"),
/* Safari, Android, iOS */
url("../fonts/roboto-mono-v12-latin-regular.svg#RobotoMono") format("svg"); /* Legacy iOS */
} }
/* ibm-plex-mono-500italic - latin */ /* ibm-plex-mono-500italic - latin */
@font-face { @font-face {
font-display: swap; font-display: swap;
font-family: 'IBM Plex Mono'; font-family: "IBM Plex Mono";
font-style: italic; font-style: italic;
font-weight: 500; font-weight: 500;
src: url('../fonts/ibm-plex-mono-v6-latin-500italic.eot'); /* IE9 Compat Modes */ src: url("../fonts/ibm-plex-mono-v6-latin-500italic.eot"); /* IE9 Compat Modes */
src: local('IBM Plex Mono Medium Italic'), local('IBMPlexMono-MediumItalic'), src: local("IBM Plex Mono Medium Italic"), local("IBMPlexMono-MediumItalic"),
url('../fonts/ibm-plex-mono-v6-latin-500italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url("../fonts/ibm-plex-mono-v6-latin-500italic.eot?#iefix")
url('../fonts/ibm-plex-mono-v6-latin-500italic.woff2') format('woff2'), /* Super Modern Browsers */ format("embedded-opentype"),
url('../fonts/ibm-plex-mono-v6-latin-500italic.woff') format('woff'), /* Modern Browsers */ /* IE6-IE8 */ url("../fonts/ibm-plex-mono-v6-latin-500italic.woff2")
url('../fonts/ibm-plex-mono-v6-latin-500italic.ttf') format('truetype'), /* Safari, Android, iOS */ format("woff2"),
url('../fonts/ibm-plex-mono-v6-latin-500italic.svg#IBMPlexMono') format('svg'); /* Legacy iOS */ /* Super Modern Browsers */
url("../fonts/ibm-plex-mono-v6-latin-500italic.woff") format("woff"),
/* Modern Browsers */ url("../fonts/ibm-plex-mono-v6-latin-500italic.ttf")
format("truetype"),
/* Safari, Android, iOS */
url("../fonts/ibm-plex-mono-v6-latin-500italic.svg#IBMPlexMono")
format("svg"); /* Legacy iOS */
} }

View File

@@ -1,18 +1,18 @@
/* Markdown */ /* Markdown */
:root{ :root {
--maincolor: #a15bc2; --maincolor: #a15bc2;
--bordercl: #a15bc2; --bordercl: #a15bc2;
--callouctcolor:dodgerblue; --callouctcolor: dodgerblue;
--hovercolor: #a15bc2; --hovercolor: #a15bc2;
--darkMaincolor: #a15bc2; --darkMaincolor: #a15bc2;
} }
html { html {
color: #232333; color: #232333;
font-family: 'Roboto Mono', monospace; font-family: "Roboto Mono", monospace;
font-size: 18px; font-size: 18px;
line-height: 1.6em; line-height: 1.6em;
} }
body{ body {
display: block; display: block;
background-color: #f8f8f8; background-color: #f8f8f8;
margin: 8px; margin: 8px;
@@ -27,7 +27,7 @@ body{
} }
p { p {
font-family: 'Roboto Light', sans-serif; font-family: "Roboto Light", sans-serif;
line-height: 1.5; line-height: 1.5;
} }
@@ -50,8 +50,8 @@ a {
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
background-color: var(--hovercolor); background-color: var(--hovercolor);
color: #fff; color: #fff;
} }
ul { ul {
@@ -62,7 +62,7 @@ ul li {
text-indent: -2ch; text-indent: -2ch;
} }
ul > li::before { ul > li::before {
content: '* '; content: "* ";
font-weight: bold; font-weight: bold;
} }
@@ -95,13 +95,13 @@ figure h4 {
margin-bottom: 1em; margin-bottom: 1em;
} }
figure h4::before { figure h4::before {
content: ''; content: "";
} }
/* Code blocks */ /* Code blocks */
code { code {
background-color: #f1f1f1; background-color: #f1f1f1;
padding: 0em .0.1em; padding: 0em 0.1em;
} }
pre { pre {
@@ -145,17 +145,40 @@ header {
header .main { header .main {
font-size: 1.5rem; font-size: 1.5rem;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 1.2rem; font-size: 1.2rem;
margin-top: 2em; margin-top: 2em;
} }
h1::before { color: var(--maincolor); content: '# '; } h1::before {
h2::before { color: var(--maincolor); content: '## '; } color: var(--maincolor);
h3::before { color: var(--maincolor); content: '### '; } content: "# ";
h4::before { color: var(--maincolor); content: '#### '; } }
h5::before { color: var(--maincolor); content: '##### '; } h2::before {
h6::before { color: var(--maincolor); content: '###### '; } color: var(--maincolor);
content: "## ";
}
h3::before {
color: var(--maincolor);
content: "### ";
}
h4::before {
color: var(--maincolor);
content: "#### ";
}
h5::before {
color: var(--maincolor);
content: "##### ";
}
h6::before {
color: var(--maincolor);
content: "###### ";
}
.meta { .meta {
color: #999; color: #999;
@@ -198,7 +221,6 @@ article .title {
margin-bottom: 1em; margin-bottom: 1em;
} }
/* Callout */ /* Callout */
.callout { .callout {
background-color: var(--callouctcolor); background-color: var(--callouctcolor);
@@ -207,7 +229,7 @@ article .title {
} }
.callout p { .callout p {
font-family: 'IBM Plex Mono', monospace; font-family: "IBM Plex Mono", monospace;
margin: 0; margin: 0;
} }
@@ -221,32 +243,32 @@ article .title {
} }
.site-description { .site-description {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.tags li::before{ .tags li::before {
content: "- "; content: "- ";
} }
.tags a{ .tags a {
border-bottom: 3px solid var(--maincolor); border-bottom: 3px solid var(--maincolor);
} }
.tags a:hover{ .tags a:hover {
color:white; color: white;
background-color: var(--hovercolor); background-color: var(--hovercolor);
} }
svg{ svg {
max-height: 15px; max-height: 15px;
} }
.soc:hover{ .soc:hover {
color: white; color: white;
} }
.draft-label{ .draft-label {
color: var(--bordercl); color: var(--bordercl);
text-decoration: none; text-decoration: none;
padding: 2px 4px; padding: 2px 4px;
border-radius: 4px; border-radius: 4px;
margin-left: 6px; margin-left: 6px;
background-color: #f9f2f4; background-color: #f9f2f4;
} }
.highlight { .highlight {
position: relative; position: relative;
@@ -269,51 +291,51 @@ svg{
top: 0; top: 0;
} }
.highlight pre code[class=language-javaScript]::before, .highlight pre code[class="language-javaScript"]::before,
.highlight pre code[class="language-js"]::before { .highlight pre code[class="language-js"]::before {
content: "js"; content: "js";
background: #f7df1e; background: #f7df1e;
color: black; color: black;
} }
.highlight pre code[class*='language-yml']::before, .highlight pre code[class*="language-yml"]::before,
.highlight pre code[class*='language-yaml']::before { .highlight pre code[class*="language-yaml"]::before {
content: 'yaml'; content: "yaml";
background: #f71e6a; background: #f71e6a;
color: white; color: white;
} }
.highlight pre code[class*='language-shell']::before, .highlight pre code[class*="language-shell"]::before,
.highlight pre code[class*='language-bash']::before, .highlight pre code[class*="language-bash"]::before,
.highlight pre code[class*='language-sh']::before { .highlight pre code[class*="language-sh"]::before {
content: 'shell'; content: "shell";
background: green; background: green;
color:white color: white;
} }
.highlight pre code[class*='language-json']::before{ .highlight pre code[class*="language-json"]::before {
content: 'json'; content: "json";
background: dodgerblue; background: dodgerblue;
color: #000000 color: #000000;
} }
.highlight pre code[class*='language-python']::before, .highlight pre code[class*="language-python"]::before,
.highlight pre code[class*='language-py']::before { .highlight pre code[class*="language-py"]::before {
content: 'py'; content: "py";
background: blue; background: blue;
color: yellow ; color: yellow;
} }
.highlight pre code[class*='language-css']::before{ .highlight pre code[class*="language-css"]::before {
content: 'css'; content: "css";
background: cyan; background: cyan;
color: black ; color: black;
} }
.highlight pre code[class*='language-go']::before{ .highlight pre code[class*="language-go"]::before {
content: 'Go'; content: "Go";
background: cyan; background: cyan;
color: royalblue ; color: royalblue;
} }
.highlight pre code[class*='language-md']::before, .highlight pre code[class*="language-md"]::before,
.highlight pre code[class*='language-md']::before{ .highlight pre code[class*="language-md"]::before {
content: 'Markdown'; content: "Markdown";
background: royalblue; background: royalblue;
color: whitesmoke ; color: whitesmoke;
} }
/* table */ /* table */
@@ -322,13 +344,13 @@ table {
border-collapse: collapse; border-collapse: collapse;
} }
table th{ table th {
padding: 6px 13px; padding: 6px 13px;
border: 1px solid #dfe2e5; border: 1px solid #dfe2e5;
font-size: large; font-size: large;
} }
table td{ table td {
padding: 6px 13px; padding: 6px 13px;
border: 1px solid #dfe2e5; border: 1px solid #dfe2e5;
} }

View File

@@ -11,6 +11,9 @@
<div class="footer-info"> <div class="footer-info">
{{ dateFormat "2006" now }} {{ with .Site.Copyright }} {{ . }} {{ end }} {{ dateFormat "2006" now }} {{ with .Site.Copyright }} {{ . }} {{ end }}
</div> </div>
{{ if (findRE "<pre" .Content 1) }}
<script src="/js/copy-code-button.js"></script>
{{ end }}
</footer> </footer>
{{ if not .Site.IsServer }} {{ template "_internal/google_analytics.html" . }} {{ if not .Site.IsServer }} {{ template "_internal/google_analytics.html" . }}
{{ end }} {{- if (isset .Site.Params "social") -}} {{ end }} {{- if (isset .Site.Params "social") -}}

View File

@@ -14,4 +14,10 @@
<span id="dark-mode-toggle" onclick="toggleTheme()"></span> <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="{{ .Site.BaseURL }}js/themetoggle.js"></script> <script src="{{ .Site.BaseURL }}js/themetoggle.js"></script>
{{ end }} {{ end }}
{{ if (findRE "<pre" .Content 1) }}
{{ $copyCss := resources.Get "css/copy-code-button.css" | minify }}
<link href="{{ $copyCss.RelPermalink }}" rel="stylesheet">
{{ end }}
</header> </header>

View File

@@ -0,0 +1,58 @@
function createCopyButton(highlightDiv) {
const button = document.createElement("button");
button.className = "copy-code-button";
button.type = "button";
button.innerText = "Copy";
button.addEventListener("click", () =>
copyCodeToClipboard(button, highlightDiv)
);
highlightDiv.insertBefore(button, highlightDiv.firstChild);
const wrapper = document.createElement("div");
wrapper.className = "highlight-wrapper";
highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
wrapper.appendChild(highlightDiv);
}
document
.querySelectorAll(".highlight")
.forEach((highlightDiv) => createCopyButton(highlightDiv));
async function copyCodeToClipboard(button, highlightDiv) {
const codeToCopy = highlightDiv.querySelector(
"pre > code"
).innerText;
try {
var result = await navigator.permissions.query({ name: "clipboard-write" });
if (result.state == "granted" || result.state == "prompt") {
await navigator.clipboard.writeText(codeToCopy);
} else {
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
}
} catch (_) {
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
} finally {
button.blur();
button.innerText = "Copied!";
setTimeout(function () {
button.innerText = "Copy";
}, 2000);
}
}
function copyCodeBlockExecCommand(codeToCopy, highlightDiv) {
const textArea = document.createElement("textArea");
textArea.contentEditable = "true";
textArea.readOnly = "false";
textArea.className = "copyable-text-area";
textArea.value = codeToCopy;
highlightDiv.insertBefore(textArea, highlightDiv.firstChild);
const range = document.createRange();
range.selectNodeContents(textArea);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
textArea.setSelectionRange(0, 999999);
document.execCommand("copy");
highlightDiv.removeChild(textArea);
}