post!
@ -50,6 +50,7 @@
|
||||
.gallery {
|
||||
width: auto; /* Allow it to size naturally */
|
||||
max-width: 100%; /* Prevent overflow */
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
.prose :where(a):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
|
||||
@ -217,3 +218,40 @@ p {
|
||||
.min-w-content {
|
||||
min-width:fit-content;
|
||||
}
|
||||
|
||||
.vari-flex {
|
||||
display:flex;
|
||||
flex-wrap:nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 512px) {
|
||||
.vari-flex {
|
||||
flex-wrap:wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.card-styled {
|
||||
background-color:rgba(var(--color-primary-900), 0.5);
|
||||
border-width:2px;
|
||||
border-style:dashed;
|
||||
border-radius:2px;
|
||||
border-color:rgba(var(--color-secondary-600), 1);
|
||||
padding-top:8px;
|
||||
padding-right:8px;
|
||||
padding-left:8px;
|
||||
}
|
||||
|
||||
.caption {
|
||||
background-color:rgba(var(--color-primary-900), 0.5);
|
||||
border-width:1px;
|
||||
border-style:hidden;
|
||||
border-radius:8px;
|
||||
border-color:rgba(var(--color-secondary-600), 1);
|
||||
padding:4px;
|
||||
padding-left:8px;
|
||||
padding-right:8px;
|
||||
max-width:fit-content;
|
||||
font-style:italic;
|
||||
margin:auto;
|
||||
text-align:center;
|
||||
}
|
BIN
assets/img/background.webp
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/img/blowfish_logo.webp
Normal file
After Width: | Height: | Size: 1.1 MiB |
@ -17,7 +17,7 @@ title = "N.E.E.T. Works"
|
||||
[params.author]
|
||||
name = "rawhide kobayashi"
|
||||
email = "rawhide@neet.works"
|
||||
image = "img/blowfish_logo.png"
|
||||
image = "img/blowfish_logo.webp"
|
||||
imageQuality = 96
|
||||
headline = "beep-boop maggot!"
|
||||
bio = "ᗜ⩊ᗜ"
|
||||
|
@ -23,7 +23,7 @@ disableImageOptimization = false
|
||||
disableTextInHeader = false
|
||||
# backgroundImageWidth = 1200
|
||||
|
||||
# defaultBackgroundImage = "IMAGE.jpg" # used as default for background images
|
||||
defaultBackgroundImage = "img/background.webp" # used as default for background images
|
||||
# defaultFeaturedImage = "IMAGE.jpg" # used as default for featured images in all articles
|
||||
|
||||
# highlightCurrentMenuArea = true
|
||||
@ -50,8 +50,8 @@ giteaDefaultServer = "https://git.neet.works"
|
||||
showRecentItems = 9
|
||||
showMoreLink = true
|
||||
showMoreLinkDest = "/posts/"
|
||||
cardView = false
|
||||
cardViewScreenWidth = false
|
||||
cardView = true
|
||||
cardViewScreenWidth = true
|
||||
layoutBackgroundBlur = false # only used when layout equals background
|
||||
|
||||
[article]
|
||||
|
@ -1,9 +1,9 @@
|
||||
---
|
||||
title: Watercooling My Homelab
|
||||
description: Watercooling for my homelab with a custom, leak-resistant controller and monitoring!
|
||||
date: 2025-01-06T23:48:36.633Z
|
||||
date: 2025-01-16T05:56:41.351Z
|
||||
preview: /Supermicro_846_Internal.webp
|
||||
draft: true
|
||||
draft: false
|
||||
tags:
|
||||
- alphacool
|
||||
- arduino
|
||||
@ -16,10 +16,11 @@ categories:
|
||||
- servers
|
||||
- watercooling
|
||||
- diy
|
||||
slug: watercooling-homelab
|
||||
---
|
||||
|
||||
## Overview
|
||||
Watercooling - or, more accurately, custom loop watercooling[^badnomenclature], rather than AIOs - has increasingly transitioned to an aesthetic choice rather than a practical one in the consumer gaming space, with more energy efficient chips overclocked out the wazoo from the factory and relatively minimal gains to be made compared to cheaper and easier AIO solutions. However, there are still benefits to be had, marginal as they are, in performance, aesthetics, and longevity. In this post I'm going to showcase my solution for a leak-resistant watercooling system with monitoring that I trust to protect my beloved homelab from water damage as well as thermal throttling.
|
||||
I've been watercooling my desktop since 2020, and case modding custom cooling solutions since my first modern dGPU in 2012. I enjoy it for the aesthetic, as well as the ability to run my hardware to the redline, despite the lower gains that modern hardware has... It's still fun to try and see how high you can get on benchmark scoreboards. It was a big initial investment, but with most parts being reusable, the ongoing cost for component upgrades are minimal. Early in 2024, I bought some GPUs to use for dedicated ML tasks in my server rack, and immediately had watercooling on the mind. There weren't particularly strong reasons to do so, but it would lower the power usage a bit, give me some more VRAM overclocking headroom, and give me a bit more core clock stability, as well as the ability to use a cheap two-slot NVLINK connector without suffocating a GPU.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Triple_Card_Jank.webp"
|
||||
@ -27,19 +28,20 @@ Watercooling - or, more accurately, custom loop watercooling[^badnomenclature],
|
||||
caption="My initial setup with 3x 2080 Tis, using m.2 NVMe to PCIe risers in an ASUS prebuilt. Two are connected by NVLINK, which I found to provide a slight performance benefit on the order of ~1-5% in multi-GPU SISR training, which is not worth the typical price for NVLINK bridges from this era. I was lucky to get this ugly, quadro-oriented bridge for just $40."
|
||||
>}}
|
||||
|
||||
I had wanted to watercool my ML setup for a while, particularly so I could use NVLINK without suffocating the GPUs. The above setup worked, but it was loud, the clock speeds were inconsistent, VRAM overclocking was very limited, they would bounce off the power/temperature limit, and it was an incredible pain to move whenever I had to poke around in there. Of course, I was concerned about the possibility of water damage. I've been doing custom watercooling since 2020 in my desktop, and I've never had a leak, but there were going to be more connected components than ever, with wider temperature swings, and collectively, a whole lot more expensive hardware that might get damaged than compared to my desktop setup. The situation became more dire to me, after I upgraded my main server and discovered that the forced-air passive chassis cooling was insufficient for my new CPUs.
|
||||
I've never had a leak on my desktop, but with wider temperature swings in my garage, and collectively, a whole lot more expensive hardware that might get damaged than compared to my desktop setup, I was hesitant. The benefits seemed minimal, and I considered it a fun what-if scenario until I upgraded my main server and discovered that the forced-air passive chassis cooling was insufficient for my new CPUs. At that point, I had to make a decision: Get better heatsinks, which would be single-purpose and cost in excess of $100 each, or whole rack watercooling. I chose whole rack watercooling.
|
||||
|
||||
So, how do you make a fluid system resistant to leaks? Build it very well, with close attention to detail, tighten all the fittings very carefully, regularly replace your o-rings and leak-check extensively before operation? No! You pull a vacuum inside the fluid loop! Just think about it. Water can't get out if air is trying to get in. It's so simple. I wish I could say that I came up with the concept myself, but I didn't. After finding out that Aqua Computer has a product called LEAKSHIELD which does exactly that, I finally had the confidence to take the plunge on this project.
|
||||
With enough reason for me to go ahead with the project, and the only thing holding me back being a fear of leaks, I had to figure out how to actively monitor for, and preferably prevent such an eventuality. I happened upon a product called [LEAKSHIELD](https://shop.aquacomputer.de/Water-Cooling/Leak-testing-prevention/LEAKSHIELD-leak-prevention-system-standalone::4063.html), from Aqua Computer, that advertised itself as doing exactly that.
|
||||
|
||||
{{< youtubeLite id="8UiRv0nDch0" >}}
|
||||
|
||||
How does it work? You pull a vacuum inside the fluid loop and monitor the loss rate. Water can't get out if air is trying to get in, and if air gets in, the vacuum is reduced. It's so simple, I don't know why it took this long for such a product to enter the PC watercooling space. I could have just bought a LEAKSHIELD and called it a day, but Aqua Computer's software doesn't support Linux, and the specs for the vacuum pump seemed a bit weak for a loop of my scale. But, its functionality was something I was confident I could emulate with more robust off-the-shelf parts. Thus, sufficiently armed with esoteric plumbing knowledge, I took the plunge and started loading up on parts.
|
||||
|
||||
## The Hardware
|
||||
Most of the build uses pretty standard off-the-shelf parts for PC watercooling, but there are a few bits and pieces that most builders won't have seen before, and a couple custom solutions that provided a better experience than what standard PC parts can offer. The control system is 100% custom, based on an Arduino Uno that feeds vital statistics over serial, and features a custom pressure control system similar to the LEAKSHIELD, with PID fan control based on a set delta between the water and air temperature.
|
||||
Most of the build uses pretty standard off-the-shelf parts for PC watercooling, but there are a few bits and pieces that most builders won't have seen before, and a custom control system that offers a more relevant experience for a server rack. The control system is based on an Arduino Uno that feeds vital statistics over serial, and features pressure control and monitoring similar to the LEAKSHIELD, with fan control based on a PID algorithm keeping the water temperature at a fixed setpoint above ambient.
|
||||
|
||||
### Off-the-shelf
|
||||
#### General Details
|
||||
|
||||
The centerpiece of the build, which the control unit and pump mount to, is the "MOther of all RAdiators", version 3, from Watercool. This is the 360mm version with support for up to 18 120mm fans, or eight 180mm fans. It's constructed more in the spirit of a vehicle radiator than a traditional PC radiator, with a less restrictive fin stack and large, round tubes rather than thin rectangular ones. It provides several mounting points for accessories which I was able to utilize to secure it to my server rack in a satisfactorily sturdy fashion. An in-depth teardown on the construction method and material quality of the MO-RA can be found on [igor'sLAB](https://www.igorslab.de/en/the-big-radiator-material-test-how-much-copper-and-technology-is-in-the-watercool-mo-ra3-360-pro-part-4/). For fans, I have a collection of old DC-control Corsair Air Series SP120s. They've all been retired from regular use, because of noise-related aging issues. In fact, one of them failed to turn at all once I had everything wired up, and another had its bearing disintegrate (and I really mean disintegrate, the fan became almost entirely un-born and would consistently ram into its own frame) about 8 weeks after putting the thing into service. That being said, they did survive (and continue to survive, in the remaining 16 cases) 24/7 use for anywhere from 4-10 years, at bottom of the barrel pricing, so that's not too bad. I'm not exactly pushing the limits of this radiator here, so a few fans breaking down over time isn't the end of the world.
|
||||
The centerpiece of the build, which the control unit and pump mount to, is the "MOther of all RAdiators", version 3, from Watercool. This is the 360mm version with support for up to 18x 120mm fans, or 8x 180mm fans. It's constructed more in the spirit of a vehicle radiator than a traditional PC radiator, with a less restrictive fin stack and large, round tubes rather than thin rectangular ones. It provides several mounting points for accessories which I was able to utilize to secure it to my server rack in a satisfactorily sturdy fashion. An in-depth teardown on the construction method and material quality of the MO-RA can be found on [igor'sLAB](https://www.igorslab.de/en/the-big-radiator-material-test-how-much-copper-and-technology-is-in-the-watercool-mo-ra3-360-pro-part-4/). For fans, I have a collection of old DC-control Corsair Air Series SP120s. They've all been retired from regular use, because of noise-related aging issues. In fact, one of them failed to turn at all once I had everything wired up, and another had its bearing disintegrate about 8 weeks after putting the thing into service. That being said, they did survive (and continue to survive, in the remaining 16 cases) 24/7 use for anywhere from 4-10 years, at bottom of the barrel pricing, so that's not too bad. I'm not exactly pushing the limits of this radiator here, so a few fans breaking down over time isn't the end of the world.
|
||||
|
||||
|
||||
{{< panzoom-figure
|
||||
@ -48,7 +50,7 @@ The centerpiece of the build, which the control unit and pump mount to, is the "
|
||||
caption="A MO-RA V3 360 PRO PC Watercooling Radiator from [Watercool](https://watercool.de)"
|
||||
>}}
|
||||
|
||||
I got a secondhand Corsair XD5 pump/res combo from eBay for about sixty bucks, which is pretty good for a genuine D5-based pump/res combo. It has PWM support which I did wire up, but the flow rate ended up being so low at 100% that I just run it at 100% all the time. The flow rate is measured through an [Aqua Computer flow sensor](https://shop.aquacomputer.de/Monitoring-and-Controlling/Sensors/Flow-sensor-high-flow-LT-G1-4::3951.html), which is simply a hall-effect tachometer translated to l/h through software. I did not attempt to verify the accuracy of the sensor in my setup. The absolute accuracy is less relevant than simply getting an overall idea of whether or not the measurement is consistent with flow behavior, which it is.
|
||||
I got a secondhand Corsair XD5 pump/res combo from eBay for about sixty bucks, which is pretty good for a genuine D5-based pump/res combo. It has PWM support which I did wire up, but the flow ended up being rather anemic even at 100%, so I just run it full speed all the time. The flow rate is measured through an [Aqua Computer flow sensor](https://shop.aquacomputer.de/Monitoring-and-Controlling/Sensors/Flow-sensor-high-flow-LT-G1-4::3951.html), which is simply a hall-effect tachometer translated to l/h through software. I did not attempt to verify the accuracy of the sensor in my setup. The absolute accuracy is less relevant than simply getting an overall idea of whether or not the measurement is consistent with flow behavior, which it is.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Mounting_Detail.webp"
|
||||
@ -57,7 +59,7 @@ I got a secondhand Corsair XD5 pump/res combo from eBay for about sixty bucks, w
|
||||
>}}
|
||||
|
||||
#### CPUs
|
||||
My problematic upgrade was to dual Xeon Gold 6154s, which are Skylake-SP architecture. This specific SKU has 18 cores with sustained all-core speeds of 3.7GHz SSE / 3.3GHz AVX2 / 2.7GHz AVX512, and a TDP of 200 watts. The rated tjmax was 105C, and with the chassis cooling, they readily met that and started throttling under all-core loads, idling as high as 60-70\*C. I previously had Xeon e5-2697 v2s, which had TDPs of 130w. They got toasty, but never throttled. I'm not sure if the chassis had fan upgrades available that might have made a difference, and I certainly could have moved to 4u-compatible tower coolers rather than forced air, but I figured if I was going to cool the GPUs anyway, adding the CPUs as well would be minimal cost/effort, with more future compatibility for the waterblocks compared to a specialized LGA3647 tower cooler.
|
||||
My thermally problematic server upgrade was to dual Xeon Gold 6154s, which are Skylake-SP architecture. This specific SKU is pretty beefy, with 18 cores at sustained all-core speeds of 3.7GHz SSE / 3.3GHz AVX2 / 2.7GHz AVX512, and a TDP of 200 watts. The rated tjmax was 105C, and with the chassis cooling, they readily met that and started throttling under all-core loads, with idle as high as 60-70\*C. I previously had Xeon E5-2697 v2s, which had TDPs of 130w. They got toasty, but never throttled. I'm not sure if the chassis had any easy fan upgrades available that might have made a difference, and I certainly could have moved to 4u-compatible tower coolers rather than forced air, but since I wanted to watercool the GPUs anyway, adding the CPUs as well would be minimal cost/effort, with more future compatibility for the waterblocks compared to a specialized LGA3647 tower cooler.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Coldplate.webp"
|
||||
@ -65,7 +67,7 @@ My problematic upgrade was to dual Xeon Gold 6154s, which are Skylake-SP archite
|
||||
caption="Alphacool Eisblock XPX Pro coldplate Image credit & copyright - [igor'sLAB](https://www.igorslab.de/en/ryzen-threadripper-2990-wx-with-500-w-alphacool-iceblock-xpx-aurora-pro-plexi-digital-rgb-in-test/)"
|
||||
>}}
|
||||
|
||||
The CPU waterblocks are Alphacool Eisblock XPX Pro Aurora Light models, which are significantly cheaper than the XPX Aurora Pro not-light version. They appear to be entirely identical, functionally... I'm not sure if there any actual performance benefits offered by the not-light version. It's a relatively obscure block family without many thorough reviews, which makes sense, given this block is designed for full coverage on Xeons/Threadrippers. The coldplate appears to be skived, which is uncommon in this price bracket for a discrete block, and the fins are incredibly short and dense. In smaller desktop loops, I've seen this block criticized for having overly restrictive flow, but when you have four blocks + quick disconnects, 'good' flow is relative. At maximum load, the maximum core temperature delta relative to the water temperature is 25\*C, with a ~1-2\*C average delta between the two serially-connected sockets at a flow rate of ~130L/h, and that's more than sufficient.
|
||||
The CPU waterblocks are Alphacool Eisblock XPX Pro Aurora Light models, which are significantly cheaper than the XPX Aurora Pro not-light version. They appear to be entirely identical, functionally... I'm not sure if there any actual performance benefits offered by the not-light version. It's a relatively obscure block family without many thorough reviews, which makes sense, given this block is designed for full coverage on Xeons/Threadrippers. The coldplate appears to be [skived](https://en.wikipedia.org/wiki/Skiving_(metalworking)#Heat_sinks), which is uncommon in this price bracket for a discrete block, and the fins are incredibly short and dense. In smaller desktop loops, I've seen this block criticized for having overly restrictive flow, but when you have four blocks + quick disconnects, "good" flow is relative. At the power limit of 200w, the maximum core temperature delta relative to the water temperature is 25\*C, with a ~1-2\*C average delta between the two serially-connected sockets at a flow rate of ~130L/h, and that's more than sufficient.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Dual_Blocks_Zoom.webp"
|
||||
@ -74,8 +76,7 @@ The CPU waterblocks are Alphacool Eisblock XPX Pro Aurora Light models, which ar
|
||||
>}}
|
||||
|
||||
#### GPUs
|
||||
|
||||
The GPU blocks are Phanteks 2080 Ti Founder's Edition blocks. Nothing special, they're just the cheapest matching ones I could find in 2024 that looked like they'd fit these almost-reference-but-not-quite OEM cards without extensive modification. I bought the GPUs from a supplier dedicated to the cause of specifically selling 22GB modded 2080 Tis, [for quite a reasonable price.](https://2080ti22g.com/ "#not an ad, but it could be 🪝☝️😜") It's by far the best value for $/GB VRAM in NVIDIA GPUs,[^pascalbad] although for your usecase, you will have to judge the speed-value proposition compared to used 3090 (Ti)s. Performance improvements in ML tasks between the 2080 Ti and 3090 (Ti) ranges from as little as ~20% to as much as ~100% depending on how memory bandwidth constrained your workload is. With secondhand 3090 (Ti)s still going for minimum $700 on the used market in the US, I found the alternative 2080 Ti option to be more alluring. The idea of having a modded GPU in itself was also appealing and definitely part of why I made that decision. Pulling up a hardware monitor and seeing a 2080 Ti with 22GB of VRAM feels a little bit naughty, and I like that. I did initially buy three of them, as pictured above, but one of them failed just after the 30 day warranty period listed on their website. Despite that, they were kind enough to offer a full refund if I covered return shipping, and were very communicative and responded in <24 hours every time I sent them any kind of message/inquiry.
|
||||
The GPU blocks are Phanteks 2080 Ti Founder's Edition blocks. Nothing special, they're just the cheapest matching ones I could find in 2024 that looked like they'd fit these almost-reference-but-not-quite OEM cards. They're generic OEM models that would have gone in prebuilts. The most interesting thing about these cards, is that they've been modded to have 22GB of VRAM. There's a [dedicated supplier](https://2080ti22g.com/ "#not an ad, but it could be 🪝☝️😜") still offering them, and it's by far the best $/GB value for VRAM in modern NVIDIA GPUs.[^pascalbad] Whether or not this is a better value overall than, say, a 3090 (Ti) depends on your usecase. Performance improvements in ML tasks between the 2080 Ti and 3090 (Ti) range from as little as ~20% to as much as ~100% depending on how memory bandwidth constrained your workload is. With secondhand 3090 (Ti)s still going for minimum $700 on the used market in the US, I found the alternative 2080 Ti option to be more alluring for my usecase, which is primarily single image super-resolution. More VRAM is desirable to increase the size of tiles for inference, and to increase the batch size during training. Training speed scales almost linearly, and inference speed scales linearly, per GPU. So, for my usecase, where I'm not really limited by the performance of a single GPU, the 2080 Ti mod route offers better overall value both for VRAM and combined core performance compared to 3090 (Ti)s. The idea of having a modded GPU in itself was also appealing and definitely part of why I made that decision. Pulling up a hardware monitor and seeing a 2080 Ti with 22GB of VRAM feels a little bit naughty, and I like that.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/GPUs_Installed.webp"
|
||||
@ -83,13 +84,11 @@ The GPU blocks are Phanteks 2080 Ti Founder's Edition blocks. Nothing special, t
|
||||
caption="The blocks installed in an ASUS prebuilt gaming tower."
|
||||
>}}
|
||||
|
||||
With the stock air cooler, I couldn't maintain 1800MHz core clock without alternatively power/thermal throttling. 1800MHz is a somewhat arbitrary choice of clock speed that is technically overclocked from the 2080 Ti base, but still reasonably power efficient. The actual temperature is not a concern, in terms of longevity, despite what some/many/most people seem to believe. It does have a direct impact on performance, but most people are not suffering thermal throttling to the degree that their performance is affected in a way that they would actually notice in a blind test.
|
||||
I did initially buy three of them, as pictured at the beginning of this post, but one of them failed just after the 30 day warranty period listed on their website. Despite that, they were kind enough to offer a full refund if I covered return shipping, and were very communicative and responded in <24 hours every time I sent them any kind of message/inquiry.
|
||||
|
||||
The biggest benefit that watercooling brings to modern video cards is a prolonged lifespan. Not due to lower core temperatures, in an absolute sense, but due to the reduced stress from thermal cycles. Mismatches in the rate of thermal expansion between the die and the substrate will eventually cause their bond to break, and this happens faster the larger your die is. Today's GPU dies are huge, and this failure mode is the most common.
|
||||
The biggest benefit that watercooling theoretically brings to modern video cards is a prolonged lifespan. Not due to lower core temperatures,[^thermalfears] in an absolute sense, but due to the reduced stress from thermal cycles. Mismatches in the rate of thermal expansion between the die and the substrate will eventually cause their bond to break, and this happens faster the larger your die is, and the more extreme the temperature differences are. Today's GPU dies are huge, and it's hard to say how many failures are attributable to this factor alone, but it is certain to be more of a risk than it has been in the past. I'd rather buy a used mining GPU than a used gaming GPU any day, because it has likely been kept at roughly the same temperature for most of its life, as opposed to experiencing wide periodic swings.
|
||||
|
||||
Logically, provided you don't somehow break things while installing the block, watercooling is the second-best method to ensure the longevity of your GPU behind never using it, or always keeping it under full load. It also generally allows the memory to clock a bit higher as it can be kept significantly cooler by the less-heat-saturated surface area of the block compared to a traditional air cooler. Although I can't benchmark the before and after memory temperature on these cards in particular as they do not expose VRAM temperature sensors, I can confirm that putting them under water allowed the memory to clock marginally higher than under the stock air cooler.
|
||||
|
||||
{{< panzoom-gallery caption="The GPU blocks required a *moderate amount of light massaging* to properly fit on these OEM model cards. The power plugs are in a different position and a singular capacitor on these models is slightly taller than on the actual Founder's Edition reference card, but they're otherwise identical. Enough.">}}
|
||||
{{< panzoom-gallery caption="The GPU blocks required a *moderate amount of light massaging* to properly fit on these OEM model cards. The power plugs are in a different position and a singular capacitor on these models is slightly taller than on the actual Founder's Edition reference card, but they're otherwise close enough to identical.">}}
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Block_Mod_Detail_A.webp"
|
||||
alt="Trimmed area for the capacitor."
|
||||
@ -111,12 +110,11 @@ Logically, provided you don't somehow break things while installing the block, w
|
||||
>}}
|
||||
{{< /panzoom-gallery >}}
|
||||
|
||||
Temperature, as an absolute value, within manufacturer limits, affects boost clocks, and leakage current. A cooler chip will use less power to run at the same clock speed compared to a hotter chip due to reduced leakage current, making them measurably more energy efficient per clock cycle the colder they run. Quantifying the exact drop in power use due to reduced leakage current is not possible as I do not have an isolated measurement of how much power the fan used, which draws from the total board power budget. In my case, with the fan on max, while not thermal throttling, these GPUs would bounce off the power limit of 280w while attempting to hit a core clock of 1800MHz. Under water, at a measured core temperature of ~30*C, the reported board power draw is only ~220w at 1800MHz core clock for the same workload. The type of fan typically found in these coolers is rated anywhere from 15-30w on its own.
|
||||
|
||||
### Putting the I in DIY
|
||||
That's not to say that there are no benefits from lowering the operating temperature. As an absolute value, within manufacturer limits, it affects boost clocks, and [leakage current](https://en.wikipedia.org/wiki/Leakage_(electronics)#In_semiconductors). A cooler chip will use less power to run at the same clock speed compared to a hotter chip due to reduced leakage current, making them measurably more energy efficient per clock cycle the colder they run. In my case, with the fan on max, while not thermal throttling, these GPUs would bounce off the power limit of 280w while attempting to hit a core clock of 1800MHz. Under water, at a reported core temperature of ~30*C, the reported board power draw is only ~220w at 1800MHz[^overclockingonlinux] core clock for the same workload. The type of fan typically found in these coolers is rated anywhere from 15-30w on its own, so a reduction of at least 30w can likely be attributed to a lower leakage current.
|
||||
|
||||
### DIY Time
|
||||
In no particular order, here is a list of the major components involved in the control system.
|
||||
- Generic metal box, that used to contain backup batteries for a PBX system.
|
||||
- Generic metal box, formerly from a PBX system.
|
||||
- Arduino Uno clone, unknown brand
|
||||
- 60mm Corsair fan
|
||||
- RS232 TTL shifter
|
||||
@ -133,32 +131,28 @@ In no particular order, here is a list of the major components involved in the c
|
||||
|
||||
{{< panzoom-figure
|
||||
src="images/compressed/Test_Fit.webp"
|
||||
alt="Plopping all the major components in a box to see what happens in my brain."
|
||||
caption="Plopping all the major components in a box to see what happens in my brain."
|
||||
alt="Fit check for all the major components."
|
||||
caption="Fit check for all the major components."
|
||||
>}}
|
||||
|
||||
|
||||
Unfortunately, I didn't take excruciatingly detailed pictures of literally every single step of the assembly/prototyping process, but it's not that complicated or interesting in terms of electrical engineering. For the most part, it's just plugging pre-made components together. The most interesting production notes include the pressure sensor and the power supply.
|
||||
I didn't take excruciatingly detailed pictures of every single step of the assembly/prototyping process. For the most part, I was just plugging pre-made components together. The most interesting production notes include the pressure sensor and the power supply.
|
||||
|
||||
#### Putting New Life into an iMac PSU
|
||||
The power supply I used is from a first-gen Intel White iMac, which is visually very similar to the G5. It was one of the earliest things that I installed Linux on, and I used it as a seedbox for a bit, but eventually took it apart and saved some of the more interesting stuff.
|
||||
|
||||
Some time ago, my aunt gave me her first-gen Intel White iMac, which is visually very similar to the G5, and it was one of the earliest things that I installed Linux on. I used it as a seedbox for a bit, but eventually took it apart and saved some of the more interesting stuff. The hard drive is still running in my router today!
|
||||
All the credit goes to the user *ersterhernd*, from [this thread](https://www.tonymacx86.com/threads/imac-isight-model-power-supply-unleashed.150793/) on the [tonymacx86.com](https://tonymacx86.com) forum for figuring out the pinout of this PSU, which is almost entirely identical to the one that was in my unit, apart from the power rating on mine being 200w. There are two banks of pins, half of which are always on, half of which are toggleable. Each bank has 12v, 5v, and 3.3v. I didn't end up using 3.3v for anything other than the power switch. I have no idea what the energy efficiency of this unit is, obviously it doesn't have an 80+ certification... But I'm assuming that Apple would make it at least halfway decent. Hopefully more efficient than a random 12v power brick with additional converters, I'd hope.
|
||||
|
||||
{{< panzoom-figure
|
||||
src="schematic_minify.svg"
|
||||
alt="My schematic for the control unit. It's the first time I've used KiCad, and the first time I've ever made a schematic like this at all. I hope it's relatively legible."
|
||||
caption="My schematic for the control unit. It's the first time I've used KiCad, and the first time I've ever made a schematic like this at all. I hope it's relatively legible."
|
||||
alt="My schematic for the control unit. It was the first time I've ever used KiCad, and the first time I've ever made a schematic like this at all. I hope it's relatively legible."
|
||||
caption="My schematic for the control unit. It was the first time I've ever used KiCad, and the first time I've ever made a schematic like this at all. I hope it's relatively legible."
|
||||
>}}
|
||||
|
||||
All the credit goes to the user 'ersterhernd', from [this thread](https://www.tonymacx86.com/threads/imac-isight-model-power-supply-unleashed.150793/) on the [tonymacx86.com](https://tonymacx86.com) forum for figuring out the pinout of this PSU, which is almost entirely identical to the one that was in my unit, apart from the power rating on mine being 200w. There are two banks of pins, half of which are always on, half of which are toggleable. Each bank has 12v, 5v, and 3.3v. I didn't end up using 3.3v for anything other than the power switch. I have no idea what the energy efficiency of this unit is, obviously it doesn't have an 80+ certification... But I'm assuming that Apple would make it at least halfway decent, right? Certainly more than a random 12v power brick with additional converters, I'd hope.
|
||||
|
||||
As you can see in the schematic above, the always-on 3.3v pin is connected to SYS_POWERUP through a relay board. The relay input is pulled low by a single pole switch, which turns the relay on, which connects ground to SYS_POWERUP, engaging the other rail of the power supply. This is kind of a convoluted solution to not having a double-pole switch... But I didn't have a double-pole switch, so that's what I did.
|
||||
|
||||
While I did wire up the pump PWM, tachometer, and fan tachometer, I didn't really end up using them. There's no reason for the pump to ever run below 100%, especially given the restrictive loop, and the tachometer readings I found to be very inconsistent for all but the flow meter. I still haven't figured out for sure what the problem is. My best guess is that the PWM signal for the fans is interfering with the readings for those two pins, somehow... But I'm not sure. In the end, I took fan tachometer monitoring out of the script entirely, as the flow meter will inform of pump failure, and air vs water temperature deltas will inform of total fan failure. I haven't integrated monitoring into the server-side of the script yet, beyond simple stat readouts. I plan to integrate it with Zabbix, once I have that installed... Soon™️.
|
||||
|
||||
#### Measuring vacuum
|
||||
|
||||
The leak-resisting aspect all hinges on monitoring the pressure of the loop. For some reason, I had a really hard time finding a vacuum pressur sensor. There are plenty of physical, analogue vacuum gauges available, but an actual, electronic sensor... At least for reasonable prices, located in the US, I could only find ones that measured positive pressure. Maybe I had the wrong search terms. Eventually I found an unpackaged sensor with obscure, not entirely legible datasheets that claimed to have an acceptable pressure range for my application. The [MD-PS002](https://electronperdido.com/wp-content/uploads/2021/12/MD_PS002-Datasheet.zh-CN.en_.pdf) is what I settled on, available on Amazon in the US in a 2-pack for $8. It's a tiny little thing, and it took two attempts to successfully create a sensor package that didn't leak.
|
||||
The leak-resisting aspect all hinges on monitoring the pressure of the loop... Or potentially running a vacuum pump constantly, but that's stupid. For some reason, I had a really hard time finding a vacuum pressur sensor. There are plenty of physical, analogue vacuum gauges available, but as far as an electronic sensor... I just couldn't find any located in the US, at a reasonable price. There were a few hobbyist grade differential sensors, but I wanted to be able to measure down to an almost complete vacuum, and they didn't have the range. Maybe I had the wrong search terms, but I just wasn't finding anything. Eventually I found an unpackaged sensor with obscure, not entirely legible datasheets that claimed to have an acceptable pressure range for my application. The [MD-PS002](https://electronperdido.com/wp-content/uploads/2021/12/MD_PS002-Datasheet.zh-CN.en_.pdf) is what I settled on, available on Amazon in the US in a 2-pack for $8. It's a tiny little thing, and it took two attempts to successfully create a sensor package that didn't leak.
|
||||
|
||||
{{< panzoom-gallery caption="Sensor package details, installed and all gooped up.">}}
|
||||
{{< panzoom-figure
|
||||
@ -177,9 +171,13 @@ The leak-resisting aspect all hinges on monitoring the pressure of the loop. For
|
||||
>}}
|
||||
{{< /panzoom-gallery >}}
|
||||
|
||||
I drilled a hole in a G1/4" plug, just slightly bigger than the metal ring on the sensor, coated that ring with J-B Weld, and inserted it, letting it cure before grinding away the exterior of the top of the plug and building up more J-B weld to add some strain relief for the wires as well as edge-to-edge sealing. The vacuum loss rate, after running the system for a few months to allow the loop to thoroughly de-gas, is now less than 50mbar per day at -500 to -600mbar. I was slightly worried about the lifetime of the pump, given it's a cheap thing from Amazon, but given it only has to run for about a second every other day, I imagine that won't be an issue.
|
||||
I drilled a hole in a G1/4" plug, just slightly bigger than the metal ring on the sensor, coated that ring with J-B Weld, and inserted it, letting it cure before grinding away the exterior of the top of the plug and building up more J-B weld to add some strain relief for the wires as well as edge-to-edge sealing. The current vacuum loss rate, after running the system for a few months, allowing the loop to very thoroughly de-gas, is now less than 50mbar per day at -500 to -600mbar. I was slightly worried about the lifetime of the pump, given it's a cheap thing from Amazon, but given it only has to run for about a second every 2-3 days, I imagine that won't be an issue.
|
||||
|
||||
This sensor is a wheatstone bridge, which works the same way as load cells for digital scales. The resistance changes are very, very low, thus the signal must be amplified before being fed into an ADC. You could use an op-amp, and feed that signal into an analog input on the Arduino, but I felt more comfortable using the HX711, a two-channel ADC with integrated amplifier designed to be used with wheatstone bridge load cells. Here's a code snippet showing how I converted the raw analog measurement to mbar.
|
||||
Here's a quick video showing the system not leaking!
|
||||
|
||||
{{< youtubeLite id="wCmtzoBKFZg" >}}
|
||||
|
||||
This pressure sensor is a wheatstone bridge, which works the same way as load cells for digital scales. The resistance changes are very, very low, thus the signal must be amplified before being fed into an ADC. You could use an op-amp, and feed that signal into an analog input on the Arduino, but I felt more comfortable using the HX711, a two-channel ADC with integrated amplifier designed to be used with wheatstone bridge load cells. Here's a code snippet showing how I converted the raw analog measurement to mbar.
|
||||
|
||||
```c++
|
||||
float pressure_raw_to_mbar(int32_t pressure_raw) {
|
||||
@ -190,8 +188,7 @@ float pressure_raw_to_mbar(int32_t pressure_raw) {
|
||||
I calibrated it manually, comparing it to an analogue gauge. It's calibrated to a zero point at atmospheric pressure in my locale, and from -700mbar to +1000mbar. I figured out that, when setting the HX711 to a gain of 64 with the Adafruit HX711 library, a change of 100mbar is a change in the ADC measurement by 30k, highly consistent across the entire pressure range that I tested. I can't be 100% sure how accurate the analogue gauge is, but 100% accuracy doesn't really matter for this application. All I really need to know is the fact that an adequate vacuum is present, and a general idea of the leak rate, which is a requirement that this setup meets.
|
||||
|
||||
#### Other stuff
|
||||
|
||||
Everything else was mostly uneventful. I got a medium-power PWM motor driver with L298 logic, claiming a continuous current of 7 amps per channel, which nicely fit my requirements. 120mm PC fans are typically 0.2-0.3 amps, mine in particular are 0.25. So, for 18 fans, it should be approximately 4.5 amps at 100% speed. It's a bit oversized, and I'm only using one channel, but it leaves me the option in the future to use larger, generic radiator fans that have more demanding power requirements. PC fans are infamously overpriced, after all. Eventually enough of them are going to fail that I'll have to do something.
|
||||
I got a beefy PWM motor driver with L298 logic, claiming a continuous current of 7 amps per channel, which nicely fit my requirements. 120mm PC fans are typically 0.2-0.3 amps, and mine in particular are 0.25. For 18 fans, it should be approximately 4.5 amps at 100% speed. It's a bit oversized, and I'm only using one channel, but it leaves me the option in the future to use larger, generic radiator fans that have more demanding power requirements. I'm already down two from eighteen, eventually enough of them are going to fail that I'll have to find another solution.
|
||||
|
||||
{{< panzoom-gallery caption="Required additions to the solenoid, pump motor, and the complete assembly without cover.">}}
|
||||
{{< panzoom-figure
|
||||
@ -211,90 +208,20 @@ Everything else was mostly uneventful. I got a medium-power PWM motor driver wit
|
||||
>}}
|
||||
{{< /panzoom-gallery >}}
|
||||
|
||||
In my initial tests, I found that operating the pump and solenoid would cause the Arduino to reset, seemingly at random, or cause other undefined behavior. Since they were not electrically isolated on a second power supply, that makes sense. They were backfeeding energy and causing a notable amount of general interference during operation, to the point that the LEDs on the inactive relay modules would dimly illuminate when the motor was in operation, and very visibly illuminate whenever the motor or the solenoid deactivated. I had to add flyback diodes, and, for peace of mind, I added ceramic filtering capacitors to the pump as well. Those additions completely eliminated the issues. Electrical engineering is real. Below is a video demonstrating the issue.
|
||||
In my initial tests, I found that operating the pump and solenoid would cause the Arduino to reset, seemingly at random, or cause other undefined behavior. Since they were not electrically isolated on a second power supply, that makes sense. They were backfeeding energy and causing a notable amount of general interference during operation, to the point that the LEDs on the inactive relay modules would dimly illuminate when the motor was in operation, and very visibly illuminate whenever the motor or the solenoid deactivated. I had to add flyback diodes, and, for peace of mind, I added ceramic filtering capacitors to the pump as well. Those additions completely eliminated the issue. Below is a video demonstrating the bad behavior.
|
||||
|
||||
{{< youtubeLite id="E-Ngy0T2RyM" >}}
|
||||
|
||||
I soldered up a sort of bus bar for the fan connectors, used an Adafruit proto-shield to interface several connectors with the Arduino, and did a similar plug-drilling setup for the water temperature sensors with a generic Dallas temperature probe. That pretty much covers everything noteworthy about the hardware.
|
||||
I did a similar plug-drilling setup for the water temperature sensor with a generic Dallas temperature probe. The air probe was taped to the exterior of the box, in the path of the incoming air. All that remained was to solder up a sort of bus bar for the radiator fan connectors, get the temperature probes and pull-up resistors wired into the proto board, and hook everything up to the Arduino, then write the software to tie it all together.
|
||||
|
||||
## The Software
|
||||
|
||||
{{< gitea server="https://git.neet.works" repo="rawhide_k/server-watercooling-controller">}}
|
||||
|
||||
As I mentioned earlier, my software is incomplete. The server-side is currently just a brute-force JSON-over-serial reader writte in Python. I will update this section in the future when I have the JSON-serial-Zabbix bridge setup. It will mostly be for intellectual interest to see how the temperatures change throughout the year and whether or not the leak rate changes meaningfully over time. I plan to setup alerts and emergency shutdowns for out-of-bounds leak rates, or pump failure, of course, but with proper soft-tubing setups spontaneous failures are exceedingly rare, and the negative pressure should prevent/notify of any kind of impending failure before anything actually leaks. D5 pump failures are exceedingly rare when run in clean systems at a fixed speed with infrequent starts/stops, but they do happen.
|
||||
The Arduino operates independently, without a server. The fan speed and loop pressure are managed autonomously. The serial connection is only used to report vital stats, for later integration into more connected monitoring systems. Ultimately, there are only two actions it can take: Change the fan speed, and turn on the vacuum pump. Neither of these require any external knowledge. It doesn't need any information about the connected hardware to function correctly. All it's concerned with is keeping the water temperature at a certain delta above ambient temperature, and keeping the loop pressure within a certain range. Ultimately, very simple.
|
||||
|
||||
The Arduino does not take commands from the server. It manages the fans and pressure autonomously, for ease of programming / debugging, and so that it can operate independently of a connection to an active server. It doesn't need to know how many devices are in use, or the temperatures of any components, because there are ultimately only two actions it can take. Change the pump speed, or change the fan speed. Fan speed should never be associated with component temperature. It should be associated with water temperature.
|
||||
Once per second, the temperature sensors are sampled, the PID loop for the fans runs with the new temperature data points, and the fan speed, temperature data, vacuum pressure, and pump/flow measurements are sent over serial with the help of the ArduinoJSON library. I settled on a target water delta of 4\*C relative to ambient, with a chosen min/max temperature range where the fans turn off or pin themselves to 100% completely. The 4\*C delta is rather arbitrary. It's approximately the delta that exists when the systems are on, but idle, and the fans are at their minimum speed. That delta can be maintained during 100% CPU load, and during medium-heavy GPU loads, but not both combined. It still stays well under a 10\*C delta in that case, though, so I can't complain.
|
||||
|
||||
Occasionally, the temperature probes as well as the HX711 return spurious readings that cause poor behavior, such as crashing the Arduino. In particular, the temperature probes will sometimes return -127, which caused my PID algorithm to crash the Arduino for reasons I could not divine. In addition, the HX711 occasionally returns wildly wrong results that need to be filtered out.
|
||||
|
||||
For the temperature probes, I simply ignore the one problematic result that I've observed.
|
||||
|
||||
```c++
|
||||
new_water_temp = sensors.getTempC(water_therm);
|
||||
new_air_temp = sensors.getTempC(air_therm);
|
||||
|
||||
if (new_water_temp != -127) {
|
||||
water_temp = new_water_temp;
|
||||
}
|
||||
|
||||
if (new_air_temp != -127) {
|
||||
air_temp = new_air_temp;
|
||||
}
|
||||
|
||||
sensors.requestTemperatures();
|
||||
```
|
||||
|
||||
For the pressure detection issues, I wait one second, and if the pressure is still below the threshold, I then begin pumping. This check happens approximately ten times per second, as the default behavior of the HX711 board that I have is to run in 10hz mode. I'm not sure if the issue springs from some kind of interference with the tachometer interrupts messing up the signaling timing, or if I'm misunderstanding the correct way to sample the HX711 over time.
|
||||
|
||||
```c++
|
||||
if (cur_loop_timestamp - last_pressure_check >= 100) {
|
||||
loop_pressure = pressure_raw_to_mbar(hx711.readChannelRaw(CHAN_A_GAIN_64));
|
||||
|
||||
if (sucking == false) {
|
||||
if (loop_pressure > low_pressure_threshold) {
|
||||
if (checking_low_pressure == false) {
|
||||
checking_low_pressure = true;
|
||||
low_pressure_confirmation_timestamp = cur_loop_timestamp;
|
||||
}
|
||||
if (cur_loop_timestamp - low_pressure_confirmation_timestamp >= 1000) {
|
||||
digitalWrite(pump_relay, HIGH);
|
||||
digitalWrite(solenoid_relay, HIGH);
|
||||
sucking = true;
|
||||
checking_low_pressure = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (cur_loop_timestamp - low_pressure_confirmation_timestamp >= 1000) {
|
||||
checking_low_pressure = false;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (loop_pressure < high_pressure_threshold) {
|
||||
digitalWrite(pump_relay, LOW);
|
||||
digitalWrite(solenoid_relay, LOW);
|
||||
sucking = false;
|
||||
}
|
||||
}
|
||||
last_pressure_check = cur_loop_timestamp;
|
||||
}
|
||||
```
|
||||
|
||||
In case of any other issues, I also enabled the watchdog timer for 2 seconds. So, if, for some reason, it does freeze/crash, it should self reset after 2 seconds. It seems to be working, although I guess time will tell in the long-term. I haven't experienced any operation issues since I added it over a month ago. The other concern is undefined behavior when the timer overflows. The Uno only has a 32-bit timer, so it will overflow around 50 days of uptime. This function pre-emptively resets it.
|
||||
|
||||
```c++
|
||||
//we will use this function to periodically self-reset to avoid timer overflows
|
||||
void(* resetFunc) (void) = 0;
|
||||
|
||||
...
|
||||
|
||||
//reset the system when approaching timer overflow
|
||||
if (cur_loop_timestamp >= 4000000000) {
|
||||
resetFunc();
|
||||
}
|
||||
```
|
||||
|
||||
Once per second, the temperature sensors are sampled, the PID loop for the fans runs with the new temperature data points, and the fan speed, temperature data, vacuum pressure, and pump/flow measurements are sent over serial with the help of the ArduinoJSON library. I settled on a target water delta of 4\*C relative to ambient, with a chosen min/max temperature range where the fans turn off or pin themselves to 100% completely. I'm not sure if either of those temperatures will ever be reached, realistically, but it's better to be safe than sorry, right?
|
||||
There are also hard stops to turn the fans off if the water temperature hits 5\*C, and pin them to max if it hits 40\*C. I'm not sure how realistic either of those figures are, but it's better to be safe than frozen up and/or exploded.
|
||||
|
||||
```c++
|
||||
int fan_PID(float* air_temp, float* water_temp, uint32_t* cur_loop_timestamp) {
|
||||
@ -347,11 +274,79 @@ int fan_PID(float* air_temp, float* water_temp, uint32_t* cur_loop_timestamp) {
|
||||
}
|
||||
```
|
||||
|
||||
Theoretically the loop should handle water temperatures in excess of 60\*C without the components actually overheating, but lower is better. With all the currently connected components running at 100% use, and 100% fan speed, the delta between air and water is <10\*C. In the summer, the water temperature might broach 40\*C, but I don't know. I haven't monitored the actual ambient temperature in the garage before now. My garage is partially underground, and my rack is situated in the back, where it is deepest, so the temperatures tend to stay more mild than the outside. So far this winter, the air temperature measured by the Arduino has tended to stay 10-20\*C higher than the ambient air temperature outside, so it would need to be *very* cold to actually have the loop be at-risk of freezing. In that extreme case, in my testing, turning off the fans allows heat to accumulate to a sufficient degree (even at idle) that there is no need to be concerned with antifreeze additives.
|
||||
Occasionally, the temperature probes as well as the HX711 return spurious readings that cause poor behavior, such as crashing the Arduino. In particular, the temperature probes will sometimes return -127, which caused my PID algorithm to crash the Arduino for reasons I could not divine.
|
||||
|
||||
For the temperature probes, I simply ignore the one problematic result that I've observed.
|
||||
|
||||
```c++
|
||||
new_water_temp = sensors.getTempC(water_therm);
|
||||
new_air_temp = sensors.getTempC(air_therm);
|
||||
|
||||
if (new_water_temp != -127) {
|
||||
water_temp = new_water_temp;
|
||||
}
|
||||
|
||||
if (new_air_temp != -127) {
|
||||
air_temp = new_air_temp;
|
||||
}
|
||||
|
||||
sensors.requestTemperatures();
|
||||
```
|
||||
|
||||
In case of any other freezing/crashing issues, I also enabled the watchdog timer for 2 seconds. So, if, for some reason, it does freeze/crash, it should self reset after 2 seconds. It seems to be working, although I guess time will tell in the long-term. I haven't experienced any operation issues since I added it over a month ago. The other concern is undefined behavior when the timer overflows. The Uno only has a 32-bit timer, so it will overflow around 50 days of uptime. This function pre-emptively resets it.
|
||||
|
||||
```c++
|
||||
//we will use this function to periodically self-reset to avoid timer overflows
|
||||
void(* resetFunc) (void) = 0;
|
||||
|
||||
...
|
||||
|
||||
//reset the system when approaching timer overflow
|
||||
if (cur_loop_timestamp >= 4000000000) {
|
||||
resetFunc();
|
||||
}
|
||||
```
|
||||
|
||||
In addition to the temperature probe problem, the HX711 occasionally returns wildly wrong results that need to be filtered out. To compensate for that, if the pressure dips below the threshold, I wait one second, and if the pressure is still below the threshold, I then begin pumping. This check happens approximately ten times per second, as the default behavior of the HX711 board that I have is to run in 10hz mode. I'm not sure if the issue springs from some kind of interference with the tachometer interrupts messing up the signaling timing, or if I'm misunderstanding the correct way to sample the HX711 over time.
|
||||
|
||||
```c++
|
||||
if (cur_loop_timestamp - last_pressure_check >= 100) {
|
||||
loop_pressure = pressure_raw_to_mbar(hx711.readChannelRaw(CHAN_A_GAIN_64));
|
||||
|
||||
if (sucking == false) {
|
||||
if (loop_pressure > low_pressure_threshold) {
|
||||
if (checking_low_pressure == false) {
|
||||
checking_low_pressure = true;
|
||||
low_pressure_confirmation_timestamp = cur_loop_timestamp;
|
||||
}
|
||||
if (cur_loop_timestamp - low_pressure_confirmation_timestamp >= 1000) {
|
||||
digitalWrite(pump_relay, HIGH);
|
||||
digitalWrite(solenoid_relay, HIGH);
|
||||
sucking = true;
|
||||
checking_low_pressure = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (cur_loop_timestamp - low_pressure_confirmation_timestamp >= 1000) {
|
||||
checking_low_pressure = false;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (loop_pressure < high_pressure_threshold) {
|
||||
digitalWrite(pump_relay, LOW);
|
||||
digitalWrite(solenoid_relay, LOW);
|
||||
sucking = false;
|
||||
}
|
||||
}
|
||||
last_pressure_check = cur_loop_timestamp;
|
||||
}
|
||||
```
|
||||
|
||||
Currently, my server-side software is incomplete. It's just a brute-force JSON-over-serial reader written in Python, that I glance at from time to time. I plan write a Zabbix bridge, and have that manage the monitoring, alerts, and reactions to catostraphic events, once I have Zabbix properly setup for my systems... But that hasn't happened just yet. I don't expect it to be a particularly interesting event, but if anything comes up I might write a post about it.
|
||||
|
||||
## Other Thoughts?
|
||||
|
||||
Just a note, the software hadn't been 100% finalized when I took the below pictures. The control box does have a lid now, and all the cable management is a lot cleaner... Promise!
|
||||
The Arduino's software hadn't been 100% finalized when I took the below pictures. The control box does have a lid now, and all the cable management is a lot cleaner... Promise!
|
||||
|
||||
{{< panzoom-gallery caption="Everything installed and working!">}}
|
||||
{{< panzoom-figure
|
||||
@ -366,16 +361,22 @@ Just a note, the software hadn't been 100% finalized when I took the below pictu
|
||||
>}}
|
||||
{{< /panzoom-gallery >}}
|
||||
|
||||
When I was testing it, I had an incident where the Arduino crashed, which means the fans stopped... That's a big drawback with the motor controller that I have, it fails off instead of on. But, I haven't experienced any more issues after adding those software fixes. At that time, I was running a full GPU workload... The water temperature exceeded 70\*C. It happened at night, and I have no idea how long it ran like that... Hours. Pretty scary stuff, but it all came out alright.
|
||||
|
||||
This project had a lot of firsts for me. It was the first time I've done any kind of embedded-adjacent development beyond "ooooo look at the blinky light, oooooooo it turns off when you press the button, wwaaaow", and the first time I'd designed something with so many individual parts. I've never worked with air pumps, solenoids, or pressure sensing before, nor had to debug issues like the lack of flyback diodes.
|
||||
|
||||
I learned that I hate drilling through sheet steel, especially without a drill press. I really, really hate drilling through steel. I should have gotten an aluminum or plastic project box instead of using that stupid battery box. If I were to ever take it apart again, I'd add a passthrough for the SPI header, and/or an external reset button. I'd like to think that I'm going to stop poking into boxes that have live electricity inside of them, but I'm not sure that one is going to stick. I should have gotten a physical display of some type that could show the sensors and debug info on the device itself without being connected to another device to readout the data.
|
||||
The biggest mistake I made was using that stupid battery box. It's steel, and I don't have the tools or experience to work with steel in the way that I intended to. I thought it would look cool, and it does, but if I did it again, I'd use a generic aluminum or plastic project box instead, because it took two entire days plus waiting for new drill bits that can actually cut through it.
|
||||
|
||||
I'd like to get a second pump, for redundancy's sake and to increase the flow rate. But it's going to be such a pain to install that I feel like I'm never going to bother to do it, unless the current pump fails, or I add more components to be cooled and the flow is adversely affected. I was also slightly concerned about the evaporation rate of the liquid via the vacuum tank, and that I'd need to add some kind of fluid level detection system, but there's been no noticeable loss thus far. Now that I know the pump turns on so infrequently, I can't imagine that it's going to need to be topped up anytime soon.
|
||||
If I were to ever take it apart again, I'd add a passthrough for the SPI header, and/or an external reset button. I should have gotten a physical display of some type that could show the sensors and debug info on the device itself without being connected to another device to readout the data.
|
||||
|
||||
Godbwye.
|
||||
I'd like to get a second pump, for redundancy's sake and to increase the flow rate. But it's going to be such a pain to install that I feel like I'm never going to bother to do it, unless the current pump fails, or I add more components to be cooled and the flow is adversely affected. I was slightly concerned about the evaporation rate of the liquid via the vacuum tank, and that I'd need to add some kind of fluid level detection system, but there's been no noticeable loss thus far. Now that I know the pump turns on so infrequently, I can't imagine that it's going to need to be topped up anytime soon.
|
||||
|
||||
[^pascalbad]: In modern, post-Turing cards, that is. Please stop buying mesozoic-era Kepler/Maxwell Quadros and Teslas just because they have VRAM. There's a reason they're going for like, $20, and if you paid more for anything from that era, I'm sorry. Electrical costs are a thing, and your life is worth more than waiting for any meaningful, current-year work to happen on those decrepit e-waste cards. You can make an argument for Volta, but only if you're doing some deranged pure FP64 stuff. Consumer Turing and newer are faster at everything else! And if you're buying them for HW-accel encode... The quality is awful compared to any Intel ARC card. Buy one of those instead.
|
||||
In terms of value... This was unbelievably bad. Buying tower coolers would have allowed the CPUs to run without throttling, and buying another GPU would have overpowered any benefits gained by NVLINK. I haven't tallied up exactly how much I spent on it, but it was at least $1000, including buying new tools and excess materials that I haven't fully used, and excluding the original cost of re-using some parts I already had. I've added risk, maintenance overhead, and pain whenever I swap out hardware in the future. Custom watercooling[^nomenclature] is an ongoing abusive relationship between your fingertips and your ego, or your fascination for slightly more optimized numbers on a screen... But I'd do it again in a heartbeat, because it was fun.
|
||||
|
||||
[^pascalbad]: In modern, post-Turing cards, that is. Please stop buying mesozoic-era Kepler/Maxwell Quadros and Teslas just because they have VRAM. There's a reason they're going for like, $20, and if you paid more for anything from that era, I'm sorry. Electrical costs are a thing, and your life is worth more than waiting for any meaningful, current-year work to happen on those decrepit e-waste cards. I feel even worse for you if you got tricked into buying one of those "24GB" or "16GB" cards that are actually 2x12GB and 2x8GB. You can make an argument for Volta, but only if you're doing some deranged pure FP64 stuff. Consumer Turing and newer are faster at everything else! And if you're buying them for HW-accel encode... The quality is awful compared to any Intel ARC card. Buy one of those instead.
|
||||
|
||||
[^thermalfears]: I don't understand why people don't trust the manufacturer specifications when it comes to silicon temperature limits, beyond unfounded conspiracy nonsense around planned destruction/obselence. In terms of Intel server SKUs, you find that the throttling temp is *higher* than on consumer SKUs, despite the higher reliability demanded by the enterprise market... I'm assuming that this is due to reduced hotspot variance thanks to generally lower voltage spread from lower boosting clock speeds. On enterprise SKUs which are focused on single threaded performance, the throttling temp is typically lower than those without the ability to boost as high. If you have evidence to the contrary, let me know.
|
||||
|
||||
[^badnomenclature]: I don't understand why people call custom loops 'open loops'. They're not open. They're closed. People correctly use the phrase 'closed loop' when referring to AIOs. This phrasing has been pervasive for at least ten years and it bugs me a lot. AIOs are sealed units where the liquid has no interaction with the external environment. Custom loops are sealed units where the liquid has no interaction with the external environment. They're both closed in operation. Outside of the PC watercooling space, 'open loop' would imply that your cooling method intakes fresh coolant and outputs waste that is not directly recovered. LN2 overclocking, in the PC world, is a form of open loop liquid cooling. If you were putting water into your loop via your sink, and dumping the output into the drain, that would be open loop water cooling. Eternally recycling the same liquid in a sealed loop is not open. It's closed. It's a closed loop.
|
||||
[^nomenclature]: Stop calling them open loops. Open loop systems exchange fluid with the environment. Unless you're getting your water out of the sink and flushing it right down the drain, your system is not open loop. It's closed. I don't understand why people call custom loops "open" and AIOs "closed" when their modes of operation are identical. It's just plain wrong.
|
||||
|
||||
[^overclockingonlinux]: NVIDIA overclocking on Linux is awful. There's no way to edit the voltage-frequency curve through the Linux drivers. You can only set the offset. So you can't really make use of dynamic boosting if you want to undervolt. I have the max clock speed clamped at 1800MHz with a core offset to emulate undervolting as you would do on Windows, but it's hard to say if I'm getting the peak performance that I could be getting at whatever the core voltage is under these circumstances - because NVIDIA's Linux drivers ALSO don't report that. VRAM temperature? Nope. VRM? Nope. Hotspot? Nope. You better hope your card works with NVML, too, because otherwise you're going to have to mess around with X to use nvidia-settings.
|
@ -50,7 +50,7 @@
|
||||
{{ if not (.Params.showAuthorBottom | default ( .Site.Params.article.showAuthorBottom | default false)) }}
|
||||
|
||||
|
||||
<div class="flex flex-row">
|
||||
<div class="vari-flex">
|
||||
{{ if .Params.showAuthor | default (.Site.Params.article.showAuthor | default true) }}
|
||||
{{ $showAuthor = 1 }}
|
||||
{{ partial "author.html" . }}
|
||||
|
76
layouts/partials/article-link/card-related.html
Normal file
@ -0,0 +1,76 @@
|
||||
{{ $disableImageOptimization := .Page.Site.Params.disableImageOptimization | default false }}
|
||||
{{ with .Params.externalUrl }}
|
||||
<a href="{{ . }}" target="_blank" rel="external" class="min-w-full">
|
||||
{{ else }}
|
||||
<a href="{{ .RelPermalink }}" class="min-w-full">
|
||||
{{ end }}
|
||||
<div class="min-h-full border border-neutral-200 dark:border-neutral-700 border-2 rounded overflow-hidden shadow-2xl relative">
|
||||
|
||||
{{- with $.Params.images -}}
|
||||
{{- range first 6 . }}
|
||||
<meta property="og:image" content="{{ . | absURL }}" />{{ end -}}
|
||||
{{- else -}}
|
||||
{{- $images := $.Resources.ByType "image" -}}
|
||||
{{- $featured := $images.GetMatch "*feature*" -}}
|
||||
{{- if not $featured }}{{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" }}{{ end -}}
|
||||
{{ if and .Params.featureimage (not $featured) }}
|
||||
{{- $url:= .Params.featureimage -}}
|
||||
{{ $featured = resources.GetRemote $url }}
|
||||
{{ end }}
|
||||
{{- if not $featured }}{{ with .Site.Params.defaultFeaturedImage }}{{ $featured = resources.Get . }}{{ end }}{{ end -}}
|
||||
{{- with $featured -}}
|
||||
{{ if or $disableImageOptimization (strings.HasSuffix $featured ".svg")}}
|
||||
{{ with . }}
|
||||
<div class="w-full thumbnail_card_related nozoom" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ with .Resize "600x" }}
|
||||
<div class="w-full thumbnail_card_related nozoom" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{- else -}}
|
||||
{{- with $.Site.Params.images }}
|
||||
<meta property="og:image" content="{{ index . 0 | absURL }}" />{{ end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{ if and .Draft .Site.Params.article.showDraftLabel }}
|
||||
<span class="absolute top-0 right-0 m-2">
|
||||
{{ partial "badge.html" (i18n "article.draft" | emojify) }}
|
||||
</span>
|
||||
{{ end }}
|
||||
|
||||
<div class="px-6 py-4">
|
||||
|
||||
{{ with .Params.externalUrl }}
|
||||
<div>
|
||||
<div
|
||||
class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral">
|
||||
{{ $.Title | emojify }}
|
||||
<span class="text-xs align-top cursor-default text-neutral-400 dark:text-neutral-500">
|
||||
<span class="rtl:hidden">↗</span>
|
||||
<span class="ltr:hidden">↖</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral"
|
||||
href="{{ .RelPermalink }}">{{ .Title | emojify }}</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="text-sm text-neutral-500 dark:text-neutral-400">
|
||||
{{ partial "article-meta/basic.html" . }}
|
||||
</div>
|
||||
|
||||
{{ if .Params.showSummary | default (.Site.Params.list.showSummary | default false) }}
|
||||
<div class="py-1 prose dark:prose-invert">
|
||||
{{ .Summary | plainify }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
77
layouts/partials/article-link/card.html
Normal file
@ -0,0 +1,77 @@
|
||||
{{ $disableImageOptimization := .Page.Site.Params.disableImageOptimization | default false }}
|
||||
{{ with .Params.externalUrl }}
|
||||
<a href="{{ . }}" target="_blank" rel="external" class="min-w-full">
|
||||
{{ else }}
|
||||
<a href="{{ .RelPermalink }}" class="min-w-full">
|
||||
{{ end }}
|
||||
<div class="min-h-full overflow-hidden shadow-2xl relative card-styled">
|
||||
|
||||
{{- with $.Params.images -}}
|
||||
{{- range first 6 . }}
|
||||
<meta property="og:image" content="{{ . | absURL }}" />{{ end -}}
|
||||
{{- else -}}
|
||||
{{- $images := $.Resources.ByType "image" -}}
|
||||
{{- $featured := $images.GetMatch "*feature*" -}}
|
||||
{{- if not $featured }}{{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" }}{{ end -}}
|
||||
{{ if and .Params.featureimage (not $featured) }}
|
||||
{{- $url:= .Params.featureimage -}}
|
||||
{{ $featured = resources.GetRemote $url }}
|
||||
{{ end }}
|
||||
{{- if not $featured }}{{ with .Site.Params.defaultFeaturedImage }}{{ $featured = resources.Get . }}{{ end }}{{ end -}}
|
||||
{{ if .Params.hideFeatureImage }}{{ $featured = false }}{{ end }}
|
||||
{{- with $featured -}}
|
||||
{{ if or $disableImageOptimization (strings.HasSuffix $featured ".svg")}}
|
||||
{{ with . }}
|
||||
<div class="w-full thumbnail_card nozoom" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ with .Resize "600x" }}
|
||||
<div class="w-full thumbnail_card nozoom" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{- else -}}
|
||||
{{- with $.Site.Params.images }}
|
||||
<meta property="og:image" content="{{ index . 0 | absURL }}" />{{ end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{ if and .Draft .Site.Params.article.showDraftLabel }}
|
||||
<span class="absolute top-0 right-0 m-2">
|
||||
{{ partial "badge.html" (i18n "article.draft" | emojify) }}
|
||||
</span>
|
||||
{{ end }}
|
||||
|
||||
<div class="px-6 py-4">
|
||||
|
||||
{{ with .Params.externalUrl }}
|
||||
<div>
|
||||
<div
|
||||
class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral">
|
||||
{{ $.Title | emojify }}
|
||||
<span class="text-xs align-top cursor-default text-neutral-400 dark:text-neutral-500">
|
||||
<span class="rtl:hidden">↗</span>
|
||||
<span class="ltr:hidden">↖</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="font-bold text-xl hover:underline hover:underline-offset-2 cool-title"
|
||||
href="{{ .RelPermalink }}">{{ .Title | emojify }}</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="text-sm text-neutral-500 dark:text-neutral-400">
|
||||
{{ partial "article-meta/basic.html" . }}
|
||||
</div>
|
||||
|
||||
{{ if .Params.showSummary | default (.Site.Params.list.showSummary | default false) }}
|
||||
<div class="py-1 prose dark:prose-invert">
|
||||
{{ .Summary | plainify }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
101
layouts/partials/article-link/simple.html
Normal file
@ -0,0 +1,101 @@
|
||||
{{ $constrainItemsWidth := .Page.Site.Params.list.constrainItemsWidth | default false }}
|
||||
|
||||
{{ $articleClasses := "flex flex-wrap article" }}
|
||||
{{ if .Site.Params.list.showCards }}
|
||||
{{ $articleClasses = delimit (slice $articleClasses "border border-neutral-200 dark:border-neutral-700 border-2 rounded-md overflow-hidden") " " }}
|
||||
{{ else }}
|
||||
{{ $articleClasses = delimit (slice $articleClasses "") " " }}
|
||||
{{ end }}
|
||||
|
||||
{{ $articleImageClasses := "w-full md:w-auto h-full thumbnail nozoom" }}
|
||||
{{ if .Site.Params.list.showCards }}
|
||||
{{ $articleImageClasses = delimit (slice $articleImageClasses "") " " }}
|
||||
{{ else }}
|
||||
{{ $articleImageClasses = delimit (slice $articleImageClasses "thumbnailshadow md:mr-7") " " }}
|
||||
{{ end }}
|
||||
|
||||
{{ $disableImageOptimization := .Page.Site.Params.disableImageOptimization | default false }}
|
||||
|
||||
{{ $articleInnerClasses := "" }}
|
||||
{{ if .Site.Params.list.showCards }}
|
||||
{{ $articleInnerClasses = delimit (slice $articleInnerClasses "p-4") " " }}
|
||||
{{ else }}
|
||||
{{ $articleInnerClasses = delimit (slice $articleInnerClasses "mt-3 md:mt-0") " " }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $constrainItemsWidth }}
|
||||
{{ $articleClasses = delimit (slice $articleClasses "max-w-prose") " " }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{ with .Params.externalUrl }}
|
||||
<a class="{{ $articleClasses }}" href="{{ . }}" target="_blank" rel="external">
|
||||
{{ else }}
|
||||
<a class="{{ $articleClasses }}" href="{{ .RelPermalink }}">
|
||||
{{ end }}
|
||||
{{- with $.Params.images -}}
|
||||
{{- range first 6 . }}
|
||||
<meta property="og:image" content="{{ . | absURL }}" />{{ end -}}
|
||||
{{- else -}}
|
||||
{{- $images := $.Resources.ByType "image" -}}
|
||||
{{- $featured := $images.GetMatch "*feature*" -}}
|
||||
{{- if not $featured }}{{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" }}{{ end -}}
|
||||
{{ if and .Params.featureimage (not $featured) }}
|
||||
{{- $url:= .Params.featureimage -}}
|
||||
{{ $featured = resources.GetRemote $url }}
|
||||
{{ end }}
|
||||
{{- if not $featured }}{{ with .Site.Params.defaultFeaturedImage }}{{ $featured = resources.Get . }}{{ end }}{{ end -}}
|
||||
{{ if .Params.hideFeatureImage }}{{ $featured = false }}{{ end }}
|
||||
{{- with $featured -}}
|
||||
{{ if or $disableImageOptimization (strings.HasSuffix $featured ".svg")}}
|
||||
{{ with . }}
|
||||
<div class="{{ $articleImageClasses }}" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ with .Resize "600x" }}
|
||||
<div class="{{ $articleImageClasses }}" style="background-image:url({{ .RelPermalink }});"></div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{- else -}}
|
||||
{{- with $.Site.Params.images }}
|
||||
<meta property="og:image" content="{{ index . 0 | absURL }}" />{{ end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
<div class="{{ $articleInnerClasses }}">
|
||||
<div class="items-center text-left text-xl font-semibold">
|
||||
{{ with .Params.externalUrl }}
|
||||
<div>
|
||||
<div
|
||||
class="font-bold text-xl hover:underline hover:underline-offset-2 cool-title">
|
||||
{{ $.Title | emojify }}
|
||||
<span class="text-xs align-top cursor-default text-neutral-400 dark:text-neutral-500">
|
||||
<span class="rtl:hidden">↗</span>
|
||||
<span class="ltr:hidden">↖</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral"
|
||||
href="{{ .RelPermalink }}">{{ .Title | emojify }}</div>
|
||||
{{ end }}
|
||||
{{ if and .Draft .Site.Params.article.showDraftLabel }}
|
||||
<div class=" ltr:ml-2 rtl:mr-2">
|
||||
{{ partial "badge.html" (i18n "article.draft" | emojify) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ if templates.Exists "partials/extend-article-link.html" }}
|
||||
{{ partial "extend-article-link.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="text-sm text-neutral-500 dark:text-neutral-400">
|
||||
{{ partial "article-meta/basic.html" . }}
|
||||
</div>
|
||||
{{ if .Params.showSummary | default (.Site.Params.list.showSummary | default false) }}
|
||||
<div class="py-1 max-w-fit prose dark:prose-invert">
|
||||
{{ .Summary | plainify }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</a>
|
@ -1,39 +1,37 @@
|
||||
{{ $disableImageOptimization := .Site.Params.disableImageOptimization | default false }}
|
||||
<div class="flex author min-w-content">
|
||||
{{ with .Site.Params.Author.image }}
|
||||
{{ $authorImage := "" }}
|
||||
{{ if or (strings.HasPrefix . "http:") (strings.HasPrefix . "https:") }}
|
||||
{{ $authorImage = resources.GetRemote . }}
|
||||
{{ else }}
|
||||
{{ $authorImage = resources.Get . }}
|
||||
{{ end }}
|
||||
{{ if $authorImage }}
|
||||
{{ if not $disableImageOptimization }}
|
||||
{{ $authorImage = $authorImage.Fill "192x192" }}
|
||||
{{ end }}
|
||||
<img class="!mt-0 !mb-0 h-24 w-24 rounded-full ltr:mr-4 rtl:ml-4" width="96" height="96"
|
||||
alt="{{ $.Site.Params.Author.name | default " Author" }}" src="{{ $authorImage.RelPermalink }}" />
|
||||
{{ else }}
|
||||
{{ $authorImage := resources.GetRemote . }}
|
||||
{{ if not $disableImageOptimization }}
|
||||
{{ $authorImage = $authorImage.Fill "192x192" }}
|
||||
{{ end }}
|
||||
<img class="!mt-0 !mb-0 h-24 w-24 rounded-full ltr:mr-4 rtl:ml-4" width="96" height="96"
|
||||
alt="{{ $.Site.Params.Author.name | default " Author" }}" src="{{ $authorImage.RelPermalink }}" />
|
||||
{{ end }}
|
||||
{{ with .Site.Params.Author.image }}
|
||||
{{ $authorImage := "" }}
|
||||
{{ if or (strings.HasPrefix . "http:") (strings.HasPrefix . "https:") }}
|
||||
{{ $authorImage = resources.GetRemote . }}
|
||||
{{ else }}
|
||||
{{ $authorImage = resources.Get . }}
|
||||
{{ end }}
|
||||
<div class="place-self-center">
|
||||
{{ with .Site.Params.Author.name | markdownify }}
|
||||
<div class="text-[0.6rem] uppercase leading-3 text-neutral-500 dark:text-neutral-400">
|
||||
{{ i18n "author.byline_title" | markdownify }}
|
||||
</div>
|
||||
<div class="font-semibold leading-6 text-neutral-800 dark:text-neutral-300">
|
||||
{{ . }}
|
||||
</div>
|
||||
{{ if $authorImage }}
|
||||
{{ if not $disableImageOptimization }}
|
||||
{{ $authorImage = $authorImage.Fill "192x192" }}
|
||||
{{ end }}
|
||||
{{ with .Site.Params.Author.bio | markdownify }}
|
||||
<div class="text-sm text-neutral-700 dark:text-neutral-400">{{ . }}</div>
|
||||
<img class="!mt-0 !mb-0 h-24 w-24 rounded-full ltr:mr-4 rtl:ml-4" width="96" height="96"
|
||||
alt="{{ $.Site.Params.Author.name | default " Author" }}" src="{{ $authorImage.RelPermalink }}" />
|
||||
{{ else }}
|
||||
{{ $authorImage := resources.GetRemote . }}
|
||||
{{ if not $disableImageOptimization }}
|
||||
{{ $authorImage = $authorImage.Fill "192x192" }}
|
||||
{{ end }}
|
||||
<div class="text-2xl sm:text-lg">{{ partialCached "author-links.html" . }}</div>
|
||||
<img class="!mt-0 !mb-0 h-24 w-24 rounded-full ltr:mr-4 rtl:ml-4" width="96" height="96"
|
||||
alt="{{ $.Site.Params.Author.name | default " Author" }}" src="{{ $authorImage.RelPermalink }}" />
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<div class="place-self-center">
|
||||
{{ with .Site.Params.Author.name | markdownify }}
|
||||
<div class="text-[0.6rem] uppercase leading-3 text-neutral-500 dark:text-neutral-400">
|
||||
{{ i18n "author.byline_title" | markdownify }}
|
||||
</div>
|
||||
<div class="font-semibold leading-6 text-neutral-800 dark:text-neutral-300">
|
||||
{{ . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with .Site.Params.Author.bio | markdownify }}
|
||||
<div class="text-sm text-neutral-700 dark:text-neutral-400">{{ . }}</div>
|
||||
{{ end }}
|
||||
<div class="text-2xl sm:text-lg">{{ partialCached "author-links.html" . }}</div>
|
||||
</div>
|
||||
|
@ -10,6 +10,10 @@
|
||||
{{- $target := .Get "target" | default "_blank" }}
|
||||
{{- $gallery_class := .Get "gallery_class" }}
|
||||
|
||||
{{- if not $gallery_class }}
|
||||
<hr>
|
||||
{{- end }}
|
||||
|
||||
<div class="panzoom-container {{ with $gallery_class }} {{ . }}{{ end }}">
|
||||
{{- with $href }}<a href="{{ . }}" {{ with $target }}target="{{ . }}"{{ end }}>{{ end -}}
|
||||
{{- if findRE "^https?" $url.Scheme }}
|
||||
@ -67,5 +71,8 @@
|
||||
{{- end }}
|
||||
{{ if $href }}</a>{{ end }}
|
||||
</div>
|
||||
{{ with $caption }}<figcaption>{{ . | markdownify }}</figcaption>{{ end }}
|
||||
{{ with $caption }}<figcaption class="caption">{{ . | markdownify }}</figcaption>{{ end }}
|
||||
{{- if not $gallery_class }}
|
||||
<hr>
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
{{- $caption := .Get "caption" }}
|
||||
|
||||
|
||||
<hr>
|
||||
<div id="{{ $id }}" class="gallery">
|
||||
{{ .Inner }}
|
||||
</div>
|
||||
{{ with $caption }}<figcaption>{{ . | markdownify }}</figcaption>{{ end }}
|
||||
{{ with $caption }}<figcaption class="caption">{{ . | markdownify }}</figcaption>{{ end }}
|
||||
<hr>
|
6
public/404.html
Normal file
BIN
public/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
public/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
public/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 55 KiB |
6
public/authors/index.html
Normal file
1
public/authors/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Authors on N.E.E.T. Works</title><link>https://blog.neet.works/authors/</link><description>Recent content in Authors on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><atom:link href="https://blog.neet.works/authors/index.xml" rel="self" type="application/rss+xml"/></channel></rss>
|
15
public/categories/diy/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Diy · N.E.E.T. Works</title>
|
||||
<meta name=title content="Diy · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/categories/diy/><link rel=alternate type=application/rss+xml href=/categories/diy/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/categories/diy/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Diy"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Diy"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Diy</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row"></section><section class="space-y-10 w-full"><a class="flex flex-wrap article" href=/posts/watercooling-homelab/><div class="w-full md:w-auto h-full thumbnail nozoom thumbnailshadow md:mr-7" style=background-image:url(/posts/watercooling-homelab/featured_hu13568191302889737537.webp)></div><div class="mt-3 md:mt-0"><div class="items-center text-left text-xl font-semibold"><div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral" href=/posts/watercooling-homelab/>Watercooling My Homelab</div></div><div class="text-sm text-neutral-500 dark:text-neutral-400"><div class="flex flex-row flex-wrap items-center"><time datetime=2025-01-16T05:56:41+00:00>January 16 2025</time><span class="px-2 text-primary-500">·</span><span>5240 words</span></div><hr><div class="flex flex-row flex-wrap items-center">Watercooling for my homelab with a custom, leak-resistant controller and monitoring!</div><hr><div class="flex flex-row flex-wrap items-center"><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/homelab/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Homelab
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/servers/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Servers
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/watercooling/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Watercooling
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/diy/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Diy
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/alphacool/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Alphacool
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/arduino/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Arduino
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/intel/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Intel
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/nvidia/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Nvidia
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/supermicro/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Supermicro
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/aqua-computer/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Aqua Computer</span></span></span></div></div></div></a></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/categories/diy/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Diy on N.E.E.T. Works</title><link>https://blog.neet.works/categories/diy/</link><description>Recent content in Diy on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/categories/diy/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
2
public/categories/diy/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/categories/diy/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/categories/diy/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/categories/diy/"></head></html>
|
15
public/categories/homelab/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Homelab · N.E.E.T. Works</title>
|
||||
<meta name=title content="Homelab · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/categories/homelab/><link rel=alternate type=application/rss+xml href=/categories/homelab/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/categories/homelab/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Homelab"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Homelab"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Homelab</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row"></section><section class="space-y-10 w-full"><a class="flex flex-wrap article" href=/posts/watercooling-homelab/><div class="w-full md:w-auto h-full thumbnail nozoom thumbnailshadow md:mr-7" style=background-image:url(/posts/watercooling-homelab/featured_hu13568191302889737537.webp)></div><div class="mt-3 md:mt-0"><div class="items-center text-left text-xl font-semibold"><div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral" href=/posts/watercooling-homelab/>Watercooling My Homelab</div></div><div class="text-sm text-neutral-500 dark:text-neutral-400"><div class="flex flex-row flex-wrap items-center"><time datetime=2025-01-16T05:56:41+00:00>January 16 2025</time><span class="px-2 text-primary-500">·</span><span>5240 words</span></div><hr><div class="flex flex-row flex-wrap items-center">Watercooling for my homelab with a custom, leak-resistant controller and monitoring!</div><hr><div class="flex flex-row flex-wrap items-center"><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/homelab/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Homelab
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/servers/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Servers
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/watercooling/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Watercooling
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/diy/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Diy
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/alphacool/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Alphacool
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/arduino/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Arduino
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/intel/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Intel
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/nvidia/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Nvidia
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/supermicro/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Supermicro
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/aqua-computer/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Aqua Computer</span></span></span></div></div></div></a></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/categories/homelab/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Homelab on N.E.E.T. Works</title><link>https://blog.neet.works/categories/homelab/</link><description>Recent content in Homelab on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/categories/homelab/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
2
public/categories/homelab/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/categories/homelab/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/categories/homelab/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/categories/homelab/"></head></html>
|
14
public/categories/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Categories · N.E.E.T. Works</title>
|
||||
<meta name=title content="Categories · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/categories/><link rel=alternate type=application/rss+xml href=/categories/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/categories/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Categories"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Categories"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Categories</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="flex flex-wrap max-w-prose -mx-2 overflow-hidden"><article class="w-full px-2 my-3 overflow-hidden sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/4"><h2 class="flex items-center"><a class="text-xl font-medium decoration-primary-500 hover:underline hover:underline-offset-2" href=/categories/diy/>Diy</a>
|
||||
<span class="px-2 text-base text-primary-500">·</span>
|
||||
<span class="text-base text-neutral-400">1</span></h2></article><article class="w-full px-2 my-3 overflow-hidden sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/4"><h2 class="flex items-center"><a class="text-xl font-medium decoration-primary-500 hover:underline hover:underline-offset-2" href=/categories/homelab/>Homelab</a>
|
||||
<span class="px-2 text-base text-primary-500">·</span>
|
||||
<span class="text-base text-neutral-400">1</span></h2></article><article class="w-full px-2 my-3 overflow-hidden sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/4"><h2 class="flex items-center"><a class="text-xl font-medium decoration-primary-500 hover:underline hover:underline-offset-2" href=/categories/servers/>Servers</a>
|
||||
<span class="px-2 text-base text-primary-500">·</span>
|
||||
<span class="text-base text-neutral-400">1</span></h2></article><article class="w-full px-2 my-3 overflow-hidden sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/4"><h2 class="flex items-center"><a class="text-xl font-medium decoration-primary-500 hover:underline hover:underline-offset-2" href=/categories/watercooling/>Watercooling</a>
|
||||
<span class="px-2 text-base text-primary-500">·</span>
|
||||
<span class="text-base text-neutral-400">1</span></h2></article></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/categories/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Categories on N.E.E.T. Works</title><link>https://blog.neet.works/categories/</link><description>Recent content in Categories on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/categories/index.xml" rel="self" type="application/rss+xml"/><item><title>Diy</title><link>https://blog.neet.works/categories/diy/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/categories/diy/</guid><description/></item><item><title>Homelab</title><link>https://blog.neet.works/categories/homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/categories/homelab/</guid><description/></item><item><title>Servers</title><link>https://blog.neet.works/categories/servers/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/categories/servers/</guid><description/></item><item><title>Watercooling</title><link>https://blog.neet.works/categories/watercooling/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/categories/watercooling/</guid><description/></item></channel></rss>
|
15
public/categories/servers/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Servers · N.E.E.T. Works</title>
|
||||
<meta name=title content="Servers · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/categories/servers/><link rel=alternate type=application/rss+xml href=/categories/servers/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/categories/servers/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Servers"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Servers"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Servers</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row"></section><section class="space-y-10 w-full"><a class="flex flex-wrap article" href=/posts/watercooling-homelab/><div class="w-full md:w-auto h-full thumbnail nozoom thumbnailshadow md:mr-7" style=background-image:url(/posts/watercooling-homelab/featured_hu13568191302889737537.webp)></div><div class="mt-3 md:mt-0"><div class="items-center text-left text-xl font-semibold"><div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral" href=/posts/watercooling-homelab/>Watercooling My Homelab</div></div><div class="text-sm text-neutral-500 dark:text-neutral-400"><div class="flex flex-row flex-wrap items-center"><time datetime=2025-01-16T05:56:41+00:00>January 16 2025</time><span class="px-2 text-primary-500">·</span><span>5240 words</span></div><hr><div class="flex flex-row flex-wrap items-center">Watercooling for my homelab with a custom, leak-resistant controller and monitoring!</div><hr><div class="flex flex-row flex-wrap items-center"><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/homelab/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Homelab
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/servers/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Servers
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/watercooling/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Watercooling
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/diy/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Diy
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/alphacool/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Alphacool
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/arduino/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Arduino
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/intel/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Intel
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/nvidia/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Nvidia
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/supermicro/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Supermicro
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/aqua-computer/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Aqua Computer</span></span></span></div></div></div></a></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/categories/servers/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Servers on N.E.E.T. Works</title><link>https://blog.neet.works/categories/servers/</link><description>Recent content in Servers on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/categories/servers/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
2
public/categories/servers/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/categories/servers/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/categories/servers/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/categories/servers/"></head></html>
|
15
public/categories/watercooling/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Watercooling · N.E.E.T. Works</title>
|
||||
<meta name=title content="Watercooling · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/categories/watercooling/><link rel=alternate type=application/rss+xml href=/categories/watercooling/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/categories/watercooling/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Watercooling"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Watercooling"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Watercooling</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row"></section><section class="space-y-10 w-full"><a class="flex flex-wrap article" href=/posts/watercooling-homelab/><div class="w-full md:w-auto h-full thumbnail nozoom thumbnailshadow md:mr-7" style=background-image:url(/posts/watercooling-homelab/featured_hu13568191302889737537.webp)></div><div class="mt-3 md:mt-0"><div class="items-center text-left text-xl font-semibold"><div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral" href=/posts/watercooling-homelab/>Watercooling My Homelab</div></div><div class="text-sm text-neutral-500 dark:text-neutral-400"><div class="flex flex-row flex-wrap items-center"><time datetime=2025-01-16T05:56:41+00:00>January 16 2025</time><span class="px-2 text-primary-500">·</span><span>5240 words</span></div><hr><div class="flex flex-row flex-wrap items-center">Watercooling for my homelab with a custom, leak-resistant controller and monitoring!</div><hr><div class="flex flex-row flex-wrap items-center"><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/homelab/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Homelab
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/servers/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Servers
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/watercooling/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Watercooling
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/diy/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Diy
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/alphacool/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Alphacool
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/arduino/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Arduino
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/intel/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Intel
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/nvidia/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Nvidia
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/supermicro/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Supermicro
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/aqua-computer/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Aqua Computer</span></span></span></div></div></div></a></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/categories/watercooling/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Watercooling on N.E.E.T. Works</title><link>https://blog.neet.works/categories/watercooling/</link><description>Recent content in Watercooling on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/categories/watercooling/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
2
public/categories/watercooling/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/categories/watercooling/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/categories/watercooling/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/categories/watercooling/"></head></html>
|
BIN
public/favicon-16x16.png
Normal file
After Width: | Height: | Size: 932 B |
BIN
public/favicon-32x32.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/img/background.webp
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
public/img/blowfish_logo_hu13719681768044762498.webp
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
public/img/blowfish_logo_hu536110971430689468.webp
Normal file
After Width: | Height: | Size: 9.1 KiB |
18
public/index.html
Normal file
1
public/index.json
Normal file
1
public/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>N.E.E.T. Works</title><link>https://blog.neet.works/</link><description>Recent content on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
@ -0,0 +1 @@
|
||||
const sitePreference=document.documentElement.getAttribute("data-default-appearance"),userPreference=localStorage.getItem("appearance");(sitePreference==="dark"&&userPreference===null||userPreference==="dark")&&document.documentElement.classList.add("dark"),document.documentElement.getAttribute("data-auto-appearance")==="true"&&(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches&&userPreference!=="light"&&document.documentElement.classList.add("dark"),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{e.matches?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")})),window.addEventListener("DOMContentLoaded",e=>{const t=document.getElementById("appearance-switcher"),n=document.getElementById("appearance-switcher-mobile");updateMeta(),this.updateLogo?.(getTargetAppearance()),t&&(t.addEventListener("click",()=>{document.documentElement.classList.toggle("dark");var e=getTargetAppearance();localStorage.setItem("appearance",e),updateMeta(),this.updateLogo?.(e)}),t.addEventListener("contextmenu",e=>{e.preventDefault(),localStorage.removeItem("appearance")})),n&&(n.addEventListener("click",()=>{document.documentElement.classList.toggle("dark");var e=getTargetAppearance();localStorage.setItem("appearance",e),updateMeta(),this.updateLogo?.(e)}),n.addEventListener("contextmenu",e=>{e.preventDefault(),localStorage.removeItem("appearance")}))});var updateMeta=()=>{var e=document.querySelector("body"),t=getComputedStyle(e);document.querySelector('meta[name="theme-color"]').setAttribute("content",t.backgroundColor)},getTargetAppearance=()=>document.documentElement.classList.contains("dark")?"dark":"light";window.addEventListener("DOMContentLoaded",e=>{const t=document.getElementById("top-scroller"),n=document.getElementById("site-footer");t&&n&&t.getBoundingClientRect().top>n.getBoundingClientRect().top&&(t.hidden=!0)})
|
@ -0,0 +1 @@
|
||||
var viewed,liked,liked_page=!1,id=oid&&oid.replaceAll("/","-"),id_likes=oid_likes&&oid_likes.replaceAll("/","-");typeof auth!="undefined"&&(viewed=localStorage.getItem(id),viewed||auth.signInAnonymously().then(()=>{var e=db.collection("views").doc(id);localStorage.setItem(id,!0),e.get().then(e=>{e.exists?db.collection("views").doc(id).update({views:firebase.firestore.FieldValue.increment(1)}):db.collection("views").doc(id).set({views:1})}).catch(e=>{console.log("Error getting document:",e)})}).catch(e=>{var t=e.code,n=e.message;console.error(t,n)}),liked=localStorage.getItem(id_likes),liked&&(liked_page=!0,document.querySelectorAll("span[id='button_likes_heart']")[0].style.display="",document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display="none",document.querySelectorAll("span[id='button_likes_text']")[0].innerText=""));function like_article(e){auth.signInAnonymously().then(()=>{var t=db.collection("likes").doc(e);t.get().then(t=>{liked_page=!0,localStorage.setItem(e,!0),document.querySelectorAll("span[id='button_likes_heart']")[0].style.display="",document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display="none",document.querySelectorAll("span[id='button_likes_text']")[0].innerText="",t.exists?db.collection("likes").doc(e).update({likes:firebase.firestore.FieldValue.increment(1)}):db.collection("likes").doc(e).set({likes:1})}).catch(e=>{console.log("Error getting document:",e)})}).catch(e=>{var t=e.code,n=e.message;console.error(t,n)})}function remove_like_article(e){auth.signInAnonymously().then(()=>{var t=db.collection("likes").doc(e);t.get().then(t=>{liked_page=!1,localStorage.removeItem(e),document.querySelectorAll("span[id='button_likes_heart']")[0].style.display="none",document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display="",document.querySelectorAll("span[id='button_likes_text']")[0].innerText="\xa0Like",t.exists?db.collection("likes").doc(e).update({likes:firebase.firestore.FieldValue.increment(-1)}):db.collection("likes").doc(e).set({likes:0})}).catch(e=>{console.log("Error getting document:",e)})}).catch(e=>{var t=e.code,n=e.message;console.error(t,n)})}function process_article(){liked_page?remove_like_article(id_likes):like_article(id_likes)}
|
@ -0,0 +1,131 @@
|
||||
// AI GENNED AS FUCK NGL
|
||||
|
||||
// Define the handler variables outside of any event listener
|
||||
let activeContainer = null;
|
||||
let panzoomInstance = null;
|
||||
let isProcessingClick = false;
|
||||
let isInitialized = false; // Add a flag to prevent multiple initializations
|
||||
|
||||
// Handle keyboard events
|
||||
function handleKeyPress(e) {
|
||||
if (e.key === "Escape" && activeContainer) {
|
||||
closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
// Function to close the popup and cleanup
|
||||
function closePopup() {
|
||||
if (activeContainer) {
|
||||
// Remove the keyboard event listener
|
||||
document.removeEventListener("keydown", handleKeyPress);
|
||||
|
||||
// Clean up Panzoom instance
|
||||
if (panzoomInstance && typeof panzoomInstance.destroy === 'function') {
|
||||
panzoomInstance.destroy();
|
||||
}
|
||||
|
||||
activeContainer.remove();
|
||||
activeContainer = null;
|
||||
panzoomInstance = null;
|
||||
isProcessingClick = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the panzoom functionality
|
||||
function initializePanzoom() {
|
||||
if (isInitialized) return; // Prevent multiple initializations
|
||||
|
||||
// Create a single delegated click handler at the document level
|
||||
document.body.addEventListener('click', function(event) {
|
||||
// First, check if we clicked a zoomable image
|
||||
const clickedImage = event.target.closest('.zoomable');
|
||||
if (!clickedImage) return; // Exit if we didn't click a zoomable image
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation(); // Stop event from bubbling
|
||||
|
||||
// If there's already a container or we're processing a click, don't create another
|
||||
if (activeContainer || isProcessingClick) {
|
||||
console.log('Already processing or container exists'); // Debug log
|
||||
return;
|
||||
}
|
||||
|
||||
isProcessingClick = true;
|
||||
|
||||
// Create the popup container
|
||||
activeContainer = document.createElement("div");
|
||||
activeContainer.className = "panzoom-popup";
|
||||
|
||||
// Use the clicked image's source and alt
|
||||
const imgSrc = clickedImage.dataset.src || clickedImage.src;
|
||||
const imgAlt = clickedImage.alt || '';
|
||||
|
||||
activeContainer.innerHTML = `
|
||||
<div class="panzoom-overlay">
|
||||
<img src="${imgSrc}" alt="${imgAlt}" />
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(activeContainer);
|
||||
|
||||
// Initialize Panzoom on the image
|
||||
const popupImage = activeContainer.querySelector("img");
|
||||
|
||||
// Wait for the image to load before initializing Panzoom
|
||||
popupImage.onload = () => {
|
||||
// Get the image and viewport dimensions
|
||||
const imageWidth = popupImage.naturalWidth;
|
||||
const imageHeight = popupImage.naturalHeight;
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
|
||||
// Calculate the scaling factor to fit the image within the viewport
|
||||
const scaleX = viewportWidth / imageWidth;
|
||||
const scaleY = viewportHeight / imageHeight;
|
||||
|
||||
// Use the smaller scaling factor to ensure the image fits within the viewport
|
||||
const scale = Math.min(scaleX, scaleY);
|
||||
|
||||
// Calculate the initial x and y coordinates to center the image after scaling
|
||||
const startX = (viewportWidth - imageWidth * scale) / 2;
|
||||
const startY = (viewportHeight - imageHeight * scale) / 2;
|
||||
|
||||
// But only modifying y is necessary because centering works VIA CESSPOOL HORIZONTALLY BUT NOT VERTICALLY
|
||||
panzoomInstance = Panzoom(popupImage, {
|
||||
startY: startY,
|
||||
startScale: 1,
|
||||
maxScale: 5
|
||||
});
|
||||
|
||||
// Enable wheel zoom
|
||||
activeContainer.addEventListener("wheel", panzoomInstance.zoomWithWheel);
|
||||
isProcessingClick = false;
|
||||
};
|
||||
|
||||
// Handle errors
|
||||
popupImage.onerror = () => {
|
||||
console.error('Failed to load image:', imgSrc);
|
||||
closePopup();
|
||||
isProcessingClick = false;
|
||||
};
|
||||
|
||||
// Close popup when clicking outside the image
|
||||
activeContainer.addEventListener("click", function (e) {
|
||||
if (e.target === activeContainer || e.target.classList.contains("panzoom-overlay")) {
|
||||
closePopup();
|
||||
}
|
||||
});
|
||||
|
||||
// Add keyboard support for closing
|
||||
document.addEventListener("keydown", handleKeyPress);
|
||||
});
|
||||
|
||||
isInitialized = true; // Mark as initialized
|
||||
}
|
||||
|
||||
// Initialize only once when the DOM is loaded
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initializePanzoom);
|
||||
} else {
|
||||
initializePanzoom();
|
||||
}
|
@ -0,0 +1 @@
|
||||
if(typeof auth!="undefined"){var update_views,update_likes,viewsCollection=db.collection("views"),likesCollection=db.collection("likes");function numberWithCommas(e){return e.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function toggleLoaders(e){var t,s,n=e.className;if(n=="")return;t=n.split(" ");for(s in t)e.classList.toggle(t[s])}update_views=function(e,t){viewsCollection.doc(t).onSnapshot(t=>{var n=t.data();n?e.innerText=numberWithCommas(n.views):e.innerText=0,toggleLoaders(e)})},update_likes=function(e,t){likesCollection.doc(t).onSnapshot(t=>{var n=t.data();n?e.innerText=numberWithCommas(n.likes):e.innerText=0,toggleLoaders(e)})},auth.signInAnonymously().then(()=>{var e,t,n,s,o=document.querySelectorAll("span[id^='views_']");for(n in o)e=o[n],t=e.id?e.id.replaceAll("/","-"):e.id,t&&update_views(e,t);s=document.querySelectorAll("span[id^='likes_']");for(n in s)e=s[n],t=e.id?e.id.replaceAll("/","-"):e.id,t&&update_likes(e,t)}).catch(e=>{var t=e.code,n=e.message;console.error(t,n)})}
|
@ -0,0 +1 @@
|
||||
function _getDefaultPackeryOptions(){return{percentPosition:!0,gutter:5,resize:!0,itemSelector:".panzoom-container"}}(function(){$(window).on("load",function(){let e=[],t=document.querySelectorAll(".gallery");t.forEach(t=>{let n=new Packery(t,_getDefaultPackeryOptions());e.push(n)}),console.groupEnd()})})()
|
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* A lightweight youtube embed. Still should feel the same to the user, just MUCH faster to initialize and paint.
|
||||
*
|
||||
* Thx to these as the inspiration
|
||||
* https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html
|
||||
* https://autoplay-youtube-player.glitch.me/
|
||||
*
|
||||
* Once built it, I also found these:
|
||||
* https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube (👍👍)
|
||||
* https://github.com/Daugilas/lazyYT
|
||||
* https://github.com/vb/lazyframe
|
||||
*/
|
||||
class LiteYTEmbed extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.videoId = this.getAttribute('videoid');
|
||||
|
||||
let playBtnEl = this.querySelector('.lty-playbtn');
|
||||
// A label for the button takes priority over a [playlabel] attribute on the custom-element
|
||||
this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute('playlabel') || 'Play';
|
||||
|
||||
this.dataset.title = this.getAttribute('title') || "";
|
||||
|
||||
/**
|
||||
* Lo, the youtube poster image! (aka the thumbnail, image placeholder, etc)
|
||||
*
|
||||
* See https://github.com/paulirish/lite-youtube-embed/blob/master/youtube-thumbnail-urls.md
|
||||
*/
|
||||
if (!this.style.backgroundImage) {
|
||||
this.style.backgroundImage = `url("https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg")`;
|
||||
this.upgradePosterImage();
|
||||
}
|
||||
|
||||
// Set up play button, and its visually hidden label
|
||||
if (!playBtnEl) {
|
||||
playBtnEl = document.createElement('button');
|
||||
playBtnEl.type = 'button';
|
||||
playBtnEl.classList.add('lty-playbtn');
|
||||
this.append(playBtnEl);
|
||||
}
|
||||
if (!playBtnEl.textContent) {
|
||||
const playBtnLabelEl = document.createElement('span');
|
||||
playBtnLabelEl.className = 'lyt-visually-hidden';
|
||||
playBtnLabelEl.textContent = this.playLabel;
|
||||
playBtnEl.append(playBtnLabelEl);
|
||||
}
|
||||
|
||||
this.addNoscriptIframe();
|
||||
|
||||
// for the PE pattern, change anchor's semantics to button
|
||||
if(playBtnEl.nodeName === 'A'){
|
||||
playBtnEl.removeAttribute('href');
|
||||
playBtnEl.setAttribute('tabindex', '0');
|
||||
playBtnEl.setAttribute('role', 'button');
|
||||
// fake button needs keyboard help
|
||||
playBtnEl.addEventListener('keydown', e => {
|
||||
if( e.key === 'Enter' || e.key === ' ' ){
|
||||
e.preventDefault();
|
||||
this.activate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// On hover (or tap), warm up the TCP connections we're (likely) about to use.
|
||||
this.addEventListener('pointerover', LiteYTEmbed.warmConnections, {once: true});
|
||||
this.addEventListener('focusin', LiteYTEmbed.warmConnections, {once: true});
|
||||
|
||||
// Once the user clicks, add the real iframe and drop our play button
|
||||
// TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time
|
||||
// We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003
|
||||
this.addEventListener('click', this.activate);
|
||||
|
||||
// Chrome & Edge desktop have no problem with the basic YouTube Embed with ?autoplay=1
|
||||
// However Safari desktop and most/all mobile browsers do not successfully track the user gesture of clicking through the creation/loading of the iframe,
|
||||
// so they don't autoplay automatically. Instead we must load an additional 2 sequential JS files (1KB + 165KB) (un-br) for the YT Player API
|
||||
// TODO: Try loading the the YT API in parallel with our iframe and then attaching/playing it. #82
|
||||
this.needsYTApi = this.hasAttribute("js-api") || navigator.vendor.includes('Apple') || navigator.userAgent.includes('Mobi');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a <link rel={preload | preconnect} ...> to the head
|
||||
*/
|
||||
static addPrefetch(kind, url, as) {
|
||||
const linkEl = document.createElement('link');
|
||||
linkEl.rel = kind;
|
||||
linkEl.href = url;
|
||||
if (as) {
|
||||
linkEl.as = as;
|
||||
}
|
||||
document.head.append(linkEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin pre-connecting to warm up the iframe load
|
||||
* Since the embed's network requests load within its iframe,
|
||||
* preload/prefetch'ing them outside the iframe will only cause double-downloads.
|
||||
* So, the best we can do is warm up a few connections to origins that are in the critical path.
|
||||
*
|
||||
* Maybe `<link rel=preload as=document>` would work, but it's unsupported: http://crbug.com/593267
|
||||
* But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity.
|
||||
*/
|
||||
static warmConnections() {
|
||||
if (LiteYTEmbed.preconnected) return;
|
||||
|
||||
// The iframe document and most of its subresources come right off youtube.com
|
||||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube-nocookie.com');
|
||||
// The botguard script is fetched off from google.com
|
||||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com');
|
||||
|
||||
// Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling.
|
||||
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net');
|
||||
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net');
|
||||
|
||||
LiteYTEmbed.preconnected = true;
|
||||
}
|
||||
|
||||
fetchYTPlayerApi() {
|
||||
if (window.YT || (window.YT && window.YT.Player)) return;
|
||||
|
||||
this.ytApiPromise = new Promise((res, rej) => {
|
||||
var el = document.createElement('script');
|
||||
el.src = 'https://www.youtube.com/iframe_api';
|
||||
el.async = true;
|
||||
el.onload = _ => {
|
||||
YT.ready(res);
|
||||
};
|
||||
el.onerror = rej;
|
||||
this.append(el);
|
||||
});
|
||||
}
|
||||
|
||||
/** Return the YT Player API instance. (Public L-YT-E API) */
|
||||
async getYTPlayer() {
|
||||
if(!this.playerPromise) {
|
||||
await this.activate();
|
||||
}
|
||||
|
||||
return this.playerPromise;
|
||||
}
|
||||
|
||||
async addYTPlayerIframe() {
|
||||
this.fetchYTPlayerApi();
|
||||
await this.ytApiPromise;
|
||||
|
||||
const videoPlaceholderEl = document.createElement('div')
|
||||
this.append(videoPlaceholderEl);
|
||||
|
||||
const paramsObj = Object.fromEntries(this.getParams().entries());
|
||||
|
||||
this.playerPromise = new Promise(resolve => {
|
||||
let player = new YT.Player(videoPlaceholderEl, {
|
||||
width: '100%',
|
||||
videoId: this.videoId,
|
||||
playerVars: paramsObj,
|
||||
events: {
|
||||
'onReady': event => {
|
||||
event.target.playVideo();
|
||||
resolve(player);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add the iframe within <noscript> for indexability discoverability. See https://github.com/paulirish/lite-youtube-embed/issues/105
|
||||
addNoscriptIframe() {
|
||||
const iframeEl = this.createBasicIframe();
|
||||
const noscriptEl = document.createElement('noscript');
|
||||
// Appending into noscript isn't equivalant for mysterious reasons: https://html.spec.whatwg.org/multipage/scripting.html#the-noscript-element
|
||||
noscriptEl.innerHTML = iframeEl.outerHTML;
|
||||
this.append(noscriptEl);
|
||||
}
|
||||
|
||||
getParams() {
|
||||
const params = new URLSearchParams(this.getAttribute('params') || []);
|
||||
params.append('autoplay', '1');
|
||||
params.append('playsinline', '1');
|
||||
return params;
|
||||
}
|
||||
|
||||
async activate(){
|
||||
if (this.classList.contains('lyt-activated')) return;
|
||||
this.classList.add('lyt-activated');
|
||||
|
||||
if (this.needsYTApi) {
|
||||
return this.addYTPlayerIframe(this.getParams());
|
||||
}
|
||||
|
||||
const iframeEl = this.createBasicIframe();
|
||||
this.append(iframeEl);
|
||||
|
||||
// Set focus for a11y
|
||||
iframeEl.focus();
|
||||
}
|
||||
|
||||
createBasicIframe(){
|
||||
const iframeEl = document.createElement('iframe');
|
||||
iframeEl.width = 560;
|
||||
iframeEl.height = 315;
|
||||
// No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include
|
||||
iframeEl.title = this.playLabel;
|
||||
iframeEl.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture';
|
||||
iframeEl.allowFullscreen = true;
|
||||
// AFAIK, the encoding here isn't necessary for XSS, but we'll do it only because this is a URL
|
||||
// https://stackoverflow.com/q/64959723/89484
|
||||
iframeEl.src = `https://www.youtube-nocookie.com/embed/${encodeURIComponent(this.videoId)}?${this.getParams().toString()}`;
|
||||
return iframeEl;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the spirit of the `lowsrc` attribute and progressive JPEGs, we'll upgrade the reliable
|
||||
* poster image to a higher resolution one, if it's available.
|
||||
* Interestingly this sddefault webp is often smaller in filesize, but we will still attempt it second
|
||||
* because getting _an_ image in front of the user if our first priority.
|
||||
*
|
||||
* See https://github.com/paulirish/lite-youtube-embed/blob/master/youtube-thumbnail-urls.md for more details
|
||||
*/
|
||||
upgradePosterImage() {
|
||||
// Defer to reduce network contention.
|
||||
setTimeout(() => {
|
||||
const webpUrl = `https://i.ytimg.com/vi_webp/${this.videoId}/sddefault.webp`;
|
||||
const img = new Image();
|
||||
img.fetchPriority = 'low'; // low priority to reduce network contention
|
||||
img.referrerpolicy = 'origin'; // Not 100% sure it's needed, but https://github.com/ampproject/amphtml/pull/3940
|
||||
img.src = webpUrl;
|
||||
img.onload = e => {
|
||||
// A pretty ugly hack since onerror won't fire on YouTube image 404. This is (probably) due to
|
||||
// Youtube's style of returning data even with a 404 status. That data is a 120x90 placeholder image.
|
||||
// … per "annoying yt 404 behavior" in the .md
|
||||
const noAvailablePoster = e.target.naturalHeight == 90 && e.target.naturalWidth == 120;
|
||||
if (noAvailablePoster) return;
|
||||
|
||||
this.style.backgroundImage = `url("${webpUrl}")`;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
// Register custom element
|
||||
customElements.define('lite-youtube', LiteYTEmbed);
|
95
public/lib/lite-youtube-embed/lite-yt-embed.css
Normal file
@ -0,0 +1,95 @@
|
||||
lite-youtube {
|
||||
background-color: #000;
|
||||
position: relative;
|
||||
display: block;
|
||||
contain: content;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
max-width: 720px;
|
||||
}
|
||||
|
||||
/* gradient */
|
||||
lite-youtube::before {
|
||||
content: attr(data-title);
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/* Pixel-perfect port of YT's gradient PNG, using https://github.com/bluesmoon/pngtocss plus optimizations */
|
||||
background-image: linear-gradient(180deg, rgb(0 0 0 / 67%) 0%, rgb(0 0 0 / 54%) 14%, rgb(0 0 0 / 15%) 54%, rgb(0 0 0 / 5%) 72%, rgb(0 0 0 / 0%) 94%);
|
||||
height: 99px;
|
||||
width: 100%;
|
||||
font-family: "YouTube Noto",Roboto,Arial,Helvetica,sans-serif;
|
||||
color: hsl(0deg 0% 93.33%);
|
||||
text-shadow: 0 0 2px rgba(0,0,0,.5);
|
||||
font-size: 18px;
|
||||
padding: 25px 20px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
lite-youtube:hover::before {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* responsive iframe with a 16:9 aspect ratio
|
||||
thanks https://css-tricks.com/responsive-iframes/
|
||||
*/
|
||||
lite-youtube::after {
|
||||
content: "";
|
||||
display: block;
|
||||
padding-bottom: calc(100% / (16 / 9));
|
||||
}
|
||||
lite-youtube > iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* play button */
|
||||
lite-youtube > .lty-playbtn {
|
||||
display: block;
|
||||
/* Make the button element cover the whole area for a large hover/click target… */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* …but visually it's still the same size */
|
||||
background: no-repeat center/68px 48px;
|
||||
/* YT's actual play button svg */
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 48"><path d="M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24s-.06-10.95-1.48-16.26z" fill="red"/><path d="M45 24 27 14v20" fill="white"/></svg>');
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
filter: grayscale(100%);
|
||||
transition: filter .1s cubic-bezier(0, 0, 0.2, 1);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
lite-youtube:hover > .lty-playbtn,
|
||||
lite-youtube .lty-playbtn:focus {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
/* Post-click styles */
|
||||
lite-youtube.lyt-activated {
|
||||
cursor: unset;
|
||||
}
|
||||
lite-youtube.lyt-activated::before,
|
||||
lite-youtube.lyt-activated > .lty-playbtn {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.lyt-visually-hidden {
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
13
public/lib/packery/packery.pkgd.min.js
vendored
Normal file
2
public/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/"></head></html>
|
15
public/posts/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html><html lang=en dir=ltr class=scroll-smooth data-default-appearance=dark data-auto-appearance=false><head><meta charset=utf-8><meta http-equiv=content-language content="en"><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Posts · N.E.E.T. Works</title>
|
||||
<meta name=title content="Posts · N.E.E.T. Works"><meta name=description content="random tech stuff from a sane and normal individual"><link rel=canonical href=https://blog.neet.works/posts/><link rel=alternate type=application/rss+xml href=/posts/index.xml title="N.E.E.T. Works"><link type=text/css rel=stylesheet href=/css/main.bundle.min.40e00100ae5ec4637cecd46ba4ae5f8db39bb83da61b5efe4900676fc0f4c10ac17e7da11e467fb8f1f39dfa5a5070c05bba06b4c05c629c2d389f4263d4c633.css integrity="sha512-QOABAK5exGN87NRrpK5fjbObuD2mG17+SQBnb8D0wQrBfn2hHkZ/uPHznfpaUHDAW7oGtMBcYpwtOJ9CY9TGMw=="><script type=text/javascript src=/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj+e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script><script defer type=text/javascript id=script-bundle src=/js/main.bundle.min.a2d78d78672e549fbfc972ece871725b5478ba0b65708dda20cb97ab80a865eae6d247e1b05a4aec6ebbf78647ec3233bad8b2609ed98eee53cd58aa17128bc7.js integrity="sha512-oteNeGcuVJ+/yXLs6HFyW1R4ugtlcI3aIMuXq4CoZerm0kfhsFpK7G6794ZH7DIzutiyYJ7Zju5TzViqFxKLxw==" data-copy data-copied></script><link rel=apple-touch-icon sizes=180x180 href=/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/favicon-16x16.png><link rel=manifest href=/site.webmanifest><meta property="og:url" content="https://blog.neet.works/posts/"><meta property="og:site_name" content="N.E.E.T. Works"><meta property="og:title" content="Posts"><meta property="og:description" content="random tech stuff from a sane and normal individual"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Posts"><meta name=twitter:description content="random tech stuff from a sane and normal individual"><meta name=author content="rawhide kobayashi"><link href=mailto:rawhide@neet.works rel=me><link href=https://git.neet.works/rawhide_k rel=me><link href=https://github.com/rawhide-kobayashi rel=me><script src=/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj+KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script><meta name=theme-color><script type=text/javascript src=/js/panzoom.min.b48202c3408ba8ef63ef9a6cc583e9d7ddb6574828cf79a4aaefe3c3964d0098ad77da46fdd5dddb66314ca975f6b9562093fa227ef51db7eba6d640facf448c.js integrity="sha512-tIICw0CLqO9j75psxYPp1922V0goz3mkqu/jw5ZNAJitd9pG/dXd22YxTKl19rlWIJP6In71HbfrptZA+s9EjA=="></script><script type=text/javascript src=/js/panzoom-util.0b774e030782a9868719da996178ac3b16e1b62d1e91bc2d30acff9d859a5621b373e1ae37cef8bbb467283f80648346c36d54b799a38d6da96aeac3bf4ff8e1.js integrity="sha512-C3dOAweCqYaHGdqZYXisOxbhti0ekbwtMKz/nYWaViGzc+GuN874u7RnKD+AZINGw21Ut5mjjW2paurDv0/44Q=="></script></head><body class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600"><div id=the-top class="absolute flex self-center"><a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600" href=#main-content><span class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">↓</span>Skip to main content</a></div><div style=padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start space-x-3"><div class="flex flex-1 items-center justify-between"><nav class="flex space-x-3"><a href=/ class="text-base font-medium text-gray-500 hover:text-gray-900">N.E.E.T. Works</a></nav><nav class="hidden md:flex items-center space-x-5 md:ml-12 h-12"><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Blog</p></a><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Categories</p></a><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-base font-medium" title>Tags</p></a><button id=search-button aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></nav><div class="flex md:hidden items-center space-x-5 md:ml-12 h-12"><span></span>
|
||||
<button id=search-button-mobile aria-label=Search class="text-base hover:text-primary-600 dark:hover:text-primary-400" title>
|
||||
<span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></button></div></div><div class="-my-2 -mr-2 md:hidden"><label id=menu-button class=block><div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 448 512"><path fill="currentcolor" d="M0 96C0 78.33 14.33 64 32 64H416c17.7.0 32 14.33 32 32 0 17.7-14.3 32-32 32H32C14.33 128 0 113.7.0 96zM0 256c0-17.7 14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32H32c-17.67.0-32-14.3-32-32zM416 448H32c-17.67.0-32-14.3-32-32s14.33-32 32-32H416c17.7.0 32 14.3 32 32s-14.3 32-32 32z"/></svg></span></div><div id=menu-wrapper style=padding-top:5px class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50"><ul class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl"><li id=menu-close-button><span class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400"><span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></span></li><li class=mt-1><a href=/posts/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Blog</p></a></li><li class=mt-1><a href=/categories/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Categories</p></a></li><li class=mt-1><a href=/tags/ class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"><p class="text-bg font-bg" title>Tags</p></a></li></ul></div></label></div></div><div class="relative flex flex-col grow"><main id=main-content class=grow><header><h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">Posts</h1><div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden"><div class="flex flex-row flex-wrap items-center"></div></div></header><section class="mt-0 prose flex max-w-full flex-col dark:prose-invert lg:flex-row"><div class="min-w-0 min-h-0 max-w-prose"></div></section><section class="space-y-10 w-full"><h2 class="mt-12 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">2025</h2><a class="flex flex-wrap article" href=/posts/watercooling-homelab/><div class="w-full md:w-auto h-full thumbnail nozoom thumbnailshadow md:mr-7" style=background-image:url(/posts/watercooling-homelab/featured_hu13568191302889737537.webp)></div><div class="mt-3 md:mt-0"><div class="items-center text-left text-xl font-semibold"><div class="font-bold text-xl text-neutral-800 decoration-primary-500 hover:underline hover:underline-offset-2 dark:text-neutral" href=/posts/watercooling-homelab/>Watercooling My Homelab</div></div><div class="text-sm text-neutral-500 dark:text-neutral-400"><div class="flex flex-row flex-wrap items-center"><time datetime=2025-01-16T05:56:41+00:00>January 16 2025</time><span class="px-2 text-primary-500">·</span><span>5240 words</span></div><hr><div class="flex flex-row flex-wrap items-center">Watercooling for my homelab with a custom, leak-resistant controller and monitoring!</div><hr><div class="flex flex-row flex-wrap items-center"><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/homelab/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Homelab
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/servers/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Servers
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/watercooling/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Watercooling
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/categories/diy/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Diy
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/alphacool/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Alphacool
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/arduino/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Arduino
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/intel/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Intel
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/nvidia/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Nvidia
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/supermicro/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Supermicro
|
||||
</span></span></span><span style=margin-top:.5rem class=mr-2 onclick='return window.open("/tags/aqua-computer/","_self"),!1'><span class=flex style=cursor:pointer><span class="rounded-md border border-primary-400 px-1 py-[1px] text-xs font-normal">Aqua Computer</span></span></span></div></div></div></a></section></main><footer id=site-footer class="py-10 print:hidden"><div class="flex items-center justify-between"><p class="text-sm text-neutral-500 dark:text-neutral-400"><em>© 2025 rawhide kobayashi | <strong>Original content</strong> licensed under <strong><a href=https://creativecommons.org/licenses/by-sa/4.0/ target=_blank>CC BY-SA 4.0</a></strong> unless otherwise noted.</em></p><p class="text-xs text-neutral-500 dark:text-neutral-400">Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://gohugo.io/ target=_blank rel="noopener noreferrer">Hugo</a> & <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href=https://blowfish.page/ target=_blank rel="noopener noreferrer">Blowfish</a></p></div><script></script><script type=text/javascript src=/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh+sCQ0E53ghYrxgYqw+0GCRyIEpA=="></script></footer><div id=search-wrapper class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" data-url=https://blog.neet.works/ style=z-index:500><div id=search-modal class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"><header class="relative z-10 flex items-center justify-between flex-none px-2"><form class="flex items-center flex-auto min-w-0"><div class="flex items-center justify-center w-8 h-8 text-neutral-400"><span class="relative block icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" viewBox="0 0 512 512"><path fill="currentcolor" d="M505 442.7 405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9.0 208 0S0 93.1.0 208s93.1 208 208 208c48.3.0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9.0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7.0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7.0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg></span></div><input type=search id=search-query class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent" placeholder=Search tabindex=0></form><button id=close-search-button class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400" title="Close (Esc)">
|
||||
<span class="relative block icon"><svg viewBox="0 0 320 512"><path fill="currentcolor" d="M310.6 361.4c12.5 12.5 12.5 32.75.0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3 54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75.0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75.0-45.25s32.75-12.5 45.25.0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25.0s12.5 32.75.0 45.25l-105.4 105.4L310.6 361.4z"/></svg></span></button></header><section class="flex-auto px-2 overflow-auto"><ul id=search-results></ul></section></div></div></div></body></html>
|
1
public/posts/index.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on N.E.E.T. Works</title><link>https://blog.neet.works/posts/</link><description>Recent content in Posts on N.E.E.T. Works</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>rawhide@neet.works (rawhide kobayashi)</managingEditor><webMaster>rawhide@neet.works (rawhide kobayashi)</webMaster><copyright>*© 2025 rawhide kobayashi | **Original content** licensed under **[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)** unless otherwise noted.*</copyright><lastBuildDate>Thu, 16 Jan 2025 05:56:41 +0000</lastBuildDate><atom:link href="https://blog.neet.works/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Watercooling My Homelab</title><link>https://blog.neet.works/posts/watercooling-homelab/</link><pubDate>Thu, 16 Jan 2025 05:56:41 +0000</pubDate><author>rawhide@neet.works (rawhide kobayashi)</author><guid>https://blog.neet.works/posts/watercooling-homelab/</guid><description/><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.neet.works/posts/watercooling-homelab/featured.webp"/></item></channel></rss>
|
2
public/posts/page/1/index.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!doctype html><html lang=en><head><title>https://blog.neet.works/posts/</title>
|
||||
<link rel=canonical href=https://blog.neet.works/posts/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=https://blog.neet.works/posts/"></head></html>
|
BIN
public/posts/watercooling-homelab/featured.webp
Normal file
After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 835 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 845 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 840 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
public/posts/watercooling-homelab/images/compressed/MO-RA!.webp
Normal file
After Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 931 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |