[{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/","section":"","summary":"","title":"","type":"page"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/blog/","section":"Blog","summary":"","title":"Blog","type":"blog"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/driving-gloves/","section":"Tags","summary":"","title":"Driving Gloves","type":"tags"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/henry/","section":"Tags","summary":"","title":"Henry","type":"tags"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/index/","section":"Tags","summary":"","title":"Index","type":"tags"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/kessler/","section":"Tags","summary":"","title":"Kessler","type":"tags"},{"content":"Remembering James Bond films where he cruises in a convertible wearing sleek leather driving gloves, I wanted a pair for my own car a few years ago. I held off due to the price and the fact that they’re not strictly necessary.\nRecently, I bought my first convertible, and the idea returned. I wanted perforated leather gloves with a retro look, so after some online research, I narrowed it down to the Kessler Henry model.\nSaffron wasn’t available at the time, so I went with cork. Available colors include saffron, cork, loden green, oak, and black. Made from peccary leather, these gloves are comfortable and soft yet durable enough to last.\nThe feel while driving is excellent, I even wear them for short trips. Touchscreen compatibility works decently, and they slip on and off easily. The leather quality stands out.\nIf you can afford quality driving gloves, I recommend the Kessler Henry for that enhanced driving enjoyment. Even if not these, get some — gloves add a real level of pleasure to the drive.\n","date":"April 20, 2026","externalUrl":null,"permalink":"/blog/kessler-henry-gloves/","section":"Blog","summary":"Remembering James Bond films where he cruises in a convertible wearing sleek leather driving gloves, I wanted a pair for my own car a few years ago. I held off due to the price and the fact that they’re not strictly necessary.\n","title":"Kessler Henry Driver’s Gloves: A Personal Review","type":"blog"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/categories/motorcycles/","section":"Categories","summary":"","title":"Motorcycles","type":"categories"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/peccary-leather-gloves/","section":"Tags","summary":"","title":"Peccary Leather Gloves","type":"tags"},{"content":"","date":"April 20, 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"March 12, 2026","externalUrl":null,"permalink":"/tags/2s002339/","section":"Tags","summary":"","title":"2S002339","type":"tags"},{"content":"The CNC-machined, black-anodized aluminum handlebar end weights (part number 2S002339) are a perfect fit for E5+ RSV4 and Tuono V4 models. Each one weighs 59g compared to the stock 61g, with a precision-crafted circular grooves and protective plastic cap. In the photos, you can compare these optional weights to the stock ones. They’re similar in design, but the aftermarket ones feature two machined grooves for enhanced aesthetics, along with the plastic cap. I didn’t fully insert the cap into the end weight to make removal easier, as I opted to keep the originals installed.\n","date":"March 12, 2026","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-oem-accessory-handlebar-weights/","section":"Blog","summary":"The CNC-machined, black-anodized aluminum handlebar end weights (part number 2S002339) are a perfect fit for E5+ RSV4 and Tuono V4 models. Each one weighs 59g compared to the stock 61g, with a precision-crafted circular grooves and protective plastic cap. ","title":"Aprilia 2S002339 Handlebar End Weights: Upgrade for RSV4 \u0026 Tuono V4 E5+","type":"blog"},{"content":"","date":"March 12, 2026","externalUrl":null,"permalink":"/tags/aprilia-rsv4-1100-e5+/","section":"Tags","summary":"","title":"Aprilia RSV4 1100 E5+","type":"tags"},{"content":"","date":"March 12, 2026","externalUrl":null,"permalink":"/tags/aprilia-tuono-v4-1100-e5+/","section":"Tags","summary":"","title":"Aprilia Tuono V4 1100 E5+","type":"tags"},{"content":"","date":"March 12, 2026","externalUrl":null,"permalink":"/tags/handlebar-end-weights/","section":"Tags","summary":"","title":"Handlebar End Weights","type":"tags"},{"content":"","date":"March 12, 2026","externalUrl":null,"permalink":"/tags/oem-accessories/","section":"Tags","summary":"","title":"OEM Accessories","type":"tags"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/kawasaki-h2-sx-se/","section":"Tags","summary":"","title":"Kawasaki H2 SX SE","type":"tags"},{"content":"Kawasaki H2 SX SE comes factory-equipped with a built-in cigarette lighter socket, which isn’t very practical. I used a cigarette lighter USB adapter for a while, but that solution wasn’t ideal, mainly because it offered no protection against rain. So, I decided to install a built-in USB charger to replace the stock lighter socket.\nIn the first two photos, you can see the original cigarette lighter socket as well as all the materials needed for the new setup. Unfortunately, the USB charger’s diameter is about 1 mm larger than the original socket, so I had to slightly widen the hole with a file. However, I used a new power connector identical to the factory one, which means I didn’t have to cut or damage any of the motorcycle’s wiring — I simply connected the USB charger to the existing connector.\nI checked which wire was positive and which was negative, labeled the terminals, and completed the wiring and installation. The USB charger was purchased from AliExpress and is supposedly rated at 83 W total output — 65 W from the USB-C port and 18 W from the USB-A port. Honestly, this is how the motorcycle should have come from the factory, not with an outdated cigarette lighter socket.\n","date":"February 22, 2026","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-usb/","section":"Blog","summary":"Kawasaki H2 SX SE comes factory-equipped with a built-in cigarette lighter socket, which isn’t very practical. I used a cigarette lighter USB adapter for a while, but that solution wasn’t ideal, mainly because it offered no protection against rain. So, I decided to install a built-in USB charger to replace the stock lighter socket.\n","title":"Kawasaki H2 SX USB Charger Upgrade – Replacing the Factory Cigarette Lighter Socket","type":"blog"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/motorcycle-electrical-mods/","section":"Tags","summary":"","title":"Motorcycle Electrical Mods","type":"tags"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/motorcycle-usb-charger/","section":"Tags","summary":"","title":"Motorcycle USB Charger","type":"tags"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/motorcycle-wiring/","section":"Tags","summary":"","title":"Motorcycle Wiring","type":"tags"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/replace-cigarette-lighter-socket/","section":"Tags","summary":"","title":"Replace Cigarette Lighter Socket","type":"tags"},{"content":"","date":"February 22, 2026","externalUrl":null,"permalink":"/tags/usb-adapter-installation/","section":"Tags","summary":"","title":"USB Adapter Installation","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/android-auto/","section":"Tags","summary":"","title":"Android Auto","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/apple-carplay/","section":"Tags","summary":"","title":"Apple CarPlay","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/aprilia-tuono-v4-factory-1100/","section":"Tags","summary":"","title":"Aprilia Tuono V4 Factory 1100","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/calimoto/","section":"Tags","summary":"","title":"Calimoto","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/chigee-aio-6-max/","section":"Tags","summary":"","title":"Chigee AIO-6 Max","type":"tags"},{"content":"Installing the Chigee AIO-6 Max smart riding display on a 2025 Aprilia Tuono V4 Factory 1100 brings a customizable tech upgrade to this hypernaked beast, complementing its stock 5-inch TFT dash. I paired it with Chigee’s Quick-Release Module for seamless swaps to my Kawasaki H2 SX SE and possibly more bikes later. The Anti-Theft Lock for Quick Release secures the display while mounted on the bike, preventing unauthorized removal.\nThe AIO-6 Max offers a bright 6-inch IPS screen readable in direct sun, plus wireless Apple CarPlay/Android Auto and optional extras like tire pressure monitoring, dash cams, etc.. Its IP68/IPX9K rating and sturdy build handle real-world abuse from rain to gravel splash.\nOn the Tuono V4, the included handlebar mount centered neatly above the fork stem. Cable routing under the tank involved removing the top tank bolt and loosening two under-seat bolts. You can see the route of the cable on the supplied pictures.\nI hooked +12V and ground straight to the battery, ACC ignition to a fuse (post-fuse side for safety). No ECU glitches, and it wakes cleanly with the key. Cable tidiness is crucial like in all my installations.\nRiding twisty roads on the Tuono, this setup gives navigation without distracting from its sharp handling. Swapping between bikes works great. Good upgrade for tech riders who want GPS even on fast machines.\n","date":"January 23, 2026","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-chigee-smart-display/","section":"Blog","summary":"Installing the Chigee AIO-6 Max smart riding display on a 2025 Aprilia Tuono V4 Factory 1100 brings a customizable tech upgrade to this hypernaked beast, complementing its stock 5-inch TFT dash. I paired it with Chigee’s Quick-Release Module for seamless swaps to my Kawasaki H2 SX SE and possibly more bikes later. The Anti-Theft Lock for Quick Release secures the display while mounted on the bike, preventing unauthorized removal.\n","title":"Chigee AIO-6 Max Install on 2025 Aprilia Tuono V4 Factory 1100","type":"blog"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/chigee-anti-theft-lock-for-quick-release/","section":"Tags","summary":"","title":"Chigee Anti-Theft Lock for Quick-Release","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/chigee-handlebar-mount/","section":"Tags","summary":"","title":"Chigee Handlebar Mount","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/chigee-quick-release-module/","section":"Tags","summary":"","title":"Chigee Quick-Release Module","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/google-maps/","section":"Tags","summary":"","title":"Google Maps","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/gps/","section":"Tags","summary":"","title":"Gps","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/navigation/","section":"Tags","summary":"","title":"Navigation","type":"tags"},{"content":"","date":"January 23, 2026","externalUrl":null,"permalink":"/tags/smart-riding-display/","section":"Tags","summary":"","title":"Smart Riding Display","type":"tags"},{"content":"Mixed experiences with the Garmin zūmo XT2 on my Kawasaki H2 SX SE left me seeking better options, while smartphone apps like Calimoto and Google Maps delivered much better results. Quad Lock mounts kept my phone viable as a backup, but for enhanced visibility and security on long rides, a dedicated smart display became essential. Extensive research led straight to the Chigee AIO-6 Max, perfectly suited for Apple CarPlay and Android Auto on motorcycles.\nThe Chigee Fork Stem Mount comes with six adapter plugs covering fork stem holes from 12 mm to 29 mm. Selecting the right fit was simple; I secured it to the stem and paired it with the Quick-Release cradle. This central position optimizes viewing without cluttering the cockpit.\nThree connectors grace the AIO-6 Max: two orange for cameras (skipped here) and one red handling 12V power, ground, and ignition-switched ACC. I wired power and ground straight to the battery, tapping ACC via a non-invasive T-connector into the lighter socket for switched operation. This preserved all factory wiring while ensuring reliable startups.\nMonths of riding have shown the Chigee AIO-6 Max to work well alongside phone apps, offering a noticeable step up from traditional GPS devices. Desktop route planning, music apps, and navigation all display clearly on the bright, glove-friendly screen without visibility issues. The unit’s build holds up through various weather and road conditions.\nChigee’s Quick-Release Anti-Theft Locks had reliability issues at first, requiring multiple claims that resulted in a full refund. Repairs by a friend allowed reinstallation on both of my bikes, making the system practical again. The design aims to prevent theft pretty effectively when it functions properly.\nThe Chigee AIO-6 Max provides a solid navigation upgrade for the Kawasaki H2 SX SE, combining phone app strengths with dedicated display benefits. Chigee Quick-Release system adds practicality, while Quad Lock remains a good backup option. Riders prioritizing app integration may find it worth considering.\n","date":"January 22, 2026","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-chigee-smart-display/","section":"Blog","summary":"Mixed experiences with the Garmin zūmo XT2 on my Kawasaki H2 SX SE left me seeking better options, while smartphone apps like Calimoto and Google Maps delivered much better results. Quad Lock mounts kept my phone viable as a backup, but for enhanced visibility and security on long rides, a dedicated smart display became essential. Extensive research led straight to the Chigee AIO-6 Max, perfectly suited for Apple CarPlay and Android Auto on motorcycles.\n","title":"Chigee AIO-6 Max With Quick-Release Module Install on Kawasaki H2 SX SE","type":"blog"},{"content":"","date":"January 22, 2026","externalUrl":null,"permalink":"/tags/chigee-fork-stem-mount/","section":"Tags","summary":"","title":"Chigee Fork Stem Mount","type":"tags"},{"content":"","date":"January 21, 2026","externalUrl":null,"permalink":"/tags/evotech-performance/","section":"Tags","summary":"","title":"Evotech-Performance","type":"tags"},{"content":"Choosing the perfect tail tidy for the Aprilia Tuono V4 Factory 1100 turned out to be more challenging than expected. With this being a new model, there weren’t many real-world photos or reviews online to help guide the decision. After narrowing down the options to three notable contenders — Top Block Racing , LighTech , and Evotech Performance — the final choice went to the British-made Evotech-Performance kit.\nThe main reason for choosing Evotech was its smart integration and attention to detail. Unlike other brands, this design completely conceals the wiring — a small but important detail that makes a big difference in the visual finish. Clean lines, no exposed cables, and a form that complements the Tuono’s aggressive tail section made it, in my eyes, the best-looking solution available.\nOne point of concern before ordering was the weight. None of the manufacturers published specific weight data, leaving some uncertainty about how substantial the units might be. Those concerns vanished as soon as the Evotech unit arrived. It’s impressively light while feeling sturdy, reflecting the precise CNC-machining and powder-coated aluminum construction the company is known for. Fit and finish are outstanding, and the assembly feels entirely purpose-built for the Tuono V4 2025.\nInstallation was straightforward and can easily be done without disassembling the rear seat structure. The original tail assembly is held by just three bolts. The only slight challenge is holding the upper nut with a 10 mm spanner while loosening the bolt from underneath the tail — but even that can be done without removing any interior parts.\nEvotech provides all necessary fasteners, including a small spacer for the central rear mounting point, while the other two bolts reuse the original nuts. The OEM indicators and number plate light fit directly into the Evotech bracket, maintaining both the stock appearance and full road legality.\nShould you need guidance, Evotech offers a step-by-step video tutorial on their official product page, making the whole process foolproof even for riders with minimal workshop experience.\nMounted and secured, the Evotech tail tidy transforms the Tuono’s rear profile. Despite the bulkier dimensions of German license plates, the tail still looks compact and aggressive. The new bracket sits much closer to the tail top, giving the bike a sleeker, race-inspired silhouette that enhances the overall design harmony of the V4 Factory.\nIn short, Evotech-Performance’s Tail Tidy for the Aprilia Tuono V4 Factory 1100 MY2025+ strikes an ideal balance between aesthetic refinement, functional precision, and lightweight engineering. It’s a premium accessory that delivers exactly what you expect: flawless fitment, smart design, and a visual upgrade worthy of one of Italy’s most exciting hypernakeds.\n","date":"January 21, 2026","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-evotech-performance-tail-tidy/","section":"Blog","summary":"Choosing the perfect tail tidy for the Aprilia Tuono V4 Factory 1100 turned out to be more challenging than expected. With this being a new model, there weren’t many real-world photos or reviews online to help guide the decision. After narrowing down the options to three notable contenders — Top Block Racing , LighTech , and Evotech Performance — the final choice went to the British-made Evotech-Performance kit.\n","title":"Evotech-Performance Tail Tidy Review for Aprilia Tuono V4 Factory 1100 MY2025+","type":"blog"},{"content":"","date":"January 21, 2026","externalUrl":null,"permalink":"/tags/license-plate-holder/","section":"Tags","summary":"","title":"License Plate Holder","type":"tags"},{"content":"","date":"January 21, 2026","externalUrl":null,"permalink":"/tags/tail-tidy/","section":"Tags","summary":"","title":"Tail Tidy","type":"tags"},{"content":"","date":"January 14, 2026","externalUrl":null,"permalink":"/tags/pillion-seat-cover/","section":"Tags","summary":"","title":"Pillion Seat Cover","type":"tags"},{"content":"","date":"January 14, 2026","externalUrl":null,"permalink":"/tags/rear-seat-cover/","section":"Tags","summary":"","title":"Rear Seat Cover","type":"tags"},{"content":"","date":"January 14, 2026","externalUrl":null,"permalink":"/tags/seat-cowl/","section":"Tags","summary":"","title":"Seat Cowl","type":"tags"},{"content":"","date":"January 14, 2026","externalUrl":null,"permalink":"/tags/stegosaurus-finlets/","section":"Tags","summary":"","title":"Stegosaurus Finlets","type":"tags"},{"content":"While searching for a license plate holder for the 2025 Aprilia Tuono V4 Factory 1100, I spent some time on the Evotech-Performance website , fully expecting to find well-engineered solutions. What I didn’t expect was to be distracted by their pillion seat cover assembly designed specifically for the latest Tuono. Given Aprilia’s decision to emphasize the rear with pronounced aerodynamic fins, the tail section can look visually busy, so I was genuinely curious how a cleaner aftermarket solution would change the bike’s overall balance.\nEvotech’s pillion seat cover aims to streamline the rear end by replacing the standard passenger seat or stegosaurus finlets seat cover with a sculpted cowl that integrates neatly with the existing bodywork. The result is a flatter, more cohesive tail profile that tones down the aggressive styling without diluting the Tuono’s muscular character. It’s a subtle change, but one that noticeably alters the bike’s proportions when viewed from the side and rear.\nInside the box are two molded plastic components that are joined together, onto which the original protective pad, rubber elements, screws, and locking pin from the OEM pillion seat cover are transferred. This approach keeps the installation straightforward and fully reversible, maintaining factory mounting points and functionality without permanent modification.\nFor riders who rarely carry a passenger and prefer a more focused, single-seat look, the Evotech-Performance pillion seat cover makes a strong case. It doesn’t try to transform the Tuono into a race replica; instead, it refines the design, reducing visual clutter and giving the rear end a cleaner, more intentional finish — exactly what many Tuono owners are looking for.\nIf you’re not familiar with Aprilia’s original pillion seat cover with its distinctive stegosaurus finlets, this is how it looks in practice. With winter still in full swing in Germany, the bike remains parked for now, but more appealing outdoor photos will follow once spring arrives.\n","date":"January 14, 2026","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-evotech-performance-pillion-seat-cover/","section":"Blog","summary":"While searching for a license plate holder for the 2025 Aprilia Tuono V4 Factory 1100, I spent some time on the Evotech-Performance website , fully expecting to find well-engineered solutions. What I didn’t expect was to be distracted by their pillion seat cover assembly designed specifically for the latest Tuono. Given Aprilia’s decision to emphasize the rear with pronounced aerodynamic fins, the tail section can look visually busy, so I was genuinely curious how a cleaner aftermarket solution would change the bike’s overall balance.\n","title":"Taming the Tail: A Closer Look at the Evotech-Performance Pillion Seat Cover for Aprilia Tuono V4 Factory 1100","type":"blog"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/series/custom-daytona-motorcycle-boots/","section":"Series","summary":"","title":"Custom Daytona Motorcycle Boots","type":"series"},{"content":"In the previous article of this series, I mentioned that I would write a follow-up once my boots were delivered. However, since the riding season had already started by that time, it was naturally more important to be out on the road than to write blog articles. The delivery was delayed by about ten days, but to be fair, no exact delivery date had been promised, only an approximate timeframe. While the boots were being made, I was already traveling on my Triumph Rocket 3 Storm R, using a different set of gear, so the wait wasn’t an issue.\nWhen the boots finally arrived, I was satisfied with their appearance, they were well made, symmetrical and neatly finished. The only issue was that they felt slightly loose around the ankle area, so I decided to report that to the manufacturer. We agreed that I would visit their factory again so the adjustment could be done on-site. Indeed, when I arrived, they slightly narrowed both boots at the ankle, and the entire process took about half an hour.\nSince I’m writing this article several months later, at the end of the motorcycle season in the northern hemisphere, I can now provide a review based on real-world use and direct experience. The boots are very comfortable, they don’t fatigue the feet even after a full day of riding, they are completely waterproof, and they still look quite decent after roughly 8–9 thousands kilometers of use.\nI noticed two minor damages: a slightly scratched fluorescent strip on the left boot and some worn-off letters on the sole, also on the left one. I’m not entirely sure whether these were manufacturing defects. The strip seemed fine initially. As for the letters, it’s possible they weren’t properly bonded, or it might simply be from regular wear, perhaps I stepped on something. Either way, it’s not a significant issue since functionality and safety remain unaffected.\nI contacted the Daytona factory about the damaged lettering on the sole, asking whether they could send me the letters so I could reattach them myself. They explained that the soles come as a complete unit with the branding already applied, so replacing individual letters isn’t possible. The only option would be a full sole replacement. Considering the boots are still in great condition, I decided to postpone that until the soles actually need replacing, or perhaps until I buy a new pair altogether. Once again, the team at Daytona was very polite and even offered a future discount should any repairs be needed.\nThe price of custom made motorcycle boots is certainly not low, but in my case, it was the only way to get high-quality, waterproof and protective motorcycle boots. Based on my experience, I can confidently recommend Daytona. It\u0026rsquo;s unlikely to go wrong with them.\n","date":"October 24, 2025","externalUrl":null,"permalink":"/blog/daytona-made-to-measure-boots-2/","section":"Blog","summary":"In the previous article of this series, I mentioned that I would write a follow-up once my boots were delivered. However, since the riding season had already started by that time, it was naturally more important to be out on the road than to write blog articles. The delivery was delayed by about ten days, but to be fair, no exact delivery date had been promised, only an approximate timeframe. While the boots were being made, I was already traveling on my Triumph Rocket 3 Storm R, using a different set of gear, so the wait wasn’t an issue.\n","title":"Custom Daytona Motorcycle Boots - Real-World Experience and Review - Part 2/2","type":"blog"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/daytona/","section":"Tags","summary":"","title":"Daytona","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/evo-sports/","section":"Tags","summary":"","title":"Evo Sports","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/evo-sports-gtx/","section":"Tags","summary":"","title":"Evo Sports Gtx","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/evo-voltex/","section":"Tags","summary":"","title":"Evo Voltex","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/evo-voltex-gtx/","section":"Tags","summary":"","title":"Evo Voltex Gtx","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/motorcycle-boots/","section":"Tags","summary":"","title":"Motorcycle Boots","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/racing-sport/","section":"Tags","summary":"","title":"Racing Sport","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/review/","section":"Tags","summary":"","title":"Review","type":"tags"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"October 24, 2025","externalUrl":null,"permalink":"/tags/waterproof/","section":"Tags","summary":"","title":"Waterproof","type":"tags"},{"content":"","date":"October 23, 2025","externalUrl":null,"permalink":"/tags/2s001379/","section":"Tags","summary":"","title":"2S001379","type":"tags"},{"content":"","date":"October 23, 2025","externalUrl":null,"permalink":"/tags/accessories/","section":"Tags","summary":"","title":"Accessories","type":"tags"},{"content":"","date":"October 23, 2025","externalUrl":null,"permalink":"/tags/brake-cooling/","section":"Tags","summary":"","title":"Brake Cooling","type":"tags"},{"content":"","date":"October 23, 2025","externalUrl":null,"permalink":"/tags/carbon-brake-air-ducts/","section":"Tags","summary":"","title":"Carbon Brake Air Ducts","type":"tags"},{"content":"When browsing through the official accessories catalog for my Aprilia Tuono V4 Factory 1100, I noticed the carbon front brake air ducts (part number 2S001379). However, considering their high price, I initially decided there were far more important accessories to get first, for example, an SC Project exhaust, a more discreet license plate holder, or better-looking mirrors, so I postponed the purchase. But then, I happened to find the same ducts second-hand, in like-new condition, and decided to buy them earlier than planned. The rest of the accessories are scheduled for purchase and installation during the winter, which you’ll also be able to follow here on the blog.\nThe first step in installing the ducts was cleaning the brake calipers with brake cleaner. Next, the calipers need to be removed, and the lower screw on the front fender mount undone. The spacers for the brake calipers are taken off and replaced with the carbon ducts, after which all bolts are reinstalled. The caliper bolts should be tightened to 50 Nm (this is not official information, please consult the service manual).\nThe front brake air ducts improve cooling and help maintain consistent braking performance. They’re a direct product of Aprilia’s MotoGP know-how and racing experience. Made of carbon fiber, they reduce weight while maintaining a high-quality feel. Are they necessary on a motorcycle that’s mostly used on public roads? Probably not, but they do look cool, give the bike a more aggressive appearance, so why not.\n","date":"October 23, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-front-brake-air-intake/","section":"Blog","summary":"When browsing through the official accessories catalog for my Aprilia Tuono V4 Factory 1100, I noticed the carbon front brake air ducts (part number 2S001379). However, considering their high price, I initially decided there were far more important accessories to get first, for example, an SC Project exhaust, a more discreet license plate holder, or better-looking mirrors, so I postponed the purchase. But then, I happened to find the same ducts second-hand, in like-new condition, and decided to buy them earlier than planned. The rest of the accessories are scheduled for purchase and installation during the winter, which you’ll also be able to follow here on the blog.\n","title":"Installing Aprilia Carbon Front Brake Air Ducts on the Tuono V4 Factory 1100","type":"blog"},{"content":"","date":"October 23, 2025","externalUrl":null,"permalink":"/tags/motogp/","section":"Tags","summary":"","title":"MotoGP","type":"tags"},{"content":"","date":"October 22, 2025","externalUrl":null,"permalink":"/tags/2s001789/","section":"Tags","summary":"","title":"2S001789","type":"tags"},{"content":"I enjoy dynamic riding the most, especially on winding roads, which makes a GPS device an essential part of my setup even on a naked bike. My final choice was the Chigee AIO-6, a device that supports Apple CarPlay and Android Auto. However, since it relies on a smartphone connection, and smartphone batteries rarely last a full day of riding, it was necessary to ensure a constant power supply during trips. Fortunately, most Aprilia motorcycles, including the Tuono series, offer a factory USB socket (part number 2S001789) as a convenient solution.\nInstalling the USB socket on the Aprilia Tuono V4 Factory 1100 is quite straightforward. The process involves unscrewing and removing the plastic panel located to the left of the display, routing the USB socket through the designated hole, connecting the plug, and reinstalling the plastic trim. The photos illustrate several stages of the process and show the final setup once completed.\nAt the time of installing this, only the Quad Lock phone mount was installed on the bike, but I later repositioned it slightly to make room in the center of the handlebar for the Chigee AIO-6. I prefer having two GPS navigation options in case one fails, a lesson learned from past experiences when technology didn’t always cooperate at the right moment.\nInterestingly, Aprilia also offers an integrated turn-by-turn navigation system that displays directional arrows on the TFT screen. This means my Tuono now effectively has three GPS solutions, the built-in one, the Chigee AIO-6, and the smartphone itself.\nSomeone might say that all three solutions depend on a smartphone, creating a potential single point of failure. But, if something happens to the phone, losing navigation becomes the least of the concerns. Still, it’s a reminder that even advanced setups have practical limits.\n","date":"October 22, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-usb-socket/","section":"Blog","summary":"I enjoy dynamic riding the most, especially on winding roads, which makes a GPS device an essential part of my setup even on a naked bike. My final choice was the Chigee AIO-6, a device that supports Apple CarPlay and Android Auto. However, since it relies on a smartphone connection, and smartphone batteries rarely last a full day of riding, it was necessary to ensure a constant power supply during trips. Fortunately, most Aprilia motorcycles, including the Tuono series, offer a factory USB socket (part number 2S001789) as a convenient solution.\n","title":"Installing a USB Socket on the Aprilia Tuono V4 Factory 1100","type":"blog"},{"content":"","date":"October 22, 2025","externalUrl":null,"permalink":"/tags/smart-phone-charging/","section":"Tags","summary":"","title":"Smart Phone Charging","type":"tags"},{"content":"","date":"October 22, 2025","externalUrl":null,"permalink":"/tags/usb/","section":"Tags","summary":"","title":"USB","type":"tags"},{"content":"","date":"October 22, 2025","externalUrl":null,"permalink":"/tags/usb-installation/","section":"Tags","summary":"","title":"USB Installation","type":"tags"},{"content":"","date":"October 22, 2025","externalUrl":null,"permalink":"/tags/usb-socket-installation/","section":"Tags","summary":"","title":"USB Socket Installation","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/2s002389/","section":"Tags","summary":"","title":"2S002389","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/2s002475/","section":"Tags","summary":"","title":"2S002475","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/alarm-pmp-not-configured/","section":"Tags","summary":"","title":"Alarm PMP Not Configured","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/aprilia-connectivity-module/","section":"Tags","summary":"","title":"Aprilia Connectivity Module","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/aprilia-gps-sensor/","section":"Tags","summary":"","title":"Aprilia GPS Sensor","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/aprilia-mia/","section":"Tags","summary":"","title":"Aprilia MIA","type":"tags"},{"content":"The Aprilia Tuono V4 Factory 1100 offers smartphone connectivity through an optional accessory known as the Aprilia MIA multimedia platform. The latest version of this module, part number 2S002475, features updated hardware with built‑in memory capable of storing data from track sessions without requiring a connected smartphone. When paired with the additional GPS sensor (part number 2S002389), the module can record complete lap timing data independently.\nI purchased the MIA unit from an authorized Aprilia dealer and decided to handle the installation personally. The official procedure involves removing the fuel tank to secure the module to the frame using two screws. Given the lightweight design, I opted instead for a simpler approach, mounting it with double‑sided adhesive tape. After several rides, the installation proved stable. Should the tank ever need to come off for maintenance, I may take that opportunity to add the screws as originally intended. Connection is straightforward: the blanking insert removed from the near plug, and the MIA unit connects directly to the existing harness.\nAlthough my dealer mentioned that diagnostic pairing was unnecessary, an error message appeared when I powered up the bike. A quick visit to the dealership resolved the issue within about 15 minutes.\nOnce operational, the system provides Bluetooth pairing with iOS or Android devices, enabling phone and media control, navigation display on the TFT dashboard, and compatibility with the Aprilia MIA smartphone app for ride data analysis. However, I encountered a practical drawback during everyday use: when my phone was already streaming music to the helmet communicator, connecting the motorcycle over Bluetooth interrupted playback. To avoid repeated interruptions, I disabled the MIA pairing except when explicitly needed, such as for the built-in GPS or track‑related features.\nThis behavior is not exclusive to Aprilia’s system. I experienced identical issues with the connectivity interface on my Kawasaki H2 SX SE and previously on Triumph Rocket 3 Storm R, suggesting that the limitation lies in smartphone Bluetooth handling rather than in the motorcycle system itself. Riders who do not play music are unlikely to be affected.\nOverall, the MIA module functions as a comprehensive connectivity platform and data‑logging tool for Aprilia’s high‑performance models. While not essential for everyday riding, it can be advantageous for those interested in performance analysis or GPS-based corner-by-corner electronics tuning, including traction control, wheelie control, and engine braking parameters, customizable via the MIA app for specific racetracks.\n","date":"October 21, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-mia-module/","section":"Blog","summary":"The Aprilia Tuono V4 Factory 1100 offers smartphone connectivity through an optional accessory known as the Aprilia MIA multimedia platform. The latest version of this module, part number 2S002475, features updated hardware with built‑in memory capable of storing data from track sessions without requiring a connected smartphone. When paired with the additional GPS sensor (part number 2S002389), the module can record complete lap timing data independently.\n","title":"Aprilia MIA Module on the Tuono V4 Factory: Practical Test and Real-World Impressions","type":"blog"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/aprilia-multimedia-system/","section":"Tags","summary":"","title":"Aprilia Multimedia System","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/aprilia-smartphone-integration/","section":"Tags","summary":"","title":"Aprilia Smartphone Integration","type":"tags"},{"content":"","date":"October 21, 2025","externalUrl":null,"permalink":"/tags/track-data-logging/","section":"Tags","summary":"","title":"Track Data Logging","type":"tags"},{"content":"","date":"October 20, 2025","externalUrl":null,"permalink":"/tags/2wheels-company/","section":"Tags","summary":"","title":"2Wheels-Company","type":"tags"},{"content":"","date":"October 20, 2025","externalUrl":null,"permalink":"/tags/motorcycle-protection/","section":"Tags","summary":"","title":"Motorcycle Protection","type":"tags"},{"content":"","date":"October 20, 2025","externalUrl":null,"permalink":"/tags/oil-cooler-guard/","section":"Tags","summary":"","title":"Oil Cooler Guard","type":"tags"},{"content":"The next protection I wanted to install on my Aprilia Tuono V4 Factory 1100 was a guard for the coolant and oil radiators. It often happens that small stones appear on the road and get thrown by the front wheel toward one of the radiators, potentially causing damage. In most cases, the radiator remains intact, perhaps losing a fraction of its cooling efficiency due to bent fins, but occasionally, a stone can pierce the radiator and end a trip abruptly. I wanted this protection to be made of aluminum, and after some research, I found a wide selection on the market including inexpensive options on AliExpress and well known brands like Evotech Performance . However, I discovered that the German company 2Wheels-Company offers a very similar product at a competitive price, with the added advantage of a free return option in case it didn’t fit or meet expectations.\nUnfortunately, I don’t have any photos from the installation process, I may have deleted them by accident or never taken them, but I remember that the installation was fairly complex and took several hours. This isn’t specific to this particular product; the procedure is generally complicated on this motorcycle. The reason is that both side fairings need to be removed, and to do that, the front aerodynamic spoiler also has to come off. The radiators must be completely exposed to attach the upper guard clips to the top radiator. I had to slightly narrow those clips and widen their holes to make them fit properly. I’m not entirely sure if this was due to minor design differences between the Tuono MY2025 and previous model years or simply due to manufacturing tolerances, but these adjustments were necessary for a precise and clean installation.\nInstalling the oil radiator guard was much simpler thanks to easier access. The final result looks neat and cohesive, so despite the minor fitting adjustments, I would still consider this product a good choice. The most time consuming part was disassembling and reassembling the plastic fairings. I’m also planning to install the OEM belly pan soon, although I’m not yet sure if it will fit over the lower guard or if I’ll need to modify or remove it. That will be a topic for one of the next articles.\n","date":"October 20, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-2wheels-company-radiator-guard/","section":"Blog","summary":"The next protection I wanted to install on my Aprilia Tuono V4 Factory 1100 was a guard for the coolant and oil radiators. It often happens that small stones appear on the road and get thrown by the front wheel toward one of the radiators, potentially causing damage. In most cases, the radiator remains intact, perhaps losing a fraction of its cooling efficiency due to bent fins, but occasionally, a stone can pierce the radiator and end a trip abruptly. I wanted this protection to be made of aluminum, and after some research, I found a wide selection on the market including inexpensive options on AliExpress and well known brands like Evotech Performance . However, I discovered that the German company 2Wheels-Company offers a very similar product at a competitive price, with the added advantage of a free return option in case it didn’t fit or meet expectations.\n","title":"Radiator and Oil Cooler Protection for Aprilia Tuono V4 Factory 1100 – Installation Experience and Fitment Notes","type":"blog"},{"content":"","date":"October 20, 2025","externalUrl":null,"permalink":"/tags/radiator-guard/","section":"Tags","summary":"","title":"Radiator Guard","type":"tags"},{"content":"","date":"October 20, 2025","externalUrl":null,"permalink":"/tags/radiator-protection/","section":"Tags","summary":"","title":"Radiator Protection","type":"tags"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/front-and-rear-fork-protection/","section":"Tags","summary":"","title":"Front and Rear Fork Protection","type":"tags"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/lightech-wheel-axle-sliders/","section":"Tags","summary":"","title":"LighTech Wheel Axle Sliders","type":"tags"},{"content":"After installing the frame sliders, it was time to choose some protection for the wheel axles, specifically for the front and rear forks of the motorcycle. I considered options from GSG, R\u0026amp;G, and several other manufacturers, but eventually decided on the LighTech wheel axle sliders . From the photos, they didn’t look particularly robust, yet I opted for them primarily for aesthetic reasons. Some protection is still better than none, so I was ready for that compromise.\nThese wheel axle sliders come in black, like most others, but they feature colored rings in the center that can be matched to the motorcycle’s color scheme. Available options include black, gold, red, and grey. I chose red, which suited my Thunder best. Each of the four sliders uses a different mounting adapter, and the manual specifies a tightening torque of 6 Nm.\nIf that value hadn’t been stated, I would have tightened them by feel. However, since the manufacturer clearly listed the torque specification, I decided to use a torque wrench. Three of the sliders were tightened without issue, but the fourth, the front right one, slipped during installation. Later I discovered that it was the only one without any firm support from its adapter, meaning the plastic alone provided resistance during tightening, and it eventually gave up.\nI contacted the manufacturer, explained the situation, and they promptly sent me a replacement slider without any hassle. It’s worth noting this detail if you decide on this product, but the after-sales support from LighTech was efficient and professional.\nAs mentioned earlier, the LighTech wheel axle sliders don’t appear particularly sturdy, but in my view, they are among the most visually appealing. If you ride your motorcycle on track days, you might prefer axle sliders with a rod passing through the entire wheel axle, a considerably more robust solution. In my case, however, aesthetics were the priority, so for now, these sliders stay on the bike.\n","date":"October 19, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-lightech-wheel-axle-sliders/","section":"Blog","summary":"After installing the frame sliders, it was time to choose some protection for the wheel axles, specifically for the front and rear forks of the motorcycle. I considered options from GSG, R\u0026G, and several other manufacturers, but eventually decided on the LighTech wheel axle sliders . From the photos, they didn’t look particularly robust, yet I opted for them primarily for aesthetic reasons. Some protection is still better than none, so I was ready for that compromise.\n","title":"LighTech Wheel Axle Sliders for Aprilia Tuono V4 Factory 1100: Aesthetic Choice with Practical Considerations","type":"blog"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/motorcycle-accessories/","section":"Tags","summary":"","title":"Motorcycle Accessories","type":"tags"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/motorcycle-axle-protection/","section":"Tags","summary":"","title":"Motorcycle Axle Protection","type":"tags"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/motorcycle-crash-protection/","section":"Tags","summary":"","title":"Motorcycle Crash Protection","type":"tags"},{"content":"","date":"October 19, 2025","externalUrl":null,"permalink":"/tags/wheel-axle-sliders-review/","section":"Tags","summary":"","title":"Wheel Axle Sliders Review","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/crash-pads/","section":"Tags","summary":"","title":"Crash Pads","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/ducati-streetfighter-v4-s/","section":"Tags","summary":"","title":"Ducati Streetfighter V4 S","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/frame-sliders/","section":"Tags","summary":"","title":"Frame Sliders","type":"tags"},{"content":"After a little more than a year, I began seriously considering selling my Triumph Rocket 3 Storm R. Many will wonder why, since it’s a true motorcycle icon, but the simple answer is, it just wasn’t the right bike for me.\nI rode it in a rather sporty way, and while it can handle that despite being a cruiser at heart, it’s ultimately too heavy and its geometry isn’t made for aggressive cornering or fast transitions.\nThat led me to look for something lighter, and my first choice was the Triumph Speed Triple 1200 RS. I was immediately impressed. Its electronics are excellent, and the engine is extremely capable. Right then I realized the Rocket 3 had to go, and a naked bike would be its replacement.\nEncouraged by my son, and partly out of curiosity, I decided to try the Aprilia Tuono V4 Factory 1100. The excitement only grew. The performance was close to the Speed Triple, but the sound made all the difference.\nThe 1100 cc V4 engine with a 65° angle sounds incredible, probably the best motorcycle sound I’ve ever heard.\nLast year I also tested the Ducati Multistrada V4 S, but its sound wasn’t nearly as striking, likely because its cylinder angle is 90°.\nI also considered trying the Ducati Streetfighter V4 S, but the rainy period started, and the local dealer wasn’t particularly cooperative, so I ended up buying the Tuono instead.\nI won’t keep praising it, just try it for yourself; you might not like it as much. For now, I’m very satisfied, and my garage will keep two bikes: the Kawasaki H2 SX SE MY2023 and the Aprilia Tuono V4 Factory 1100 MY2025.\nThe Aprilia serves for daily rides and shorter solo trips with a distinctly sporty style, while the Kawasaki is my choice for longer journeys and two-up touring.\nNow, this article is primarily about Top Block Racing frame sliders. If you’ve been following my blog, you’ve probably noticed that I’m a fan of this brand, so I was pleased to see they offer a model for my new bike.\nThey looked quite solid in the photos, so I decided to order them. Another option was Evotech Italy frame sliders, but they appeared less robust. They’re probably lighter than the TBR sliders, which I later found out weigh almost 1 kg each, but I decided that durability matters more and I can always lose 2 kg myself to make up for it.\nThe sliders arrived well packaged, they have rubber dampers for impact absorption, and installation was straightforward. I won’t go into mounting details, just follow the instructions and you’ll be fine. I tightened the engine mount bolts to 50 Nm based on data from a service manual for an older model, but don’t rely solely on that, check your own sources.\nIn conclusion, I’m satisfied with the purchase. They fit the Tuono nicely, blend well with the bike’s design, and yes, they’re heavy, but as always, a compromise has to be made somewhere.\n","date":"October 18, 2025","externalUrl":null,"permalink":"/blog/aprilia-tuono-v4-tbr-frame-sliders/","section":"Blog","summary":"After a little more than a year, I began seriously considering selling my Triumph Rocket 3 Storm R. Many will wonder why, since it’s a true motorcycle icon, but the simple answer is, it just wasn’t the right bike for me.\n","title":"From Triumph Rocket 3 to Aprilia Tuono V4 Factory: Choosing the Right Bike and Installing Top Block Racing Frame Sliders","type":"blog"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/naked-bike/","section":"Tags","summary":"","title":"Naked Bike","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/tbr/","section":"Tags","summary":"","title":"Tbr","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/top-block-racing/","section":"Tags","summary":"","title":"Top Block Racing","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/triumph-rocket-3/","section":"Tags","summary":"","title":"Triumph Rocket 3","type":"tags"},{"content":"","date":"October 18, 2025","externalUrl":null,"permalink":"/tags/triumph-speed-triple-1200-rs/","section":"Tags","summary":"","title":"Triumph Speed Triple 1200 RS","type":"tags"},{"content":"","date":"October 17, 2025","externalUrl":null,"permalink":"/tags/motorcycle-tank-bag/","section":"Tags","summary":"","title":"Motorcycle Tank Bag","type":"tags"},{"content":"","date":"October 17, 2025","externalUrl":null,"permalink":"/tags/motorcycle-travel/","section":"Tags","summary":"","title":"Motorcycle Travel","type":"tags"},{"content":"","date":"October 17, 2025","externalUrl":null,"permalink":"/tags/sw-motech-pro-city/","section":"Tags","summary":"","title":"SW-Motech Pro City","type":"tags"},{"content":"The largest tank bag from the SW-Motech Pro collection that fits well on the Kawasaki H2 SX SE is the SW-Motech Pro City. Other bags are either too large, blocking the navigation screen, or don’t match the tank shape properly, sometimes even interfering when turning the handlebars to full lock. As visible in the photos, this bag sits quite well on the bike. The navigation display (in my case, a Chigee AIO-6) is only slightly obscured, and when leaning forward, you might occasionally touch the bag’s edge with your chest. but such compromises are often necessary and acceptable here.\n","date":"October 17, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-sw-motech-pro-city-tank-bag/","section":"Blog","summary":"The largest tank bag from the SW-Motech Pro collection that fits well on the Kawasaki H2 SX SE is the SW-Motech Pro City. Other bags are either too large, blocking the navigation screen, or don’t match the tank shape properly, sometimes even interfering when turning the handlebars to full lock. As visible in the photos, this bag sits quite well on the bike. The navigation display (in my case, a Chigee AIO-6) is only slightly obscured, and when leaning forward, you might occasionally touch the bag’s edge with your chest. but such compromises are often necessary and acceptable here.\n","title":"SW-Motech Pro City Tank Bag on Kawasaki H2 SX SE","type":"blog"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/bridgestone-battlax-hypersport-s23/","section":"Tags","summary":"","title":"Bridgestone Battlax Hypersport S23","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/eazyrizer-big-blue/","section":"Tags","summary":"","title":"EazyRizer Big Blue","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/kern-stabi-spindle-stand-x4/","section":"Tags","summary":"","title":"Kern-Stabi Spindle Stand X4","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/metzeler-cruisetec/","section":"Tags","summary":"","title":"Metzeler Cruisetec","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/motorcycle-lift-review/","section":"Tags","summary":"","title":"Motorcycle Lift Review","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/motorcycle-tire-change/","section":"Tags","summary":"","title":"Motorcycle Tire Change","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/motorcycle-tire-replacement/","section":"Tags","summary":"","title":"Motorcycle Tire Replacement","type":"tags"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/s23/","section":"Tags","summary":"","title":"S23","type":"tags"},{"content":"Although I own two motorcycles, by the end of May this year the tires on both were worn out and needed replacement. As I mentioned before, for lifting the Triumph Rocket 3 Storm R I had previously acquired the EazyRizer Big Blue lift, while for the Kawasaki H2 SX SE the Kern-Stabi Spindle Stand X4 2049 front stand was sufficient. I won’t go into the procedure itself, you can find plenty of detailed videos on YouTube and other websites, but I wanted to share a few photos showing how the process looked in my case. The conclusion is straightforward: both lifts performed their intended functions effectively, allowing me to remove the wheels without much effort, take them to a tire shop for replacement and balancing, and then reinstall them on the motorcycles.\nFor those interested, I fitted Metzeler Cruisetec tires on the Triumph Rocket 3 Storm R, and Bridgestone Battlax Hypersport S23 tires on the Kawasaki H2 SX SE. I am satisfied with both tire choices, particularly with the performance of the S23s.\n","date":"October 16, 2025","externalUrl":null,"permalink":"/blog/tire-change-2025/","section":"Blog","summary":"Although I own two motorcycles, by the end of May this year the tires on both were worn out and needed replacement. As I mentioned before, for lifting the Triumph Rocket 3 Storm R I had previously acquired the EazyRizer Big Blue lift, while for the Kawasaki H2 SX SE the Kern-Stabi Spindle Stand X4 2049 front stand was sufficient. I won’t go into the procedure itself, you can find plenty of detailed videos on YouTube and other websites, but I wanted to share a few photos showing how the process looked in my case. The conclusion is straightforward: both lifts performed their intended functions effectively, allowing me to remove the wheels without much effort, take them to a tire shop for replacement and balancing, and then reinstall them on the motorcycles.\n","title":"Tire Replacement on Triumph Rocket 3 Storm R and Kawasaki H2 SX SE: Practical Experience with EazyRizer and Kern-Stabi Stands","type":"blog"},{"content":"","date":"October 16, 2025","externalUrl":null,"permalink":"/tags/triumph-rocket-3-storm-r/","section":"Tags","summary":"","title":"Triumph Rocket 3 Storm R","type":"tags"},{"content":"","date":"October 15, 2025","externalUrl":null,"permalink":"/tags/fork-stem-mount/","section":"Tags","summary":"","title":"Fork Stem Mount","type":"tags"},{"content":"","date":"October 15, 2025","externalUrl":null,"permalink":"/tags/handlebar-clamp-bolt-mount/","section":"Tags","summary":"","title":"Handlebar Clamp Bolt Mount","type":"tags"},{"content":"","date":"October 15, 2025","externalUrl":null,"permalink":"/tags/quad-lock/","section":"Tags","summary":"","title":"Quad Lock","type":"tags"},{"content":"Quad Lock is well known among riders for secure and practical smartphone mounting systems. I recently had the chance to examine two of their PRO models — the Fork Stem Mount PRO and the Handlebar Clamp Bolt Mount PRO. Both feature metal construction, clean design, and the same dual-stage locking system found across the Quad Lock range.\nThe Fork Stem Mount PRO is designed for sport and touring bikes with a hollow steering stem. It fits neatly into the tube and allows easy adjustment of viewing angle and height with the included Allen key. The result is a solid, central position for the phone, ideal for navigation without cluttering the cockpit.\nThe Handlebar Clamp Bolt Mount PRO, meanwhile, replaces one of the M8 bolts on the handlebar clamp. It offers a 135° pivot for angle adjustment and uses anti-rotation serrations to stay fixed under vibration. It’s a discreet, integrated-looking solution that suits naked and roadster motorcycles well.\nBoth mounts are robust, quick to use, and compatible with all Quad Lock cases and adapters. While this isn’t a long-term test, the first impression is that these PRO versions deliver practical, durable solutions for riders who value stability and clean design.\n","date":"October 15, 2025","externalUrl":null,"permalink":"/blog/quad-lock-pro-mounts/","section":"Blog","summary":"Quad Lock is well known among riders for secure and practical smartphone mounting systems. I recently had the chance to examine two of their PRO models — the Fork Stem Mount PRO and the Handlebar Clamp Bolt Mount PRO. Both feature metal construction, clean design, and the same dual-stage locking system found across the Quad Lock range.\n","title":"Quad Lock Mounts for Motorcycles: Fork Stem and Handlebar Clamp Bolt PRO Review","type":"blog"},{"content":"","date":"October 15, 2025","externalUrl":null,"permalink":"/tags/smartphone-mount-for-motorcycles/","section":"Tags","summary":"","title":"Smartphone Mount for Motorcycles","type":"tags"},{"content":"","date":"October 13, 2025","externalUrl":null,"permalink":"/tags/motorcycle-navigation/","section":"Tags","summary":"","title":"Motorcycle Navigation","type":"tags"},{"content":"","date":"October 13, 2025","externalUrl":null,"permalink":"/tags/motorcycle-phone-holder/","section":"Tags","summary":"","title":"Motorcycle Phone Holder","type":"tags"},{"content":"","date":"October 13, 2025","externalUrl":null,"permalink":"/tags/motorcycle-phone-mount/","section":"Tags","summary":"","title":"Motorcycle Phone Mount","type":"tags"},{"content":"","date":"October 13, 2025","externalUrl":null,"permalink":"/tags/quad-lock-brake/clutch-mount/","section":"Tags","summary":"","title":"Quad Lock Brake/Clutch Mount","type":"tags"},{"content":"Since I had already bought a Quad Lock case for my smartphone, it was only natural to equip my Kawasaki H2 SX SE with a proper mount from the same brand. My fork stem had previously hosted a Garmin zūmo XT2 mount, which I planned to replace with a Chigee AIO-6 unit, so I needed a Quad Lock mount for some other position on the bike. After some research and consideration, I went with the Brake/Clutch Mount, a compact and sturdy system that attaches directly to the brake or clutch lever clamp. On my bike, I mounted it to the brake side, where it offers a pretty clear view of the screen without interfering with handlebar movement.\nI later swapped the blue lever for a black one to better match the bike’s deep green color, a small but important aesthetic detail for those of us who care about design harmony. This mount serves as my backup navigation solution, in case my main GPS system ever fails, something that once happened to me during a trip through France. Ever since, I make sure to have two navigation options available. The Quad Lock system isn’t quite as effortless to clip in as the promotional videos suggest, but once your phone is locked in place, it stays there rock solid, no matter the road conditions.\nOverall, the Quad Lock Brake/Clutch Mount delivers what it promises: a reliable, well-engineered solution for securely holding your phone on a motorcycle. While brands like SP Connect and Peak Design offer interesting alternatives, with the latter featuring a magnetic mounting system that looks particularly promising, I haven’t personally tested either of them yet, so I can’t give a fair comparison.\n","date":"October 13, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-quad-lock/","section":"Blog","summary":"Since I had already bought a Quad Lock case for my smartphone, it was only natural to equip my Kawasaki H2 SX SE with a proper mount from the same brand. My fork stem had previously hosted a Garmin zūmo XT2 mount, which I planned to replace with a Chigee AIO-6 unit, so I needed a Quad Lock mount for some other position on the bike. After some research and consideration, I went with the Brake/Clutch Mount, a compact and sturdy system that attaches directly to the brake or clutch lever clamp. On my bike, I mounted it to the brake side, where it offers a pretty clear view of the screen without interfering with handlebar movement.\n","title":"Quad Lock Brake/Clutch Mount on Kawasaki H2 SX – A Practical Phone Mounting Solution","type":"blog"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/front-wheel-stand/","section":"Tags","summary":"","title":"Front Wheel Stand","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/kern-stabi/","section":"Tags","summary":"","title":"Kern-Stabi","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/maintenance/","section":"Tags","summary":"","title":"Maintenance","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/motorcycle-lift/","section":"Tags","summary":"","title":"Motorcycle Lift","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/motorcycle-stand/","section":"Tags","summary":"","title":"Motorcycle Stand","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/motorcycle-workshop-tools/","section":"Tags","summary":"","title":"Motorcycle Workshop Tools","type":"tags"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/spindle-stand-x4-2049/","section":"Tags","summary":"","title":"Spindle Stand X4 2049","type":"tags"},{"content":"For riders in regions with long winters, like Munich, parking the bike for months is inevitable. Some might simply cover it and forget it, but for those of us who treat our motorcycles like mechanical art, that’s never enough. I prefer to lift my bike off the ground entirely, relieving both the suspension and the tires from constant pressure. Call it meticulous—because it is—but it’s the kind of care that pays off when spring comes.\nDuring my last winter prep, my Kawasaki H2 SX SE, with its built-in center stand, made the rear easy to raise. The front wheel, however, still rested on the cold concrete. Leaving tires under static load for months can cause subtle flat spots, and the suspension, too, benefits from being at rest. These are small details, sure—but for those of us who enjoy fine-tuning every element of motorcycle care, they matter.\nThere are plenty of front stands on the market, but not all are built equal. I heard from my son that one of his friends had found a seriously good stand. After tracking down the model, I immediately understood what made it different. Unlike typical lever-action stands, this one uses a threaded spindle to lift the bike smoothly and with precision, no brute force required.\nManufactured in Germany, Kern-Stabi has a reputation for precision engineering and rock-solid workshop gear. The Spindelständer X4 2049 is one of their flagship innovations, a screw-jack-based stand designed for long-term stability and mechanical reliability. Once the motorcycle is elevated, it can remain suspended for months without losing pressure or tilting, a perfect feature for winter storage.\nThe stand operates from one side of the bike, leaving the rest completely free for maintenance work, whether you’re removing the front wheel, cleaning fork legs, or detailing the underbody. Its high load capacity and robust steel construction mean it’s equally suitable for light sportbikes and heavier tourers. The precision spindle allows gradual, controlled lifting that feels reassuringly solid.\nThe lifting process can be performed with a hand tool or, for frequent users, a power drill, making it effortless even for heavier machines. The motion is linear, quiet, and smooth, with no sudden jerks or shifts. It’s this mechanical serenity that sets the Kern-Stabi apart from most fold-up stands on the market.\nWhile it shines during off-season storage, the Spindle Stand X4 2049 is just as useful year-round. Tire changes, fork maintenance, brake work, this stand turns your garage into a miniature workshop. Its compact footprint also makes it ideal for limited spaces, where stability and access are both essential.\nIf you take your motorcycle maintenance seriously or simply want to protect your machine during the cold months, the Kern-Stabi Spindelständer X4 2049 is one of the most thoughtfully designed tools you can own. It’s not just a stand, it’s a precision lifting system born from German engineering excellence. Highly recommended to all true moto enthusiasts.\n","date":"October 12, 2025","externalUrl":null,"permalink":"/blog/kern-stabi-spindle-stand-x4-2049/","section":"Blog","summary":"For riders in regions with long winters, like Munich, parking the bike for months is inevitable. Some might simply cover it and forget it, but for those of us who treat our motorcycles like mechanical art, that’s never enough. I prefer to lift my bike off the ground entirely, relieving both the suspension and the tires from constant pressure. Call it meticulous—because it is—but it’s the kind of care that pays off when spring comes.\n","title":"The Kern-Stabi Spindle Stand X4 2049 – A German Masterpiece for Motorcycle Care","type":"blog"},{"content":"","date":"October 12, 2025","externalUrl":null,"permalink":"/tags/winter-motorcycle-storage/","section":"Tags","summary":"","title":"Winter Motorcycle Storage","type":"tags"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/big-blue-lift/","section":"Tags","summary":"","title":"Big Blue Lift","type":"tags"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/eazy-rizer/","section":"Tags","summary":"","title":"Eazy Rizer","type":"tags"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/eazyrizer/","section":"Tags","summary":"","title":"Eazyrizer","type":"tags"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/england/","section":"Tags","summary":"","title":"England","type":"tags"},{"content":"Winters in Munich can feel endless, especially for those of us who live and breathe motorcycles. When the roads turn icy and the bikes go into hibernation, I like to give my machines the best possible rest. That means keeping the suspension relaxed and the tires off the ground to prevent flat spots. It might sound overly meticulous, but if you can do something to extend your bike’s lifespan—why not?\nLast winter, I faced a particular challenge: lifting a Triumph Rocket 3, a motorcycle that redefines the word heavy. I needed a lift that could handle serious weight with absolute stability. After some thorough research, I landed on the EazyRizer Big Blue Motorcycle Lift from Quasar Products Ltd.—a piece of British engineering that’s become something of a benchmark among home mechanics.\nI ordered the dedicated adapter kit for the Rocket 3, along with adapters for sport and superbikes, ensuring flexibility for future bikes. That turned out to be a smart move—since I’ve since sold the Rocket, but the lift remains an indispensable part of my garage setup.\nWhat sets the EazyRizer Big Blue apart is its robust all-steel construction and purely mechanical operation. There’s no hydraulic fluid to leak, no air to lose—just a solid, reliable lifting mechanism that locks firmly into place. It can safely suspend even the heaviest motorcycles for months on end without any hint of instability. Despite its strength, it’s surprisingly easy to move around, and its compact footprint means I can lift a bike right next to my parked car without feeling cramped or unsafe.\nIn short: the EazyRizer Big Blue is a professional-grade lift for serious riders and tinkerers alike. It’s built to last a lifetime, inspires total confidence, and makes winter storage—or any major maintenance job—a pleasure rather than a hassle.\nMy only real headache was dealing with customs during import, but that’s hardly a strike against the product itself. In fact, Quasar’s customer support was excellent—responsive, helpful, and clearly passionate about what they build.\nIf you’re looking for a heavy-duty, long-term lifting solution, especially for large bikes, look no further. The EazyRizer Big Blue is a tool you’ll buy once and use for decades.\n","date":"October 11, 2025","externalUrl":null,"permalink":"/blog/eazy-rizer-big-blue-lift/","section":"Blog","summary":"Winters in Munich can feel endless, especially for those of us who live and breathe motorcycles. When the roads turn icy and the bikes go into hibernation, I like to give my machines the best possible rest. That means keeping the suspension relaxed and the tires off the ground to prevent flat spots. It might sound overly meticulous, but if you can do something to extend your bike’s lifespan—why not?\n","title":"Lifting the Beast: My Experience with the EazyRizer Big Blue Motorcycle Lift","type":"blog"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/quasar-products/","section":"Tags","summary":"","title":"Quasar Products","type":"tags"},{"content":"","date":"October 11, 2025","externalUrl":null,"permalink":"/tags/wales/","section":"Tags","summary":"","title":"Wales","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/cruiser/","section":"Tags","summary":"","title":"Cruiser","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/handlebar-mount-pro/","section":"Tags","summary":"","title":"Handlebar Mount Pro","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/iphone/","section":"Tags","summary":"","title":"Iphone","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/lock/","section":"Tags","summary":"","title":"Lock","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/motorcycle/","section":"Tags","summary":"","title":"Motorcycle","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/quad/","section":"Tags","summary":"","title":"Quad","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/rocket-3/","section":"Tags","summary":"","title":"Rocket 3","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/storm/","section":"Tags","summary":"","title":"Storm","type":"tags"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/triumph/","section":"Tags","summary":"","title":"Triumph","type":"tags"},{"content":"I’ve already sold my Triumph Rocket 3 Storm R and moved on to a new bike, but I still wanted to show how the Quad Lock phone mount sits on this machine. From experience, it can be tricky to find real-world pictures of how certain products fit specific motorcycles, so I like to share that insight whenever I can. Installing the Quad Lock Handlebar Mount Pro with vibration dampener is straightforward on any bike with standard handlebars, and it looks sharp on the Rocket 3. The phone remains impressively stable, making this a mount I’d confidently recommend to any rider.\nQuad Lock is a Melbourne-based company, founded in 2012, that quickly made its mark by introducing a patented dual-stage locking system for smartphones—secure yet easy to attach and detach with one hand. Their range of mounts spans activities like cycling, driving, running, and notably motorcycling, and today their products are available in over 100 countries globally.\nFor motorcyclists specifically, Quad Lock offers a variety of durable mounts—from sturdy glass-filled nylon models with a blue lever to premium machined aluminum Pro versions with a black lever—designed to fit a wide range of handlebar diameters and configurations. Optional accessories like a vibration dampener mitigate high-frequency vibrations that can damage smartphone camera stabilization, and there’s even a weatherproof wireless charging head for on-the-go charging.\n","date":"September 3, 2025","externalUrl":null,"permalink":"/blog/triumph-rocket-3-quad-lock/","section":"Blog","summary":"I’ve already sold my Triumph Rocket 3 Storm R and moved on to a new bike, but I still wanted to show how the Quad Lock phone mount sits on this machine. From experience, it can be tricky to find real-world pictures of how certain products fit specific motorcycles, so I like to share that insight whenever I can. Installing the Quad Lock Handlebar Mount Pro with vibration dampener is straightforward on any bike with standard handlebars, and it looks sharp on the Rocket 3. The phone remains impressively stable, making this a mount I’d confidently recommend to any rider.\n","title":"Triumph Rocket 3 - Quad Lock Handlebar Mount Pro","type":"blog"},{"content":"","date":"September 3, 2025","externalUrl":null,"permalink":"/tags/vibration-dampener/","section":"Tags","summary":"","title":"Vibration Dampener","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/back-protector/","section":"Tags","summary":"","title":"Back Protector","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/comparison/","section":"Tags","summary":"","title":"Comparison","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/d3o/","section":"Tags","summary":"","title":"D3o","type":"tags"},{"content":"I’ve previously covered Held Exosafe by D3O Back Protector along with several other Held D3O protectors. Recently, I had the opportunity to handle the Richa D3O Viper Stealth back protectors as well, and I wanted to share my observations. My intention wasn’t to conduct a direct comparison—originally, I was looking for a back protector with a different shape for a jacket I ultimately didn’t purchase—but given the limited visual references available, it seemed useful to present this side-by-side perspective. Before diving into the details, a few words about D3O.\nD3O is a protective material developed by D3O Labs, a British company specializing in impact protection technologies. It is a flexible and pliable substance that hardens upon impact. D3O is commonly used for low-profile protection in phones, laptops, and other electronic devices, as well as in motorcycle gear, defense equipment such as helmets, body armor, and footwear.\nThe Held protector I tested is size L (50 x 35 cm), while the Richa Viper Stealth comes in L (44.4 x 27.5 cm) and XL (47.7 x 31.6 cm). The difference in dimensions and shape is immediately noticeable. Ideally, a larger back protector provides more coverage, though jacket pocket size often dictates the maximum dimensions. Regardless of the choice, these protectors are exceptionally safe, flexible, and breathable, and they rank among the best options currently on the market. I can confidently recommend any of them.\nIt’s worth noting that many motorcycle jackets include only thin inserts rather than true back protection. For enhanced safety, investing in a dedicated back protector is highly advisable, and D3O remains an excellent choice in this category.\n","date":"September 2, 2025","externalUrl":null,"permalink":"/blog/d3o-back-protectors/","section":"Blog","summary":"I’ve previously covered Held Exosafe by D3O Back Protector along with several other Held D3O protectors. Recently, I had the opportunity to handle the Richa D3O Viper Stealth back protectors as well, and I wanted to share my observations. My intention wasn’t to conduct a direct comparison—originally, I was looking for a back protector with a different shape for a jacket I ultimately didn’t purchase—but given the limited visual references available, it seemed useful to present this side-by-side perspective. Before diving into the details, a few words about D3O.\n","title":"D3O Back Protectors Reviewed: Held Exosafe vs. Richa Viper Stealth","type":"blog"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/held/","section":"Tags","summary":"","title":"Held","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/richa/","section":"Tags","summary":"","title":"Richa","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/size/","section":"Tags","summary":"","title":"Size","type":"tags"},{"content":"","date":"September 2, 2025","externalUrl":null,"permalink":"/tags/visual/","section":"Tags","summary":"","title":"Visual","type":"tags"},{"content":"","date":"May 4, 2025","externalUrl":null,"permalink":"/tags/bag/","section":"Tags","summary":"","title":"Bag","type":"tags"},{"content":"","date":"May 4, 2025","externalUrl":null,"permalink":"/tags/leather/","section":"Tags","summary":"","title":"Leather","type":"tags"},{"content":"","date":"May 4, 2025","externalUrl":null,"permalink":"/tags/rear-rack/","section":"Tags","summary":"","title":"Rear Rack","type":"tags"},{"content":"Last year, while searching for a side stand enlargement for my Triumph Rocket 3 motorcycle, I discovered the Italian company XRay . To my knowledge, their side stand enlargement for this bike remains unique in the market, there is no other offer known to me. At that time I also noticed their rear rack bag , crafted from genuine leather in Italy, and now I decided to get one and explore it further.\nThe XRay rear rack bag for the Triumph Rocket 3 is meticulously handcrafted in Tuscany, utilizing premium water-resistant cow leather. The bag is expandable from a volume of 12 liters to 18 liters through a simple perimeter zipper, making it a versatile accessory. With the provided straps, it can also be transformed into a convenient, elegant, and practical backpack.\nThe dimensions of the bag are 30 x 30 x 14.5 cm, and when expanded, it measures 30 x 30 x 22 cm.\nThe bag has a practical fastening system utilizing scratch-proof nylon straps and hooks.\nIn my opinion, this stylish bag is a must-have for those seeking to stand out from mass-produced options. While I haven\u0026rsquo;t tested it in the rain, the presence of a large zipper suggests using an internal waterproof bag to safeguard the contents. The bag exudes a robust and aesthetically pleasing design and it fits well to the look of the bike.\n","date":"May 4, 2025","externalUrl":null,"permalink":"/blog/triumph-rocket-3-xray-rear-rack-bag/","section":"Blog","summary":"Last year, while searching for a side stand enlargement for my Triumph Rocket 3 motorcycle, I discovered the Italian company XRay . To my knowledge, their side stand enlargement for this bike remains unique in the market, there is no other offer known to me. At that time I also noticed their rear rack bag , crafted from genuine leather in Italy, and now I decided to get one and explore it further.\n","title":"Triumph Rocket 3 - XRay Genuine Italian Leather Rear Rack Bag","type":"blog"},{"content":"","date":"May 4, 2025","externalUrl":null,"permalink":"/tags/xray/","section":"Tags","summary":"","title":"Xray","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/garmin/","section":"Tags","summary":"","title":"Garmin","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/h2-sx/","section":"Tags","summary":"","title":"H2 Sx","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/h2-sx-se/","section":"Tags","summary":"","title":"H2 Sx Se","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/holder/","section":"Tags","summary":"","title":"Holder","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/kawasaki/","section":"Tags","summary":"","title":"Kawasaki","type":"tags"},{"content":"Mounting a navigation holder on certain motorcycles can present a challenge, particularly when dealing with models that lack traditional handlebars. Thankfully, there are versatile holders available that can be affixed to the fork stem, mirrors, screens, and various other locations. However, the real challenge lies in establishing a power supply without compromising the motorcycle\u0026rsquo;s original wiring, while ensuring the installation is both safe and tidy. My preferred method involves connecting the power supply to an existing connector that offers switched voltage. Some motorcycles, like the Kawasaki H2 SX SE, come equipped with dedicated accessory wiring. This particular model features a lighter power outlet, which I consider the optimal spot for attaching navigation power supply wires.\nAfter identifying the connector used for the power outlet, I scoured the internet for compatible male and female connectors that match those on the bike. I ordered three variants, and fortunately, two were correct. One of these had pre-attached wires, which I opted to use. I connected the male and female connectors, attached the navigation power supply wires, and ensured both contacts were soldered and properly insulated. The cable was routed to minimize visibility, protect against damage, and maintain an organized appearance. Once the left trim was reinstalled, I positioned the holder in the fork stem and verified that the navigation device automatically powered on with the motorcycle. It functioned perfectly, shutting off when the motorcycle was turned off, prompting the navigation device, like the Garmin XT2, to ask for shutdown.\nOverall, I\u0026rsquo;m delighted with this clean installation, reminiscent of the satisfaction I experienced when performing a similar setup on my Triumph Rocket 3, as detailed in a previous blog article.\n","date":"March 13, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-navigation-holder/","section":"Blog","summary":"Mounting a navigation holder on certain motorcycles can present a challenge, particularly when dealing with models that lack traditional handlebars. Thankfully, there are versatile holders available that can be affixed to the fork stem, mirrors, screens, and various other locations. However, the real challenge lies in establishing a power supply without compromising the motorcycle’s original wiring, while ensuring the installation is both safe and tidy. My preferred method involves connecting the power supply to an existing connector that offers switched voltage. Some motorcycles, like the Kawasaki H2 SX SE, come equipped with dedicated accessory wiring. This particular model features a lighter power outlet, which I consider the optimal spot for attaching navigation power supply wires.\n","title":"Kawasaki H2 SX SE - Installing Garmin zūmo XT/XT2 holder","type":"blog"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/xt/","section":"Tags","summary":"","title":"Xt","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/xt2/","section":"Tags","summary":"","title":"Xt2","type":"tags"},{"content":"","date":"March 13, 2025","externalUrl":null,"permalink":"/tags/zumo/","section":"Tags","summary":"","title":"Zumo","type":"tags"},{"content":"Finding the perfect pair of motorcycle boots can be a daunting task for many riders, but for some, like myself, it can feel nearly impossible. My journey in search of the ideal fit led me to discover that only two models, the Daytona AC Dry GTX G2 and Alpinestars New Land, could accommodate my unique foot shape. The former features shoelaces, while the latter employs velcro, allowing them to stretch sufficiently to fit my feet, which have a large over-ankle and calf circumference.\nWhen I decided to venture into the realm of sport boots, my search proved challenging. Despite scouring the Internet for suitable models, attempts with Alpinestars Supertech R boots, Alpinestars SMX Plus V2 and several others were unsuccessful due to their narrow fit. Only one model from Vanucci was wearable, but it lacked the necessary circumference to accommodate leather pants tucked inside.\nDetermined to find a solution, I explored the possibility of custom-tailored boots and reached out to Daytona. Their headquarters in Bavaria, conveniently located near my home in Munich, offered a promising opportunity. Daytona\u0026rsquo;s meticulous craftsmanship involves approximately 80 work steps and 120 individual parts, enabling them to create bespoke motorcycle boots. After trying the Evo Voltex GTX and Evo Sports GTX models, it became clear that the Evo Sports GTX was the only option capable of extending up to 10 cm in circumference.\nWhile the Evo Voltex GTX could be modified, it was limited to a few centimeters, whereas my requirements ranged from 2.5 cm at the bottom to 10.5 cm at the top of the boot neck. The owner of Daytona graciously took precise measurements of my feet, and we agreed on a price and delivery date. Although custom boots come at a premium, they offer a tailored fit that, in my case, was the only viable option. Additionally, I had the opportunity to customize the appearance of the Evo Sports GTX, selecting a color combination that complemented my leather suit and personal style.\nI plan to write a follow-up article once I receive the boots, providing a comprehensive review to help fellow riders determine if this investment is worthwhile.\n","date":"March 12, 2025","externalUrl":null,"permalink":"/blog/daytona-made-to-measure-boots-1/","section":"Blog","summary":"Finding the perfect pair of motorcycle boots can be a daunting task for many riders, but for some, like myself, it can feel nearly impossible. My journey in search of the ideal fit led me to discover that only two models, the Daytona AC Dry GTX G2 and Alpinestars New Land, could accommodate my unique foot shape. The former features shoelaces, while the latter employs velcro, allowing them to stretch sufficiently to fit my feet, which have a large over-ankle and calf circumference.\n","title":"Custom Daytona Motorcycle Boots - Ordering - Part 1/2","type":"blog"},{"content":"","date":"March 12, 2025","externalUrl":null,"permalink":"/tags/ordering/","section":"Tags","summary":"","title":"Ordering","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/anti-slip/","section":"Tags","summary":"","title":"Anti-Slip","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/cover/","section":"Tags","summary":"","title":"Cover","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/dark/","section":"Tags","summary":"","title":"Dark","type":"tags"},{"content":"The Kawasaki H2 SX SE is a motorcycle that embodies the perfect blend of sportiness and functionality, and the Z-Racing Screen by Puig is an accessory that enhances this balance. Designed specifically for this motorcycle, the Z-Racing Screen not only improves the aerodynamic coefficient but also significantly increases rider protection. This screen is crafted to provide your motorcycle with the sport character you have always desired, offering a sleek design that complements the aggressive aesthetics of the bike.\nThe Z-Racing Screen is meticulously engineered using advanced technologies in Puig\u0026rsquo;s facilities near the Barcelona-Catalunya race track. Made from 3mm thick high-impact acrylic, it offers great resistance and lightness, ensuring durability and clear visibility. The screen\u0026rsquo;s double height design and side ribs effectively channel and divert air, reducing pressure on the rider\u0026rsquo;s helmet and upper torso. This results in a 20% improvement in comfort and reduced fatigue during rides, as the screen supports 0.8kg less pressure compared to the original screen.\nAerodynamic efficiency is a key feature of the Z-Racing Screen, which has been exhaustively tested in a virtual wind tunnel. It boasts a 12.7% average increase in aerodynamic protection and an impressive 61% enhancement in the racing position compared to the stock model. This makes it an ideal choice for riders seeking both performance and comfort. Additionally, the screen is available in a variety of colors, allowing for personalization to match your style. Installation is straightforward, requiring no additional parts, and each screen comes with an in-depth aerodynamic study to highlight the improvements in performance and rider protection.\nIn summary, the Z-Racing Screen for the Kawasaki H2 SX SE is a testament to precision engineering and thoughtful design. It enhances the motorcycle\u0026rsquo;s sport aesthetics while providing superior aerodynamic protection and comfort for the rider. With its easy installation and customization options, it is a valuable upgrade for any Kawasaki H2 SX SE owner looking to elevate their riding experience.\n","date":"March 11, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-puig-z-racing-screen/","section":"Blog","summary":"The Kawasaki H2 SX SE is a motorcycle that embodies the perfect blend of sportiness and functionality, and the Z-Racing Screen by Puig is an accessory that enhances this balance. Designed specifically for this motorcycle, the Z-Racing Screen not only improves the aerodynamic coefficient but also significantly increases rider protection. This screen is crafted to provide your motorcycle with the sport character you have always desired, offering a sleek design that complements the aggressive aesthetics of the bike.\n","title":"Kawasaki H2 SX SE - Puig Z-Racing Screen (Dark Smoke)","type":"blog"},{"content":"The SW-Motech PRO Roadpack motorcycle tail bag is a versatile and compact accessory designed to enhance the functionality of small and sporty motorcycles like the Kawasaki H2 SX SE. With an expandable volume ranging from 8 to 14 liters, this tail bag offers ample storage space for essentials such as keys, wallets, and other small items. The bag\u0026rsquo;s design includes stiffened sides and a molded EVA lid, ensuring it maintains its shape even during sporty rides. The PRO Roadpack is crafted from durable 1680 D Ballistic Nylon, originally developed for military use, providing high-quality workmanship and thoughtful features like reflective attachments for better visibility.\nOne of the standout features of the PRO Roadpack is its flexible attachment system. It includes lashing hooks that allow for quick and secure fastening to the motorcycle\u0026rsquo;s seat or rack. The straps can be hooked and tensioned in one step, and the excess strap length can be secured with a Velcro fastener, making it adaptable for use on different motorcycles. This ease of attachment and removal makes the PRO Roadpack a convenient choice for riders who frequently switch between bikes or need to adjust strap lengths.\nThe PRO Roadpack also boasts additional features that cater to the needs of modern motorcyclists. It includes a MOLLE attachment on the top for accessory bags, enhancing its storage capabilities. The bag\u0026rsquo;s underside is made of anti-slip material, ensuring stability during rides. For weather protection, the PRO Roadpack comes with a waterproof inner bag, making it suitable for various riding conditions. With its robust construction and practical design, the PRO Roadpack is an ideal companion for riders seeking a reliable and stylish tail bag for their Kawasaki H2 SX SE.\n","date":"March 11, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-sw-motech-pro-roadpack-tail-bag/","section":"Blog","summary":"The SW-Motech PRO Roadpack motorcycle tail bag is a versatile and compact accessory designed to enhance the functionality of small and sporty motorcycles like the Kawasaki H2 SX SE. With an expandable volume ranging from 8 to 14 liters, this tail bag offers ample storage space for essentials such as keys, wallets, and other small items. The bag’s design includes stiffened sides and a molded EVA lid, ensuring it maintains its shape even during sporty rides. The PRO Roadpack is crafted from durable 1680 D Ballistic Nylon, originally developed for military use, providing high-quality workmanship and thoughtful features like reflective attachments for better visibility.\n","title":"Kawasaki H2 SX SE - SW-Motech PRO Roadpack Tail Bag","type":"blog"},{"content":"The Triboseat anti-slip pillion seat cover for the Kawasaki H2 SX SE is a well-crafted and practical accessory that enhances the riding experience for both the passenger and the rider. Designed with precision and attention to detail, this seat cover offers a unique solution to a common problem faced by motorcyclists: the sliding of passengers during rides.\nThis motorcycle accessory ensures that passengers remain securely seated even during sudden braking or acceleration. This feature not only enhances the comfort of the passenger but also reduces the strain on the rider\u0026rsquo;s arms by limiting weight transfer, thereby creating a more stable ride overall.\nOne of the standout features of the Triboseat is its ease of installation. The clever draw-string attachment system eliminates the need for staples or modifications, making it a hassle-free addition to any motorcycle.\nIn summary, the Triboseat anti-slip pillion seat cover is a valuable accessory for any Kawasaki H2 SX SE owner looking to improve the riding experience for both themselves and their passengers.\n","date":"March 11, 2025","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-triboseat-anti-slip-pillion-seat-cover/","section":"Blog","summary":"The Triboseat anti-slip pillion seat cover for the Kawasaki H2 SX SE is a well-crafted and practical accessory that enhances the riding experience for both the passenger and the rider. Designed with precision and attention to detail, this seat cover offers a unique solution to a common problem faced by motorcyclists: the sliding of passengers during rides.\n","title":"Kawasaki H2 SX SE - Triboseat Anti-slip Pillion Seat Cover","type":"blog"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/pillion/","section":"Tags","summary":"","title":"Pillion","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/pro/","section":"Tags","summary":"","title":"Pro","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/puig/","section":"Tags","summary":"","title":"Puig","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/roadpack/","section":"Tags","summary":"","title":"Roadpack","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/screen/","section":"Tags","summary":"","title":"Screen","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/seat/","section":"Tags","summary":"","title":"Seat","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/smoke/","section":"Tags","summary":"","title":"Smoke","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/sw-motech/","section":"Tags","summary":"","title":"Sw-Motech","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/tail/","section":"Tags","summary":"","title":"Tail","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/triboseat/","section":"Tags","summary":"","title":"Triboseat","type":"tags"},{"content":"","date":"March 11, 2025","externalUrl":null,"permalink":"/tags/z-racing/","section":"Tags","summary":"","title":"Z-Racing","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/about/","section":"Tags","summary":"","title":"About","type":"tags"},{"content":"Hobbies: riding motorcycles, playing guitar\nMotorcycles: Kawasaki H2 SX SE 2023, Aprilia Tuono V4 Factory 1100 2025\nCar: VW T-Roc Convertible 2024\nFormer motorcycles: Yamaha R6 2004, Yamaha FZ6 S2 2008, Yamaha XT660R 2008, Yamaha FZ1 SA 2008, BMW K1300R 2013, BMW K1600GT 2023, Triumph Rocket 3 Storm R 2024\nContact: Loading email address... Please enable JavaScript to view the email address. ","date":"February 14, 2025","externalUrl":null,"permalink":"/about/","section":"","summary":"Hobbies: riding motorcycles, playing guitar\nMotorcycles: Kawasaki H2 SX SE 2023, Aprilia Tuono V4 Factory 1100 2025\nCar: VW T-Roc Convertible 2024\nFormer motorcycles: Yamaha R6 2004, Yamaha FZ6 S2 2008, Yamaha XT660R 2008, Yamaha FZ1 SA 2008, BMW K1300R 2013, BMW K1600GT 2023, Triumph Rocket 3 Storm R 2024\n","title":"About Me","type":"page"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/acimovic/","section":"Tags","summary":"","title":"Acimovic","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/boban/","section":"Tags","summary":"","title":"Boban","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/engineer/","section":"Tags","summary":"","title":"Engineer","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/munich/","section":"Tags","summary":"","title":"Munich","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/pozarevac/","section":"Tags","summary":"","title":"Pozarevac","type":"tags"},{"content":"","date":"February 14, 2025","externalUrl":null,"permalink":"/tags/software/","section":"Tags","summary":"","title":"Software","type":"tags"},{"content":"","date":"November 9, 2024","externalUrl":null,"permalink":"/tags/akrapovic/","section":"Tags","summary":"","title":"Akrapovic","type":"tags"},{"content":"","date":"November 9, 2024","externalUrl":null,"permalink":"/tags/akrapovi%C4%8D/","section":"Tags","summary":"","title":"Akrapovič","type":"tags"},{"content":"","date":"November 9, 2024","externalUrl":null,"permalink":"/tags/exhaust/","section":"Tags","summary":"","title":"Exhaust","type":"tags"},{"content":"As the 2024 motorcycle season drew to a close, I found myself the proud owner of the 2023 Kawasaki Ninja H2 SX SE, a machine that has quickly become my favorite ride to date. This motorcycle offers an exceptional seating position and top-notch suspension, making it a joy to ride. Despite the occasional critique from sport riders who find it a bit on the heavy side, I find it remarkably light, especially when transitioning from the BMW K 1600 GT and still owning a Triumph Rocket 3 Storm R. The H2 SX SE is incredibly agile, effortlessly leaning into curves and accommodating sporty riding, all while allowing for some luggage on board. For me, it epitomizes the ideal sport touring motorcycle.\nBeing a 2023 model, Kawasaki Ninja H2 SX SE comes equipped with a Euro 5 compliant exhaust system, which, while efficient, is notably large, heavy, and rather quiet. As someone who has consistently upgraded the exhaust systems on my bikes, I decided to do the same with this one. The only aftermarket option available for this model is the Akrapovič silencer. To my knowledge, no other alternatives exist. This Akrapovič exhaust is 2.2 kg lighter and boosts the bike\u0026rsquo;s performance with an additional 1.4 kW (1.9 PS) and 1.8 Nm of torque. Although it remains quite sizable and doesn\u0026rsquo;t significantly enhance the bike\u0026rsquo;s aesthetics compared to the stock exhaust, I opted for it nonetheless.\nThe installation process began with preparing the new silencer by inserting the catalytic converter and attaching the clamps and link pipe.\nA graphite gasket is required between the link and exhaust pipes, and I carefully placed it inside before fitting the muffler.\nWith a bit of gentle persuasion and rotation, I managed to secure the muffler to the exhaust pipe. Following this, I installed the fastening bolt and the carbon fiber heat shield. The heat shield not only adds a touch of elegance but also ensures the clamps are correctly aligned. Once everything was in place, I fine-tuned the muffler\u0026rsquo;s position and tightened the fastening bolt and clamps. The installation manual provides all the necessary torque specifications.\nWhile the Akrapovič exhaust for the Kawasaki Ninja H2 SX SE is still quite large and perhaps not the most visually striking, it does deliver a satisfying pops and a noticeable increase in power and torque. With winter upon us, I haven\u0026rsquo;t had the opportunity to fully experience the ride, but my initial impressions are positive. The setup is certainly an improvement over the factory exhaust.\nThe carbon fiber heat shield is a particularly nice touch, adding a sleek look to the overall setup.\nFor those interested in the auditory difference between the factory and Akrapovič exhausts, you can hear it for yourself in the following videos.\n","date":"November 9, 2024","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-akrapovic-exhaust/","section":"Blog","summary":"As the 2024 motorcycle season drew to a close, I found myself the proud owner of the 2023 Kawasaki Ninja H2 SX SE, a machine that has quickly become my favorite ride to date. This motorcycle offers an exceptional seating position and top-notch suspension, making it a joy to ride. Despite the occasional critique from sport riders who find it a bit on the heavy side, I find it remarkably light, especially when transitioning from the BMW K 1600 GT and still owning a Triumph Rocket 3 Storm R. The H2 SX SE is incredibly agile, effortlessly leaning into curves and accommodating sporty riding, all while allowing for some luggage on board. For me, it epitomizes the ideal sport touring motorcycle.\n","title":"Kawasaki H2 SX SE - Installing Akrapovič Exhaust","type":"blog"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/downpipe/","section":"Tags","summary":"","title":"Downpipe","type":"tags"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/guard/","section":"Tags","summary":"","title":"Guard","type":"tags"},{"content":"Many Kawasaki H2 SX and H2 SX SE owners have reported issues with radiator damage, often attributed to stones being thrown up by the front wheel. The primary concern is Kawasaki\u0026rsquo;s decision not to include a radiator protector as standard. But how prevalent is this issue, and what extent of damage can it cause?\nAfter just over a week with my new bike, I noticed two to three minor dents and one more significant damage to the radiator. Despite not hearing any stones hit, the damage was evident. This occurred while riding on relatively clean local roads around Munich, highlighting the vulnerability of the radiator even under seemingly benign conditions.\nIn response, I attempted to straighten the fins and subsequently installed a radiator protector. Although I had ordered radiator and downpipe protectors before acquiring the bike, they arrived late. In hindsight, my enthusiasm for riding overshadowed the necessity of installing these protectors immediately. Using a plastic stick, I managed to realign the fins sufficiently to maintain airflow, which was satisfactory. For those in a similar predicament, I recommend ordering protectors well in advance and installing them as soon as you take possession of the bike.\nTo access the cooler, both side panels and the surrounding fairing must be removed. This process is straightforward, but care must be taken with the plastic rivets.\nOnce the panels are off, remove the two bolts at the top and one at the bottom of the radiator to mount the radiator guard. The downpipe guard installation is slightly more complex, as it is secured beneath the radiator where the side panels attach with long bolts. Initially, position it provisionally, then reattach the fairings and secure them. For the lower side, use two washers and nuts over the bottom bolts of the fairing. Although a bit challenging, the end result is both sturdy and aesthetically pleasing.\nR\u0026amp;G Racing has excelled in crafting these guards from lightweight, high-quality materials, ensuring a precise fit.\n","date":"October 31, 2024","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-radiator-downpipe-guards/","section":"Blog","summary":"Many Kawasaki H2 SX and H2 SX SE owners have reported issues with radiator damage, often attributed to stones being thrown up by the front wheel. The primary concern is Kawasaki’s decision not to include a radiator protector as standard. But how prevalent is this issue, and what extent of damage can it cause?\n","title":"Kawasaki H2 SX SE - Installing R\u0026G Racing Radiator and Downpipe Guards","type":"blog"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/protector/","section":"Tags","summary":"","title":"Protector","type":"tags"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/rg/","section":"Tags","summary":"","title":"R\u0026g","type":"tags"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/rg-racing/","section":"Tags","summary":"","title":"R\u0026g Racing","type":"tags"},{"content":"","date":"October 31, 2024","externalUrl":null,"permalink":"/tags/radiator/","section":"Tags","summary":"","title":"Radiator","type":"tags"},{"content":"","date":"October 28, 2024","externalUrl":null,"permalink":"/tags/power/","section":"Tags","summary":"","title":"Power","type":"tags"},{"content":"","date":"October 28, 2024","externalUrl":null,"permalink":"/tags/supply/","section":"Tags","summary":"","title":"Supply","type":"tags"},{"content":"The 2024 Triumph Rocket 3 Storm R comes equipped with a basic navigation system, accessible through a communication module (part number A9820200) and a smartphone application. This setup provides directional arrows and voice-guided turn-by-turn instructions, but lacks a detailed map view. For more complex routing needs, alternative solutions may be necessary. Having previously used a Garmin Zumo XT2 with my BMW K 1600 GT, I decided to adapt it for use with the Rocket 3.\nInstalling an external navigation system on a motorcycle presents two primary challenges: securing a suitable mount and sourcing a power supply that activates only when the engine is running. To address these, I consulted various Triumph Rocket 3 forums and Facebook groups, ultimately devising a practical solution.\nInitially, I examined the ISO 4165 socket on the dashboard, discovering it offers a switched power supply, active only when the ignition is engaged. This was ideal for my needs. To connect the navigation cable, I first removed the flyscreen.\nUpon disconnecting the socket, I identified the connector type and ordered compatible male and female versions.\nI soldered the Garmin power cable to one connector, ensuring the socket remained powered by connecting the other.\nFortunately, the front panel casing provided ample space for the connectors and Garmin cable, eliminating the need to shorten the cable, a consideration for future adaptability.\nAfter verifying the power connection, reassembling the flyscreen, and installing the holder, only a small portion of the Garmin power cable was visible. The cable was neatly routed alongside existing bike cables, resulting in a clean and organized installation.\nThe final setup positions the navigation device below the screen, offering protection from insects and rain, despite its water-resistant design. The space is well-utilized, allowing easy attachment and detachment of the device. With this setup, my Rocket 3 is ready to explore new routes with confidence.\n","date":"October 28, 2024","externalUrl":null,"permalink":"/blog/triumph-rocket-3-navigation-holder/","section":"Blog","summary":"The 2024 Triumph Rocket 3 Storm R comes equipped with a basic navigation system, accessible through a communication module (part number A9820200) and a smartphone application. This setup provides directional arrows and voice-guided turn-by-turn instructions, but lacks a detailed map view. For more complex routing needs, alternative solutions may be necessary. Having previously used a Garmin Zumo XT2 with my BMW K 1600 GT, I decided to adapt it for use with the Rocket 3.\n","title":"Triumph Rocket 3 - Installing Garmin zūmo XT/XT2 holder","type":"blog"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/a9838177/","section":"Tags","summary":"","title":"A9838177","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/a9838197/","section":"Tags","summary":"","title":"A9838197","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/daypack-pro/","section":"Tags","summary":"","title":"Daypack Pro","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/direction-indicators/","section":"Tags","summary":"","title":"Direction Indicators","type":"tags"},{"content":"The Kawasaki H2 SX SE, like many of its contemporary counterparts from Kawasaki, features a tank ring with concealed screws, necessitating its replacement to accommodate the tank bag ring.\nTo begin, safeguard the tank opening with a cloth to prevent any debris from entering — a simple precaution that can save considerable effort later. Proceed by loosening the four bolts with a hex key.\nFollowing this, remove the two screws securing the cap using a Phillips head screwdriver.\nApply a medium thread locker to the bolts supplied in the kit, and secure the cap to the new ring.\nNext, attach the provided metal and plastic horseshoes.\nThe transformation from a silver plastic ring to a sleek black aluminum one not only enhances the aesthetic appeal but also adds durability. While it may introduce a slight increase in weight, the functionality of the tank bag, ideal for storing essential documents and items, makes it a worthwhile upgrade.\nThe bag featured in the previous four images is the SW-Motech Daypack Pro.\n","date":"October 27, 2024","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-sw-motech-tank-ring/","section":"Blog","summary":"The Kawasaki H2 SX SE, like many of its contemporary counterparts from Kawasaki, features a tank ring with concealed screws, necessitating its replacement to accommodate the tank bag ring.\n","title":"Kawasaki H2 SX SE - Installing SW-Motech Tank Ring Pro","type":"blog"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/led-indicators/","section":"Tags","summary":"","title":"Led Indicators","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/scrolling-indicators/","section":"Tags","summary":"","title":"Scrolling Indicators","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/tank-bag/","section":"Tags","summary":"","title":"Tank Bag","type":"tags"},{"content":"","date":"October 27, 2024","externalUrl":null,"permalink":"/tags/tank-ring/","section":"Tags","summary":"","title":"Tank Ring","type":"tags"},{"content":"Triumph Rocket 3 has long been equipped with LED direction indicators, but for those seeking a sleeker, more modern aesthetic, Triumph offers scrolling direction indicators as aftermarket styling enhancements. These not only add a touch of sophistication but also enhance the bike\u0026rsquo;s visual appeal.\nThe part numbers for these stylish upgrades are A9838177 for the front and A9838197 for the rear, with the latter featuring a shorter cable for easy installation. To replace the front indicators, begin by removing the flyscreen to access the connectors. Carefully detach the indicators from their casing, disconnect them, and gently pull out the cables.\nOnce the connectors are free, release the brackets to swap out the indicators. A word of caution: the nuts inside the brackets may not stay in place while you unfasten the bolts, so it’s advisable to hold them steady with pliers cushioned by a soft cloth to avoid any damage.\nAfter securing the new indicators, apply a dab of contact grease to the connectors to ensure a reliable connection, and reassemble everything in reverse order. Although I haven\u0026rsquo;t documented the rear indicator replacement, rest assured, the process is straightforward and intuitive.\nThe transformation these indicators bring to the Rocket 3 is nothing short of remarkable, adding a dynamic flair to this powerhouse of a motorcycle. Thank you for joining me on this journey to enhance your ride\u0026rsquo;s style and functionality.\n","date":"October 27, 2024","externalUrl":null,"permalink":"/blog/triumph-rocket-3-scrolling-indicators/","section":"Blog","summary":"Triumph Rocket 3 has long been equipped with LED direction indicators, but for those seeking a sleeker, more modern aesthetic, Triumph offers scrolling direction indicators as aftermarket styling enhancements. These not only add a touch of sophistication but also enhance the bike’s visual appeal.\n","title":"Triumph Rocket 3 - Installing scrolling direction indicators","type":"blog"},{"content":"","date":"October 18, 2024","externalUrl":null,"permalink":"/tags/oem/","section":"Tags","summary":"","title":"Oem","type":"tags"},{"content":"When it comes to high-performance motorcycles like the Kawasaki H2 SX and H2 SX SE, ensuring the safety and longevity of your bike is paramount. One of the most effective ways to protect your investment is by installing frame sliders. These essential accessories are designed to minimize damage to the motorcycle\u0026rsquo;s frame and engine in the event of a fall or collision.\nIn the European market, options for frame sliders are somewhat limited. Aside from the TBR frame sliders I discussed in my previous blog post and the mushroom-shaped sliders, the only other viable choice is the Kawasaki OEM sliders. Let\u0026rsquo;s take a closer look at these.\nThese sliders are mounted inside the frame pipe over the engine fastening bolt. Make sure to torque the frame slider bolt to 30 Nm for optimal security.\nSome H2 SX owners have raised concerns about the robustness of these OEM sliders, claiming they can break even in minor drops. This debate about the sturdiness of frame sliders is quite nuanced. On one hand, more robust sliders might offer better protection for the fairing but could risk bending the frame or damaging the engine mount thread. On the other hand, less robust sliders might provide less protection for the fairing but ensure that the frame and engine remain undamaged. Ultimately, each owner must make their own decision. Additionally, proper installation and fastening are crucial factors. Since I am not a fan of mushroom-shaped sliders and the TBR sliders didn\u0026rsquo;t fit the 2023 model, I opted for the OEM sliders.\nDesigned by Kawasaki engineers, who arguably understand these machines better than we do, these frame sliders are impressively lightweight at just 497g. Plus, they don\u0026rsquo;t look half bad; in fact, they are quite aesthetically pleasing.\n","date":"October 18, 2024","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-oem-frame-sliders/","section":"Blog","summary":"When it comes to high-performance motorcycles like the Kawasaki H2 SX and H2 SX SE, ensuring the safety and longevity of your bike is paramount. One of the most effective ways to protect your investment is by installing frame sliders. These essential accessories are designed to minimize damage to the motorcycle’s frame and engine in the event of a fall or collision.\n","title":"OEM Frame Sliders for Kawasaki H2 SX SE","type":"blog"},{"content":"","date":"October 18, 2024","externalUrl":null,"permalink":"/tags/sport/","section":"Tags","summary":"","title":"Sport","type":"tags"},{"content":"","date":"October 18, 2024","externalUrl":null,"permalink":"/tags/touring/","section":"Tags","summary":"","title":"Touring","type":"tags"},{"content":"","date":"October 16, 2024","externalUrl":null,"permalink":"/tags/top-block/","section":"Tags","summary":"","title":"Top Block","type":"tags"},{"content":"I have been familiar with the French company Top Block Racing (TBR) for several years. My first encounter with their products was when I acquired frame sliders for my BMW K1300R, a bike I rode from 2014 until the autumn of 2023. Recently, while searching for frame sliders for my new Kawasaki H2 SX SE, I discovered that TBR manufactures them for this model as well. Despite some uncertainty from a German dealer regarding compatibility with the 2023 model, I decided to place an order, knowing they fit models from 2018 to 2022. Unfortunately, the sliders did not fit my bike, possibly due to minor changes in the frame or thicker welds. Nevertheless, I felt compelled to write about these frame sliders because of their exceptional aesthetics and high quality.\nThe frame sliders for both the left and right sides consist of a robust aluminum holder and a synthetic pad. The holder is exceptionally sturdy and is bolted through the frame to the engine. The installation requires the use of longer bolts provided by TBR, which replace the original engine bolts. If you decide to mount these sliders on your bike, ensure that the tightening torque is set to 45 Nm.\nThe synthetic pads are also impressively durable and well-designed. They integrate seamlessly with the bike\u0026rsquo;s aesthetics, complementing the stripes on the fairing. However, the total weight of the sliders is 1470 grams, which is relatively heavy compared to the Kawasaki OEM sliders for this bike, which weigh only 500 grams. This added weight and robustness can be seen as a disadvantage. While frame sliders are intended to protect the motorcycle from drops and accidents, overly robust sliders might bend the frame, causing more damage than just scratches on the fairing. This is a highly debatable topic, and opinions vary widely. The decision ultimately depends on various factors, such as how you use your motorcycle (street or track), your insurance coverage, and your risk tolerance.\nIn conclusion, the TBR sliders are arguably the most aesthetically pleasing option for the Kawasaki H2 SX SE. However, potential buyers should be aware that some compromises might be necessary.\n","date":"October 16, 2024","externalUrl":null,"permalink":"/blog/kawasaki-h2sx-tbr-frame-sliders/","section":"Blog","summary":"I have been familiar with the French company Top Block Racing (TBR) for several years. My first encounter with their products was when I acquired frame sliders for my BMW K1300R, a bike I rode from 2014 until the autumn of 2023. Recently, while searching for frame sliders for my new Kawasaki H2 SX SE, I discovered that TBR manufactures them for this model as well. Despite some uncertainty from a German dealer regarding compatibility with the 2023 model, I decided to place an order, knowing they fit models from 2018 to 2022. Unfortunately, the sliders did not fit my bike, possibly due to minor changes in the frame or thicker welds. Nevertheless, I felt compelled to write about these frame sliders because of their exceptional aesthetics and high quality.\n","title":"Top Block Racing Frame Sliders for Kawasaki H2 SX 2018-2022","type":"blog"},{"content":"","date":"October 15, 2024","externalUrl":null,"permalink":"/tags/infill/","section":"Tags","summary":"","title":"Infill","type":"tags"},{"content":"","date":"October 15, 2024","externalUrl":null,"permalink":"/tags/riding/","section":"Tags","summary":"","title":"Riding","type":"tags"},{"content":"","date":"October 15, 2024","externalUrl":null,"permalink":"/tags/solo/","section":"Tags","summary":"","title":"Solo","type":"tags"},{"content":"Triumph has rolled out two distinct variants of its Rocket 3 motorcycle: the R and the GT. At first glance, these models seem quite similar, but a deeper dive reveals key differences in handlebars, seat configuration, and foot control placement. While the GT includes a backrest as standard, you can easily retrofit the R with one from your Triumph dealer, making it possible to convert between the two variants to suit your preference.\nWhen choosing between the R and the GT, my decision leaned towards the R primarily due to its mid-mounted foot controls, as I’m not a fan of forward-set pegs. However, after experiencing some back discomfort, I borrowed the GT\u0026rsquo;s default touring seat from my local dealer. The added comfort was undeniable, prompting me to make the switch. I\u0026rsquo;m confident many Rocket 3 enthusiasts face similar decisions, so I’ve penned this article for their benefit.\nComparison images show the touring seat on the left and the sport seat on the right. Notably, the touring seat extends longer for the rider, offering more room to shift positions, thereby reducing fatigue on long rides. On the contrary, the pillion touring seat is thicker but shorter than the sport variant.\nSignificantly, components of the sport and touring seats, including aluminum trims, are not interchangeable. A touring pillion seat won\u0026rsquo;t fit with a sport rider seat and vice versa.\nFor solo riding, Triumph offers a stylish pillion infill piece. However, you cannot mix and match between the sport and touring variants of these infills. Previous set of images illustrates the incompatibility of the touring pillion infill with the sport rider seat.\nConversely, the last three images showcase the seamless fit and enhanced aesthetic when pairing the touring rider seat with the touring pillion infill, complemented by the elegant metal Triumph plate for an even more refined appearance.\nBy understanding these nuanced differences, Rocket 3 riders can make informed choices tailored to their riding preferences.\n","date":"October 15, 2024","externalUrl":null,"permalink":"/blog/triumph-rocket-3-seats-comparison/","section":"Blog","summary":"Triumph has rolled out two distinct variants of its Rocket 3 motorcycle: the R and the GT. At first glance, these models seem quite similar, but a deeper dive reveals key differences in handlebars, seat configuration, and foot control placement. While the GT includes a backrest as standard, you can easily retrofit the R with one from your Triumph dealer, making it possible to convert between the two variants to suit your preference.\n","title":"Triumph Rocket 3 - Comparison of touring and sport seats","type":"blog"},{"content":"","date":"June 5, 2024","externalUrl":null,"permalink":"/tags/dumping/","section":"Tags","summary":"","title":"Dumping","type":"tags"},{"content":"","date":"June 5, 2024","externalUrl":null,"permalink":"/tags/grip/","section":"Tags","summary":"","title":"Grip","type":"tags"},{"content":"","date":"June 5, 2024","externalUrl":null,"permalink":"/tags/handlebars/","section":"Tags","summary":"","title":"Handlebars","type":"tags"},{"content":"Grip puppies are made to reduce handlebars vibrations on the grips preventing hands fatigue. For riders with bigger hands they also may provide a better comfort because of the increased diameter. Someone may argue that they may also endanger the feeling of the front end but in my experience that is not the case or at least there is enough good feeling in a regular traffic riding. Sports riding on a track is probably different story.\nFirst remove the bar end finisher using 4 mm hex key.\nThen remove the mirror using 5 mm hex key. You may want to mark the position of the mirror for easier setting back to the right place. Or simply make a photo.\nSpray some soapy water onto the grip and inside the grip puppy tube to allow easier pulling on the grips. Using this technique it is quite easy to install them.\nInstall the mirror back to the same position and tighten the pinch bolt to 3.5 Nm.\nUse some medium thread locker for the bar end bolt and torque it to 5 Nm.\nI like grip puppies since I discovered them probably somewhere 2015. I hope they will work well on the Rocket bike as well. If you are wondering do they prevent heating on the heated grips, the answer is no. The heat spreads through grip puppies no problem. You maybe have to wait few moments longer to feel the heat but after that it works just like expected.\n","date":"June 5, 2024","externalUrl":null,"permalink":"/blog/triumph-rocket-3-grip-puppies/","section":"Blog","summary":"Grip puppies are made to reduce handlebars vibrations on the grips preventing hands fatigue. For riders with bigger hands they also may provide a better comfort because of the increased diameter. Someone may argue that they may also endanger the feeling of the front end but in my experience that is not the case or at least there is enough good feeling in a regular traffic riding. Sports riding on a track is probably different story.\n","title":"Installing grip puppies on Triumph Rocket 3 Storm R","type":"blog"},{"content":"","date":"June 5, 2024","externalUrl":null,"permalink":"/tags/puppies/","section":"Tags","summary":"","title":"Puppies","type":"tags"},{"content":"","date":"June 5, 2024","externalUrl":null,"permalink":"/tags/vibration/","section":"Tags","summary":"","title":"Vibration","type":"tags"},{"content":"","date":"June 4, 2024","externalUrl":null,"permalink":"/tags/enlargement/","section":"Tags","summary":"","title":"Enlargement","type":"tags"},{"content":"","date":"June 4, 2024","externalUrl":null,"permalink":"/tags/side-stand/","section":"Tags","summary":"","title":"Side Stand","type":"tags"},{"content":"Most motorcycles have a side stand with relatively small foot which secures the bike nicely on a pavement but if you try to park on a gravel or muddy terrain, you may experience problems. The side stand may sink into the surface and the bike may fall. I used some kind of side stand foot enlargements on all my bikes since 2014 but this time I wanted it for my new Triumph Rocket 3 Storm R and I couldn\u0026rsquo;t find it. The aftermarket accessories for Rocket 3 2500cc are quite limited. After some searches and inquiries on forums, I finally found it. Fortunately, Italian company XRay offers few Rocket 3 accessories and among them is also a side stand foot enlargement.\nBesides the side stand foot enlargement you will also get a rubber pad which you may need to glue on the existing rubber pad on the bike which holds the side stand in the retracted position. I got information from the manufacturer that this may not be needed on all bikes but I still glued it on mine in order to avoid the side stand eventually hit the exhaust. The rubber pad is 6 mm thick. The enlargement itself is very light, 127 g.\nThe top plate is padded with some rubber stripes in order not to scratch the side stand foot. Great detail which improves the impression of quality.\nThe bottom part is made of aluminum while the top part is probably a stainless steel.\nSince the bottom plate is bellow 2.5 mm thick, it won\u0026rsquo;t make a noticeable change in the lean angle of the motorcycle.\nI glued the rubber pad to the existing one and let it cure.\nI used a medium thread locker and tightened the screws by hand.\nAs you can see on this picture, I maybe didn\u0026rsquo;t need to add the rubber pad since there seem to be enough clearance. I didn\u0026rsquo;t check this beforehand but it is what it is, I will just leave it. If you retract the side stand slowly, it for sure won\u0026rsquo;t hit the exhaust even if you don\u0026rsquo;t have the extra padding, but if you just let the spring work out with full force, it may compress the original rubber enough to hit the exhaust. Maybe a little thinner rubber pad is the way to go, maybe 2-4 mm. I will just check out if the retracted side stand stays stable at this position and if so, I won\u0026rsquo;t do anything further.\nI may write another article to review the real life functionality of this product.\n","date":"June 4, 2024","externalUrl":null,"permalink":"/blog/triumph-rocket-3-side-stand-foot-enlargement/","section":"Blog","summary":"Most motorcycles have a side stand with relatively small foot which secures the bike nicely on a pavement but if you try to park on a gravel or muddy terrain, you may experience problems. The side stand may sink into the surface and the bike may fall. I used some kind of side stand foot enlargements on all my bikes since 2014 but this time I wanted it for my new Triumph Rocket 3 Storm R and I couldn’t find it. The aftermarket accessories for Rocket 3 2500cc are quite limited. After some searches and inquiries on forums, I finally found it. Fortunately, Italian company XRay offers few Rocket 3 accessories and among them is also a side stand foot enlargement.\n","title":"XRay side stand foot enlargement installation on Triumph Rocket 3 Storm R","type":"blog"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/back/","section":"Tags","summary":"","title":"Back","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/elbow/","section":"Tags","summary":"","title":"Elbow","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/exosafe/","section":"Tags","summary":"","title":"Exosafe","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/ghost/","section":"Tags","summary":"","title":"Ghost","type":"tags"},{"content":"D3O is a protective material made by D3O Labs , British company specializing in impact protection technologies. It\u0026rsquo;s a flexible and pliable material which solidifies in the event of collision. It is used as a low-profile impact protection for phones, laptops and other electronic devices, motorcycle riding gear, defense products like helmets, body armor and footwear, etc. Held has it\u0026rsquo;s own palette of D3O based protectors in association with D3O Labs and we are going to review most of them in this article. I want to mention that this article is not sponsored by anyone and I bought all the stuff myself. I kept just protectors that I liked and needed and returned all the rest.\nBack protector # Held Exosafe by D3O Back Protector is a great Level 2 insert protector for your jacket. As very large piece of D3O this is the best example how flexible, pliable and soft this material is. Thanks to many holes it will allow perspiration and keep your backs dry and protected. It is made in three sizes S (41 x 33 cm), M (45 x 33,5 cm) and L (50 x 29 cm). Before purchasing take care that it can fit into the back pocket of your jacket. Manufacturer of your jacket might have their own line of D3O protectors which might fit better for you jacket, check it out. I am very happy with this protector and it fits very comfortable in my Held Sonic mesh jacket.\nChest protector # Similar as the back protector, Held Exosafe by D3O Chest Protector is also ventilated to allow the air flow and keep your chest dry. As you can see at the pictures, this Level 1 protector comes in two pieces inserted in supplied velcro pockets. It can be inserted into your jacket if it has chest protector pockets or velcro attachments at the right places. If not, you better skip it as it is not that crucial as back, shoulder and elbow protectors. The size is 24.5 x 17.5 cm. As this can\u0026rsquo;t be fitted into my jackets, I returned it.\nShoulder protectors # On this picture you can see two D3O shoulder protectors and two standard protectors (black) which I took out from my jackets. The orange protector on the left hand side is Held D3O Ghost Shoulder/Hip Protector, protector with size of 23.9 x 14.7 cm and thickness below 1 cm. Besides being this thin, it offers Level 2 protection and it is almost invisible inserted into your jacket or pants. I liked it so much that I ordered two additional pairs to use in both my jackets and one jeans. The orange protector on the right hand side is Held Exosafe by D3O Shoulder Protector which looks very robust and protective, but in the same time it is well ventilated and flexible. However, I returned these because I liked Ghost much more even though they are probably a bit less protective. However, they make you feel much more comfortable which probably gives better safety at the end.\nElbow protectors # Same as on the previous picture, here you can also see two D3O protectors, but this time for elbows. Then also two standard, black protectors that I took out from my jackets. The orange one on the left hand side is Held D3O Ghost Elbow/Knee Protector, again my favorite. Same as with the shoulder/hip Ghost protector I ordered two more sets and put them in the same two jackets and one jeans. Now basically all motorcycle clothes I have are equipped with D3O Ghost Level 2 protectors and this makes me feel much more comfortable but still having in mind that I have quite good level of protection. Since I can move much easier than having a hard and big protectors, I pretty much believe this is a safer option because I am more flexible when riding and my moves are quicker and more precise. The orange one on the right hand side is Held Exosafe by D3O Elbow Protector. Same as with the shoulder protectors, I returned these for the same reason even they might be safer on impact. Being able to move easily is probably more important in order not to crash.\nHip protectors # From left to right, in this picture you can see a standard hip protector that I took out from my Trilobite jeans, Held Exosafe by D3O Rib/Hip Protector and Held D3O Ghost Shoulder/Hip Protector. I don\u0026rsquo;t have anything new to say here, the same I commented about the Exosafe and Ghost versions apply here as well.\nKnee protectors # Finally, on these pictures you can see Held Exosafe by D3O Elbow/Knee Large Protector, standard knee protector from Fastway textile pants, Held D3O Ghost Elbow/Knee Protector, standard knee protector from my Trilobite jeans and finally Held D3O Ghost Elbow/Knee Small Protector. Exosafe Large is probably too big for elbows and Exosafe Small is for sure too small for knees. However, the later one might fit kids\u0026rsquo; knees very well. All the comments I had on Exosafe and Ghost versions apply here as well.\nFinal Words # To summarize this article, I want to repeat that in my opinion comfort is very important for safety and crash prevention so this is why I choose my equipment to be flexible and allow pretty good range of movements. On the other hand, more robust protection is probably better in case of accident so at the end we have again to make compromises. In my case this is better comfort and maybe a little bit lower level of protection rather than having difficulties to move and have a bit higher level of protection. You choose yourself. 🙂\n","date":"May 23, 2024","externalUrl":null,"permalink":"/blog/held-d3o-protectors/","section":"Blog","summary":"D3O is a protective material made by D3O Labs , British company specializing in impact protection technologies. It’s a flexible and pliable material which solidifies in the event of collision. It is used as a low-profile impact protection for phones, laptops and other electronic devices, motorcycle riding gear, defense products like helmets, body armor and footwear, etc. Held has it’s own palette of D3O based protectors in association with D3O Labs and we are going to review most of them in this article. I want to mention that this article is not sponsored by anyone and I bought all the stuff myself. I kept just protectors that I liked and needed and returned all the rest.\n","title":"Held D3O Protectors","type":"blog"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/hip/","section":"Tags","summary":"","title":"Hip","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/insert/","section":"Tags","summary":"","title":"Insert","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/knee/","section":"Tags","summary":"","title":"Knee","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/rider/","section":"Tags","summary":"","title":"Rider","type":"tags"},{"content":"","date":"May 23, 2024","externalUrl":null,"permalink":"/tags/shoulder/","section":"Tags","summary":"","title":"Shoulder","type":"tags"},{"content":"Is Akrapovič sport exhaust just a nice add-on for BMW K 1600 GT or does it do something more? What kind of sound does it make? Does it change the behavior of the bike? It was quite difficult to find these information online but I still decided to give it a try. Hence, let\u0026rsquo;s share some more information about it.\nExhausts are packed flawlessly. I haven\u0026rsquo;t checked if they are really 3.3kg lighter than the factory ones, but I could feel the difference by lifting them. Titanium and carbon finish are mint, simply Akrapovič quality.\nThe replacement silencers are also shorter than the factory ones. They fit and look much better on the bike. But what about performances? Well, Akrapovič claims 2.3HP and 2.7Nm more. Throttle feels more responsive, sound is a bit deeper and there are pops as well. For an Euro 5 exhaust with standing noise of 89dB I am pretty happy with the sound. It also gives more joy during the ride for sure. Is it worth money? I think yes and do not regret buying them. And now for the end the best part, check out the sound difference. 😉\n","date":"April 17, 2024","externalUrl":null,"permalink":"/blog/bmw-k1600gt-akrapovic-exhaust/","section":"Blog","summary":"Is Akrapovič sport exhaust just a nice add-on for BMW K 1600 GT or does it do something more? What kind of sound does it make? Does it change the behavior of the bike? It was quite difficult to find these information online but I still decided to give it a try. Hence, let’s share some more information about it.\n","title":"Akrapovič sport exhaust installation on BMW K 1600 GT","type":"blog"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/alpine/","section":"Tags","summary":"","title":"Alpine","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/bmw/","section":"Tags","summary":"","title":"Bmw","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/communicatr/","section":"Tags","summary":"","title":"Communicatr","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/earplugs/","section":"Tags","summary":"","title":"Earplugs","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/engine/","section":"Tags","summary":"","title":"Engine","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/k1600gt/","section":"Tags","summary":"","title":"K1600gt","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/moto/","section":"Tags","summary":"","title":"Moto","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/motosafe/","section":"Tags","summary":"","title":"Motosafe","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/motosafepro/","section":"Tags","summary":"","title":"Motosafepro","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/noise/","section":"Tags","summary":"","title":"Noise","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/quies/","section":"Tags","summary":"","title":"Quies","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/race/","section":"Tags","summary":"","title":"Race","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/reduction/","section":"Tags","summary":"","title":"Reduction","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/sound/","section":"Tags","summary":"","title":"Sound","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/specific/","section":"Tags","summary":"","title":"Specific","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/test/","section":"Tags","summary":"","title":"Test","type":"tags"},{"content":" Alpine MotoSafe Tour and Race # Alpine Hearing Protection is founded 1994 in Netherlands as a producer of customized earplugs for professional applications. They claim their motorcyclists earplugs are the best for the motorway and racing circuit. Their earplugs have special filter which reduces wind noise while keeping the sound or the engine and helmet communicator.\nTheir main products are MotoSafe Tour (with black filter) and Race (with red filter) which provide 17dB and 20dB noise reduction respectively. MotoSafePro that you can see on the pictures is actually a set of both of these earplugs with included carrying bag, insertion stick and cleaning spray. Further, Alpine sponsors MotoGP so they have a special edition of MotoSafe Race with MotoGP branding (black earplugs with red filter).\nTour earplugs work well at a lower noise levels like in the city environment or at lower speeds. At higher speeds wind noise becomes significant. On the other hand, Race version has higher noise reduction and it is more suitable for motorways, highways and circuits. After testing both of them I have to admit that I prefer Race version and would not buy Tour anymore. Tour is probably good just if you ride a scooter or smaller motorcycle with speeds up to 80km/h. But both versions reduces some level of noise while allowing to hear your communicator, engine, horns and other sounds that should not be removed or attenuated. Of course, they don\u0026rsquo;t reduce the wind noise completely, if you drive very fast the noise will be there, but specially with the Race version it\u0026rsquo;s going to be reduced significantly. Alpine recommends to insert the earplugs using the provided stick but still I find insertion a little bit difficult and sometimes you have to try several times before the earplug is positioned correctly and not falling out.\nQuies Specific Moto # Quies is a French family company founded in 1921 and they specialize in hearing protection. Instead of providing a keyring pouch, they provide a plastic carrying box.\nQuies Specific Moto earplugs provide noise reduction of 22dB which is comparable to Alpine MotoSafe Race. Actually it is a little bit higher noise reduction than Alpines but while wearing them I would say they are similar. It is really difficult to compare precisely but Quies can just do better reduction for sure or in the worse case similar.\nBesides that, they are a little bit curved so they sit better in the ears and won\u0026rsquo;t fall out that easy as Alpines. Quies also uses a special noise filter in the middle of the earplugs which filters out just wind noise while keeping useful sounds still present.\nConclusion # I could use my communicator pretty normally using any of these earplugs and all of them fit nicely in ears and could be wore for several hours. Alpine MotoSafe Tour doesn\u0026rsquo;t provide enough noise reduction for my taste and I would eliminate it first. Comparing Alpine MotoSafe Race and Quies Specific Moto, I can say that it is much easier to insert Quies and they also might have better noise reduction so I think the conclusion is clear. Since all these earplugs are similarly priced my obvious choice is Quies Moto Specific. If I couldn\u0026rsquo;t get them for some reason, Alpine MotoSafe Race is acceptable replacement.\n","date":"April 17, 2024","externalUrl":null,"permalink":"/blog/moto-earplugs/","section":"Blog","summary":"Alpine MotoSafe Tour and Race # ","title":"Test of Alpine MotoSafe and Quies Moto earplugs","type":"blog"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/tour/","section":"Tags","summary":"","title":"Tour","type":"tags"},{"content":"","date":"April 17, 2024","externalUrl":null,"permalink":"/tags/wind/","section":"Tags","summary":"","title":"Wind","type":"tags"},{"content":"","date":"April 16, 2024","externalUrl":null,"permalink":"/tags/click/","section":"Tags","summary":"","title":"Click","type":"tags"},{"content":"After unsuccessful try to use SW-Motech Daypack Pro tank bag on my K 1600 GT, I searched for an alternative and found a new series of tank bags from Wunderlich named CLICK BAG. They offer 5 different sizes, 3L, 6L, 13L and finally 16L. CLICK BAG 3L is not extendable, but remaining sizes expand to 8, 16 and 19 liters respectively. 3L bag is the only one that comes with the rain cover while other bags come with internal waterproof bags. This second solution also keeps your goods dry but I find it not that practical. First, it occupies some space inside and second, it\u0026rsquo;s more difficult to put the stuff in and take them out. Anyways, the bags are really good quality and they attach to appropriate tank rings very easily, just one click. This attachment system is very similar to SW-Motech Pro but without magnets. Wunderlich is an expensive brand but some of their CLICK BAGS are basically the only safe options for BMW K 1600 GT, namely 3L and 6L. Unfortunately SW-Motech Pro tank bags collide with the fully turned handlebars and random switches might got pressed. Besides that, this may limit the movement of the handlebars to the end which may make turning the bike around more difficult. But let\u0026rsquo;s see how Wunderlich tank bags fit on K 1600 GT and which one I chose for my bike.\nCLICK BAG 3L # CLICK BAG 3L looks very cute on the bike. It is relatively small but still provides enough space for basic things that you might need on a short trip.\nThe bag doesn\u0026rsquo;t obscure the view to the cockpit or additional navigation at all. I forgot to check if fully turned handlebars touch the bag, but since they touch 6L version just slightly, I guess they don\u0026rsquo;t touch 3L at all or maybe even less than in case of 6L. I would conclude that this bag is the most safe and the only complaint I have about it is that it is maybe too small. If you can afford to have one more bigger CLICK BAG, then this small one makes sense for shorter trips. However, if you want to buy just one, this wouldn\u0026rsquo;t be my primary choice.\nCLICK BAG 6L # Like previously said, handlebars slightly touch the sides of CLICK BAG 6L. On the left hand side fog lights button may get pressed but this is not dangerous. On the right hand side the SOS call button cap touches the bag but in both cases the bag doesn\u0026rsquo;t prevent fully movement of the handlebars to the left or the right hand side. Comparing to SW-Motech, Wunderlich tank ring moves their tank bags to the rear and allow better clearance.\nAgain, the view to the cockpit and additional navigation device are unobstructed.\nCLICK BAG 13L # Finally we come the the biggest version I have tried on my bike, CLICK BAG 13L. Even bigger one, 16L is not recommended for K 1600 GT at all. I forgot to try if the handlebars touch the bag when fully turned, but I discarded this bag anyways because it obscures the view to the navigation which was not acceptable in my case.\nOn some other bikes CLICK BAG 13L may fit nicer but my conclusion is that it is too big for K 1600 GT.\nConclusion # Well, you may have already guessed that my choice was CLICK BAG 6L. I think it is the best compromise of all, it doesn\u0026rsquo;t obstruct the riders view on the instruments, it is big enough to pack navigation case, wallet, earplugs box, keys, balaclava, gloves, documents and few more little things. As I wrote at the beginning, this bag comes with the waterproof inner bag instead of the rain cover, but fortunately rain cover from SW-Motech Daypack Pro fits very well so I got one. 😀\n","date":"April 16, 2024","externalUrl":null,"permalink":"/blog/bmw-k1600gt-wunderlich-click-tankbags/","section":"Blog","summary":"After unsuccessful try to use SW-Motech Daypack Pro tank bag on my K 1600 GT, I searched for an alternative and found a new series of tank bags from Wunderlich named CLICK BAG. They offer 5 different sizes, 3L, 6L, 13L and finally 16L. CLICK BAG 3L is not extendable, but remaining sizes expand to 8, 16 and 19 liters respectively. 3L bag is the only one that comes with the rain cover while other bags come with internal waterproof bags. This second solution also keeps your goods dry but I find it not that practical. First, it occupies some space inside and second, it’s more difficult to put the stuff in and take them out. Anyways, the bags are really good quality and they attach to appropriate tank rings very easily, just one click. This attachment system is very similar to SW-Motech Pro but without magnets. Wunderlich is an expensive brand but some of their CLICK BAGS are basically the only safe options for BMW K 1600 GT, namely 3L and 6L. Unfortunately SW-Motech Pro tank bags collide with the fully turned handlebars and random switches might got pressed. Besides that, this may limit the movement of the handlebars to the end which may make turning the bike around more difficult. But let’s see how Wunderlich tank bags fit on K 1600 GT and which one I chose for my bike.\n","title":"Fitting Wunderlich CLICK BAGS 3, 6 and 13L on BMW K 1600 GT","type":"blog"},{"content":"","date":"April 16, 2024","externalUrl":null,"permalink":"/tags/tank/","section":"Tags","summary":"","title":"Tank","type":"tags"},{"content":"","date":"April 16, 2024","externalUrl":null,"permalink":"/tags/wunderlich/","section":"Tags","summary":"","title":"Wunderlich","type":"tags"},{"content":"I am not sure if I have previously mentioned, but my previous bike was K1300R which I owned from 2013 till 2023, quite 10 years and I was very happy with it. There were no particular reasons to sell it except that I wanted a new bike and I couldn\u0026rsquo;t keep both of them because of the space in my underground garage. I got SW-Motech tank ring and Daypack bag on this bike and it served very well, great quality. The same tank ring fits on K1600GT, but none of the SW-Motech bags fit. You may ask what\u0026rsquo;s the reason for this and the answer is simple, when you completely turn handle bars they collide with the bag and some buttons may be accidentally be pressed. This is obviously not safe even you don\u0026rsquo;t have to completely turn the handlebars during the ride, but just at stand. I searched the web and found out that there is just one more quick mount and release tank bag option this time manufactured by Wunderlich. Unfortunately, their tank ring was not available until few days ago, but I have ordered it almost immediately and mounted it on my bike, so here you can find out the installation instructions and my experience with it.\nFirst unscrew two bolts closest to the rider, put Wunderlich provided washers, put some medium thread locker and tighten them to 4Nm.\nThe right torque is 4Nm, not 3.8 like on my picture. 😀\nThen take out the remaining 4 bolts and put provided spacers.\nAgain put some medium thread locker and tighten the bolts to the same torque.\nAnd how do I compare SW-Motech and Wunderlich tank rings? Well, I like SW-Motech a little bit more, it is easier to attach the bag because of the magnets, but Wunderlich is quite nice as well. They simply moved the bag mounting point away from the handlebars and allowed some more clearance. Hence, they became the only provider of a quick mount tank bags for K1600GT. Keep following this blog if you want to find out how different Wunderlich tank bags fit on the bike. Thank you.\n","date":"February 29, 2024","externalUrl":null,"permalink":"/blog/bmw-k1600gt-wunderlich-tankring/","section":"Blog","summary":"I am not sure if I have previously mentioned, but my previous bike was K1300R which I owned from 2013 till 2023, quite 10 years and I was very happy with it. There were no particular reasons to sell it except that I wanted a new bike and I couldn’t keep both of them because of the space in my underground garage. I got SW-Motech tank ring and Daypack bag on this bike and it served very well, great quality. The same tank ring fits on K1600GT, but none of the SW-Motech bags fit. You may ask what’s the reason for this and the answer is simple, when you completely turn handle bars they collide with the bag and some buttons may be accidentally be pressed. This is obviously not safe even you don’t have to completely turn the handlebars during the ride, but just at stand. I searched the web and found out that there is just one more quick mount and release tank bag option this time manufactured by Wunderlich. Unfortunately, their tank ring was not available until few days ago, but I have ordered it almost immediately and mounted it on my bike, so here you can find out the installation instructions and my experience with it.\n","title":"BMW K 1600 GT Wunderlich tank ring","type":"blog"},{"content":"","date":"February 29, 2024","externalUrl":null,"permalink":"/tags/ring/","section":"Tags","summary":"","title":"Ring","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/bags/","section":"Tags","summary":"","title":"Bags","type":"tags"},{"content":"I have already explained in the previous blog what means \u0026ldquo;best quality inner bag(s)\u0026rdquo; means to me and that is not just the quality of materials and manufacture, but also the weight, space usage, space optimization and so on. I found out that Kleinert inner bags for side cases for BMW K1600GT/GTL and R1250RT are the best at the market, in my opinion, and in this blog I would like to announce the winner for the top case. Other riders may have different opinions but I want to help you with this blog to decide what is best for you.\nHere you can see Wunderlich top case liner which fits very well into the top case, it\u0026rsquo;s high quality, no bad smell, it comes inside the free waterproof bag, it can be extended to fulfil almost all space in the top case but anyways it allows some room for small items that you might need to access quickly during the ride.\nThe manufacture, quality and the look fits very well with the side bags\u0026rsquo; liners from the previous blog, which makes quite difficult to figure out that the bags are not manufactured by the same brand.\nAgain, BMW has quite nice option here, they also offer a bag of a very good quality but what made me decide for Wunderlich is the space that the bag itself occupies. BMW\u0026rsquo;s bag has a rubber bottom which is great for standalone bag but for inner bag I think it occupies some space which can actually be better used by your items.\nI have also tried another 3rd party alternative but that one was of lower quality, with bad small and it didn\u0026rsquo;t use the inner space properly. I want to have some extra space around for things like rain suite and so, but not too much. With Wunderlich you can choose if you want more or less extra space since the bag can be extended but even then you can fit some small items around.\nI think I solved my search for the inner bags and my bike is ready for the tours next season. Something else may work better for you, it really depends on personal preferences. I want to make a not that this applies to European market and the situation may be different in US and other markets.\n","date":"October 3, 2023","externalUrl":null,"permalink":"/blog/top-case-inner-bag/","section":"Blog","summary":"I have already explained in the previous blog what means “best quality inner bag(s)” means to me and that is not just the quality of materials and manufacture, but also the weight, space usage, space optimization and so on. I found out that Kleinert inner bags for side cases for BMW K1600GT/GTL and R1250RT are the best at the market, in my opinion, and in this blog I would like to announce the winner for the top case. Other riders may have different opinions but I want to help you with this blog to decide what is best for you.\n","title":"Best inner bag for BMW K1600GT top case","type":"blog"},{"content":"What would \u0026ldquo;best inner bags\u0026rdquo; mean, just the quality of the bags or something more? Well, since plastic side cases very often have irregular inner shape, in my opinion, optimal space usage is as important as the quality. Instead of the further explanation, let\u0026rsquo;s see the internals of the BMW touring cases:\nBMW offers good quality inner bags but according to the pictures and forum\u0026rsquo;s opinions I could find online, they do not occupy all internal space. This can be good in case you want to add some additional items like rain clothes, but these small items may also very easily fall out of the cases when you open them so my conclusion is that it is better to use the whole internal space of the side cases by inner bags and keep all small items in the top case.\nBy searching online I could also find some bags with an external pocket which allegedly occupies the cases very well, but this is actually not quite true. It maybe uses more space than the original bags, but still the shape of this external pockets has nothing to do with the shape of the side cases. It is far away from occupying the whole available space. Besides that, the ones I got smelled quite bad and the quality was actually not that good as claimed.\nFinally I got these bags:\nAs you can see on the pictures, these bags are shaped very well in order to occupy the internal space, the quality of materials are great, there is no bad smell, zippers are made by Held and so far I simply claim these are the best inner bags for your touring cases either for K1600GT/GTL or R1250RT. If you share my opinion, you can get the bags from Kleinert .\n","date":"October 3, 2023","externalUrl":null,"permalink":"/blog/side-cases-inner-bags/","section":"Blog","summary":"What would “best inner bags” mean, just the quality of the bags or something more? Well, since plastic side cases very often have irregular inner shape, in my opinion, optimal space usage is as important as the quality. Instead of the further explanation, let’s see the internals of the BMW touring cases:\n","title":"Best inner bags for BMW K1600GT side cases","type":"blog"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/case/","section":"Tags","summary":"","title":"Case","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/cases/","section":"Tags","summary":"","title":"Cases","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/inner/","section":"Tags","summary":"","title":"Inner","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/liner/","section":"Tags","summary":"","title":"Liner","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/liners/","section":"Tags","summary":"","title":"Liners","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/r1250rt/","section":"Tags","summary":"","title":"R1250rt","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/side/","section":"Tags","summary":"","title":"Side","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/top/","section":"Tags","summary":"","title":"Top","type":"tags"},{"content":"","date":"October 3, 2023","externalUrl":null,"permalink":"/tags/tourenkoffer/","section":"Tags","summary":"","title":"Tourenkoffer","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/communicator/","section":"Tags","summary":"","title":"Communicator","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/gt-air-3/","section":"Tags","summary":"","title":"Gt-Air 3","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/helmet/","section":"Tags","summary":"","title":"Helmet","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/neotec-3/","section":"Tags","summary":"","title":"Neotec 3","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/prallschutz/","section":"Tags","summary":"","title":"Prallschutz","type":"tags"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/sena/","section":"Tags","summary":"","title":"Sena","type":"tags"},{"content":"Like promised in the previous blog, we will discuss here more about the newest Sena communicator for the newest Shoei helmets Neotec 3 and GT-Air 3. After installing SLR3 into the helmet, the main impression is very seamless integration. All cables safely routed, virtually invisible, speakers fit exactly to the sockets, everything is so clean. Great work both from Sena and Shoei.\nOn the left cheek you can see main controls.\nMesh intercommunication controls are placed on the right cheek of the helmet.\nUSB-C connector for charging is very accessible and practical.\nVery nice integration can also be seen from the underneath.\nMicrophone cable is nicely routed and the microphone itself is attached by velcro to the socket just in front the mouth for the best sound quality.\nSpeakers just clicked into the sockets. There is no obstruction for ears, the helmet is just as comfortable as without the communicator.\nWiFi adapter charging cable can be used both for charging the device and for automatic firmware updates.\nI might talk more about riding experience using this helmet and this communicator later, but I do not promise. More riding is better than talking or writing. 😀\n","date":"September 28, 2023","externalUrl":null,"permalink":"/blog/sena-slr3/","section":"Blog","summary":"Like promised in the previous blog, we will discuss here more about the newest Sena communicator for the newest Shoei helmets Neotec 3 and GT-Air 3. After installing SLR3 into the helmet, the main impression is very seamless integration. All cables safely routed, virtually invisible, speakers fit exactly to the sockets, everything is so clean. Great work both from Sena and Shoei.\n","title":"Sena SLR3","type":"blog"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/shoei/","section":"Tags","summary":"","title":"Shoei","type":"tags"},{"content":"Are you wondering who would ever write a blog of installation of some rubbery impact protectors for some motorcycle\u0026rsquo;s side cases? I completely understand you. 😀\nSo why did I write this? I recently bought K1600GT and started looking for some aftermarket parts. But I was surprised that there are actually not many information about some of the products, very often no pictures or just bad quality ones, no videos, quite strange. This specially applies BMW genuine parts. Some forums contain some information but very often without any pictures. All this makes decision to buy something or not very difficult.\nSo, here are the protectors for the right touring case and installation templates. Fortunately, installation manual can be found online .\nFixing lower protector\nRear crash bars are not offered by BMW anymore, they are heavy and pretty much ugly so I decided not to get them, but get these protectors instead. Maybe not good as the crash bars but still better than no protection.\n","date":"September 28, 2023","externalUrl":null,"permalink":"/blog/bmw-touring-cases-impact-protection/","section":"Blog","summary":"Are you wondering who would ever write a blog of installation of some rubbery impact protectors for some motorcycle’s side cases? I completely understand you. 😀\nSo why did I write this? I recently bought K1600GT and started looking for some aftermarket parts. But I was surprised that there are actually not many information about some of the products, very often no pictures or just bad quality ones, no videos, quite strange. This specially applies BMW genuine parts. Some forums contain some information but very often without any pictures. All this makes decision to buy something or not very difficult.\n","title":"Side cases' impact protectors for BMW K1600GT","type":"blog"},{"content":"","date":"September 28, 2023","externalUrl":null,"permalink":"/tags/slr3/","section":"Tags","summary":"","title":"Slr3","type":"tags"},{"content":" Motorcycles # Generate MotoGP Calendar For Your Mobile Phone Noise Ban In Austria 10 Best Alps Roads Motorcycle Recalls Accessories and tools # alpha Technik Beta Tools BTR Corbin Denali Electronics - LED headlights Der Bikepolsterer - MedPol-Polsterservice Eiweiss Evotech Performance HEX ezCAN - CAN management of accessories HEX Innovate - Diagnostic Tools Highsider Hornig IBEX Ilium Works Ilmberger Carbon INNOVV - Dash cameras Isotta LabelBike - Tankpads, stickers and decals Laser Tools Mosko Moto Moto-Vision motogadget Motorrad Sattlerei Sam MotoScan - Diagnostic mobile app MTP-Racing MV Motorrad Profi Products - Chain Tools Puig Rabaconda Tire Changers SBV Tools SW-Motech Touratech Triumph Instructions Tuning Parts 24 Unior Tools Weiser - LED indicators Wunderlich Riders\u0026rsquo; Equipment # How to fit a motorcycle helmet Motorcycle helmet fit guide Motorcycle Helmet Buyer\u0026rsquo;s Guide Cardo Communicators Sena Communicators Forcefield Body Armor Camera mounts # Chin Mounts MiBike MotoRadds POV Mounts Camera accessories # BRDRC Falcam Flymile Freewell JJC K\u0026amp;F Concept Neewer Pgytech Puluz SmallRig Sunnylife Telesin Ulanzi Phone mounts # Peak Design Quad Lock SP Connect Routing # HelmTube komoot Kurviger Tourstart Transport # Anhänger Kirchberger ANHÄNGERWIRTZ Autocar Autohaus Möller Balhanger Cochet For-One Trailers Moto Helios Moto Trailers Hi-Q Tools Loading ramp with steps Lorries Marathontrailers Martz motolug Motowippe - Motorcycle rockers Neptun Pit Bull Trailer Restraint System Sawiko - Motorradverladehilfe Schultes - Motorcycle trailers and accessories Stema Temared TREILER - Folding motorcycle trailer Trelex Unitrailer Moto 3 - Folding motorcycle trailer Trainings # 99 Racing School by Kec ADAC Motorcycle Driving Safety Trainings Jochen Schweizer Motorcycle Training König Motorcycle Training MVZ Motorcycle Training Verkehrswacht München e.V. Motorcycle Trainings BMW Motorrad # Original Parts BMW K 1300 R # Hattech - Original Silencer Noise Reduction 94dB Install SW-Motech Pro Tank Ring And Daypack BMW K 1600 GT # BikePenR GT-10-1 K1600 Forum Kleinert - Sidecases inner bags WOMET TECH Wunderlich Triumph Rocket 3 # CarbonFBF Evotech Performance F\u0026amp;F Carbon Hepco \u0026amp; Becker Lamonster Garage MH Carbon Moto Vision - Carbon and Other Parts Motorrad special - Garmin Zumo XT/XT2 Holder mto3 - Carbon Parts R3 Owners TRIK Custom Motorcycle Parts Waase Crash Bars for GT Wunderking Custom XRay Project Kawasaki H2 SX SE # BikePenR GTB-15 Evotech Performance H2SX Riders Klauz Goerz MH Carbon motorrad-ersatzteile24 MTP-Racing probrake Puig Renngrib RSI-Performance Motorsport Sound Control Systems Useful H2SXRiders.net Forum Resources Aprilia Tuono V4 Factory 1100 # 2Wheels-Company AF1 Racing Aprilia Chassis Service Manual 2Q000654 Aprilia Engine Service Manual 2Q000592 Aprilia OEM Accessories Aprilia OnlineShop Aprilia Tuono V4 mirror adapter for Highsider and Mo.view aSpecialParts Bagoros Performance Bonamici Racing Evotech Italy Evotech Performance GSG Mototechnik Highsider Blinkers 3in1 Ilmberger Carbon LabelBike - Tankpads, stickers and decals LighTech LighTech MG Biketec Motostorm MTP-Racing probrake R\u0026amp;G Racing Renngrib Rizoma Stein-Dinse TecBike Top Block Racing UpMap WRS WSC Shop Accessories I may buy # AF1 Racing - Chassis Service Manual AF1 Racing - Tall Windscreen aSpecialParts - GPS Sensor Installation Kit aSpecialParts - GPS Sensor WRS Sport Dark Smoked Windscreen WRS Touring Dark Smoked Windscreen WSC Shop - Rear lights eliminator Guitars # Best IR\u0026rsquo;s Cheap and Easy DIY Guitar Nut Lubricant Fender Stratocaster - How to Setup Your Electric Guitar Fingerpicking Tips To Save Years of Guitar Practice Fretastic - Learn your fretboard Fretmonster - Learn Your Fretboard Guitar Fretboard - Virtual Fretboard Chart with All Notes How to Learn How to Transpose Any Song to Any Key on Your Guitar How to Read Guitar tabs Lead guitar With 2 Easy Square Shapes Music theory for nerds Oolimo - Guitar Chord Analyzer/Identifier PRS - How to Setup Your Electric Guitar Remuda Lite - USB Guitar Amplifier Control App ScaleChords - Chord Identifier (Reverse Chord Finder) Fender Mustang # Linux Tools # Dictum Hosco ","date":"September 23, 2023","externalUrl":null,"permalink":"/links/","section":"","summary":"Motorcycles # Generate MotoGP Calendar For Your Mobile Phone Noise Ban In Austria 10 Best Alps Roads Motorcycle Recalls Accessories and tools # alpha Technik Beta Tools BTR Corbin Denali Electronics - LED headlights Der Bikepolsterer - MedPol-Polsterservice Eiweiss Evotech Performance HEX ezCAN - CAN management of accessories HEX Innovate - Diagnostic Tools Highsider Hornig IBEX Ilium Works Ilmberger Carbon INNOVV - Dash cameras Isotta LabelBike - Tankpads, stickers and decals Laser Tools Mosko Moto Moto-Vision motogadget Motorrad Sattlerei Sam MotoScan - Diagnostic mobile app MTP-Racing MV Motorrad Profi Products - Chain Tools Puig Rabaconda Tire Changers SBV Tools SW-Motech Touratech Triumph Instructions Tuning Parts 24 Unior Tools Weiser - LED indicators Wunderlich Riders’ Equipment # How to fit a motorcycle helmet Motorcycle helmet fit guide Motorcycle Helmet Buyer’s Guide Cardo Communicators Sena Communicators Forcefield Body Armor Camera mounts # Chin Mounts MiBike MotoRadds POV Mounts Camera accessories # BRDRC Falcam Flymile Freewell JJC K\u0026F Concept Neewer Pgytech Puluz SmallRig Sunnylife Telesin Ulanzi Phone mounts # Peak Design Quad Lock SP Connect Routing # HelmTube komoot Kurviger Tourstart Transport # Anhänger Kirchberger ANHÄNGERWIRTZ Autocar Autohaus Möller Balhanger Cochet For-One Trailers Moto Helios Moto Trailers Hi-Q Tools Loading ramp with steps Lorries Marathontrailers Martz motolug Motowippe - Motorcycle rockers Neptun Pit Bull Trailer Restraint System Sawiko - Motorradverladehilfe Schultes - Motorcycle trailers and accessories Stema Temared TREILER - Folding motorcycle trailer Trelex Unitrailer Moto 3 - Folding motorcycle trailer Trainings # 99 Racing School by Kec ADAC Motorcycle Driving Safety Trainings Jochen Schweizer Motorcycle Training König Motorcycle Training MVZ Motorcycle Training Verkehrswacht München e.V. Motorcycle Trainings BMW Motorrad # Original Parts BMW K 1300 R # Hattech - Original Silencer Noise Reduction 94dB Install SW-Motech Pro Tank Ring And Daypack BMW K 1600 GT # BikePenR GT-10-1 K1600 Forum Kleinert - Sidecases inner bags WOMET TECH Wunderlich Triumph Rocket 3 # CarbonFBF Evotech Performance F\u0026F Carbon Hepco \u0026 Becker Lamonster Garage MH Carbon Moto Vision - Carbon and Other Parts Motorrad special - Garmin Zumo XT/XT2 Holder mto3 - Carbon Parts R3 Owners TRIK Custom Motorcycle Parts Waase Crash Bars for GT Wunderking Custom XRay Project Kawasaki H2 SX SE # BikePenR GTB-15 Evotech Performance H2SX Riders Klauz Goerz MH Carbon motorrad-ersatzteile24 MTP-Racing probrake Puig Renngrib RSI-Performance Motorsport Sound Control Systems Useful H2SXRiders.net Forum Resources Aprilia Tuono V4 Factory 1100 # 2Wheels-Company AF1 Racing Aprilia Chassis Service Manual 2Q000654 Aprilia Engine Service Manual 2Q000592 Aprilia OEM Accessories Aprilia OnlineShop Aprilia Tuono V4 mirror adapter for Highsider and Mo.view aSpecialParts Bagoros Performance Bonamici Racing Evotech Italy Evotech Performance GSG Mototechnik Highsider Blinkers 3in1 Ilmberger Carbon LabelBike - Tankpads, stickers and decals LighTech LighTech MG Biketec Motostorm MTP-Racing probrake R\u0026G Racing Renngrib Rizoma Stein-Dinse TecBike Top Block Racing UpMap WRS WSC Shop Accessories I may buy # AF1 Racing - Chassis Service Manual AF1 Racing - Tall Windscreen aSpecialParts - GPS Sensor Installation Kit aSpecialParts - GPS Sensor WRS Sport Dark Smoked Windscreen WRS Touring Dark Smoked Windscreen WSC Shop - Rear lights eliminator Guitars # Best IR’s Cheap and Easy DIY Guitar Nut Lubricant Fender Stratocaster - How to Setup Your Electric Guitar Fingerpicking Tips To Save Years of Guitar Practice Fretastic - Learn your fretboard Fretmonster - Learn Your Fretboard Guitar Fretboard - Virtual Fretboard Chart with All Notes How to Learn How to Transpose Any Song to Any Key on Your Guitar How to Read Guitar tabs Lead guitar With 2 Easy Square Shapes Music theory for nerds Oolimo - Guitar Chord Analyzer/Identifier PRS - How to Setup Your Electric Guitar Remuda Lite - USB Guitar Amplifier Control App ScaleChords - Chord Identifier (Reverse Chord Finder) Fender Mustang # Linux Tools # Dictum Hosco ","title":"Links","type":"page"},{"content":"","date":"September 23, 2023","externalUrl":null,"permalink":"/tags/links/","section":"Tags","summary":"","title":"Links","type":"tags"},{"content":"After quite a while, I decided to blog about my other hobbies, namely motorcycling. In the future, I will more about my past, current and future motorcycles, but the reason for this blog item today is the new generation of the Shoei GT-Air helmets, GT-Air 3 Realm TC-5. I just received this helmet and it looks amazing. Since today, I have been using GT-Air 1, which is a great helmet, but after 5-6 years of usage it was time to get the new one.\nA month or two ago I was searching for a new helmet that could replace the old one and since I am a touring kind of rider, the only logical decision was to get GT-Air 3. Of course, I have also looked at Schubert S3 but then I realized that I have already tried their helmets and they still have a problem of having just two shell sizes. The smaller size is up to the L size and then from size XL they are using the bigger shell. Unfortunately, my helmet size is L and with Schubert that size is too small to me and then XL is to big. The only logical decision was to look again for Shoei since they have three shell sizes.\nAfter some research my thoughts were focused to GT-Air 2 but then I realized it is just ECE 22/05 homologated and not ECE 22/06. I said to myself they must release new versions soon, so let\u0026rsquo;s wait for a while. And yes, I was right. Just few weeks later I found the news on their website that they are about to release the Neotec 3 (flip-up) ang GT-Air 3 (integral) helmets. I was patient enough to wait for it and even there is a shortage at the moment, I got my GT-Air 3 today.\nI didn\u0026rsquo;t get the stickers off yet, I haven\u0026rsquo;t tried it in the ride, but still I want to share with you about how it feels and looks like. Since the weather in Munich is not that nice today anyways, I can just write a blog today. So let\u0026rsquo;s start. As usual, graphics and manufacturing quality of the helmet is great, just traditional Shoei quality. Material inside feels very plushy and comfortable.\nI can\u0026rsquo;t really compare GT-Air 2 and GT-Air 3 since I never had the former one, but GT-Air 3 is quite improved comparing to the first version. The visor and pinlock visor are different, helmet is tighter around the neck which should mean even further reduced noise, sun visor is a little bit bigger but still has more space around the nose. I didn\u0026rsquo;t have problems with the sun visor before, but if they claim it is improved, let\u0026rsquo;s believe so.\nJust like on the GT-Air 2, the rear vent is gone comparing to GT-Air 1, the helmet ventilation to the rear is always opened, which is completely fine with me. Because of ECE 22/06 the visor handle is moved from the left hand side of the visor to the center and I like this change, now you can open the visor with any hand. Another change is that the front ventilation better prevents the bugs to enter the helmet from outside.\nThe biggest difference from the GT-Air 1 is that the integration with communicator is much more efficient even though you have just one option which integrates well, Sena SLR3. I have used Cardo Packtalk with my old helmet, but it is attached to the left chin of the helmet, it is exposed to the airflow, wires do not have any preformed paths through the inside of the helmet and so on. It was basically not a natural addition at that time, it was pretty much new stuff not planned buy the helmet construction.\nHowever, with the GT-Air 3. Sena SLR3 integrates completely into the helmet with no outside obstructions to the airflow. There is a compartment at the rear side where you can mount the Sena\u0026rsquo;s main unit which includes the battery as well, but also provides a possibility to cable charge it without having to set the helmet on the side. Besides that, you can integrate control buttons on the provided slots on the chins and there are also wire routes in the styrofoam.\nI actually got the Sena SLR3 before the helmet but I haven\u0026rsquo;t even opened the box yet. It features Harman Kardon speakers, Bluetooth 5, noise control and so on, but please wait for the details in some of the next posts, stay tuned.\n","date":"September 23, 2023","externalUrl":null,"permalink":"/blog/shoei-gt-air-3/","section":"Blog","summary":"After quite a while, I decided to blog about my other hobbies, namely motorcycling. In the future, I will more about my past, current and future motorcycles, but the reason for this blog item today is the new generation of the Shoei GT-Air helmets, GT-Air 3 Realm TC-5. I just received this helmet and it looks amazing. Since today, I have been using GT-Air 1, which is a great helmet, but after 5-6 years of usage it was time to get the new one.\n","title":"Shoei GT-Air 3","type":"blog"},{"content":"","date":"July 16, 2023","externalUrl":null,"permalink":"/categories/go/","section":"Categories","summary":"","title":"Go","type":"categories"},{"content":"","date":"July 16, 2023","externalUrl":null,"permalink":"/tags/go/","section":"Tags","summary":"","title":"Go","type":"tags"},{"content":"","date":"July 16, 2023","externalUrl":null,"permalink":"/tags/pgx/","section":"Tags","summary":"","title":"Pgx","type":"tags"},{"content":"","date":"July 16, 2023","externalUrl":null,"permalink":"/series/whats-new-in-pgx-v5/","section":"Series","summary":"","title":"What's New in Pgx V5","type":"series"},{"content":"This is the third part of the pgx v5 series. Let\u0026rsquo;s discuss the new features from the title.\nCollectRows and RowToStructByName # CollectRows allow us to fetch an array of rows and set them into a slice of structs. Further, RowToStructByName is a long awaited feature which allows to store a row into a struct. sqlx module became very popular in Go community exactly for this reason, but pgx now supports something similar. RowToStructByName is a generic function of the func(row CollectableRow) (T, error) and it\u0026rsquo;s not the only one of this type, there are also RowTo, RowToStructByPos and RowToStructByNameLax. Under the hood, RowToStructByName is using reflection so it may be slightly slower than classic way of scanning the rows, but if you don\u0026rsquo;t mind this, it is very easy to use. All field names are going to be mapped to lowercased public struct field names and you may also use db struct tags if some field name differs from the struct field name. This explanation may sound difficult, but the following example will actually show that it is actually very easy to use.\npackage main import ( \u0026#34;context\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;os\u0026#34; \u0026#34;github.com/jackc/pgx/v5\u0026#34; \u0026#34;github.com/jackc/pgx/v5/pgtype\u0026#34; \u0026#34;github.com/jackc/pgx/v5/pgxpool\u0026#34; ) type account struct { ID string Username string Role string Address pgtype.Text ZipCode pgtype.Text `db:\u0026#34;zip_code\u0026#34;` } func main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() rows, err := dbpool.Query(ctx, \u0026#34;SELECT * FROM accounts\u0026#34;) if err != nil { exit(\u0026#34;failed query\u0026#34;, err) } accounts, err := pgx.CollectRows(rows, pgx.RowToStructByName[account]) if err != nil { exit(\u0026#34;failed collecting rows\u0026#34;, err) } for _, account := range accounts { fmt.Printf(\u0026#34;%#v\\n\u0026#34;, account) } } func exit(msg string, err error) { fmt.Fprintf(os.Stderr, \u0026#34;%s: %v\\n\u0026#34;, msg, err) os.Exit(1) } As you can see in the account struct, our field name in the accounts table is zip_code and the struct field name is ZipCode. This simple struct tag, db:\u0026quot;zip_code\u0026quot; allows the correct mapping. For other struct fields we didn\u0026rsquo;t need to override the mapping hence we have no tags there. Take care that using CollectRows with many returned records may take lot of memory so you may want switch back to using cursor way of fetching the data row by row any maybe sending it to a channel, so kind of streaming.\nCollectOneRow and RowToStructByPos # CollectOneRow is similar to CollectRows but as the name says, it fetches just one row meaning if your query produces multiple rows, just the first one will be scanned. Instead of using RowToStructByName function, in the next example we are using RowToStructByPos which maps the returned row fields to the public fields of the struct. Take care that the order (position) of fields must match.\nfunc main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() rows, err := dbpool.Query(ctx, \u0026#34;SELECT * FROM accounts ORDER BY id DESC LIMIT 1\u0026#34;) if err != nil { exit(\u0026#34;failed query\u0026#34;, err) } account, err := pgx.CollectOneRow(rows, pgx.RowToStructByPos[account]) if err != nil { exit(\u0026#34;failed collecting rows\u0026#34;, err) } fmt.Printf(\u0026#34;%#v\\n\u0026#34;, account) SQL query in this example fetches the first user account ordered by id which is not quite sensible, but you may want to use this combination with queries that fetch for example single user by username or email, something like that. It\u0026rsquo;s maybe worth mentioning that RowToStructByPos is also using reflection.\nForEachRow # This functions allows to iterate over all returned rows and execute a given function for each one. This is just a nicer way of using for rows.Next() {} loop.\nfunc main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() rows, err := dbpool.Query(ctx, \u0026#34;SELECT id, username, role, address, zip_code FROM accounts\u0026#34;) if err != nil { exit(\u0026#34;failed query\u0026#34;, err) } var ( id, username, role string address, zip pgtype.Text ) pgx.ForEachRow(rows, []any{\u0026amp;id, \u0026amp;username, \u0026amp;role, \u0026amp;address, \u0026amp;zip}, func() error { fmt.Printf(\u0026#34;id: %s username: %s role: %s address: %s, zip: %s\\n\u0026#34;, id, username, role, address.String, zip.String) return nil }) } And here we come to the end of part 3 of pgx v5 and in the next one we are going to take a look at SendBatch. Happy coding.\n","date":"July 16, 2023","externalUrl":null,"permalink":"/blog/pgx-v5-3/","section":"Blog","summary":"This is the third part of the pgx v5 series. Let’s discuss the new features from the title.\nCollectRows and RowToStructByName # CollectRows allow us to fetch an array of rows and set them into a slice of structs. Further, RowToStructByName is a long awaited feature which allows to store a row into a struct. sqlx module became very popular in Go community exactly for this reason, but pgx now supports something similar. RowToStructByName is a generic function of the func(row CollectableRow) (T, error) and it’s not the only one of this type, there are also RowTo, RowToStructByPos and RowToStructByNameLax. Under the hood, RowToStructByName is using reflection so it may be slightly slower than classic way of scanning the rows, but if you don’t mind this, it is very easy to use. All field names are going to be mapped to lowercased public struct field names and you may also use db struct tags if some field name differs from the struct field name. This explanation may sound difficult, but the following example will actually show that it is actually very easy to use.\n","title":"What's new in pgx v5: CollectRows, RowToStructByName, CollectOneRow, RowToStructByPos and ForEachRow","type":"blog"},{"content":"In this second part of the pgx v5 series, we are going to discuss the QueryRewriter interface and NamedArgs. Let\u0026rsquo;s first check out the signature of the Exec method of the pgxpool.Pool struct.\n// Exec acquires a connection from the Pool and executes the given SQL. // SQL can be either a prepared statement name or an SQL string. // Arguments should be referenced positionally from the SQL string as $1, $2, etc. // The acquired connection is returned to the pool when the Exec function returns. func (p *Pool) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error) According to this, we can execute some SQL query by providing the context, SQL query string and arguments to the Exec. But is this the only option? Let\u0026rsquo;s look at this example:\npackage main import ( \u0026#34;context\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;os\u0026#34; \u0026#34;github.com/jackc/pgx/v5\u0026#34; \u0026#34;github.com/jackc/pgx/v5/pgtype\u0026#34; \u0026#34;github.com/jackc/pgx/v5/pgxpool\u0026#34; \u0026#34;github.com/rs/xid\u0026#34; ) type account struct { ID string Username string Role string Address pgtype.Text ZipCode pgtype.Text } func (a *account) RewriteQuery(ctx context.Context, conn *pgx.Conn, sql string, args []any) (newSQL string, newArgs []any, err error) { return `INSERT INTO accounts (id, username, role, address, zip_code) VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING`, []any{a.ID, a.Username, a.Role, a.Address, a.ZipCode}, nil } func main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() user := \u0026amp;account{ ID: xid.New().String(), Username: \u0026#34;simpson\u0026#34;, Role: \u0026#34;user\u0026#34;, Address: pgtype.Text{String: \u0026#34;742 Evergreen Terrace\u0026#34;, Valid: true}, ZipCode: pgtype.Text{String: \u0026#34;80085\u0026#34;, Valid: true}, } if _, err := dbpool.Exec(ctx, \u0026#34;\u0026#34;, user); err != nil { exit(\u0026#34;failed insert\u0026#34;, err) } } func exit(msg string, err error) { fmt.Fprintf(os.Stderr, \u0026#34;%s: %v\\n\u0026#34;, msg, err) os.Exit(1) } QueryRewriter # Here we can see that we called Exec with empty SQL query string. How is this possible? Well, pgx v5 contains an internal magic which checks if an object implements QueryRewriter interface and in such case calls RewriteQuery method on the object. In the example above we really do not rewrite the query but we just generate it. However, if we provided a non empty SQL query string, we could also use this method to rewrite it for whatever reason. Here we could use some complex logic, but in this simple example we have just achieved kind of encapsulation by having insert query inside the object we want to insert into the database.\nNamedArgs # If you have used PostgreSQL previously, you very likely know that is supports parameter placeholders like $1, $2 and so on. This is very useful for prepared statements but also for security reasons. Let\u0026rsquo;s look at this example:\nINSERT INTO accounts (id, username, role, address, zip_code) VALUES ($1, $2, $3, $4, $5) By using placeholders for arguments we can achieve significant performance benefits since we can prepare this query just once and then execute it multiple times using different arguments. pgx prepares statements for us automatically but this is efficient just if we use placeholders. Like said above, the other benefit is that PostgreSQL will also do sanity checks of our arguments so we don\u0026rsquo;t have to check the user input manually but instead let the PostgreSQL do it of us. Yes, this prevents the SQL injection as well.\nOver the top of this, pgx v5 introduces the named arguments or named placeholder. This way we can use names of parameters instead of variables like $1, $2, etc. Here is an example:\nfunc main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() user := account{ ID: xid.New().String(), Username: \u0026#34;simpson\u0026#34;, Role: \u0026#34;user\u0026#34;, Address: pgtype.Text{String: \u0026#34;742 Evergreen Terrace\u0026#34;, Valid: true}, ZipCode: pgtype.Text{String: \u0026#34;80085\u0026#34;, Valid: true}, } if _, err := dbpool.Exec(ctx, \u0026#34;INSERT INTO accounts (id, username, role, address, zip_code) VALUES (@id, @username, @role, @address, @zip)\u0026#34;, pgx.NamedArgs{ \u0026#34;id\u0026#34;: user.ID, \u0026#34;username\u0026#34;: user.Username, \u0026#34;role\u0026#34;: user.Role, \u0026#34;address\u0026#34;: user.Address, \u0026#34;zip\u0026#34;: user.ZipCode, }); err != nil { exit(\u0026#34;failed insert\u0026#34;, err) } } As you can see, the syntax is @name and then instead of passing the arguments we pass the pgx.NamedArgs map with all fields values.\nHere we come to the end of this part and in the next one we are going to discuss about CollectRows, RowToStructByName, CollectOneRow, RowToStructByPos and ForEachRow. Stay tuned.\n","date":"July 15, 2023","externalUrl":null,"permalink":"/blog/pgx-v5-2/","section":"Blog","summary":"In this second part of the pgx v5 series, we are going to discuss the QueryRewriter interface and NamedArgs. Let’s first check out the signature of the Exec method of the pgxpool.Pool struct.\n","title":"What's new in pgx v5: QueryRewriter and NamedArgs","type":"blog"},{"content":"Since some time apt-key is deprecated and lot of Ubuntu 22.04 based systems throws the following warning:\nKey is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details You can easily fix this by properly installing Docker and Kubernetes apt archives public keys:\nwget -qO - https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/docker-archive-keyring.gpg echo \u0026#39;deb [ arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg ] https://download.docker.com/linux/ubuntu jammy stable\u0026#39; | sudo tee /etc/apt/sources.list.d/docker.list wget -qO - https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/kubernetes-archive-keyring.gpg echo \u0026#39;deb [ arch=amd64 signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg ] http://apt.kubernetes.io/ kubernetes-xenial main\u0026#39; | sudo tee /etc/apt/sources.list.d/kubernetes.list Take a look at /etc/apt/sources.list.d and find out if there is also an old source definition and if you find it, just delete it, the new one will suffice. You can also find out if there are duplicates if you run sudo apt-get update. Just delete the old version which doesn\u0026rsquo;t contain signed-by inside.\nIf this is a fresh installation, you can continue with the following commands:\nsudo apt-get update sudo apt-get remove docker docker-engine docker.io containerd runc sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo apt-get install kubectl This will install the newest versions of Docker and kubectl on your desktop. If you take a careful look, it will also install the buildx plugin for Docker which greatly speeds up the builds. If you want to permanently active buildx, just run this command export DOCKER_BUILDKIT=1 and if you want the old way of seeing the build progress, you can also do export BUILDKIT_PROGRESS=plain.\nHowever, if you already had these two installed, you just have to do the upgrade:\nsudo apt-get update sudo apt-get upgrade ","date":"March 18, 2023","externalUrl":null,"permalink":"/blog/install-docker-kubectl-ubuntu-22-04/","section":"Blog","summary":"Since some time apt-key is deprecated and lot of Ubuntu 22.04 based systems throws the following warning:\nKey is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details You can easily fix this by properly installing Docker and Kubernetes apt archives public keys:\n","title":"How to install Docker and kubectl on Ubuntu 22.04 desktop","type":"blog"},{"content":"","date":"March 18, 2023","externalUrl":null,"permalink":"/tags/linux/","section":"Tags","summary":"","title":"Linux","type":"tags"},{"content":"","date":"March 18, 2023","externalUrl":null,"permalink":"/categories/linux-mint/","section":"Categories","summary":"","title":"Linux Mint","type":"categories"},{"content":"","date":"March 18, 2023","externalUrl":null,"permalink":"/tags/mint/","section":"Tags","summary":"","title":"Mint","type":"tags"},{"content":"","date":"March 18, 2023","externalUrl":null,"permalink":"/categories/ubuntu/","section":"Categories","summary":"","title":"Ubuntu","type":"categories"},{"content":"","date":"March 18, 2023","externalUrl":null,"permalink":"/tags/ubuntu/","section":"Tags","summary":"","title":"Ubuntu","type":"tags"},{"content":"Go has very rich standard library which also contains database/sql module with generic interface over SQL databases. Further, lib/pq PostgreSQL driver is fully compatible with database/sql and provides all basic database operations. However, since this is generic implementation over all supported databases, using it is a trade-off not supporting some PostgreSQL specific features. Fans of PostgreSQL (in further text pg) may want more and here comes pgx in help. pgx is a very rich pg driver supporting LISTEN / NOTIFY, COPY, type mapping between pg and Go, all specific pg types, wire protocol and much more.\nIn the latest version v5, maintainer of pgx starting using generics in the project and introduced many new features including:\nnew tracing logger with hooks for tools like OpenTelemetry CollectRows function to collect results into a slice using RowTo* functions CollectOneRow function to collect one row also using RowTo* functions RowToStructByName and RowToStructByPos functions to scan rows into Go struct types ForEachRow function to iterate over resulting rows and perform an arbitrary function QueryRewriter interface and NamedArgs implementation for named query parameters improved SendBatch function It this series we are going to cover all of these changes and try to disclose some of the pgx secrets, specially the new ones. In order to make our code able to access the pg database, we are going to create the following docker-compose.yml file in our project:\nversion: \u0026#39;3.9\u0026#39; services: postgres: image: postgres:15-alpine restart: always volumes: - .docker:/docker-entrypoint-initdb.d environment: - POSTGRES_DB=test - POSTGRES_HOST_AUTH_METHOD=trust ports: - 5432:5432 And also some initial database schema in .docker/schema.sql:\nBEGIN; CREATE DOMAIN zip_code AS TEXT CHECK( VALUE ~ \u0026#39;^\\d{5}$\u0026#39; OR VALUE ~ \u0026#39;^\\d{5}-\\d{4}$\u0026#39; ); CREATE TYPE role AS ENUM (\u0026#39;admin\u0026#39;, \u0026#39;editor\u0026#39;, \u0026#39;user\u0026#39;); CREATE TABLE accounts ( id CHAR(20) PRIMARY KEY CHECK (length(id) = 20), username TEXT UNIQUE NOT NULL CHECK (username != \u0026#39;\u0026#39;), role role NOT NULL, address TEXT, zip_code zip_code ); COMMIT; As you can see in the last snippet, we are going to use some fancy pg features like domain and enum types, constraint checks and xid as a primary key.\nTo initialize Go project, just type go mod init following by the name by your choice, e.g. go mod init pgx5 and create main.go file with the following contents:\npackage main import ( \u0026#34;context\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;os\u0026#34; \u0026#34;github.com/jackc/pgx/v5/pgxpool\u0026#34; ) func main() { ctx := context.Background() dbpool, err := pgxpool.New(ctx, \u0026#34;postgres://postgres@localhost:5432/test\u0026#34;) if err != nil { exit(\u0026#34;failed creating pgx pool\u0026#34;, err) } defer dbpool.Close() } func exit(msg string, err error) { fmt.Fprintf(os.Stderr, \u0026#34;%s: %v\\n\u0026#34;, msg, err) os.Exit(1) } In this snippet we created the pgx connection pool and now we are ready for the next part of the series where we will discuss on QueryRewriter interface and NamedArgs implementation. Stay tuned.\n","date":"December 4, 2022","externalUrl":null,"permalink":"/blog/pgx-v5-1/","section":"Blog","summary":"Go has very rich standard library which also contains database/sql module with generic interface over SQL databases. Further, lib/pq PostgreSQL driver is fully compatible with database/sql and provides all basic database operations. However, since this is generic implementation over all supported databases, using it is a trade-off not supporting some PostgreSQL specific features. Fans of PostgreSQL (in further text pg) may want more and here comes pgx in help. pgx is a very rich pg driver supporting LISTEN / NOTIFY, COPY, type mapping between pg and Go, all specific pg types, wire protocol and much more.\n","title":"What's new in pgx v5: Introduction","type":"blog"},{"content":"Go is over ten years old language but generics (type parameters) are introduced just in the March this year. Hence, still lot of developers avoid using them or have certain problems once decided to give it a try. One of the common problems is how to check the concrete type of a generic parameter, specially of non constrained parameters. So, if you try to do the following, it won\u0026rsquo;t work:\nfunc example[T any](s T) { switch s.(type) { case string: // do something default: // do something else. } } Compiler will just throw an error cannot use type switch on type parameter value s (variable of type T constrained by any). What the heck does this mean? Simply, Go can find out the concrete type just for a variable of type any (alias for interface{}) and our variable in this example is actually of generic type T with constraint any, but this is not the same. The trick how to fix this is simple, you just have to convert the s variable to type any:\nfunc example[T any](s T) { switch any(s).(type) { case string: // do something default: // do something else. } } And voila, it compiles and works as expected. Besides switching on type, you can also assure the type of a variable using similar approach:\nfunc example[T any](s T) { if s, ok := any(s).(string); ok { fmt.Printf(\u0026#34;we got string %s\\n\u0026#34;, s) } } Here is the Go Playground link if you want to practice this yourself.\n","date":"December 3, 2022","externalUrl":null,"permalink":"/blog/check-type-of-generic-parameter/","section":"Blog","summary":"Go is over ten years old language but generics (type parameters) are introduced just in the March this year. Hence, still lot of developers avoid using them or have certain problems once decided to give it a try. One of the common problems is how to check the concrete type of a generic parameter, specially of non constrained parameters. So, if you try to do the following, it won’t work:\n","title":"Check type of generic parameter in Go","type":"blog"},{"content":"","date":"December 3, 2022","externalUrl":null,"permalink":"/tags/generics/","section":"Tags","summary":"","title":"Generics","type":"tags"},{"content":"Lot of the tutorials on the Web show different ways of writing Go HTTP middlewares, but most of them use functional approach meaning using functions that get dependencies as parameters and return HTTP handler function or handler. There is nothing wrong about this, but it can be quite messy to write a complex middlewares like database based authentication and authorization or simply middlewares which have lot of dependencies. In this article I am going to explain how to use more object oriented way of writing such middlewares. Let\u0026rsquo;s start with the basic object oriented middleware example:\ntype Middleware struct { next http.Handler // other dependencies } func NewMiddleware() *Middleware { return \u0026amp;Middleware{} } // Handle wraps handler. Can be called just once. func (m *Middleware) Handle(next http.Handler) http.Handler { m.next = next return m } // ServeHTTP implements http.Handler interface. func (m *Middleware) ServeHTTP(res http.ResponseWriter, req *http.Request) { res.Write([]byte(\u0026#34;do something before next\\n\u0026#34;)) m.next.ServeHTTP(res, req) res.Write([]byte(\u0026#34;do something after next\\n\u0026#34;)) } // Wrap wraps handler function. Can be called just once. func (m *Middleware) Wrap(next http.HandlerFunc) http.HandlerFunc { m.next = next return m.ServeHTTP } Here we can use NewMiddleware constructor to pass all dependencies like database connection pool and so on. We can use returning middleware object in several different ways. Now let\u0026rsquo;s check how we can use this middleware.\n1. Wrap single endpoint # func main() { welcome := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\u0026#34;welcome\\n\u0026#34;)) } m := NewMiddleware() http.HandleFunc(\u0026#34;/\u0026#34;, m.Wrap(welcome)) http.ListenAndServe(\u0026#34;:3000\u0026#34;, nil) } This method is intended to be used just to wrap a single handler function. If you use it multiple times on the same middleware instance, it may produce unwanted results because each call to Wrap method would override the next handler function. If you have to wrap multiple functions, please check the examples number 3, 4 and 5.\n2. Handle single endpoint # welcome := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\u0026#34;welcome\\n\u0026#34;)) } m := NewMiddleware() http.Handle(\u0026#34;/\u0026#34;, m.Handle(http.HandlerFunc(welcome))) http.ListenAndServe(\u0026#34;:3000\u0026#34;, nil) In this example you can see how to use Handle method. Again, this can be used just once similar as noted in the previous example.\n3. Handle multiple endpoints # It this example we are going to use Handle method to wrap calls to all available endpoints.\nfunc main() { welcome := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\u0026#34;welcome\\n\u0026#34;)) } m := NewMiddleware() mux := http.NewServeMux() mux.HandleFunc(\u0026#34;/\u0026#34;, welcome) http.ListenAndServe(\u0026#34;:3000\u0026#34;, m.Handle(mux)) } As you can see, we wrap the whole multiplexer in this example so all handler functions (http.HandleFunc) and handlers (http.Handle) would be wrapped in the middleware. This is probably the most useful example so far and it is intended to be used for authentication, authorization and similar middlewares which are gonna be used by multiple endpoints.\n4. Wrap multiple sub endpoints # func main() { welcome := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\u0026#34;welcome\\n\u0026#34;)) } m := NewMiddleware() mux := http.NewServeMux() subMux := http.NewServeMux() mux.HandleFunc(\u0026#34;/\u0026#34;, welcome) subMux.Handle(\u0026#34;/welcome\u0026#34;, m.Wrap(welcome)) mux.Handle(\u0026#34;/welcome\u0026#34;, subMux) http.ListenAndServe(\u0026#34;:3000\u0026#34;, mux) } Here we have an example where / endpoint is not wrapped by middleware and /welcome endpoint is wrapped. Just take care that you call Wrap of Handle just once on one instance of the middleware.\n5. Handle with Chi # As Chi is Go idiomatic router, I would like to show you how you can use this pattern with it.\nfunc main() { welcome := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(\u0026#34;welcome\\n\u0026#34;)) } r := chi.NewRouter() m := NewMiddleware() r.Use(m.Handle) r.Get(\u0026#34;/\u0026#34;, welcome) http.ListenAndServe(\u0026#34;:3000\u0026#34;, r) } Similar as in the example 3, we use Handle method to apply the middleware to all further endpoints.\nOnce more, take care that multiple calls to Handle or Wrap methods on the same instance of the middleware may produce unpredicted behavior because you may override the next handler. Of course, you can make your Handle and Wrap methods panic if next is already set in order to avoid confusion.\n","date":"November 13, 2022","externalUrl":null,"permalink":"/blog/complex-go-middlewares/","section":"Blog","summary":"Lot of the tutorials on the Web show different ways of writing Go HTTP middlewares, but most of them use functional approach meaning using functions that get dependencies as parameters and return HTTP handler function or handler. There is nothing wrong about this, but it can be quite messy to write a complex middlewares like database based authentication and authorization or simply middlewares which have lot of dependencies. In this article I am going to explain how to use more object oriented way of writing such middlewares. Let’s start with the basic object oriented middleware example:\n","title":"How to write complex HTTP middlewares in Go","type":"blog"},{"content":"","date":"November 13, 2022","externalUrl":null,"permalink":"/tags/http/","section":"Tags","summary":"","title":"Http","type":"tags"},{"content":"","date":"November 13, 2022","externalUrl":null,"permalink":"/tags/middleware/","section":"Tags","summary":"","title":"Middleware","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/actions/","section":"Tags","summary":"","title":"Actions","type":"tags"},{"content":"In the previous blog post I described how to define GitHub Actions pipeline to benefit from caching Rust dependencies and container images\u0026rsquo; layers. But the final result may also depend on your Dockerfile. Namely, Docker Buildx Action supports BuildKit and buildx and in order to benefit from this, your Dockerfile has to explicitly cache layers. Actually, this is quite easy to achieve, let\u0026rsquo;s see the example:\n# syntax=docker/dockerfile:1.3 FROM rust:1.61.0 AS builder ARG TARGETPLATFORM WORKDIR /root RUN --mount=type=cache,target=/usr/local/cargo/registry,id=${TARGETPLATFORM} \\ cargo install cargo-strip COPY . . RUN --mount=type=cache,target=/usr/local/cargo/registry,id=${TARGETPLATFORM} --mount=type=cache,target=/root/target,id=${TARGETPLATFORM} \\ cargo build --release \u0026amp;\u0026amp; \\ cargo strip \u0026amp;\u0026amp; \\ mv /root/target/release/\u0026lt;your-crate-name\u0026gt; /root FROM gcr.io/distroless/cc-debian11 COPY --from=builder /root/\u0026lt;your-crate-name\u0026gt; / ENTRYPOINT [\u0026#34;./\u0026lt;your-crate-name\u0026gt;\u0026#34;] EXPOSE 3000 The crucial part here is the annotation # syntax=docker/dockerfile:1.4, this will turn on the advanced features. ARG TARGETPLATFORM is optional and will be used just if you have matrix build with different platforms. If you build for single platform, you can remove this line and also ,id=${TARGETPLATFORM} from the remaining lines of the Dockerfile. The next important point is --mount=type=cache,target=/usr/local/cargo/registry. This defines which path should be actually cached as container image layer. Replace \u0026lt;your-crate-name\u0026gt; placeholder with your real crate name and you are ready to go. If you expose your service on a different port than 3000, please modify the final line EXPOSE 3000 to the correct port, or if there are no exposed ports, just delete the line.\nIf you haven\u0026rsquo;t yet achieved the speedup of GitHub Actions pipelines explained in my previous post, this modification will further accelerate your build. It is important to mention that these improvements won\u0026rsquo;t affect just GitHub Actions builds, but any builds where BuildKit is enabled, including your local builds. In order to activate this on your local machine, just run this command in terminal:\nexport DOCKER_BUILDKIT=1 And if you don\u0026rsquo;t like the new output during the build, you may revert to previous behavior:\nexport BUILDKIT_PROGRESS=plain To preserve the settings, add these commands to your .bashrc or .zshrc file.\nIn version 1.4 of the Dockerfile syntax, there are even more available options. To find out more information, click here .\n","date":"June 3, 2022","externalUrl":null,"permalink":"/blog/rust-container-image-buildkit-buildx/","section":"Blog","summary":"In the previous blog post I described how to define GitHub Actions pipeline to benefit from caching Rust dependencies and container images’ layers. But the final result may also depend on your Dockerfile. Namely, Docker Buildx Action supports BuildKit and buildx and in order to benefit from this, your Dockerfile has to explicitly cache layers. Actually, this is quite easy to achieve, let’s see the example:\n","title":"Build Rust container images faster using layer caching","type":"blog"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/buildkit/","section":"Tags","summary":"","title":"Buildkit","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/buildx/","section":"Tags","summary":"","title":"Buildx","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/dockerfile/","section":"Tags","summary":"","title":"Dockerfile","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/github/","section":"Tags","summary":"","title":"Github","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/performance/","section":"Tags","summary":"","title":"Performance","type":"tags"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/categories/rust/","section":"Categories","summary":"","title":"Rust","type":"categories"},{"content":"","date":"June 3, 2022","externalUrl":null,"permalink":"/tags/rust/","section":"Tags","summary":"","title":"Rust","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/cache/","section":"Tags","summary":"","title":"Cache","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/faster/","section":"Tags","summary":"","title":"Faster","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/firmware/","section":"Tags","summary":"","title":"Firmware","type":"tags"},{"content":"Rust is a great programming language, but it\u0026rsquo;s compiler is known to be slow. The main reason is that it checks so many things during the compilation in order to provides memory and concurrency safety. Like in many other cases, pipelines may be speeded up by caching, but it is very important to set the caching properly, otherwise it won\u0026rsquo;t help. Besides compiling your code may be slow, you also may want to use some cargo tools to lint and check your code and this will require to be compiled as well, if you don\u0026rsquo;t want to download binaries. Some popular tools are:\ncargo-deny - lint dependencies cargo-outdated - find out outdated dependencies cargo-udeps - find out unused dependencies cargo-audit - search for security vulnerabilities cargo-pants - search for security vulnerabilities (by sonatype ) I keep all my projects at GitHub, both public and private and I like the features of GitHub Actions . They support caching and for this purpose I use actions/cache . Fortunately, there are actions/cache snippets for all major languages including Rust . Before I implemented this action properly, my caching didn\u0026rsquo;t work so I had lint, check and test actions runtime at up to 15 minutes. After fixing it, all of these steps last just ~1 minute. But let\u0026rsquo;s show the reusable workflow that I use:\non: workflow_call: inputs: rust-version: type: string required: false default: nightly jobs: check: runs-on: ubuntu-latest steps: - name: Check out uses: actions/checkout@v3 - name: Install Rust uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ inputs.rust-version }} override: true components: rustfmt, clippy - name: Set up cargo cache uses: actions/cache@v3 continue-on-error: false with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-${{ hashFiles(\u0026#39;**/Cargo.lock\u0026#39;) }} restore-keys: ${{ runner.os }}-cargo- - name: Lint run: | cargo fmt --all -- --check cargo clippy -- -D warnings - name: Install cargo check tools run: | cargo install --locked cargo-deny || true cargo install --locked cargo-outdated || true cargo install --locked cargo-udeps || true cargo install --locked cargo-audit || true cargo install --locked cargo-pants || true - name: Check run: | cargo deny check cargo outdated --exit-code 1 cargo udeps rm -rf ~/.cargo/advisory-db cargo audit cargo pants - name: Test run: cargo test As you can see, I just used the recommended setup for actions/cache but then some cargo install commands used to fail in subsequent runs when binary is already installed in ~/.cargo/bin. So this is why I had to ignore these errors by adding || true after each cargo install command. There is also some funny error related to the cached advisory-db, but as temporary solution I just delete it before running cargo audit and cargo pants. I will address it properly at some time later.\nThis workflow can be invoked from any Rust project by:\nname: pipeline on: push: pull_request: workflow_dispatch: jobs: check: uses: ectobit/reusable-workflows/.github/workflows/rust-check.yaml@main But this is not all, what about the build, actually specifically docker build? By using registry type of caching in docker/build-push-action , I speeded up the builds from ~50 to ~2 minutes. At the end, my project\u0026rsquo;s pipeline speeded up from ~65 minutes in total to just ~2 minutes. Yeah, this is ~30 times faster, great. Again, here is the reusable workflow which may be used by other projects as well, not just Rust:\non: workflow_call: inputs: image: type: string required: true platforms: type: string required: false default: linux/amd64,linux/arm64 license: type: string required: false default: BSD-2-Clause-Patent vendor: type: string required: false default: ectobit.com hadolint-dockerfile: type: string required: false default: Dockerfile hadolint-ignore: type: string required: false default: \u0026#39;\u0026#39; build-args: type: string required: false default: \u0026#39;\u0026#39; secrets: container-registry-username: required: true container-registry-password: required: true jobs: build: runs-on: ubuntu-latest steps: - name: Check out uses: actions/checkout@v3 - name: Lint Dockerfile with ignore if: ${{ inputs.hadolint-ignore != \u0026#39;\u0026#39;}} uses: hadolint/hadolint-action@v2.1.0 with: dockerfile: ${{ inputs.hadolint-dockerfile }} ignore: ${{ inputs.hadolint-ignore }} - name: Lint Dockerfile if: ${{ inputs.hadolint-ignore == \u0026#39;\u0026#39;}} uses: hadolint/hadolint-action@v2.1.0 with: dockerfile: ${{ inputs.hadolint-dockerfile }} - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2.0.0 - name: Set up tags id: meta uses: docker/metadata-action@v4 with: images: ${{ inputs.image }} labels: | org.opencontainers.image.licenses=${{ inputs.license }} org.opencontainers.image.vendor=${{ inputs.vendor }} tags: | type=schedule type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} type=edge type=sha - name: Login to container registry uses: docker/login-action@v2.0.0 with: username: ${{ secrets.container-registry-username }} password: ${{ secrets.container-registry-password }} - name: Build and push image with build args to container registry uses: docker/build-push-action@v3.0.0 if: ${{ inputs.build-args != \u0026#39;\u0026#39;}} with: build-args: ${{ inputs.build-args }} platforms: ${{ inputs.platforms }} push: ${{ github.event_name != \u0026#39;pull_request\u0026#39; }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ inputs.image }}:buildcache cache-to: type=registry,ref=${{ inputs.image }}:buildcache,mode=max - name: Build and push image to container registry uses: docker/build-push-action@v3.0.0 if: ${{ inputs.build-args == \u0026#39;\u0026#39;}} with: platforms: ${{ inputs.platforms }} push: ${{ github.event_name != \u0026#39;pull_request\u0026#39; }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ inputs.image }}:buildcache cache-to: type=registry,ref=${{ inputs.image }}:buildcache,mode=max This can be invoked in your project by:\nbuild: uses: ectobit/reusable-workflows/.github/workflows/buildx.yaml@main needs: check with: image: ectobit/bond secrets: container-registry-username: ${{ secrets.REGISTRY_USERNAME }} container-registry-password: ${{ secrets.REGISTRY_PASSWORD }} That\u0026rsquo;s all folks, you may try to use this in your projects and have faster build times.\n","date":"May 18, 2022","externalUrl":null,"permalink":"/blog/speed-up-github-actions-rust-pipelines/","section":"Blog","summary":"Rust is a great programming language, but it’s compiler is known to be slow. The main reason is that it checks so many things during the compilation in order to provides memory and concurrency safety. Like in many other cases, pipelines may be speeded up by caching, but it is very important to set the caching properly, otherwise it won’t help. Besides compiling your code may be slow, you also may want to use some cargo tools to lint and check your code and this will require to be compiled as well, if you don’t want to download binaries. Some popular tools are:\n","title":"How I speeded up my Rust builds on GitHub ~30 times","type":"blog"},{"content":"If you are running default kernel with your Ubuntu or Linux Mint installation, you probably won\u0026rsquo;t face this problem during kernel updates because all packages are coming from the official distribution sources. However, if you like to run the newest Linux kernels and update them using mainline kernel installer, you may get warning possible missing firmware during the installation.\nFew days ago I got this warning on my Linux Mint 20.3 Una while installing kernel 5.17.7. In most of the cases this warning won\u0026rsquo;t affect normal functionality of your Linux machine, but if you hate warnings, like I do, here is what you can do. I guess you regularly update your apt packages, but still new kernels may complain, which further means you may need even newer package. In my case I had to install linux-firmware package from Jammy Jellyfish , the newest LTS Ubuntu, Ubuntu 22.04 LTS.\nsudo add-apt-repository \u0026#34;deb http://ca.archive.ubuntu.com/ubuntu jammy main\u0026#34; sudo apt install --fix-broken sudo apt-get install linux-firmware sudo add-apt-repository --remove \u0026#34;deb http://ca.archive.ubuntu.com/ubuntu jammy main\u0026#34; So, first add jammy repository (temporarily), then fix broken dependencies, install the bleeding edge linux-firmware and remove the repository if you don\u0026rsquo;t want to update any other package. You may also want to reinstall your newest kernel and find out that there are no such warnings.\nBuy the way, in the meantime kernels 5.7.18 and 5.7.19 are released, but my Intel AC 9560 won\u0026rsquo;t work properly, so I skipped them and wait for some further version to find out if this is fixed or I need to do something about it myself. I may update you about this problem, so let\u0026rsquo;s stay in touch.\n","date":"May 18, 2022","externalUrl":null,"permalink":"/blog/linux-mint-ubuntu-possible-missing-firmware/","section":"Blog","summary":"If you are running default kernel with your Ubuntu or Linux Mint installation, you probably won’t face this problem during kernel updates because all packages are coming from the official distribution sources. However, if you like to run the newest Linux kernels and update them using mainline kernel installer, you may get warning possible missing firmware during the installation.\n","title":"How to fix possible missing firmware warning during kernel update on Linux Mint","type":"blog"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/kernel/","section":"Tags","summary":"","title":"Kernel","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/mainland/","section":"Tags","summary":"","title":"Mainland","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/missing/","section":"Tags","summary":"","title":"Missing","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/problem/","section":"Tags","summary":"","title":"Problem","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/reusable/","section":"Tags","summary":"","title":"Reusable","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/update/","section":"Tags","summary":"","title":"Update","type":"tags"},{"content":"","date":"May 18, 2022","externalUrl":null,"permalink":"/tags/workflows/","section":"Tags","summary":"","title":"Workflows","type":"tags"},{"content":"Few days ago Go 1.18beta1 was released and with it the first official generics support. I was embarrassed with standard Go\u0026rsquo;s HTTP handler functions for quite a while. If you are not familiar with Go, you probably wonder why, but if you are familiar, I believe you know. For example, implementing a RESTful API using idiomatic Go requires lot of code repetition in order to JSON decode request bodies and JSON encode response bodies. This problem was possible to solve in some way but never in such elegant way like using generics.\nFirst, let\u0026rsquo;s take a look how Go\u0026rsquo;s idiomatic HTTP handler functions look like: func(res http.ResponseWriter, req *http.Request)\nres is just an interface providing several methods to set response and req is a concrete implementation of Go\u0026rsquo;s HTTP request. In order to get path or query parameters, you have to play around with req, but let\u0026rsquo;s forget now about that. Even worse is that in your RESTful API you don\u0026rsquo;t get concrete decoded JSON request body as concrete type, but instead you have to parse it every time. Then at the end of the request you have do encode your data to JSON response body again. So, lot\u0026rsquo;s of encoding and decoding which can\u0026rsquo;t be hidden in an easy way, at least not without generics. It\u0026rsquo;s not the point to hide these steps, but to focus to business logic and not to irrelevant tasks like this. When I say hide it\u0026rsquo;s not about magic, but about having a framework which does this for you so you can focus to the business login. If you write lot of API\u0026rsquo;s in Go, you probably realize this without my explanation. It\u0026rsquo;s so boring to handle JSON encoding/decoding and possible errors. Let\u0026rsquo;s focus to the real stuff.\nIn order to overcome this, I made gap today, small package which provides a wrapper over custom gap\u0026rsquo;s HTTP handler functions providing idiomatic HTTP functions at the end. So, it can be used with Go\u0026rsquo;s standard library HTTP implementation. gap\u0026rsquo;s handler functions accept custom request with concrete type and also custom response with concrete data type. Here is the signature: func(*gap.Request[I]) *gap.Response[O]. Generic type I here is the type of the JSON request body and O is the type of the data returned within the gap.Response. Besides the data, this custom response contains also HTTP status code and errors that may have ocurred. So, your custom handler would become concrete request type as input and you may return concrete response type as output. And the render function of gap would take care to send the JSON response to the client.\nBut, let\u0026rsquo;s jump into coding, then it will be more clear what is this about. Here is a gap\u0026rsquo;s handler example:\ntype hello struct { Message string `json:\u0026#34;message\u0026#34;` } helloHandler := func(req *gap.Request[struct{}]) *gap.Response[hello] { return \u0026amp;gap.Response[hello]{ Data: \u0026amp;hello{ Message: \u0026#34;Hello world!\u0026#34;, }, } } Because our helloHandler is GET endpoint, our concrete request body will be just struct{}, so no body. However, our response will contain data of hello type. What does it mean? Here is the gap.Response type:\ntype Response[T any] struct { StatusCode int `json:\u0026#34;-\u0026#34;` Data *T `json:\u0026#34;data,omitempty\u0026#34;` Errors []string `json:\u0026#34;errors,omitempty\u0026#34;` } So, *gap.Response[hello] in the snippet above means that we are returning *gap.Response type with data field of type hello, which is private type in this case. In order to use our helloHandler as standard Go\u0026rsquo;s HTTP handler, it\u0026rsquo;s enough just to wrap it using gap.Wrap. Besides the custom HTTP handler function, gap.Wrap requires a logger with lax.Logger interface, but this is not relevant to this article, let\u0026rsquo;s focus on the API. Here is how wrapping looks like:\nlog, _ := lax.NewDefaultZapAdapter(\u0026#34;json\u0026#34;, \u0026#34;debug\u0026#34;) http.HandleFunc(\u0026#34;/hello\u0026#34;, gap.Wrap(helloHandler, log)) Our handler function will be triggered on /hello path, will receive no body (struct{}) and will send gap.Response with gap.Response.Data of type hello (concrete private type in this case, but can be exported as well). Both JSON request body decoding and JSON response body encoding will be done by gap package.\nFor further documentation how to use this package, please check this test and this example test . At the end I would like to mention that this is project is in a very early stage and the API may suffer lot of modifications in the future. So, gap should not be used in production until the first release, but it can show the power of Go\u0026rsquo;s generics and give you ideas how to improve Go\u0026rsquo;s RESTful API\u0026rsquo;s further. Feel free to contribute to the project.\n","date":"December 19, 2021","externalUrl":null,"permalink":"/blog/custom-generic-go-http-handlers/","section":"Blog","summary":"Few days ago Go 1.18beta1 was released and with it the first official generics support. I was embarrassed with standard Go’s HTTP handler functions for quite a while. If you are not familiar with Go, you probably wonder why, but if you are familiar, I believe you know. For example, implementing a RESTful API using idiomatic Go requires lot of code repetition in order to JSON decode request bodies and JSON encode response bodies. This problem was possible to solve in some way but never in such elegant way like using generics.\n","title":"Custom Go HTTP handlers using generics","type":"blog"},{"content":"Most of the date and time related crates like time or chrono already implement serde traits making date or datetime parsing quite easy. This applies just if the format is standard, but what happens if the format is not standard? Let\u0026rsquo;s say we want to parse datetime looking like this 2021-10-24T07:48:26.389646Z. There is no timezone information so I decided to try the PrimitiveDateTime type from time crate. I didn\u0026rsquo;t consider using chrono at the moment because of the RUSTSEC-2020-0159 problem.\nFortunately, this is also not that difficult to solve, you just need to implement a custom parsing function. Let\u0026rsquo;s see the example code:\nuse anyhow::Result; use log::warn; use serde::de::Deserializer; use serde::Deserialize; use time::PrimitiveDateTime; // ... #[derive(Default, Debug, Clone, Deserialize)] pub struct Message { pub id: u64, #[serde(deserialize_with = \u0026#34;primitive_date_time_from_str\u0026#34;)] pub sent: Option\u0026lt;PrimitiveDateTime\u0026gt;, } fn primitive_date_time_from_str\u0026lt;\u0026#39;de, D: Deserializer\u0026lt;\u0026#39;de\u0026gt;\u0026gt;(d: D) -\u0026gt; Result\u0026lt;Option\u0026lt;PrimitiveDateTime\u0026gt;, D::Error\u0026gt; { let s: Option\u0026lt;String\u0026gt; = Deserialize::deserialize(d)?; if s.is_none() { return Ok(None); } let format = time::macros::format_description!( \u0026#34;[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]Z\u0026#34; ); match time::PrimitiveDateTime::parse(\u0026amp;s.unwrap(), \u0026amp;format) { Ok(o) =\u0026gt; Ok(Some(o)), Err(err) =\u0026gt; { warn!(\u0026#34;{}\u0026#34;, err); Ok(None) } } } Using serde deserialize_with field attribute, we can define which function to call in order to parse this field. In our case, we have:\n#[serde(deserialize_with = \u0026#34;primitive_date_time_from_str\u0026#34;)] pub sent: Option\u0026lt;PrimitiveDateTime\u0026gt;, This will provide the call to our function primitive_date_time_from_str. The signature of this function is important, so you have to use it in your implementations as well. In this concrete function, we first fetch the sent field value as Option\u0026lt;String\u0026gt;. Then we define our custom format using the format_description! macro. There is also a similar function in time crate, but the benefit of using the macro is that this happens at compile time. Finally, we parse our string using the provided format and return Ok(Some(o)) in case everything is fine or just Ok(None) if there are parsing problems. You may want to return an error in your use case, but here it was enough to return None because there were no cases of errors.\n","date":"October 24, 2021","externalUrl":null,"permalink":"/blog/parsing-custom-datetime-in-rust/","section":"Blog","summary":"Most of the date and time related crates like time or chrono already implement serde traits making date or datetime parsing quite easy. This applies just if the format is standard, but what happens if the format is not standard? Let’s say we want to parse datetime looking like this 2021-10-24T07:48:26.389646Z. There is no timezone information so I decided to try the PrimitiveDateTime type from time crate. I didn’t consider using chrono at the moment because of the RUSTSEC-2020-0159 problem.\n","title":"Parsing custom datetime format in Rust using serde","type":"blog"},{"content":"","date":"October 23, 2021","externalUrl":null,"permalink":"/categories/docker/","section":"Categories","summary":"","title":"Docker","type":"categories"},{"content":"","date":"October 23, 2021","externalUrl":null,"permalink":"/tags/docker-compose/","section":"Tags","summary":"","title":"Docker-Compose","type":"tags"},{"content":"","date":"October 23, 2021","externalUrl":null,"permalink":"/tags/microservice/","section":"Tags","summary":"","title":"Microservice","type":"tags"},{"content":"Go is very attractive language for microservices\u0026rsquo; development, but using acim/go-reflex image and docker-compose you can run multiple microservices including your gateway on your local machine. This image can run virtually any Go server based application and also reacts on changes in the code and recompiles the binary on the fly. If you want to debug your microservices\u0026rsquo; stack or develop a new feature where you have to touch multiple services, this is very good tool to do so. Let\u0026rsquo;s take a look at the docker-compose stack example:\nversion: \u0026#39;3.8\u0026#39; services: postgres: container_name: my-postgres image: postgres:12 restart: always environment: - POSTGRES_USER=me - POSTGRES_PASSWORD=pass - POSTGRES_DB=test ports: - 5432:5432 volumes: - postgres:/var/lib/postgresql/data service-1: container_name: my-service-1 image: acim/go-reflex restart: always depends_on: - postgres environment: - RACE_DETECTOR=1 - MY_POSTGRES_HOST=postgres - MY_POSTGRES_USER=me - MY_POSTGRES_PASSWORD=pass ports: - 3001:3000 - 50051:50051 volumes: - ../my-service-1:/app stdin_open: true tty: true service-2: container_name: my-service-2 image: acim/go-reflex restart: always depends_on: - service-1 environment: - RACE_DETECTOR=1 - MY_SERVICE_1_HOST=service-1 ports: - 3002:3000 - 50052:50051 volumes: - ../my-service-2:/app stdin_open: true tty: true api-gw: container_name: my-api-gw image: acim/go-reflex restart: always depends_on: - service-1 - service-2 environment: - RACE_DETECTOR=1 - MY_SERVICE_1_HOST=service-1 - MY_SERVICE_2_HOST=service-2 ports: - 8080:3000 volumes: - .:/app stdin_open: true tty: true volumes: postgres: The stack above contains 4 images. We assume that the docker-compose.yml file lives in the root of the my-gw project and that other microservices exist at the same level as the API gateway, so they are in the same parent directory.\nIn the first image we setup PostgreSQL database as our hypothetical dependency. We map it to host port 5432 so that we can access the data for debugging purposes. Then we configure our service-1. We assume it depends on postgres and it serves REST on port 3000 and gRPC on port 50051. We map these ports to host ports 3001 and 50051 respectively also for debugging purposes. By the way, wombat is really nice tool to debug your gRPC services. The RACE_DETECTOR environment variable is used by acim/go-reflex image to turn on go build --race flag. The crucial part in the configuration is the volume. There we map ../my-service-1 to /app directory in the container. This will allow that acim/go-reflex image works correctly and reacts to the changes in ../my-service-1 and recompiles and restarts the binary. In the next step we configure our service-2 where we also assume that it also talks REST and gRPC so we map these to ports 3002 and 50051 on the host. Now we map the volume to ../my-service-2, the location of our other microservice. Our application probably needs to know the location of my-service-1 which we pass using MY_SERVICE_1_HOST environment variable. Finally we configure the API gateway application which is our exposed service which talks to SPA, for example. Again nothing special there, everything works just by magic of acim/go-reflex. You can find further documentation here . All feature requests are welcome, just open an issue. It is important to say that the image is available for amd64 and arm64 architectures.\nP.S. If you like the project, please star it on GitHub and Docker Hub . 🙂\n","date":"October 23, 2021","externalUrl":null,"permalink":"/blog/running-microservice-stack-in-docker/","section":"Blog","summary":"Go is very attractive language for microservices’ development, but using acim/go-reflex image and docker-compose you can run multiple microservices including your gateway on your local machine. This image can run virtually any Go server based application and also reacts on changes in the code and recompiles the binary on the fly. If you want to debug your microservices’ stack or develop a new feature where you have to touch multiple services, this is very good tool to do so. Let’s take a look at the docker-compose stack example:\n","title":"Running stack of microservices using docker-compose and acim/go-reflex image","type":"blog"},{"content":"","date":"October 20, 2021","externalUrl":null,"permalink":"/tags/json/","section":"Tags","summary":"","title":"JSON","type":"tags"},{"content":"Parsing JSON in a proper way requires representing the JSON data in a structured format so that the language can find out which fields have to be parsed and which type they are. The Rust way of representing the structured data are so called structs . We could make appropriate structs manually, but thanks to the great online converter, transform.tools , we can generate the structs very easily. In this article we will parse data from songsterr.com , a web site with guitar tabs. Let\u0026rsquo;s make the request to their API. Just click here and look at the data in your browser. Scarry? Not really, just copy all data and paste here at the left hand side box. Rust structs should appear on the right side almost immediately.\nuse serde_derive::Deserialize; use serde_derive::Serialize; pub type Root = Vec\u0026lt;Root2\u0026gt;; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Root2 { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub title: String, pub artist: Artist, pub chords_present: bool, pub tab_types: Vec\u0026lt;String\u0026gt;, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Artist { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub name_without_the_prefix: String, pub use_the_prefix: bool, pub name: String, } What can we see from here? First, the root of the JSON body is an array or vector in Rust. This array contains many objects of type Root2 which is actually a song and it contains an Artist object underneath. Let\u0026rsquo;s rename the objects in the following way:\nuse serde_derive::Deserialize; use serde_derive::Serialize; pub type Response = Vec\u0026lt;Song\u0026gt;; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Song { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub title: String, pub artist: Artist, pub chords_present: bool, pub tab_types: Vec\u0026lt;String\u0026gt;, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Artist { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub name_without_the_prefix: String, pub use_the_prefix: bool, pub name: String, } It already looks better. The idea behind this is that we now make the same query in Rust, fetch the date, parse it using these structs and display for example song titles, artist names and tabs types for each of them. Let\u0026rsquo;s start from scratch. To create a project in Rust, just type cargo new tabs and open this directory in your favorite IDE. Open src/main.rs and copy previous code block except the first two (use) lines. You can paste the content bellow the main function which was generated by cargo. By the way, cargo is a powerful dependencies management tool for go and it should be installed all together with rust if you follow these instructions . For the next step we will need cargo-edit plugin to be able to easily add dependencies to our project. Just type cargo install cargo-edit and then type cargo add serde and cargo add serde_json. serde is famous Rust library for serializing and deserializing data and serde_json is it\u0026rsquo;s partner library to do this for JSON format. These two commands will just add these two dependencies in Cargo.toml file. Open the file and modify the line which imports serde to look like following:\nserde = { version = \u0026#34;1.0.130\u0026#34;, features = [\u0026#34;derive\u0026#34;] } Of course, you can keep the version previously defined by cargo if it\u0026rsquo;s differ from the version at the time of writing this article. Now type cargo run and if everything compiles correctly, you should see Hello, world! which was also generated by cargo. At this point it is important that you do not get any compiler errors. If so, we can continue. If not, just copy the following block over your main.rs contents and the next block over your Cargo.toml.\nuse serde::{Deserialize,Serialize}; fn main() { println!(\u0026#34;Hello, world!\u0026#34;); } pub type Response = Vec\u0026lt;Song\u0026gt;; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Song { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub title: String, pub artist: Artist, pub chords_present: bool, pub tab_types: Vec\u0026lt;String\u0026gt;, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Artist { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub name_without_the_prefix: String, pub use_the_prefix: bool, pub name: String, } [package] name = \u0026#34;tabs\u0026#34; version = \u0026#34;0.1.0\u0026#34; edition = \u0026#34;2018\u0026#34; # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde = { version = \u0026#34;1.0.130\u0026#34;, features = [\u0026#34;derive\u0026#34;] } serde_json = \u0026#34;1.0.68\u0026#34; In order to parse JSON, we have to fetch JSON contents first and we will do this using reqwest , another famous Rust library. Type cargo add reqwest and modify the new entry in Cargo.toml to look like this:\nreqwest = { version = \u0026#34;0.11.6\u0026#34;, features = [\u0026#34;blocking\u0026#34;, \u0026#34;json\u0026#34;] } Again, if you are reading this when a new version is present, just keep the previously set version and add the features part.\nIn order that we can use reqwest and make real HTTP request to fetch the data, we have to add new use statement at the beginning of main.rs:\nuse reqwest::blocking::get; Now we can fetch the data just using one line of code. Delete the content of the main function and put the following:\nlet res = get(\u0026#34;https://www.songsterr.com/a/ra/songs.json?pattern=Beatles\u0026#34;).unwrap(); let songs = res.json::\u0026lt;Response\u0026gt;().unwrap(); for song in songs { println!(\u0026#34;Song: {} Artist: {} Tab types: {:?}\u0026#34;, song.title, song.artist.name, song.tab_types); } Run your program by cargo run and voila, you should see lot of data on your screen. But let\u0026rsquo;s explain now what is going on here. First we make a get request to fetch the data and resolve the result by unwrap() method. Take care that this is not proper error handling and that you should handle errors much better in a real program. But for the simplicity, I did it this way. So, unwrap() will panic if something goes wrong (i.e. remote API not available).\nIn the next line we parse JSON using generic json\u0026lt;T\u0026gt; method by telling that we want to use our Response struct to collect the data. Again, we unwrap to get the result (assign the songs variable) and panic in case that parsing fails.\nFinally, we loop over songs vector (array) and display some data that we need. {} is a placeholder in Rust to display basic types like strings and numbers and {:?} is a placeholder do display (actually debug) the more complex data like vectors, structs, enums, etc. Take care that we used println!() and not println(). When you see an exclamation mark at the end of some function, this means that you are actually using a macro. And macro means that the real code for this will be generated by compiler at the compilation time. But this is quite complex topic for this article, we will discuss it at some later point.\nIf you have any trouble running this, be sure that the contents of main.rs and Cargo.toml are the following:\nuse serde::{Deserialize,Serialize}; use reqwest::blocking::get; fn main() { let res = get(\u0026#34;https://www.songsterr.com/a/ra/songs.json?pattern=Beatles\u0026#34;).unwrap(); let songs = res.json::\u0026lt;Response\u0026gt;().unwrap(); for song in songs { println!(\u0026#34;Song: {} Artist: {} Tab types: {:?}\u0026#34;, song.title, song.artist.name, song.tab_types); } } pub type Response = Vec\u0026lt;Song\u0026gt;; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Song { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub title: String, pub artist: Artist, pub chords_present: bool, pub tab_types: Vec\u0026lt;String\u0026gt;, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = \u0026#34;camelCase\u0026#34;)] pub struct Artist { pub id: i64, #[serde(rename = \u0026#34;type\u0026#34;)] pub type_field: String, pub name_without_the_prefix: String, pub use_the_prefix: bool, pub name: String, } [package] name = \u0026#34;tabs\u0026#34; version = \u0026#34;0.1.0\u0026#34; edition = \u0026#34;2018\u0026#34; # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] reqwest = { version = \u0026#34;0.11.6\u0026#34;, features = [\u0026#34;blocking\u0026#34;, \u0026#34;json\u0026#34;] } serde = { version = \u0026#34;1.0.130\u0026#34;, features = [\u0026#34;derive\u0026#34;] } serde_json = \u0026#34;1.0.68\u0026#34; And that\u0026rsquo;s all, happy rusting. 🙂\n","date":"October 20, 2021","externalUrl":null,"permalink":"/blog/parsing-json-in-rust/","section":"Blog","summary":"Parsing JSON in a proper way requires representing the JSON data in a structured format so that the language can find out which fields have to be parsed and which type they are. The Rust way of representing the structured data are so called structs . We could make appropriate structs manually, but thanks to the great online converter, transform.tools , we can generate the structs very easily. In this article we will parse data from songsterr.com , a web site with guitar tabs. Let’s make the request to their API. Just click here and look at the data in your browser. Scarry? Not really, just copy all data and paste here at the left hand side box. Rust structs should appear on the right side almost immediately.\n","title":"Parsing JSON in Rust easily explained","type":"blog"},{"content":"","date":"October 12, 2021","externalUrl":null,"permalink":"/tags/amplifier/","section":"Tags","summary":"","title":"Amplifier","type":"tags"},{"content":"","date":"October 12, 2021","externalUrl":null,"permalink":"/tags/guitar/","section":"Tags","summary":"","title":"Guitar","type":"tags"},{"content":"","date":"October 12, 2021","externalUrl":null,"permalink":"/categories/guitars/","section":"Categories","summary":"","title":"Guitars","type":"categories"},{"content":"","date":"October 12, 2021","externalUrl":null,"permalink":"/tags/mighty-plug/","section":"Tags","summary":"","title":"Mighty-Plug","type":"tags"},{"content":"","date":"October 12, 2021","externalUrl":null,"permalink":"/tags/nux/","section":"Tags","summary":"","title":"Nux","type":"tags"},{"content":"Guitarists are fans of loud amplifiers and music in general, but this is not the case with all neighbors. 😆\nI started silent practicing with plugging the headphones to my Fender Mustang and this worked well, of course, but I always had to seat close to the amplifier which was not that practical. By searching the Internet I found out about different Vox headphones amplifiers which offer just one kind of sound so if you want to have for example clean, blues and metal sounds, you need to buy three different devices. This also didn\u0026rsquo;t seem practical even though these devices are quite cheap.\nActually, soon after buying my Fender Mustang GTX100 I saw a nice headphones amplifier from Fender, Mustang Micro. I decided to take a look again but then I figured out that stocks are empty, guitarists just bought all of them. I regretted that I didn\u0026rsquo;t buy it immediately after it showed up, but at the time my son convinced me that I don\u0026rsquo;t need it.\nSo, I continued my search and found NUX Mighty Plug. I tried to find out how it compares with Fender Mustang Micro, but I couldn\u0026rsquo;t find any comparison review at the time. But as Micro was not available, I decided to go for Mighty Plug whatsoever.\nMighty Plug connects to your phone via two bluetooth channels. One is used for controlling the sound via the application and another is used as bluetooth MIDI. Here you can see Bluetooth connection indicators for both channels and the indicator for battery status. Unfortunately, charging port is USB micro and not USB-C but it can also be used to connect to your PC or tablet as an audio device. This way you can easily record your playing.\nOn the other side there are reset and power/mute buttons. I had to reset the device just once so far. It was just like frozen and didn\u0026rsquo;t react on pressing buttons but after the reset everything worked well again. Guitar jack is flexible and can easily be connected to virtually any active or passive electric guitar or bass.\nThere is just one button to control the sound modeling and by successive pressing it changes the color on the button indicating the selected model. Unfortunately, there is no volume button but you can control it over the application and set the preset volumes for each model. Using the app you can control so many parameters and store your preferences to be used the next time you play. The sound quality is very good for some models and not that good for some other, but as this is fully configurable, you could theoretically setup your favorite sounds. It\u0026rsquo;s worth mentioning that the same phone application can also be used to control your other NUX amplifiers.\nThere is also an open-source application called Mightier Amp which claims to allow even more settings by I haven\u0026rsquo;t tried it so far even though I installed it so that I don\u0026rsquo;t forget the name. Once I test it I may post the review on this blog.\nIn the meanwhile from the time I bought the Mighty Plug, a YouTube video comparing Fender Mustang Micro and NUX Mighty Plug appeared. Even though I didn\u0026rsquo;t test Micro, I would say that overall Nux Mighty Plug is better if you don\u0026rsquo;t mind using the phone application. In case you want it simple, Fender Micro would be a better choice. Micro may also have better preset sounds, but Mighty Plug is configurable so you could achieve whatever you want. If we include the price in the contest, then Mighty Plug is a hands down winner. I planned to buy Fender Micro as well once it becomes available on the market again, but in the meantime I changed my decision. Why? You will be able to read in some of the following posts on this blog. 🙂\nThis is no button, just a rubber to prevent scratches.\nSpecs: # 13 amp models with TSAC-HD White-Box algorithm 19 Impulse Response files with 512 samples resolution Rechargeable lithium battery with 4 hours playing time Dual Mode Bluetooth 4.2 metronome, 10 drum beat patterns and backtracks USB Audio Stream Control by mobile application Mighty Amp ","date":"October 12, 2021","externalUrl":null,"permalink":"/blog/nux-mighty-plug/","section":"Blog","summary":"Guitarists are fans of loud amplifiers and music in general, but this is not the case with all neighbors. 😆\nI started silent practicing with plugging the headphones to my Fender Mustang and this worked well, of course, but I always had to seat close to the amplifier which was not that practical. By searching the Internet I found out about different Vox headphones amplifiers which offer just one kind of sound so if you want to have for example clean, blues and metal sounds, you need to buy three different devices. This also didn’t seem practical even though these devices are quite cheap.\n","title":"NUX Mighty Plug","type":"blog"},{"content":"","date":"October 2, 2021","externalUrl":null,"permalink":"/tags/firefox/","section":"Tags","summary":"","title":"Firefox","type":"tags"},{"content":"This problem was bugging me for quite a while and today I finally decided to address it. There are lot of advices online to try to run Firefox in safe mode and see if that fixes the problem, so I tried that first but it didn\u0026rsquo;t help. Safe mode actually just turns off extensions, but in my case it didn\u0026rsquo;t help.\nI found out that the easiest way to reproduce the problem was to run YouTube video in one window and after that open another window with eBay. After few seconds crackling and popping always started. I run audio mainly via HDMI to my monitor, but as I have external DAC I decided to try that audio output and yes, it worked without problems. So, it seemed something was wrong with PulseAudio over HDMI.\nAfter some investigation I found out that these two settings of Firefox may fix the problem:\nreader.parse-on-load.enabled media.webspeech.synth.enabled Just type about:config in your Firefox URL line and set them to false. In my case just disabling media.webspeech.synth fixed the problem, but I still set both of these to false.\nSo, the main cause for the trouble was Firefox\u0026rsquo;s Web Speech API. If you wish, you can also completely uninstall this feature:\nkillall speech-dispatcher sudo apt remove speech-dispatcher Finally restart your browser. This may help someone.\n","date":"October 2, 2021","externalUrl":null,"permalink":"/blog/linux-mint-firefox-sound-problem/","section":"Blog","summary":"This problem was bugging me for quite a while and today I finally decided to address it. There are lot of advices online to try to run Firefox in safe mode and see if that fixes the problem, so I tried that first but it didn’t help. Safe mode actually just turns off extensions, but in my case it didn’t help.\n","title":"Firefox audio crackling and popping on Linux Mint","type":"blog"},{"content":"","date":"October 2, 2021","externalUrl":null,"permalink":"/tags/prs/","section":"Tags","summary":"","title":"Prs","type":"tags"},{"content":"After getting the Strat and Yamaha keyboard, I still felt something is missing. Of course, I wanted a Les Paul as well. 😃\nLike always, I investigated a lot but it was still hard to decide which model to buy. I looked at all Les Paul series, I read lot of articles and my conclusion was that it is quite risky to get an original one because of the neck problems. There are just so many neck cracks over the Internet including YouTube. So I decided to look for alternatives and at the end found out that PRS SE 245 would be the best guitar for me. It doesn\u0026rsquo;t have neck problems, but it is still approximately the same scale as Les Paul and I could get one for quite affordable price. I made the decision at the beginning of July and my Charcoal Burst arrived on 08.07.2021.\nAt the day of arrival I was not at home so I asked my son to come to my apartment and wait for the delivery. Of course, like all young people he was late and I got notification that the package is delivered. I asked him again to go there and find out where is the guitar but fortunately it was just in front of the door. My neighborhood in Munich is quite nice so there were no problems with missing packages. My son just put the guitar inside because I asked him not to open it. Few days later I opened it myself and found out so beautiful guitar. PRS really did a great job, charcoal burst looks so nice, the veneer top shows great wood patterns, fake wooden binding is also so cool, fret work is perfect, strings bend so easily. I couldn\u0026rsquo;t find any imperfection, Cort Indonesia did so great work for PRS.\nLike you see at the pictures, I also got PRS locking tuners which I replaced few weeks later. Original tuners were just fine, but locking tuners were so cheap that I couldn\u0026rsquo;t resist. In order to put the Gruvgear\u0026rsquo;s Fretwedge, I had to remove the truss rod cover. So, at the moment of writing this article, the guitar is already modified. 😃\nPRS guitars are really great value, even SE series were properly QC-ed. The gigbag delivered with the guitar is also very good, better than the one I got with Fender Stratocaster.\nSpecs: # Body: flamed maple top veneer, bevelled maple top, mahogany back Neck: mahogany, wide fat shape radius 10\u0026quot; Fingerboard: rosewood with birds inlays, 22 frets Scale Length: 24.5\u0026quot; (622 mm) Nut: plastic, width: 1.6875\u0026quot; (42.8 mm) Pickups: 2 x humbucking 245 S Controls: volume and tone for each pickup, 3-way switch Bridge: adjustable stoptail Hardware finish: nickel Tuning machines: PRS designed, modified to PRS SE toplocking ","date":"October 2, 2021","externalUrl":null,"permalink":"/blog/prs-se-245/","section":"Blog","summary":"After getting the Strat and Yamaha keyboard, I still felt something is missing. Of course, I wanted a Les Paul as well. 😃\n","title":"PRS SE 245","type":"blog"},{"content":"","date":"October 2, 2021","externalUrl":null,"permalink":"/tags/se-245/","section":"Tags","summary":"","title":"Se-245","type":"tags"},{"content":"","date":"September 15, 2021","externalUrl":null,"permalink":"/tags/ez-300/","section":"Tags","summary":"","title":"Ez-300","type":"tags"},{"content":"","date":"September 15, 2021","externalUrl":null,"permalink":"/tags/keyboard/","section":"Tags","summary":"","title":"Keyboard","type":"tags"},{"content":"","date":"September 15, 2021","externalUrl":null,"permalink":"/tags/piano/","section":"Tags","summary":"","title":"Piano","type":"tags"},{"content":"","date":"September 15, 2021","externalUrl":null,"permalink":"/tags/yamaha/","section":"Tags","summary":"","title":"Yamaha","type":"tags"},{"content":"I have heard many advises that the best way to learn to play music and visualize it would be to play keyboard, so I decided to get one. Of course, I didn\u0026rsquo;t have plans to become a great keyboard or piano player, nothing like that, but just to get one for fun. I know about Yamaha, Roland and Korg from my childhood but again, after so many years I had to discover what would be the best buy for a beginner. After lot of readings I came up to Yamaha PSR-E373. I almost bought it, but somehow I continued researching Yamaha\u0026rsquo;s models and found out EZ-300. This is almost the same keyboard as PSR-E373, but with illuminated keys as a help to learn playing. The price difference was minor, so I decided to go for EZ-300. It arrived on 01.06.2021.\nBoth of the mentioned instruments are the newest generation of Yamahas and include the newest version of grand piano sample, which seem to be better than on the older and more expensive models. I always liked the sound of classic piano so I couldn\u0026rsquo;t resist to get a simulated version. It really sounds great played on EZ-300 and for sure it is much easier to play than the real one. Besides this, EZ-300 features touch-sensitive keys, fingering guide, keyboard split, 622 instrument voices, 205 styles, 150 arpeggio types, etc. I am focused more to guitar playing, but I hade some fun with this keyboard and will continue learning.\nI also bought the L-2C stand, FC-5 sustain pedal and DC-110 dust cover. I advice everyone to get these accessories as well. The stand is really a good quality one, very stable even not being expensive. The sustain pedal allows some advanced playing and it is always good idea to protect stuff that you love from the dust. For the keyboard I really think it is the great one to learn playing, probably the best one on the market at this time. Yamaha also offers a 3 months free subscription to the flowkey .\n","date":"September 15, 2021","externalUrl":null,"permalink":"/blog/yamaha-ez-300/","section":"Blog","summary":"I have heard many advises that the best way to learn to play music and visualize it would be to play keyboard, so I decided to get one. Of course, I didn’t have plans to become a great keyboard or piano player, nothing like that, but just to get one for fun. I know about Yamaha, Roland and Korg from my childhood but again, after so many years I had to discover what would be the best buy for a beginner. After lot of readings I came up to Yamaha PSR-E373. I almost bought it, but somehow I continued researching Yamaha’s models and found out EZ-300. This is almost the same keyboard as PSR-E373, but with illuminated keys as a help to learn playing. The price difference was minor, so I decided to go for EZ-300. It arrived on 01.06.2021.\n","title":"Yamaha EZ-300","type":"blog"},{"content":"","date":"September 7, 2021","externalUrl":null,"permalink":"/tags/polytune/","section":"Tags","summary":"","title":"Polytune","type":"tags"},{"content":"Even though I have a tuner on my modulated amplifier, I wanted to get a clip tuner so that I can use it on any guitar including acoustic ones. After some research I found out the one which shows tuning of all six strings at once. If there is some string out of tune, you can immediately see which one and quickly tune it up. The name of this magical tuner is TC Electronic Polytune Clip. It comes in two colors, black and white, but I decided to get the black one. Somehow I think that white gadgets are too fancy and the color probably influenced by Apple.\nThis tuner supports strobe and chromatic modes, but also several tuning modes: E, Eb, D, Db, C, Bf, B, F, Gb, G, Ab and A. The display has adaptive orientation and also automatically switches between polytune mode (all 6 strings) or single string mode. Besides guitar, it also supports bass tuning. Finally, it supports auto shut off for the better battery (CR2032) life. I can recommend this tiny device, it\u0026rsquo;s really cool.\n","date":"September 7, 2021","externalUrl":null,"permalink":"/blog/tc-electronic-polytune-clip/","section":"Blog","summary":"Even though I have a tuner on my modulated amplifier, I wanted to get a clip tuner so that I can use it on any guitar including acoustic ones. After some research I found out the one which shows tuning of all six strings at once. If there is some string out of tune, you can immediately see which one and quickly tune it up. The name of this magical tuner is TC Electronic Polytune Clip. It comes in two colors, black and white, but I decided to get the black one. Somehow I think that white gadgets are too fancy and the color probably influenced by Apple.\n","title":"TC Electronic PolyTune Clip Tuner","type":"blog"},{"content":"","date":"September 7, 2021","externalUrl":null,"permalink":"/tags/tc-electronic/","section":"Tags","summary":"","title":"Tc-Electronic","type":"tags"},{"content":"","date":"September 7, 2021","externalUrl":null,"permalink":"/tags/tuner/","section":"Tags","summary":"","title":"Tuner","type":"tags"},{"content":"","date":"September 6, 2021","externalUrl":null,"permalink":"/tags/fender/","section":"Tags","summary":"","title":"Fender","type":"tags"},{"content":"Although my son had Fender Mustang I, I wanted more trendy amplifier with wi-fi and bluetooth features being able to download the effects and so on. After some research, I found out that there are two options, either Boss Katana or some newer Fender Mustang model. First I looked at the Fender GT series and later found out that there is even newer line, GTX. After reading some reviews and comparisons, I decided to get Mustang GTX50, but then I realized that more powerful model GTX100 comes with the GTX-7 foot switch and that the price difference is not that big. Yes, I got GTX100 even though I do not need 100W in my apartment, my neighbors would not like that I use each watt. It arrived the same day as my Stratocaster.\nThe amp has really nice sound, you can hear the whole spectrum of an electric guitar and the effects are really good. You can simply download an effect by the song name and you start sounding like the real. It\u0026rsquo;s that easy, no hassle with different pedals and settings. The preset effects already give wide variety of styles, but the option to download apparently any effect is really cool.\nThe interface is very intuitive and it is easy to use without reading the manual.\nI tried the looper just once and it is quite easy to use it. It\u0026rsquo;s a pity that there are no drums, but you can play them by Fender Tone app. However, to practice, you can just play a song from your phone via bluetooth directly to the amplifier.\nSpecs: # Models: Fender classics like the Blues Jr and Vibro King, as well as other amplifiers including JC Clean and Silver Jubilee Effects: Models of classic Overdrive, Fuzz, Delay and Pitch Shift effects specially-designed 12-inch Celestion® speaker 200 onboard user presets that can be modified for any style of music Fender TONE 3.0 mobile application for deep editing, preset browsing from the Fender Tone community, preset back-up and restore, and more Upgraded seven-button foot switch featuring individual bank up and down functions and easy effects selection, as well as a tap tempo and 60-second looper ","date":"September 6, 2021","externalUrl":null,"permalink":"/blog/fender-mustang/","section":"Blog","summary":"Although my son had Fender Mustang I, I wanted more trendy amplifier with wi-fi and bluetooth features being able to download the effects and so on. After some research, I found out that there are two options, either Boss Katana or some newer Fender Mustang model. First I looked at the Fender GT series and later found out that there is even newer line, GTX. After reading some reviews and comparisons, I decided to get Mustang GTX50, but then I realized that more powerful model GTX100 comes with the GTX-7 foot switch and that the price difference is not that big. Yes, I got GTX100 even though I do not need 100W in my apartment, my neighbors would not like that I use each watt. It arrived the same day as my Stratocaster.\n","title":"Fender Mustang GTX100","type":"blog"},{"content":"","date":"September 6, 2021","externalUrl":null,"permalink":"/tags/mustang/","section":"Tags","summary":"","title":"Mustang","type":"tags"},{"content":"As a beginner in playing guitar for the second time in my life, I searched for help online and found Fender Play service. I subscribed on the 1st of April and after 5 months of using it, I can really say that this is a great help for beginners, but once you reach medium level or you are close to it, it\u0026rsquo;s not that worth anymore. It is useful to learn some music theory although you can find much more details for free on YouTube. However, Fender Play is nicely organized and provides ability to advance quite quickly close to the medium level. I would recommend it for all beginners, but at the moment it is enough to pay for one year subscription and then just cancel it. If they provide more advanced tutorials in the future it may be worth resubscribing.\n","date":"August 29, 2021","externalUrl":null,"permalink":"/blog/fender-play/","section":"Blog","summary":"As a beginner in playing guitar for the second time in my life, I searched for help online and found Fender Play service. I subscribed on the 1st of April and after 5 months of using it, I can really say that this is a great help for beginners, but once you reach medium level or you are close to it, it’s not that worth anymore. It is useful to learn some music theory although you can find much more details for free on YouTube. However, Fender Play is nicely organized and provides ability to advance quite quickly close to the medium level. I would recommend it for all beginners, but at the moment it is enough to pay for one year subscription and then just cancel it. If they provide more advanced tutorials in the future it may be worth resubscribing.\n","title":"Fender Play Subscription","type":"blog"},{"content":"","date":"August 29, 2021","externalUrl":null,"permalink":"/tags/play/","section":"Tags","summary":"","title":"Play","type":"tags"},{"content":"As I child, I dreamed of having real Stratocaster and the time has finally come. I looked online at many Strats but one special caught my eye. I didn’t want a vintage guitar, I develop modern software so I wanted a modern guitar as well.\nI respect the quality of stuff, so getting something made in Japan sounded really good. The decision was made and I ordered it. My dream came true on 17.03.2021 and I opened it together with my son. He was so curious as well.\nThis is a limited series not available in Germany anymore (not in black color). Having two humbuckers, it has really great sound and the best of all is the satin finished neck. Touching the neck feels like touching something so smooth and precious. It\u0026rsquo;s pretty light weight comparing to vintage Stratocasters and keeps tuning really good thanks to the locking tuners.\nThe intonation was not quite perfect and I still didn\u0026rsquo;t set it up, but the bridge allows this and I will do it once I have enough time. Otherwise, finish of the guitar is great and I have no complaints, it is just perfect.\nSpecs: # Body: alder with polyester finish Neck: maple with satin polyurethane finish, compound back shape modern C to D Fingerboard: selected rosewood, compound radius 9.5\u0026quot;-14\u0026quot;, 22 medium jumbo frets Scale Length: 25.5\u0026quot; (648 mm) Nut: bone, width: 1.675\u0026quot; (42.5 mm) Pickups: 2 x modern modified humbucking type I Controls: master volume, neck pickup tone, bridge pickup tone, knurled flat-top knobs, 3-way switch Bridge: 2-point deluxe synchronized tremolo with pop-in arm Hardware finish: nickel/chrome Tuning machines: deluxe cast/sealed locking ","date":"August 28, 2021","externalUrl":null,"permalink":"/blog/fender-strat/","section":"Blog","summary":"As I child, I dreamed of having real Stratocaster and the time has finally come. I looked online at many Strats but one special caught my eye. I didn’t want a vintage guitar, I develop modern software so I wanted a modern guitar as well.\n","title":"Fender Made in Japan Modern Stratocaster HH","type":"blog"},{"content":"","date":"August 28, 2021","externalUrl":null,"permalink":"/tags/humbucker/","section":"Tags","summary":"","title":"Humbucker","type":"tags"},{"content":"","date":"August 28, 2021","externalUrl":null,"permalink":"/tags/stratocaster/","section":"Tags","summary":"","title":"Stratocaster","type":"tags"},{"content":"I played guitar as a child, even performed at my primary school’s festival. So why did I actually stop playing guitar?\nAt a time, guitars were really expensive and my parents bought me a beginners acoustic guitar which was quite bad even though it was still relatively expensive. The action was too high and this started being worse during the time. I figured out I could fix this a little bit by inserting a folded paper between the neck and the body which helped but it was still not good. I had quite some pain in my finger so I slowly stopped playing.\nThen my grandfather bought me a used electric guitar with home amplifier. The action was much better so I started playing again. I was probably like 15 or 16 at the time. It was quite difficult to learn playing some new song in the non-internet era, but I was still trying. After a year or two, under the influence from heavy metal guitarists, I wanted to reshape the body and the headstock so that it looks more like the ones played by my idols at the time. I disassembled it and started reshaping. I finished the rough part but then I got pneumonia followed by severe fever. I saw a mouse in my room and tried to kill it using the guitar’s neck. Unfortunately I broke the neck without killing the mice. Even worse, the day after I really couldn’t figure out did I really see the mouse or it was just an illusion because of the fever. At the time there was no way for me to get a new neck so this project was cancelled and I was forced to stop playing.\nLater I became a software engineer, I got married and started getting children, one daugter and two sons at the end. Like 15 years ago, my older son showed the interest to play guitar so I decided to get him a decent beginners guitar. Under advise of a salesman in Belgrade, we got Yamaha F310P. He started learning but I still played his guitar very seldom, maybe 2-3 times per year. Some years later he wanted an electric guitar, so I again got him a decent instrument, Fender Squier Classic Vibe Stratocaster \u0026rsquo;60s and Fender Mustang I amp. But, I still played very seldom.\nEarlier this year, as a 51 years old, I started thinking to restart playing. The idea literally came out of nowhere and I kept the secret for some time. I was looking for guitars, amplifiers, pedals and other equipment and got a feeling that I need a really good instrument which will motivate me to play. After a month of two of discovering the world of modern instruments, I told to my older son that I am considering to buy a real Fender Stratocaster and restart playing. He told me that this was the best idea of my life, so with his support there were no further barriers to get a relatively expensive instrument. Which one, you will find out in my next story.\n","date":"July 18, 2021","externalUrl":null,"permalink":"/blog/midlife-guitar/","section":"Blog","summary":"I played guitar as a child, even performed at my primary school’s festival. So why did I actually stop playing guitar?\nAt a time, guitars were really expensive and my parents bought me a beginners acoustic guitar which was quite bad even though it was still relatively expensive. The action was too high and this started being worse during the time. I figured out I could fix this a little bit by inserting a folded paper between the neck and the body which helped but it was still not good. I had quite some pain in my finger so I slowly stopped playing.\n","title":"Midlife Guitar","type":"blog"},{"content":"","date":"March 16, 2021","externalUrl":null,"permalink":"/tags/golang/","section":"Tags","summary":"","title":"Golang","type":"tags"},{"content":"","date":"March 16, 2021","externalUrl":null,"permalink":"/tags/vscode/","section":"Tags","summary":"","title":"Vscode","type":"tags"},{"content":"According to lot of online polls, Visual Studio Code is the most popular IDE among Go developers. You can start Go development immediately after installing Go extension for VSCode, but some tuning may make your life easier. First of all, you may want to format the source code and reorganize imports automatically on each file save or code paste. In order to do so, put the following JSON snippet in your settings.json:\n{ \u0026#34;[go]\u0026#34;: { \u0026#34;editor.codeActionsOnSave\u0026#34;: { \u0026#34;source.organizeImports\u0026#34;: true } }, \u0026#34;[go.mod]\u0026#34;: { \u0026#34;editor.codeActionsOnSave\u0026#34;: { \u0026#34;source.organizeImports\u0026#34;: true } }, \u0026#34;editor.find.addExtraSpaceOnTop\u0026#34;: false, \u0026#34;editor.formatOnPaste\u0026#34;: true, \u0026#34;editor.formatOnSave\u0026#34;: true, \u0026#34;files.autoSave\u0026#34;: \u0026#34;onFocusChange\u0026#34;, \u0026#34;files.insertFinalNewline\u0026#34;: true, \u0026#34;files.trimTrailingWhitespace\u0026#34;: true, \u0026#34;go.autocompleteUnimportedPackages\u0026#34;: true } Second, you may want to configure whether to do test coverage on test run and whether to do build on save. I prefer not to build on save and do the coverage on test run. I also appreciate the help of linters and prefer the most comprehensive one, golangci-lint :\n{ \u0026#34;go.buildOnSave\u0026#34;: \u0026#34;off\u0026#34;, \u0026#34;go.coverOnSingleTest\u0026#34;: true, \u0026#34;go.coverOnSingleTestFile\u0026#34;: true, \u0026#34;go.lintFlags\u0026#34;: [\u0026#34;--fast\u0026#34;], \u0026#34;go.lintTool\u0026#34;: \u0026#34;golangci-lint\u0026#34; } Third, you can tweak some git related stuff:\n{ \u0026#34;diffEditor.ignoreTrimWhitespace\u0026#34;: true, \u0026#34;git.autofetch\u0026#34;: true, \u0026#34;git.enableSmartCommit\u0026#34;: true } Fourth, you may want to set ruler to 120 characters, which is recommended line length for writing Go code:\n{ \u0026#34;editor.rulers\u0026#34;: [120] } Finally, if you want your VSCode to look even nicer, you can use the following cosmetic settings:\n{ \u0026#34;breadcrumbs.enabled\u0026#34;: true, \u0026#34;editor.cursorBlinking\u0026#34;: \u0026#34;phase\u0026#34;, \u0026#34;editor.fontFamily\u0026#34;: \u0026#34;\u0026#39;JetBrainsMono Nerd Font\u0026#39;\u0026#34;, \u0026#34;editor.fontLigatures\u0026#34;: true, \u0026#34;editor.fontSize\u0026#34;: 14, \u0026#34;editor.letterSpacing\u0026#34;: 0.4, \u0026#34;editor.smoothScrolling\u0026#34;: true, \u0026#34;terminal.integrated.fontSize\u0026#34;: 14 } As you can see, my favorite font at the moment is JetBrainsMono Nerd Font . Nerd Fonts is a collection of popular programming fonts patched by lot of glyphs (icons). These fonts are not useful just for VSCode, but you can also use them in your terminal. I would also recommend Night Owl and Material Icon themes.\nIt may be opinionated, but I also prefer to disable the minimap and use blank file on VSCode start.\n{ \u0026#34;editor.minimap.enabled\u0026#34;: false, \u0026#34;workbench.startupEditor\u0026#34;: \u0026#34;newUntitledFile\u0026#34; } At the end of this article I also want to mention that I actually use VSCodium , which is open source version of VSCode and has no tracking.\n","date":"March 16, 2021","externalUrl":null,"permalink":"/blog/vscode-go/","section":"Blog","summary":"According to lot of online polls, Visual Studio Code is the most popular IDE among Go developers. You can start Go development immediately after installing Go extension for VSCode, but some tuning may make your life easier. First of all, you may want to format the source code and reorganize imports automatically on each file save or code paste. In order to do so, put the following JSON snippet in your settings.json:\n","title":"VSCode setup for Go developers","type":"blog"},{"content":"","date":"March 16, 2021","externalUrl":null,"permalink":"/tags/vscodium/","section":"Tags","summary":"","title":"Vscodium","type":"tags"},{"content":"In the very early adoption of Go by the open source community, lot of developers already suggested the lack of generics. However, some other claimed that simplicity of Go shouldn\u0026rsquo;t be compromised by generics. Few days ago, the never ending discussions pro and contra generics are finally over. The proposal is accepted and we can expect generics in Go 1.18 somewhere in spring of 2022. You may wonder why does it take that long, but this is not just about the compiler but also some parts of the standard library may need to be rewritten in order to replace the old code which could benefit from generics.\nWhat will generics bring to us? In my opinion, lot of good features and much better abstraction. I think that generics are a must for static typed languages. Simplicity is nice, but is Go really simple without generics? Let\u0026rsquo;s check this on an example of maps. If you want to implement kind of generic, string keyed map, you would probably write something like this:\n1func NewMap() *Map { 2\treturn \u0026amp;Map{ 3\tinternal: make(map[string]interface{}), 4\t} 5} 6 7func (m *Map) Get(key string) (interface{}, bool) { 8\tm.RLock() 9\tresult, ok := m.internal[key] 10\tm.RUnlock() 11\treturn result, ok 12} 13 14func (m *Map) Set(key string, value interface{}) { 15\tm.Lock() 16\tm.internal[key] = value 17\tm.Unlock() 18} 19 20func (m *Map) Delete(key string) { 21\tm.Lock() 22\tdelete(m.internal, key) 23\tm.Unlock() 24} 25 26func (m *Map) Keys() []string { 27\tm.Lock() 28\tks := make([]string, 0, len(m.internal)) 29\tfor k, _ := range m.internal { 30\tks = append(ks, k) 31\t} 32\tm.Unlock() 33\treturn ks 34} By using empty interfaces we can use this map with basically any value type. But, after retrieving a value, we always have to do type assertion and this makes code less readable. With this implementation our map could also contain values of different types which makes things even more complicated and less strict. Let\u0026rsquo;s look at the example usage:\n1func main() { 2\tm := NewMap() 3 4\tm.Set(\u0026#34;hello\u0026#34;, \u0026#34;world\u0026#34;) 5\tm.Set(\u0026#34;number\u0026#34;, 1) 6\tm.Set(\u0026#34;url\u0026#34;, \u0026amp;url.URL{}) 7 8\tfor _, k := range m.Keys() { 9\tv, _ := m.Get(k) 10 11\tswitch v := v.(type) { 12\tcase string: 13\tfmt.Printf(\u0026#34;string %s\\n\u0026#34;, v) 14\tcase int: 15\tfmt.Printf(\u0026#34;int %d\\n\u0026#34;, v) 16\tdefault: 17\tfmt.Printf(\u0026#34;%T %v\\n\u0026#34;, v, v) 18\t} 19\t} 20} Do we really want our map to be able to store any type? Is this really type strict? Is it simple to do type assertions every now and then? In such cases very often we have to introduce reflection and this is far from simple. Now let\u0026rsquo;s take a look at the generic implementation:\n1type Map[T any] struct { 2\tsync.RWMutex 3\tinternal map[string]T 4} 5 6func NewMap[T any]() *Map[T] { 7\treturn \u0026amp;Map[T]{ 8\tinternal: make(map[string]T), 9\t} 10} 11 12func (m *Map[T]) Get(key string) (T, bool) { 13\tm.RLock() 14\tresult, ok := m.internal[key] 15\tm.RUnlock() 16\treturn result, ok 17} 18 19func (m *Map[T]) Set(key string, value T) { 20\tm.Lock() 21\tm.internal[key] = value 22\tm.Unlock() 23} 24 25func (m *Map[T]) Delete(key string) { 26\tm.Lock() 27\tdelete(m.internal, key) 28\tm.Unlock() 29} 30 31func (m *Map[T]) Keys() []string { 32\tm.Lock() 33\tks := make([]string, 0, len(m.internal)) 34\tfor k, _ := range m.internal { 35\tks = append(ks, k) 36\t} 37\tm.Unlock() 38\treturn ks 39} We can now use strictly typed map with string values:\n1func main() { 2\tm := NewMap[string]() 3 4\tm.Set(\u0026#34;hello\u0026#34;, \u0026#34;world\u0026#34;) 5\tm.Set(\u0026#34;welcome\u0026#34;, \u0026#34;generics\u0026#34;) 6 7\tfor _, k := range m.Keys() { 8\tv, _ := m.Get(k) 9\tfmt.Printf(\u0026#34;%s %s\\n\u0026#34;, k, v) 10\t} 11} This is quite clear, no type assertions and we can use the same implementation for some other value type, let\u0026rsquo;s say int:\n1func main() { 2\tm := NewMap[int]() 3 4\tm.Set(\u0026#34;one\u0026#34;, 1) 5\tm.Set(\u0026#34;two\u0026#34;, 2) 6 7\tfor _, k := range m.Keys() { 8\tv, _ := m.Get(k) 9\tfmt.Printf(\u0026#34;%s %d\\n\u0026#34;, k, v) 10\t} 11} For comparison reasons, let\u0026rsquo;s see how this last example can be written in Rust:\n1use std::collections::HashMap; 2 3fn main() { 4 let mut map = HashMap::new(); 5 map.insert(\u0026#34;one\u0026#34;.to_string(), 1); 6 map.insert(\u0026#34;two\u0026#34;.to_string(), 2); 7 8 for (k, v) in map { 9 println!(\u0026#34;{} {}\u0026#34;, k, v) 10 } 11} Like for all other types, Rust already has generic version of map, actually HashMap. There are no generic parameters in the example above because Rust can infer type from the implementation. In this case, it can figure out that it has to use HashMap\u0026lt;String, i32\u0026gt;. We will see how will type inference work in Go.\nBut let\u0026rsquo;s go back to Go. I believe Go\u0026rsquo;s standard library will also benefit a lot from generics. We may expect generic, strictly typed implementation of sync.Map, generic functions like Map, Reduce, Filter and many other goodies. Basically, for each type that uses empty interfaces we may expect a generic version.\nLet\u0026rsquo;s see how generic implementation of Filter function may look like:\n1package main 2 3import \u0026#34;fmt\u0026#34; 4 5func main() { 6\tcities := []string{\u0026#34;Amsterdam\u0026#34;, \u0026#34;Berlin\u0026#34;, \u0026#34;\u0026#34;} 7 8\tfilterEmpty := func(s string) bool { 9\tif s == \u0026#34;\u0026#34; { 10\treturn false 11\t} 12 13\treturn true 14\t} 15 16\tfmt.Println(Filter[string](cities, filterEmpty)) 17} 18 19func Filter[T any](s []T, f func(T) bool) []T { 20\tvar r []T 21 22\tfor _, v := range s { 23\tif f(v) { 24\tr = append(r, v) 25\t} 26\t} 27 28\treturn r 29} Are generics really threatening Go\u0026rsquo;s simplicity? I would say no, on the contrary. I am looking forward to version 1.18 and you?\nYou can run and play with all the examples on the following links:\nMap without generics Map with generics (string type) Map with generics (int type) Rust version Filter function ","date":"February 26, 2021","externalUrl":null,"permalink":"/blog/upcoming-gos-generics/","section":"Blog","summary":"In the very early adoption of Go by the open source community, lot of developers already suggested the lack of generics. However, some other claimed that simplicity of Go shouldn’t be compromised by generics. Few days ago, the never ending discussions pro and contra generics are finally over. The proposal is accepted and we can expect generics in Go 1.18 somewhere in spring of 2022. You may wonder why does it take that long, but this is not just about the compiler but also some parts of the standard library may need to be rewritten in order to replace the old code which could benefit from generics.\n","title":"Upcoming Go's generics","type":"blog"},{"content":"If you have just started learning Go or already developing in Go for quite some time, you may noticed that most of the Go packages are imported directly from their respective VCS repositories, but there are some packages imported from URL\u0026rsquo;s like golang.org/x/text or go.uber.org/zap . If you try to visit such URL\u0026rsquo;s, you may see different results like being redirected to documentation or just some dummy page. This is completely different from packages hosted on GitHub, for example github.com/pkg/errors where you can see the real source code. This feature of Go is called vanity imports.\nIn this article I won\u0026rsquo;t explain how is this done, but if you are interrested about the details I recommend reading this article from Márk Sági-Kazár. Instead, I want to show how you can achieve this in a very easy way. At least if you have Kubernetes server, which is a prerequisite for the method that will be described.\nSome time ago, I decided to release some interesting packages that I wrote, for example go.ectobit.com/act and I wanted to have vanity import for it. There are several available vanity servers, but as I started learning Rust, I decided to write my own while learning. As I am also a big fan of Kubernetes, I made a Helm chart to allow easy installation of the service. The chart is pretty well documented, but I will explain here the installation on the real example, previously mentioned go.ectobit.com/act . Here is the helmfile:\nreleases: - name: vanity chart: ectobit/vanity namespace: repo values: - config: domain: go.ectobit.com packages: act: https://github.com/ectobit/act - ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/ssl-redirect: \u0026#39;true\u0026#39; nginx.ingress.kubernetes.io/force-ssl-redirect: \u0026#39;true\u0026#39; external-dns.alpha.kubernetes.io/hostname: \u0026#39;go.ectobit.com\u0026#39; external-dns.alpha.kubernetes.io/ttl: \u0026#39;1800\u0026#39; hosts: - host: go.ectobit.com paths: [\u0026#39;/\u0026#39;] tls: - secretName: ectobit-com-tls hosts: - go.ectobit.com As you can see in the helmfile, there is a value config.domain which you want to replace with your domain and then you can make a map of your packages under config.packages. It is good practice to prefix your domain with go or some other hostname, otherwise you may introduce difficult rewrites on your main web server.\nAnd that\u0026rsquo;s all, install the chart and your packages will be available to _ge ge_t from a new URL\u0026rsquo;s.\n","date":"February 21, 2021","externalUrl":null,"permalink":"/blog/go-vanity-imports/","section":"Blog","summary":"If you have just started learning Go or already developing in Go for quite some time, you may noticed that most of the Go packages are imported directly from their respective VCS repositories, but there are some packages imported from URL’s like golang.org/x/text or go.uber.org/zap . If you try to visit such URL’s, you may see different results like being redirected to documentation or just some dummy page. This is completely different from packages hosted on GitHub, for example github.com/pkg/errors where you can see the real source code. This feature of Go is called vanity imports.\n","title":"Go vanity imports","type":"blog"},{"content":"In these uncertain times and multiple months of remote work, at least we have some more time to dive into something new. I have been developing in Go since 2017, learned some TypeScript in the meantime, but few days ago I wanted to get into Rust once again. First time, approximately a year ago I gave up very quickly, realizing that Rust requires lot of time to learn and I didn\u0026rsquo;t have that much time at the moment.\nThis time I took a much more serious approach starting reading The Rust Programming Language book, but comparing to the last time, I didn\u0026rsquo;t stop reading until the last page. I was not familiar with many concepts in Rust, specially traits, \u0026ldquo;borrowing\u0026rdquo; and so on, but I immediately realized the power of the expressions in Rust. Both Go and Rust claim to be systems languages, but I have to admit that Rust is much more systems language than Go.\nGo is much easier to learn, it reminds of other popular languages and the only difficult part is concurrent programming, specifically taking care of goroutines\u0026rsquo; lifetime and channel communication.\nOn the contrary, Rust is much more difficult to learn, has much more concepts and the syntax sometimes looks quite weird (macros, trait bounds, lifetime annotations, closures\u0026hellip;). But I didn\u0026rsquo;t want to stop, I wanted to start a real project and decided to give a try writing a Kubernetes controller. I have some experience writing Kubernetes controllers in Go and anyways I needed a controller that replicates secrets across different namespaces, so this was a very logical choice. The project is named Bond and it is in a very early stage. However, it allowed me to start having feeling of Rust and realizing the power of it\u0026rsquo;s expression.\nWhat many people say negative about Go are too verbose error handling and lack of generics. Thus, Rust doesn\u0026rsquo;t have such problems, error handling is really clean and generics concept is very rich. If you don\u0026rsquo;t already know, Go will probably have generics implementation at the biginning of 2022, but there are no plans of solving the errors problem. Both in Rust and Go, errors are just values, but Rust handles this in quite remarkable way.\nAnother advantage of Go is quick compiler. Rust takes much more time to compile the code and also linters take more time to analyze it. So, developing in Rust is definitely slower, specially when you are new to the language.\nOn the other side, Go has memory management based on garbage collector, just like Java for example, and this may introduce some latency in heavy duty applications, which is not the case with Rust. Rust memory management is probably the best and safest ever and takes almost no extra time to handle. Go has goroutines (green threads), while Rust has real OS threads allowing much deeper hardware access, but it also has higher level libraries allowing green threads, async programming using futures, etc.\nTo summarize, Rust is difficult to learn but if you plan to do real systems programming or develop extremely performant cloud applications, it is the best choice if not even the only good choice at this moment. It is fun to develop APIs in Go, but once it\u0026rsquo;s not good enough for your use case, definitely give Rust a try, you won\u0026rsquo;t regret. It is completely worth spending time learning it.\n","date":"December 26, 2020","externalUrl":null,"permalink":"/blog/rust-from-the-perspective-of-a-go-developer/","section":"Blog","summary":"In these uncertain times and multiple months of remote work, at least we have some more time to dive into something new. I have been developing in Go since 2017, learned some TypeScript in the meantime, but few days ago I wanted to get into Rust once again. First time, approximately a year ago I gave up very quickly, realizing that Rust requires lot of time to learn and I didn’t have that much time at the moment.\n","title":"A first impression of Rust from the perspective of a Go developer","type":"blog"},{"content":"Kubernetes simplified applications management a lot and this also applies to databases like MySQL/MariaDB, but lot of DevOps forget to apply traditional maintenance and optimization which is still necessary unless you are using some operator capable of doing so. The optimization method that will be described here applies just to single and master-slave replicated MySQL/MariaDB instances. If you run some clustered version like Galera , you probably have to find another way because of possible consistence and performance problems during the eventual optimization. This method would still work but you may have unpredictable consequences.\nThe command that should be run periodically is the following:\nmysqlcheck -h mariadb-host -u root -p -o --all-databases But how to run it on Kubernetes? It is actually quite simple using CronJob resource and an optimized image ectobit/mariadb-client . The image is based on Alpine Linux and additionally contains just mariadb-client package which includes commands like mysql (client), mysqldump, mysqlcheck and mysqladmin. Here is the manifest:\napiVersion: batch/v1beta1 kind: CronJob metadata: name: mariadb-optimize-tables spec: schedule: \u0026#39;2 2 * * 0\u0026#39; concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: containers: - name: mariadb-optimize-tables image: ectobit/mariadb-client imagePullPolicy: Always env: - name: PASSWORD valueFrom: secretKeyRef: name: mariadb key: mariadb-root-password command: - sh - -c - mysqlcheck -h mariadb-host -u root -p${PASSWORD} -o --all-databases restartPolicy: OnFailure ttlSecondsAfterFinished: 172800 You also need to create the secret mariadb in the same namespace where your database resides, containing the key mariadb-root-password. Of course you can name these differently and in that case you have to replace the names in the YAML code above.\nYou can count that the image ectobit/mariadb-client will be regularly updated in the future because it\u0026rsquo;s automatized using GitHub Dependabot . If you like the image, please give it a star on GitHub and Docker Hub . Thank you 🙃.\n","date":"December 26, 2020","externalUrl":null,"permalink":"/blog/automated-mysql-mariadb-tables-optimization-in-kubernetes/","section":"Blog","summary":"Kubernetes simplified applications management a lot and this also applies to databases like MySQL/MariaDB, but lot of DevOps forget to apply traditional maintenance and optimization which is still necessary unless you are using some operator capable of doing so. The optimization method that will be described here applies just to single and master-slave replicated MySQL/MariaDB instances. If you run some clustered version like Galera , you probably have to find another way because of possible consistence and performance problems during the eventual optimization. This method would still work but you may have unpredictable consequences.\n","title":"Automated MySQL MariaDB tables optimization in Kubernetes","type":"blog"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/controller/","section":"Tags","summary":"","title":"Controller","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/categories/kubernetes/","section":"Categories","summary":"","title":"Kubernetes","type":"categories"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/kubernetes/","section":"Tags","summary":"","title":"Kubernetes","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/mariadb/","section":"Tags","summary":"","title":"MariaDB","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/mysql/","section":"Tags","summary":"","title":"MySQL","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/optimization/","section":"Tags","summary":"","title":"Optimization","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/replicator/","section":"Tags","summary":"","title":"Replicator","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/schedule/","section":"Tags","summary":"","title":"Schedule","type":"tags"},{"content":"","date":"December 26, 2020","externalUrl":null,"permalink":"/tags/secret/","section":"Tags","summary":"","title":"Secret","type":"tags"},{"content":"","date":"November 17, 2020","externalUrl":null,"permalink":"/tags/acl/","section":"Tags","summary":"","title":"ACL","type":"tags"},{"content":"","date":"November 17, 2020","externalUrl":null,"permalink":"/tags/permission/","section":"Tags","summary":"","title":"Permission","type":"tags"},{"content":"In lot of instructions how to run docker on Ubuntu 20.04 (same applies to Linux Mint Ulyana) you may find that after installing docker you have to add your user to docker group by the following command:\nsudo usermod -aG docker $USER If you still get permission errors, you may try to set ACL:\nsudo setfacl -m user:$USER:rw /var/run/docker.sock ","date":"November 17, 2020","externalUrl":null,"permalink":"/blog/run-docker-as-normal-user-on-ubuntu-20-04/","section":"Blog","summary":"In lot of instructions how to run docker on Ubuntu 20.04 (same applies to Linux Mint Ulyana) you may find that after installing docker you have to add your user to docker group by the following command:\n","title":"Run Docker as normal user on Ubuntu 20.04","type":"blog"},{"content":"","date":"November 17, 2020","externalUrl":null,"permalink":"/tags/setfacl/","section":"Tags","summary":"","title":"Setfacl","type":"tags"},{"content":"","date":"November 17, 2020","externalUrl":null,"permalink":"/tags/usermod/","section":"Tags","summary":"","title":"Usermod","type":"tags"},{"content":"If you don\u0026rsquo;t know yet, there were major changes by Google in protobuf and gRPC implementation for Go. New version should be better in all means so you should switch as soon as possible, if you are already using these technologies. In this article I am going to focus on Linux variant, but the upgrade procedure should be quite similar on OSX or Windows.\nIn order to use protobuf compiler or generator, if you wish, you had to install protoc compiler. There are no changes in this step, you still need it although you may want to upgrade to the latest version.\nPreviously, in order to generate Go code you had to use protoc-gen-go plugin which you had to install using the following command:\ngo get github.com/golang/protobuf/protoc-gen-go Now we have new implementation which replaces the old version and you should just run:\ngo get google.golang.org/protobuf/cmd/protoc-gen-go Unfortunately, this is not all. Previously you could generate gRPC code together with protobuf without further dependencies, so it was enough to run a command similar to this:\nprotoc --go_out=plugins=grpc:. --go_opt=paths=source_relative some_path/example.proto As plugin gRPC is removed from the new implementation, flag \u0026ndash;go_out won\u0026rsquo;t work like this anymore. Instead, you have to install protoc-gen-go-grpc and you have to use the protoc the following way:\ngo get google.golang.org/grpc/cmd/protoc-gen-go-grpc protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative some_path/example.proto I f you receive some strange errors that some constants are not defined, you may want to pin github.com/golang/protobuf, google.golang.org/grpc and google.golang.org/protobuf dependencies in go.mod to the latest versions or simply delete these lines in go.mod and run go build again. Hopefully it is going to fetch the right dependencies.\nFinally, you will receive errors that your implementation of the gRPC server interfaces does not implement yourpb.mustEmbedUnimplementedYourServiceServer method. You can solve this easily by embeding appropriate your_pb.UnimplementedYourServiceServer_ in your implementation. After this the code should hapilly compile. If you have trouble solving this, you may want to check the examples from the official repository.\nIf you use vscode editor, it is worth saying that you can install proto3 extension from the marketplace and put the following snippet in the settings.json file:\n{ \u0026#34;protoc\u0026#34;: { \u0026#34;options\u0026#34;: [ \u0026#34;--go_out=.\u0026#34;, \u0026#34;--go_opt=paths=source_relative\u0026#34;, \u0026#34;--go-grpc_out=.\u0026#34;, \u0026#34;--go-grpc_opt=paths=source_relative\u0026#34; ] } } If you do so, you will be able to generate the files inside the editor. Happy protobuffing 🙂\n","date":"November 15, 2020","externalUrl":null,"permalink":"/blog/changes-in-go-implementation-of-the-new-protobuf-and-grpc/","section":"Blog","summary":"If you don’t know yet, there were major changes by Google in protobuf and gRPC implementation for Go. New version should be better in all means so you should switch as soon as possible, if you are already using these technologies. In this article I am going to focus on Linux variant, but the upgrade procedure should be quite similar on OSX or Windows.\n","title":"Changes in Go implementation of the new protobuf and gRPC","type":"blog"},{"content":"","date":"November 15, 2020","externalUrl":null,"permalink":"/tags/grpc/","section":"Tags","summary":"","title":"GRPC","type":"tags"},{"content":"","date":"November 15, 2020","externalUrl":null,"permalink":"/tags/protobuf/","section":"Tags","summary":"","title":"Protobuf","type":"tags"},{"content":"","date":"October 6, 2020","externalUrl":null,"permalink":"/tags/backup/","section":"Tags","summary":"","title":"Backup","type":"tags"},{"content":"","date":"October 6, 2020","externalUrl":null,"permalink":"/tags/minio/","section":"Tags","summary":"","title":"Minio","type":"tags"},{"content":"","date":"October 6, 2020","externalUrl":null,"permalink":"/tags/s3/","section":"Tags","summary":"","title":"S3","type":"tags"},{"content":"","date":"October 6, 2020","externalUrl":null,"permalink":"/tags/sync/","section":"Tags","summary":"","title":"Sync","type":"tags"},{"content":"In the Cloud era topics like backup became kind of less important. One of the reasons is probably possibility to take automated snapshots of your volumes, another maybe that you can use some kind of redundancy. However, there are still use cases where you need more traditional ways to backup your data. In this article we will discuss about syncing files from your Kubernetes volume to S3 compatible storage.\nIf you know the concept of Persistent Volumes in Kubernetes, then you also know three of the supported access modes: ReadWriteOnce, ReadOnlyMany or ReadWriteMany. The first mode allows a volume to be mounted just once, meaning it is usually already used by some pod and it is possible to access it just through this pod. The other two types can be mounted multiple times, meaning multiple pods can access the same data. In case of ReadOnlyMany all pods can just read the data, but in case of ReadWriteMany all pods can read and write data. In this article we are going to focus to these volumes that we can mount multiple times.\nAt the moment of writing this, the following CSI plugins support ReadWriteMany mode: AzureFile, CephFS, Glusterfs, Quobyte, NFS and PortworxVolume. As you may guess by my article written few months ago , in our example we will use NFS volume. Now let\u0026rsquo;s see the manifest:\napiVersion: batch/v1beta1 kind: CronJob metadata: name: volume-backup spec: schedule: \u0026#34;20 3 * * *\u0026#34; concurrencyPolicy: Forbid successfulJobsHistoryLimit: 2 failedJobsHistoryLimit: 2 jobTemplate: spec: template: spec: containers: - name: aws-cli image: amazon/aws-cli env: - name: AWS_ACCESS_KEY_ID value: {your_aws_access_key_ID} - name: AWS_SECRET_ACCESS_KEY value: {your_aws_secret_access_key} - name: AWS_REGION value: eu-central-1 args: - --no-progress - --delete - s3 - sync - /data - s3://your_bucket_name volumeMounts: - name: backup mountPath: /data volumes: - name: backup persistentVolumeClaim: claimName: {your_pvc_name} restartPolicy: OnFailure ttlSecondsAfterFinished: 172800 As you can see, this manifest would create a Kubernetes CronJob object which is going to trigger a job every night at 3:20. No concurrency is allowed, meaning just one job of a kind at a time is allowed. We want to keep history of two last successful and two failed jobs. Job template has just one container which is using official amazon/aws-cli image from Docker Hub . As shown in volumes section, we use existing PVC and mount it under /data path in our container. The entrypoint for this image is aws-cli (aws) itself and we pass just the arguments.\nYes, it is easy like that. Just one manifest and our volume files get synced to S3 bucket. Of course, instead of sync subcommand you can use any other available aws-cli subcommand. Finally, a note for Mino users: pass --endpoint-url=https://minio.your-domain.com:9000 as the first argument to aws-cli.\n","date":"October 6, 2020","externalUrl":null,"permalink":"/blog/sync-kubernetes-volume-with-s3-bucket/","section":"Blog","summary":"In the Cloud era topics like backup became kind of less important. One of the reasons is probably possibility to take automated snapshots of your volumes, another maybe that you can use some kind of redundancy. However, there are still use cases where you need more traditional ways to backup your data. In this article we will discuss about syncing files from your Kubernetes volume to S3 compatible storage.\n","title":"Sync Kubernetes volume with S3 bucket","type":"blog"},{"content":"","date":"October 6, 2020","externalUrl":null,"permalink":"/tags/volume/","section":"Tags","summary":"","title":"Volume","type":"tags"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/application/","section":"Tags","summary":"","title":"Application","type":"tags"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/autorecompile/","section":"Tags","summary":"","title":"Autorecompile","type":"tags"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/autorestart/","section":"Tags","summary":"","title":"Autorestart","type":"tags"},{"content":"Do you develop or plan to develop a Kubernetes native application in Golang, controller or operator? Such application strongly depends on being inside Kubernetes and development outside of Kubernetes may be a real hassle. Usually you have to build an image over and over again and restart the pod (with imagePullPolicy set to Always). This is very boring and time consuming procedure.\nTwo years ago I developed an image to auto-recompile and auto-restart Go application, named go-reflex , but it was intented to be used by docker-compose. Today I gave it a try with Kubernetes, namely with kind (Kubernetes in Docker) and it turned out it works like a charm. In this article I will describe how to set this up and save your time for something creative (i.e. beer drinking).\nAs a first step, install kind and create local cluster:\nGO111MODULE=\u0026#34;on\u0026#34; go get sigs.k8s.io/kind@v0.8.1 Now create a kind config file config.yaml:\napiVersion: kind.x-k8s.io/v1alpha4 kind: Cluster nodes: - role: control-plane extraMounts: - hostPath: /path/to/your/project/root containerPath: /app Modify hostPath to match your project root directory and create the cluster:\nkind create cluster --config=config.yaml Follow the instructions how to configure kubectl. Now deploy your pod to the cluster using the following manifest (deploy.yaml):\napiVersion: v1 kind: Pod metadata: name: your-app-name namespace: default spec: containers: - image: acim/go-reflex:1.15.0-r0 name: your-app-name env: - name: RACE_DETECTOR value: \u0026#34;1\u0026#34; volumeMounts: - mountPath: /app name: app restartPolicy: Never volumes: - hostPath: path: /app name: app Replace your-app-name with the name you want. Finally create this object within the kind cluster:\nkubectl apply -f deploy.yaml Connect to your application using standard kubectl port forwarding:\nkubectl port-forward your-app-name 3000:3000 Replace the second port number with correct port number where your application listens on and access it in browser or some REST client on port 3000 on your localhost.\nTry to modify some .go file in your application repository and notice that your application is going to be automatically recompiled and restarted inside the cluster. You can track this by following the logs:\nkubectl logs -f your-app-name That\u0026#39;s all, you are ready to make another great Kubernetes operator. Note: Take care that your main package is in the root directory of the project, otherwise this won\u0026#39;t work out of the box. In some other scenario you would have to make your own Dockerfile upon the original one from [go-reflex](https://github.com/acim/go-reflex/). ","date":"August 28, 2020","externalUrl":null,"permalink":"/blog/develop-kubernetes-native-applications-golang-autorecompile-autorestart/","section":"Blog","summary":"Do you develop or plan to develop a Kubernetes native application in Golang, controller or operator? Such application strongly depends on being inside Kubernetes and development outside of Kubernetes may be a real hassle. Usually you have to build an image over and over again and restart the pod (with imagePullPolicy set to Always). This is very boring and time consuming procedure.\n","title":"Develop Kubernetes native applications in Golang with auto-recompile and auto-restart","type":"blog"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/development/","section":"Tags","summary":"","title":"Development","type":"tags"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/native/","section":"Tags","summary":"","title":"Native","type":"tags"},{"content":"","date":"August 28, 2020","externalUrl":null,"permalink":"/tags/operator/","section":"Tags","summary":"","title":"Operator","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/acme/","section":"Tags","summary":"","title":"Acme","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/auth/","section":"Tags","summary":"","title":"Auth","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/certificate/","section":"Tags","summary":"","title":"Certificate","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/crd/","section":"Tags","summary":"","title":"Crd","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/ingress/","section":"Tags","summary":"","title":"Ingress","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/letsencrypt/","section":"Tags","summary":"","title":"Letsencrypt","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/redirect/","section":"Tags","summary":"","title":"Redirect","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/categories/traefik/","section":"Categories","summary":"","title":"Traefik","type":"categories"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/traefik/","section":"Tags","summary":"","title":"Traefik","type":"tags"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/series/traefik-2.2/","section":"Series","summary":"","title":"Traefik 2.2","type":"series"},{"content":"Learn how to setup Traefik 2.2 on Kubernetes and how to automatically get TLS wildcard certificates.\nTraefik is a modern Web server made in the cloud era so it\u0026rsquo;s authors define it as a Cloud Native edge router. It is written in Go and it\u0026rsquo;s maybe not as fast as nginx or HAProxy, but it is fast enough and in the same time it has great features not present in traditional Web servers. These features include automatic care of TLS certificates, nice control panel, support for Docker stacks and Kubernetes, etc.\nVersion 1.x of Traefik didn\u0026rsquo;t have CRD\u0026rsquo;s and supported just normal Kubernetes Ingress resource. However, version 2.0 contained breaking changes and continued supporting basic functionalities of Kubernetes Ingress but in order to use advanced features it was necesarry to use IngressRoute CRD provided by Traefik itself. This means if you use Helm, for example, to install your applications, you couldn\u0026rsquo;t setup proper ingress. I had exactly this case so I had to use raw chart to install custom IngressRoute for each application which broke encapsulation and didn\u0026rsquo;t look tidy.\nFortunatelly, since version 2.2 it is possible to use advanced features of Traefik even with normal Kubernetes Ingress thanks to special annotations . This way Traefik is again fully compatible with Kubernetes but doesn\u0026rsquo;t require any custom resources for the advanced functionality. In this article I want to show how to set this up using helmfile .\nFirst let\u0026rsquo;s install Traefik itself:\nreleases: - name: traefik chart: traefik/traefik values: - additionalArguments: - --entrypoints.web.http.redirections.entryPoint.to=:443 - --entrypoints.web.http.redirections.entryPoint.scheme=https - --entrypoints.web.http.redirections.entryPoint.priority=10000 - --certificatesresolvers.default.acme.storage=/data/acme.json - --certificatesresolvers.default.acme.email=john.doe@example.io - --certificatesresolvers.default.acme.dnsChallenge.provider=digitalocean - env: - name: DO_AUTH_TOKEN value: { { requiredEnv \u0026#34;DO_AUTH_TOKEN\u0026#34; } } Using additional arguments we redirect all traffic from http to https, we don\u0026rsquo;t want any unencrypted traffic. Then we also define our certificate resolver to DNS challenge, in my case DigitalOcean. You can find the full list of supported providers here .\nNow, let\u0026rsquo;s see what annotations do we need on the Ingress object. Let\u0026rsquo;s see an example application:\n- name: example chart: charts/example values: - ingress: enabled: true annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: \u0026#39;true\u0026#39; traefik.ingress.kubernetes.io/router.tls.certresolver: default traefik.ingress.kubernetes.io/router.tls.domains.0.main: \u0026#39;example.io\u0026#39; traefik.ingress.kubernetes.io/router.tls.domains.0.sans: \u0026#39;*.example.io\u0026#39; hosts: - host: example.io paths: [\u0026#39;/\u0026#39;] - host: www.example.io paths: [\u0026#39;/\u0026#39;] Traefik contains by default two entry points, web (http) and websecure (https). As we set the redirection from http to https, we care just about websecure entry point. Then we turn on TLS and specify to use default resolver (yes, you may have many resolvers). Finally we tell Traefik that our certificate should be for the main domain example.io and also for the wildcard domain _.example.io. At your DNS provider you need to have A records for @ and _ pointing to the right IP address. Finally we define that this ingress will be activated for hosts example.io and www.example.io and we are done.\nOr we are almost done. Why almost? Well, we have a glitch here. Our ingress will be activated if the hostname is example.io or www.example.io and this is not good for SEO, one of these hostnames should be redirected to another so that we only have one hostname. Search engines won\u0026rsquo;t like to have two hostnames with exactly the same contents. We can achieve these using middlewares in Traefik, but more about that in the following article. Have a nice traefiking ?\n","date":"July 31, 2020","externalUrl":null,"permalink":"/blog/traefik-2-2-ingress/","section":"Blog","summary":"Learn how to setup Traefik 2.2 on Kubernetes and how to automatically get TLS wildcard certificates.\nTraefik is a modern Web server made in the cloud era so it’s authors define it as a Cloud Native edge router. It is written in Go and it’s maybe not as fast as nginx or HAProxy, but it is fast enough and in the same time it has great features not present in traditional Web servers. These features include automatic care of TLS certificates, nice control panel, support for Docker stacks and Kubernetes, etc.\n","title":"Traefik 2.2 can again fully utilize Kubernetes Ingress resources","type":"blog"},{"content":"Since Traefik 2.0, this feature was possible just with custom IngressRoute resources, but it is now possible with normal Kubernetes Ingress as well.\nSo, what is the Traefik middleware, anyways? It is a piece of code which is triggered just before the Ingress itself. Here you can find the full list of available directives that you can use to create your middleware. In this article we are going to define two middlewares, one to redirect www.example.io to example.io, so that we make SEO happy and another one for basic authentication. Here is how this would look like using helmfile declaration:\nreleases: - name: traefik-resources chart: incubator/raw namespace: default values: - resources: - apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: basic-auth spec: basicAuth: secret: basic-auth - apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: redirect-no-www spec: redirectRegex: regex: ^https://www\\.(.*) replacement: https://${1} permanent: true As you can see, basic-auth middleware uses basic-auth secret which you can create using the following commands:\nhtpasswd -c auth your-username kubectl create secret generic basic-auth --from-file=auth In order to invoke the basic-auth middleware before your Ingress, you should annotate the desired ingress with the following annotation:\ntraefik.ingress.kubernetes.io/router.middlewares: default-basic-auth@kubernetescrd As you can assume, the value of this key is consisted of the namespace where the middleware exists, then dash, then the name of the middleware itself and finally the suffix @kubernetescrd.\nThe second middleware uses regular expression to find out if your hostname is prefixed with www and in such case it would remove the www prefix and just keep the basic hostname. You may want to do the opposite and in that case you have to modify the regex and the replacement values. At this moment I believe you can guess that we can invoke this middleware using the following annotation at the desired ingress:\ntraefik.ingress.kubernetes.io/router.middlewares: default-redirect-no-www@kubernetescrd Traefik was really powerfull ingress option for Kubernetes from the very beginning, but we can say now that it is back to the roots and since the version 2.2 we can use the full set of features together with the traditional Kubernetes resources. I can really recommend you to try Traefik, it is a great product.\n","date":"July 31, 2020","externalUrl":null,"permalink":"/blog/traefik-2-2-middlewares/","section":"Blog","summary":"Since Traefik 2.0, this feature was possible just with custom IngressRoute resources, but it is now possible with normal Kubernetes Ingress as well.\nSo, what is the Traefik middleware, anyways? It is a piece of code which is triggered just before the Ingress itself. Here you can find the full list of available directives that you can use to create your middleware. In this article we are going to define two middlewares, one to redirect www.example.io to example.io, so that we make SEO happy and another one for basic authentication. Here is how this would look like using helmfile declaration:\n","title":"Using Traefik 2.2 middlewares with Kubernetes Ingress resources","type":"blog"},{"content":"","date":"July 31, 2020","externalUrl":null,"permalink":"/tags/wildcard/","section":"Tags","summary":"","title":"Wildcard","type":"tags"},{"content":"","date":"July 28, 2020","externalUrl":null,"permalink":"/tags/cert-manager/","section":"Tags","summary":"","title":"Cert-Manager","type":"tags"},{"content":"","date":"July 28, 2020","externalUrl":null,"permalink":"/tags/helm/","section":"Tags","summary":"","title":"Helm","type":"tags"},{"content":"","date":"July 28, 2020","externalUrl":null,"permalink":"/tags/helmfile/","section":"Tags","summary":"","title":"Helmfile","type":"tags"},{"content":"You may wonder what the heck is helmfile ? Well, I would say what is docker-compose to Docker, this is helmfile to Helm . Basically, it allows us to install the whole stack of applications to our Kubernetes cluster in a declarative way.\nAnd you may also wonder why is cert-manager so special? I would say cert-manager itself is not that special Helm chart, but it contains CRD \u0026rsquo;s which may be installed either by using value installCRDs=true or by installing them using kubectl apply before you install the chart.\nUsing the first option is straight forward, but this is not the recommended way by the documentation . I am not sure why, but I found out that helmfile sync becomes really unresponsive when resyncing, at least on kind cluster.\nThe second way is tricky to do via helmfile, but also reapplying the CRD\u0026rsquo;s via kubectl apply makes kind unresponsive. Real cluster may behave differently for performance reasons, but can me make this universally functional? Thanks to helmfile events we can achieve this.\nHere is a helmfile snippet which installs the chart:\nreleases: - name: cert-manager chart: jetstack/cert-manager version: v0.16.0 namespace: cert-manager wait: true hooks: - events: [\u0026#39;presync\u0026#39;] command: cert-manager-crds.sh And here is the cert-manager-crds.sh script:\n#!/usr/bin/env sh set -u kubectl get crd issuers.cert-manager.io \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 if [ $? -ne 0 ] then kubectl apply --validate=false -f cert-manager.crds.yaml fi This script first checks if CRD\u0026rsquo;s are already installed and it continues execution just in case they are not. This way we avoid reapplying the manifest(s) that are already applied. The downside of this approach is that we have to update the CRD\u0026rsquo;s manually once we bump the pinned version of the chart, actually cert-manager in this case.\nThe same approach may be applied to any chart having CRD\u0026rsquo;s.\n","date":"July 28, 2020","externalUrl":null,"permalink":"/blog/install-cert-manager-using-helmfile/","section":"Blog","summary":"You may wonder what the heck is helmfile ? Well, I would say what is docker-compose to Docker, this is helmfile to Helm . Basically, it allows us to install the whole stack of applications to our Kubernetes cluster in a declarative way.\n","title":"Install cert-manager using helmfile","type":"blog"},{"content":"","date":"July 28, 2020","externalUrl":null,"permalink":"/tags/kind/","section":"Tags","summary":"","title":"Kind","type":"tags"},{"content":"I had a problem recently not being able to set Google as default search engine in Firefox of my Linux Mint installation. It is not that I like Google that much, it is actually opposite, but DuckDuckGo as default search engine doesn\u0026rsquo;t give me the satisfying search so it seems it is not possible to skip Google tracking and keep your privacy, at least not at this moment.\nIf you had such problem, this is because Google search engine doesn\u0026rsquo;t fund Linux Mint and this is why they are not on the list. In order to turn it on, check this out .\n","date":"July 26, 2020","externalUrl":null,"permalink":"/blog/add-google-search-engine-to-your-linux-mint/","section":"Blog","summary":"I had a problem recently not being able to set Google as default search engine in Firefox of my Linux Mint installation. It is not that I like Google that much, it is actually opposite, but DuckDuckGo as default search engine doesn’t give me the satisfying search so it seems it is not possible to skip Google tracking and keep your privacy, at least not at this moment.\n","title":"Add Google search engine to your Linux Mint","type":"blog"},{"content":"","date":"July 26, 2020","externalUrl":null,"permalink":"/tags/google/","section":"Tags","summary":"","title":"Google","type":"tags"},{"content":"","date":"July 26, 2020","externalUrl":null,"permalink":"/tags/nfs/","section":"Tags","summary":"","title":"NFS","type":"tags"},{"content":"Do you need ReadWriteMany storage class and your cloud provider doesn\u0026rsquo;t offer it?\nAccording to Wikipedia , Network File System (NFS) is a distributed file system protocol originally developed by Sun Microsystems (Sun) in 1984, allowing a user on a client computer to access files over a computer network much like local storage is accessed.\nEven though this idea is 35 years old, it is still very useful in your Kubernetes cluster, specially if you need ReadWriteMany storage class. If you are interrested about this, you are probably wondering how to achieve this?\nWell, just install NFS Server Provisioner Helm chart:\nhelm install stable/nfs-server-provisioner \\ --name nfs-server \\ --set persistence.enabled=true --set persistence.size=10Gi After successful installation, your Kubernetes cluster will get one more storage class, namelly nfs. Now you can turn on persistance on any of your applications just by setting storage class to nfs and even better, you can set access mode to ReadWriteMany, not just ReadWriteOnce. This allows multiple pods to use the same volume or actually, this allows replicas of your application.\n","date":"July 26, 2020","externalUrl":null,"permalink":"/blog/k8s-nfs-provisioner/","section":"Blog","summary":"Do you need ReadWriteMany storage class and your cloud provider doesn’t offer it?\nAccording to Wikipedia , Network File System (NFS) is a distributed file system protocol originally developed by Sun Microsystems (Sun) in 1984, allowing a user on a client computer to access files over a computer network much like local storage is accessed.\n","title":"NFS provisioner for your K8S cluster","type":"blog"},{"content":"","date":"July 26, 2020","externalUrl":null,"permalink":"/tags/persistence/","section":"Tags","summary":"","title":"Persistence","type":"tags"},{"content":"","date":"July 26, 2020","externalUrl":null,"permalink":"/tags/readwritemany/","section":"Tags","summary":"","title":"ReadWriteMany","type":"tags"},{"content":"","date":"July 26, 2020","externalUrl":null,"permalink":"/tags/search/","section":"Tags","summary":"","title":"Search","type":"tags"},{"content":"","date":"May 3, 2020","externalUrl":null,"permalink":"/tags/javascript/","section":"Tags","summary":"","title":"JavaScript","type":"tags"},{"content":"Someone may ask what is so special about serving single-page applications? Well, if you use hash (#) based URL\u0026rsquo;s like https://yourdomain.com/#/yourroute , there is no problem because browser recognize that this is a default page with some parameters and doesn\u0026rsquo;t make another request to the server. However, if you want to use non-hash based routes, there is a problem if you try to refresh a non-default route. In this case browser\u0026rsquo;s default action is to load such URL from the server and there is no such document on the server. For example, if you load your SPA at URL https://yourdomain.com and then you click on another route, you will see in your browser\u0026rsquo;s URL field something like https://yourdomain.com/yourroute . That works fine unless you try to reload the page. In that case browser doesn\u0026rsquo;t know this is actually already loaded SPA, but it actually tries to fetch /yourroute URI from server. As there is no such URI on the server, you will usually get the famous 404 error and your application breaks.\nIn order to overcome this, your server should always return index.html or whatever document is default for your single-page application. Maybe not literally in all cases, maybe you want to use some patterns, but in lot of cases you actually want to return index.html in all 404 cases so that your SPA can continue normal execution. JavaScript based Web server usually have such options because they are very often used to serve SPA\u0026rsquo;s, for example sirv-cli has option \u0026ndash;single which will solve the problem. But can we do this in Go based server?\nGo\u0026rsquo;s standard library includes http.FileServer handler which can serve static files. However, it doesn\u0026rsquo;t have possibility to override 404\u0026rsquo;s with some default document. You can make a handler which first checks if requested URI (file) exists on the server and if not, respond with index.html, but this involves additional file system check which you may want to avoid for performance reasons. The question is, how can we solve this without additional filesystem check?\nWe can write our own implementation of http.ResponseWriter interface which will intercept 404 errors and respond with index.html in such cases. Let\u0026rsquo;s see such an implementation:\n1type intercept404 struct { 2\thttp.ResponseWriter 3\tstatusCode int 4} 5 6func (w *intercept404) Write(b []byte) (int, error) { 7\tif w.statusCode == http.StatusNotFound { 8\treturn len(b), nil 9\t} 10\tif w.statusCode != 0 { 11\tw.WriteHeader(w.statusCode) 12\t} 13\treturn w.ResponseWriter.Write(b) 14} 15 16func (w *intercept404) WriteHeader(statusCode int) { 17\tif statusCode \u0026gt;= 300 \u0026amp;\u0026amp; statusCode \u0026lt; 400 { 18\tw.ResponseWriter.WriteHeader(statusCode) 19\treturn 20\t} 21\tw.statusCode = statusCode 22} The idea is to replace original http.ResponseWriter when invoking http.FileServer with the one above and in case of 404, replace the requested URI with index.html (actually /) and invoke http.FileServer again, but now with original http.ResponseWriter. Here is the http.HandlerFunc which implements this idea:\n1func spaFileServeFunc(dir string) func(http.ResponseWriter, *http.Request) { 2\tfileServer := http.FileServer(http.Dir(dir)) 3\treturn func(w http.ResponseWriter, r *http.Request) { 4\twt := \u0026amp;intercept404{ResponseWriter: w} 5\tfileServer.ServeHTTP(wt, r) 6\tif wt.statusCode == http.StatusNotFound { 7\tr.URL.Path = \u0026#34;/\u0026#34; 8\tw.Header().Set(\u0026#34;Content-Type\u0026#34;, \u0026#34;text/html\u0026#34;) 9\tfileServer.ServeHTTP(w, r) 10\t} 11\t} 12} Finally, here is the main function which implements the server itself:\n1func main() { 2\thttp.HandleFunc(\u0026#34;/\u0026#34;, spaFileServeFunc(\u0026#34;public\u0026#34;)) 3 4\tlog.Fatal(http.ListenAndServe(\u0026#34;:3006\u0026#34;, nil)) 5} The full implementation using Svelte as JavaScript frontend can be found here .\nSomeone may argue that we still have performance loses in case that document is not found in initial request, but this is again more or less just file system check. This is still better than doing the double file system check in all requests.\n","date":"May 3, 2020","externalUrl":null,"permalink":"/blog/serving-spa/","section":"Blog","summary":"Someone may ask what is so special about serving single-page applications? Well, if you use hash (#) based URL’s like https://yourdomain.com/#/yourroute , there is no problem because browser recognize that this is a default page with some parameters and doesn’t make another request to the server. However, if you want to use non-hash based routes, there is a problem if you try to refresh a non-default route. In this case browser’s default action is to load such URL from the server and there is no such document on the server. For example, if you load your SPA at URL https://yourdomain.com and then you click on another route, you will see in your browser’s URL field something like https://yourdomain.com/yourroute . That works fine unless you try to reload the page. In that case browser doesn’t know this is actually already loaded SPA, but it actually tries to fetch /yourroute URI from server. As there is no such URI on the server, you will usually get the famous 404 error and your application breaks.\n","title":"Serving Single-Page Applications in Go","type":"blog"},{"content":"","date":"May 3, 2020","externalUrl":null,"permalink":"/tags/spa/","section":"Tags","summary":"","title":"SPA","type":"tags"},{"content":"","date":"May 3, 2020","externalUrl":null,"permalink":"/tags/svelte/","section":"Tags","summary":"","title":"Svelte","type":"tags"},{"content":"","date":"January 15, 2020","externalUrl":null,"permalink":"/categories/svelte/","section":"Categories","summary":"","title":"Svelte","type":"categories"},{"content":"Few weeks ago I came across Svelte, a radical new approach to building user interfaces (quote from Svelte homepage ). Svelte is actually a compiler, not tradional framework like React, Angular or Vue, but it can do pretty much everything as the mentioned ones. It doesn\u0026rsquo;t use virtual DOM, but instead it compiles to vanilla JavaScript and access the DOM directly. As a consequence, Svelte generated JavaScript is very small comparing to competition, but also quite fast.\nBut the best think about Svelte is it\u0026rsquo;s syntax. It looks so easy but in the same time powerful that it intrigued even me as a backend developer. Within few minutes I decided to start learning it and try something new. I had lot of fun since.\nHere is a piece of Svelte code (component) to illustrate the simplicity and power:\n\u0026lt;script\u0026gt; async function fetchData() { const res = await fetch(\u0026#39;https://jsonplaceholder.typicode.com/todos\u0026#39;) const data = await res.json() if (res.ok) { return data } else { throw new Error(data) } } \u0026lt;/script\u0026gt; {#await fetchData()} \u0026lt;p\u0026gt;loading\u0026lt;/p\u0026gt; {:then items} {#each items as item} \u0026lt;li\u0026gt;{item.id}. {item.title}\u0026lt;/li\u0026gt; {/each} {:catch error} \u0026lt;p style=\u0026#34;color: red\u0026#34;\u0026gt;{error.message}\u0026lt;/p\u0026gt; {/await} The code lying in the script tag is just ES6 JavaScript, but the await block beneath is a syntactic sugar from Svelte. So, instead of handling await in plain JavaScript, you can actually handle it in Svelte\u0026rsquo;s await block. While waiting for asynchronous function to finish, you can also show your loading message or spinner , you can catch and display errors, so basically this block fully handles async calls.\nYou can play with the code at Svelte\u0026rsquo;s REPL here .\n","date":"January 15, 2020","externalUrl":null,"permalink":"/blog/svelte-await-blocks/","section":"Blog","summary":"Few weeks ago I came across Svelte, a radical new approach to building user interfaces (quote from Svelte homepage ). Svelte is actually a compiler, not tradional framework like React, Angular or Vue, but it can do pretty much everything as the mentioned ones. It doesn’t use virtual DOM, but instead it compiles to vanilla JavaScript and access the DOM directly. As a consequence, Svelte generated JavaScript is very small comparing to competition, but also quite fast.\n","title":"Svelte await blocks","type":"blog"},{"content":"How to deploy new Docker images to your Kubernetes cluster? Of course, there are many ways and one of the most common ways is to use kubectl set image, for example:\nkubectl set image deployment/nginx-deployment nginx=nginx:1.17.5-alpine However, what happens if you have more containers in your deployment pod spec? And what if you also have initContainers? Fortunately, kubectl patch can help. Let\u0026rsquo;s assume we have two containers and one init container. Here is the patch file (patch.yaml) we can use:\nspec: template: spec: initContainers: - name: foo image: mycompany/fooimage:1.0.1 containers: - name: bar image: mycompany/barimage:8743b520 - name: baz image: mycompany/bazimage:2.15.8 We can simply apply this by the following command:\nkubectl patch deployment mydeployment -p \u0026#34;$(cat patch.yaml)\u0026#34; And voilà, all images in the deployment are updated at once.\nOf course, you may ask what happens when image tags are variable? Of course, this information may differ in each deployment. You can use git tags or maybe git hashes for this, but how to pass it to your patch file. We can simply replace tags with variables and then use sed to replace these dummy values with the real ones. Let\u0026rsquo;s consider this template:\nspec: template: spec: initContainers: - name: foo image: mycompany/fooimage:FOOVER containers: - name: bar image: mycompany/barimage:BARVER - name: baz image: mycompany/bazimage:BAZVER Now let\u0026rsquo;s use sed to replace these variables with the real values:\nsed -i -e \u0026#34;s,FOOVER,1.0.1,g\u0026#34; patch.yaml sed -i -e \u0026#34;s,BARVER,8743b520,g\u0026#34; patch.yaml sed -i -e \u0026#34;s,BAZVER,2.15.8,g\u0026#34; patch.yaml And we are done, now just apply kubectl patch the same way as above.\n","date":"October 23, 2019","externalUrl":null,"permalink":"/blog/using-kubectl-patch-to-deploy/","section":"Blog","summary":"How to deploy new Docker images to your Kubernetes cluster? Of course, there are many ways and one of the most common ways is to use kubectl set image, for example:\n","title":"Using kubectl patch in continuous deployment","type":"blog"},{"content":"This is the first step of my intention to write a series of articles where I would explain some common patterns used in Golang. Let\u0026rsquo;s start with generator pattern :\n1type Generator func() \u0026lt;-chan int Generator is a function or method which returns a sequence of values. In Golang, this usually means returning a channel of values of desired type. In our example, we will return a channel of integers. Let\u0026rsquo;s see an implementation of this:\n1func randomGenerator() \u0026lt;-chan int { 2 count := 100 3 max := 1000 4 dc := make(chan int) 5 rand.Seed(time.Now().UnixNano()) 6 7 go func() { 8 for i := 1; i \u0026lt;= count; i++ { 9 dc \u0026lt;- 1 + rand.Intn(max) 10 } 11 close(dc) 12 }() 13 14 return dc 15} As you can see, we have a goroutine inside the function and the reason is that in Go, we usually want to do the things concurrently. This means the generator is going to generate some values and at the same time we are going to process the generated values in another goroutine. And this \u0026ldquo;another goroutine\u0026rdquo; may actually be a wait group which means a pool of workers where we wait for all workers to finish before we continue or end the execution. Now let\u0026rsquo;s see an example of Golang\u0026rsquo;s wait group:\n1type WorkerPool struct { 2\tGenerator Generator 3\twg sync.WaitGroup 4\tdata \u0026lt;-chan int 5} 6 7func (p *WorkerPool) Run(concurrency int) { 8\tp.data = p.Generator() 9 10\tfor i := 1; i \u0026lt;= concurrency; i++ { 11\tp.wg.Add(1) 12\tgo p.worker(i) 13\t} 14 15\tp.wg.Wait() 16} 17 18func (p *WorkerPool) worker(i int) { 19\tfmt.Printf(\u0026#34;Worker %d started\\n\u0026#34;, i) 20\tdefer fmt.Printf(\u0026#34;Worker %d exiting\\n\u0026#34;, i) 21\tdefer p.wg.Done() 22 23\tfor { 24\td, ok := \u0026lt;-p.data 25\tif !ok { 26\t// data channel closed 27\treturn 28\t} 29 30\tfmt.Printf(\u0026#34;Worker %d processing data: %d\\n\u0026#34;, i, d) 31\t// do some heavy lifting 32\ttime.Sleep(200 * time.Millisecond) 33\t} 34} Here we have a struct which contains one exported field, Generator and two non-exported fields, wg and data. Generator field is of Generator type described above in the article and is used to define a generator function to be used to generate a series of values. We run this method (p.Generator) early in the Run method in order to populate the data channel.\nAfter that, in the Run method we start a group of goroutines controlled by sync.WaitGroup. Before we start each worker goroutine, we run p.wg.Add method adding 1 to it, meaning we tell the wait group that there is one more goroutine to wait for. Later, each worker calls p.wg.Done, which means we are telling the wait group that one worker finished or actually there is one worker less to wait for. Add and Done methods basically add and remove a worker (goroutine) to/from the wait group. Finally, p.wg.Wait will block the execution until all workers in the wait group finish the execution.\nThat would be all about the Run method and now let\u0026rsquo;s explain the things in non-exported method, worker. We have an infinite loop there, meaning we need some way to finish the goroutine and that is the data channel. This loop will end when p.data channel is closed and we check this condition using the ok variable when we receive a value from the channel. Closed channel continuosly emits zero values, but we may use second variable (ok in this case) to find out if we really received a value from the channel or is this just a dummy emition from the closed channel. In case this is just \u0026ldquo;dummy\u0026rdquo; value, we return but still deffered methods will be executed, meaning p.wg.Done will be called anaways. You may find more about the behaviour of the closed channels here .\nFinally, let\u0026rsquo;s say something about function wrapping and closures in Golang. Generator type from above defines the signature fot this method, but in the real life we may need to pass some arguments to the function. How to do this when Generator type function has no arguments? The answer is function wrapping and we wrap a function which will call a closure in this case, because it uses variable from the wrapper function. This looks like the following:\n1func random(count, max int) Generator { 2\treturn func() \u0026lt;-chan int { 3\tdc := make(chan int) 4\trand.Seed(time.Now().UnixNano()) 5 6\tgo func() { 7\tfor i := 1; i \u0026lt;= count; i++ { 8\tdc \u0026lt;- 1 + rand.Intn(max) 9\t} 10\tclose(dc) 11\t}() 12 13\treturn dc 14\t} 15} So, function random returns a value of Generator type and this can be easily populate the exported, Generator field of WorkerPool struct. Inside the closure, we can used values passed to the random function and still return the right function of Generator type. This is very common in Golang and it is actually called functional programming.\nFinally, we run all of this in the following way:\n1func main() { 2\twp := WorkerPool{ 3\tGenerator: random(100, 1000), 4\t} 5\twp.Run(3) 6} There is not much to explain here, but you may continue learning and testing this in Go Playground.\n","date":"October 4, 2019","externalUrl":null,"permalink":"/blog/generators-waitgroups-closures-golang/","section":"Blog","summary":"This is the first step of my intention to write a series of articles where I would explain some common patterns used in Golang. Let’s start with generator pattern :\n1type Generator func() \u003c-chan int Generator is a function or method which returns a sequence of values. In Golang, this usually means returning a channel of values of desired type. In our example, we will return a channel of integers. Let’s see an implementation of this:\n","title":"Generators, wait groups and closures in Golang","type":"blog"},{"content":"Modern Linux desktop distributions contain really powerful settings possibilities, but it is very often difficult to find out how to configure something. You may want, for example, to add \u0026ndash;disk-cache-dir flag to Chromium start command in order to configure cache directory, so how to do it?\nright click on the menu start button and select \u0026ldquo;Configure\u0026rdquo; click on the \u0026ldquo;Menu\u0026rdquo; button at the top of the \u0026ldquo;Menu\u0026rdquo; window click on the \u0026ldquo;Open the menu editor\u0026rdquo; button browse the applications and find the requested one (Chromium in this case) select the application and click on \u0026ldquo;Properties\u0026rdquo; button on the right add requested command flag in the \u0026ldquo;Command\u0026rdquo; field The described procedure relates to Linux Mint 19.2 Tina - Cinnamon, but it probably applies also to Linux Mint 19.1 Tessa - Cinnamon and maybe other variants.\n","date":"October 3, 2019","externalUrl":null,"permalink":"/blog/add-flag-linux-mint/","section":"Blog","summary":"Modern Linux desktop distributions contain really powerful settings possibilities, but it is very often difficult to find out how to configure something. You may want, for example, to add –disk-cache-dir flag to Chromium start command in order to configure cache directory, so how to do it?\n","title":"Add flag to Linux Mint application start command","type":"blog"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/chromium/","section":"Tags","summary":"","title":"Chromium","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/cinnamon/","section":"Tags","summary":"","title":"Cinnamon","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/command/","section":"Tags","summary":"","title":"Command","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/flag/","section":"Tags","summary":"","title":"Flag","type":"tags"},{"content":"Official Golang documentation contains just tar.gz package to be downloaded and installed on Ubuntu Linux, but this is not quite comfortable way because Golang won\u0026rsquo;t be automatically updated after new release. Fortunatelly, there is trustable PPA that can be used.\nsudo add-apt-repository ppa:longsleep/golang-backports sudo apt-get update sudo apt-get install golang-go ","date":"October 3, 2019","externalUrl":null,"permalink":"/blog/install-golang-ppa/","section":"Blog","summary":"Official Golang documentation contains just tar.gz package to be downloaded and installed on Ubuntu Linux, but this is not quite comfortable way because Golang won’t be automatically updated after new release. Fortunatelly, there is trustable PPA that can be used.\n","title":"Install Golang package on Ubuntu Linux","type":"blog"},{"content":"Few months ago I wrote an article about replacing Minikube with MicroK8s , but now we have even better soluion, kind . Like dind allows running Docker inside Docker containers, kind allows running Kubernetes inside Docker containers. kind basically abstracts nodes as Docker containers and then runs Kubernetes inside.\nAfter you install Golang , it is quite easy to install and setup kind:\nGO111MODULE=\u0026#34;on\u0026#34; go get sigs.k8s.io/kind@v0.5.1 kind create cluster After some 30 seconds your single node cluster will be ready for development and testing. But that\u0026rsquo;s not all, kind allows much complex setup, for example three node cluster with one master and two workers. Let\u0026rsquo;s first create declarative object:\nkind: Cluster apiVersion: kind.sigs.k8s.io/v1alpha3 nodes: - role: control-plane - role: worker - role: worker Save it as cluster.yaml and run the following command:\nkind create cluster --config cluster.yaml --name multinode Yes, it is easy as that. If you are Golang developer, it is nice to know that kind also provides library to be used in Go. You can find more information watching this video .\n","date":"October 3, 2019","externalUrl":null,"permalink":"/blog/new-kind-on-the-block/","section":"Blog","summary":"Few months ago I wrote an article about replacing Minikube with MicroK8s , but now we have even better soluion, kind . Like dind allows running Docker inside Docker containers, kind allows running Kubernetes inside Docker containers. kind basically abstracts nodes as Docker containers and then runs Kubernetes inside.\n","title":"New kind on the Block","type":"blog"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/ramdisk/","section":"Tags","summary":"","title":"Ramdisk","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/tessa/","section":"Tags","summary":"","title":"Tessa","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/tina/","section":"Tags","summary":"","title":"Tina","type":"tags"},{"content":"","date":"October 3, 2019","externalUrl":null,"permalink":"/tags/tips--tricks/","section":"Tags","summary":"","title":"Tips \u0026 Tricks","type":"tags"},{"content":"","date":"September 26, 2019","externalUrl":null,"permalink":"/tags/hetzner/","section":"Tags","summary":"","title":"Hetzner","type":"tags"},{"content":"Scaleway , a French company based in Paris, owned by Illiad telecommunication provider, just announced public availability of their managed Kubernetes solution called Kapsule . Scaleway has 5 data centers, 4 in France and 1 in Netherlands, but at the moment Kapsule (public beta version) is available just in the datacenter in Paris. DigitalOcean just got competition, so we can compare the pricing schemes in the later text.\nKapsule service includes block storage (PersistentVolumeClaim), pool autoscaling, control-plane\u0026rsquo;s upgrade, S3 compatible object storage and container registry with free bandwidth. You won\u0026rsquo;t pay any special fee for Kapsule, you pay just for instances, load balancers and block storage (free for early access).\nIf we compare prices between DigitalOcean and Scaleway, Scaleway is a clear winner. Prices of load balancer are 10€ and 8,99€ respectively, which is just a slight difference, but prices of instances are also on the Scaleway\u0026rsquo;s side and you may experience much bigger savings if you choose Scaleway. However, DigitalOcean has more data centers accross Europe and USA and also more experience running managed Kubernetes, so decision is not that easy, but if you are based in France, you should give Scaleway a try.\nHetzner Cloud still remains unbeatable with instance prices at half of Scaleway ones. Yes, this is not managed Kubernetes and there are no load balancers at the moment, but at least Hetzner introduced private networking so that nodes in your cluster finally may communicate over a private network and without solutions like WireGuard . You can find instructions how to setup private network at Hetzner Cloud here . And don\u0026rsquo;t forget Hetzner Cloud Controller Manager and Container Storage Interface driver .\n","date":"September 26, 2019","externalUrl":null,"permalink":"/blog/inexpensive-managed-kubernetes-solutions/","section":"Blog","summary":"Scaleway , a French company based in Paris, owned by Illiad telecommunication provider, just announced public availability of their managed Kubernetes solution called Kapsule . Scaleway has 5 data centers, 4 in France and 1 in Netherlands, but at the moment Kapsule (public beta version) is available just in the datacenter in Paris. DigitalOcean just got competition, so we can compare the pricing schemes in the later text.\n","title":"Inexpensive managed Kubernetes solutions","type":"blog"},{"content":"","date":"September 26, 2019","externalUrl":null,"permalink":"/tags/price/","section":"Tags","summary":"","title":"Price","type":"tags"},{"content":"","date":"September 26, 2019","externalUrl":null,"permalink":"/tags/scaleway/","section":"Tags","summary":"","title":"Scaleway","type":"tags"},{"content":"","date":"July 21, 2019","externalUrl":null,"permalink":"/tags/cni/","section":"Tags","summary":"","title":"Cni","type":"tags"},{"content":"","date":"July 21, 2019","externalUrl":null,"permalink":"/tags/cri/","section":"Tags","summary":"","title":"Cri","type":"tags"},{"content":"","date":"July 21, 2019","externalUrl":null,"permalink":"/tags/csi/","section":"Tags","summary":"","title":"Csi","type":"tags"},{"content":"I\u0026rsquo;ve just seen a talk on YouTube where running self managed Kubernetes cluster was described as ninja technique. I strongly disagree with this and actually want to disapprove it in this article. Running self managed K8S can also be inexpensive if you use a provider such as Hetzner Cloud.\nAs a prerequisite to complete the following step, you need to install Go first. Now let\u0026rsquo;s install hcloud command line utility :\nexport PATH=~/go/bin:/usr/local/go/bin:$PATH go get -u github.com/hetznercloud/cli/cmd/hcloud In order to be able to connect to your Hetzner Cloud account using hcloud command, you will need to get your API key on their web console and export it:\nexport HCLOUD_TOKEN=your_key We are ready to do the real stuff now, so let\u0026rsquo;s configure the SSH key to be used and create the VM instance:\nhcloud ssh-key create --name your_ssh_key_name --public-key-from-file ~/.ssh/id_rsa.pub hcloud server create --name server_name --image ubuntu-16.04 --location nbg1 --ssh-key your_ssh_key_name --type cx41 You should see the public IP of the freshly created instance in the output or just check it out at the web console. You may want to configure DNS here, but this is out of the scope of this article. It is always a good idea to fully update your newly created Ubuntu box:\nssh root@your_ip_address apt-get update apt-get upgrade apt-get dist-upgrade reboot Now let\u0026rsquo;s install CRI (Container Runtime Interface). We will use Docker :\napt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - add-apt-repository \\ \u0026#34;deb [arch=amd64] https://download.docker.com/linux/ubuntu \\ $(lsb_release -cs) \\ stable\u0026#34; apt-get update apt-get install docker-ce cat \u0026gt; /etc/docker/daemon.json \u0026lt;\u0026lt;EOF { \u0026#34;exec-opts\u0026#34;: [\u0026#34;native.cgroupdriver=systemd\u0026#34;], \u0026#34;log-driver\u0026#34;: \u0026#34;json-file\u0026#34;, \u0026#34;log-opts\u0026#34;: { \u0026#34;max-size\u0026#34;: \u0026#34;100m\u0026#34; }, \u0026#34;storage-driver\u0026#34;: \u0026#34;overlay2\u0026#34; } EOF mkdir -p /etc/systemd/system/docker.service.d systemctl daemon-reload systemctl restart docker Kubernetes requires some capabilities which are not enabled by default on Ubuntu 16.04, so edit the /etc/ufw/sysctl.conf file and add this snippet at the bottom:\n# Kubernetes \u0026amp; Flannel net/bridge/bridge-nf-call-ip6tables=1 net/bridge/bridge-nf-call-iptables=1 net/bridge/bridge-nf-call-arptables=1 Reboot your VM and finally install the latest stable version of Kubernetes:\ncurl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add apt-add-repository \u0026#34;deb http://apt.kubernetes.io/ kubernetes-xenial main\u0026#34; apt-get update apt-get install -y kubelet kubeadm kubectl kubeadm init --pod-network-cidr=10.244.0.0/16 We can now continue configuring K8S using kubectl command, but we need to configure kubectl beforehand:\nmkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config Kubernetes also needs some CNI (Container Networking Interface). We will use Flannel :\nkubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml At this point you may want to create more nodes and join to the cluster, but we will continue with the single node \u0026ldquo;cluster\u0026rdquo;. I may write another article on this topic, but let\u0026rsquo;s keep it simple this time. In order to run your applications (pods) on master node, we need to taint it:\nkubectl taint nodes --all node-role.kubernetes.io/master- And do some security (firewall) stuff:\nufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw allow 6443/tcp ufw allow 8285/udp # Flannel ufw allow 8472/udp # Flannel ufw enable We are now ready to run our applications, but if you want to use automatic storage provisioning on Hetzner Cloud , you will need to install CSI (Container Storage Interface). Let\u0026rsquo;s first create secret with Hetzner Cloud API token:\napiVersion: v1 kind: Secret metadata: name: hcloud-csi namespace: kube-system stringData: token: PUT_YOUR_TOKEN_HERE Save this to secret-hcloud-csi.yaml and run the following commands to install CSI:\nkubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csidriver.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csinodeinfo.yaml kubectl apply -f secret-hcloud-csi.yaml kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/master/deploy/kubernetes/hcloud-csi.yml And voila, that\u0026rsquo;s all. We are finished setting up the latest Kubernetes version on Ubuntu 16.04 which is still the latest officially supported version. If you want to use Ubuntu 18.04, you can still use these instructions except you may need to modify or skip the part about configuring /etc/ufw/sysctl.conf. Have fun with K8S.\n","date":"July 21, 2019","externalUrl":null,"permalink":"/blog/run-k8s-like-ninja/","section":"Blog","summary":"I’ve just seen a talk on YouTube where running self managed Kubernetes cluster was described as ninja technique. I strongly disagree with this and actually want to disapprove it in this article. Running self managed K8S can also be inexpensive if you use a provider such as Hetzner Cloud.\n","title":"Run K8S like ninja","type":"blog"},{"content":"Minikube is very popular and the most known Kubernetes version for local software development. It runs inside a virtual machine like VirtualBox and allows developers to run Kubernetes applications locally. As Docker runs natively just on Linux, you may wonder why do we need virtual machine on Linux? Well, not anymore.\nMac users have no other way of running Docker except in a virtual machine, hidden or visible. However, Linux users should be able to run Docker and Kubernetes over it just on the bare metal. Minikube has possibility to run on Linux without a virtual machine, but as it installs locally in that case, different configuration files get spread over the host system and this is pretty much messy, actually not much different than installing Kubernetes using kubeadm . Fortunatelly, MicroK8s comes as help.\nThanks to snapd , light Linux virtualization layer available on Ubuntu and derivative operating system, you may now install MicroK8s using snap simply by running the following command:\nsudo snap install microk8s --classic To configure kubectl to use this \u0026ldquo;cluster\u0026rdquo;, you can just run:\nmicrok8s.config \u0026gt;~/.kube/config To start and stop microk8s, just type:\nsudo microk8s.stop sudo microk8s.start Well, good news for Ubuntu users, but what about Mac? Guess what, there is actually Mac version as well. Still runing in a virtual machine, but at least this virtual machine is lighter than VirtualBox. To install the Multipass on Mac, just download the latest *-Darwin.pkg from here . After that, run the following commands:\nmultipass launch --name microk8s --mem 4G --disk 40G multipass exec microk8s -- sudo snap install microk8s --classic multipass exec microk8s -- sudo iptables -P FORWARD ACCEPT You can find more usable multipass commands here .\nBesides basic Kubernetes functionality, MicroK8s provides several addons:\ndashboard dns fluentd gpu ingress istio jaeger metrics-server prometheus registry storage You can simply enable some of them using microk8s.enable.\nLinux:\nmicrok8s.enable dns dashboard Mac: ```sh multipass exec microk8s-vm -- /snap/bin/microk8s.enable dns dashboard That\u0026rsquo;s all Kubernatus, happy cube-kuttling.\n","date":"May 22, 2019","externalUrl":null,"permalink":"/blog/forget-about-minikube-try-microk8s/","section":"Blog","summary":"Minikube is very popular and the most known Kubernetes version for local software development. It runs inside a virtual machine like VirtualBox and allows developers to run Kubernetes applications locally. As Docker runs natively just on Linux, you may wonder why do we need virtual machine on Linux? Well, not anymore.\n","title":"Forget Minikube, try MicroK8s","type":"blog"},{"content":"","date":"May 22, 2019","externalUrl":null,"permalink":"/tags/microk8s/","section":"Tags","summary":"","title":"Microk8s","type":"tags"},{"content":"Helm is a great tool to deploy popular services and applications to your Kubernetes cluster, but from the moment I started using it I had a feeling that something is missing. You could easily configure and install whatever, but each chart that you use is a separate unit and there is no code containing all resources. This practically means in case of disaster it was still not easy to recreate the cluster, at least not in a quick time frame. Another contra is that in order to pin exact image versions, you would have to edit each values file every time you want to upgrade something.\nFortunately, there is a tool called helmfile which basically can integrate all your Helm charts allowing full control over installed resources, image versions and settings. You may say yeah, but there may be some more resources defined or applied by kubectl and this can\u0026rsquo;t be defined neither in Helm nor in helmfile. Wrong, there is a Helm chart called raw , which is currently in incubator phase, but it allows documenting all additional resources like secrets, TLS certificates, external services, etc. Combining these two it is really possible to finally have all resources defined as code and even better, it allows full control over upgrades and current state of the cluster.\nIf you install Helm plugin diff , you may see the differences between the current cluster state and the desired state and decide before hand weather you want to sync or not. helmfile is stateless and it will always fetch the real state inside of Kube cluster. So, I strongly suggest to install this plugin and then you can use helmfile subcommand diff.\nAnother important thing is how to protect your secrets. Of course they should not finish in your Git repository. It is maybe worth to mention that there is a nice tool called gitleaks , which can check your Git repository for leaked secrets. But let\u0026rsquo;s go back to the topic how to protect your secrets. You can do it more ways, of course and one of the best and probably most complicated would be using of Vault . If you are not runnig an enterprise Kubernetes cluster, it is probably good enough to use either helm-secrets plugin or environments variables managed by direnv .\nThe third option is the simplest. You just define your secrets as environment variables in a file called .envrc in your project directory and import them by:\ndirenv allow . In your helmfiles you can then use these wherever you have value defined as:\n{{ requiredEnv \u0026#34;ENV_VAR_NAME\u0026#34; }} Here is an example of docker-registry declaration in helmfile:\nreleases: - name: docker-registry namespace: default chart: stable/docker-registry set: - name: secrets.htpasswd value: { { requiredEnv \u0026#34;DOCKER_REGISTRY_BASIC_AUTH_PASSWD\u0026#34; } } You can apply this by:\nhelmfile -f filename.yaml sync And the final note is - don\u0026rsquo;t forget tu put .envrc in your .gitignore file ?\n","date":"May 11, 2019","externalUrl":null,"permalink":"/blog/complete-your-kubernetes-resources-as-code-using-helmfile-and-raw-chart/","section":"Blog","summary":"Helm is a great tool to deploy popular services and applications to your Kubernetes cluster, but from the moment I started using it I had a feeling that something is missing. You could easily configure and install whatever, but each chart that you use is a separate unit and there is no code containing all resources. This practically means in case of disaster it was still not easy to recreate the cluster, at least not in a quick time frame. Another contra is that in order to pin exact image versions, you would have to edit each values file every time you want to upgrade something.\n","title":"Complete your Kubernetes resources as code using helmfile and raw Helm chart","type":"blog"},{"content":"Few days ago, DigitalOcean announced PostgreSQL DBaaS , which is really nice, but even better, they promised soon availability of MySQL and Redis managed services. While we are waiting for this, I will describe in this article how to backup your Kubernetes MySQL database to Spaces , DigitalOcean\u0026rsquo;s S3 compatible storage.\nIn my case, MySQL database, actually MariaDB is running as a cluster service on my Kubernetes cluster. First you have to create your Spaces storage and you should get an endpoint similar to this one https://mybucket.ams3.digitaloceanspaces.com . Next, under menu API, on the left hand side menu, you should create your Spaces keys. These values are needed to configure the backup cronjob.\nNow we can start with the Kubernetes stuff. First let\u0026rsquo;s create secret:\nkubectl create secret generic mariadb-backup-secrets \\ --from-literal=spacesKey=\u0026#34;XXX\u0026#34; \\ --from-literal=spacesSecret=\u0026#34;YYY\u0026#34; \\ --from-literal=mariaDbPassword=\u0026#34;ZZZ\u0026#34; XXX is your Spaces key name YYY is your Spaces secret for the key ZZZ is your MySQL password (probably for user root if you want to backup all databases) Now let\u0026rsquo;s create Kubernetes CronJob:\n--- apiVersion: batch/v1beta1 kind: CronJob metadata: name: mariadb-backup spec: schedule: \u0026#39;0 3 * * *\u0026#39; concurrencyPolicy: Forbid successfulJobsHistoryLimit: 2 failedJobsHistoryLimit: 2 jobTemplate: spec: template: spec: containers: - name: mysqldump image: schickling/mysql-backup-s3 env: - name: S3_ENDPOINT value: https://ams3.digitaloceanspaces.com - name: S3_REGION value: ams3 - name: S3_BUCKET value: mybucket - name: S3_PREFIX value: \u0026#39;mariadb-backup\u0026#39; - name: S3_ACCESS_KEY_ID valueFrom: secretKeyRef: name: mariadb-backup-secrets key: spacesKey - name: S3_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: mariadb-backup-secrets key: spacesSecret - name: MYSQL_HOST value: mariadb.default.svc.cluster.local - name: MYSQL_USER value: root - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mariadb-backup-secrets key: mariaDbPassword - name: MULTI_FILES value: \u0026#39;true\u0026#39; restartPolicy: OnFailure shedule fields is crontab compatible format of the time when your job should run (see man 5 crontab) S3_ENDPOINT is your endpoint without the Spaces name. If you got https://mybucket.ams3.digitaloceanspaces.com when you configured Spaces, you should extract mybucket here. Then next part of the URL is your region, which is in my case Amsterdam. So your S3_ENDPOINT should be https://ams3.digitaloceanspaces.com S3_REGION seems to be optional, but you can set it anyways S3_BUCKET is your Spaces name, let\u0026rsquo;s sam mybucket S3_PREFIX is a directory within your Spaces. You can create this directory at DigitalOcean interface and if not, it will be created automatically after the first storage to it. You can have multiple directories for different purposes. S3_ACCESS_KEY_ID is your key name from Spaces S3_SECRET_ACCESS_KEY is your secret from Spaces MULTI_FILES defines weather all databases will be backed up in the same file or in separate files. I chose to backup in separate files so that I can easily restore if needed. Your Kubernetes CronJob will run at defined times, but you can also trigger it manually in your Dashboard or in your shell:\nkubectl create job --from=cronjob/mariadb-backup mariadb-backup-manual-001 ","date":"February 17, 2019","externalUrl":null,"permalink":"/blog/backup-mysql-databases-to-digital-ocean-spaces/","section":"Blog","summary":"Few days ago, DigitalOcean announced PostgreSQL DBaaS , which is really nice, but even better, they promised soon availability of MySQL and Redis managed services. While we are waiting for this, I will describe in this article how to backup your Kubernetes MySQL database to Spaces , DigitalOcean’s S3 compatible storage.\n","title":"Backup Kubernetes MySQL database to DigitalOcean Spaces","type":"blog"},{"content":"","date":"February 17, 2019","externalUrl":null,"permalink":"/tags/digitalocean/","section":"Tags","summary":"","title":"DigitalOcean","type":"tags"},{"content":"","date":"February 17, 2019","externalUrl":null,"permalink":"/tags/spaces/","section":"Tags","summary":"","title":"Spaces","type":"tags"},{"content":"acim.net is built and provided by Boban Acimovic. This Service is provided at no cost and is intended for use as is.\nThis page is used to inform website visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.\nCookies # Cookies are files with small amount of data that is commonly used an anonymous unique identifier. These are sent to your browser from the website that you visit and are stored on your devices\u0026rsquo;s internal memory.\nThis Services does not uses these \u0026ldquo;cookies\u0026rdquo; explicitly.\nLinks to Other Sites # This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by us. Therefore, we strongly advise you to review the Privacy Policy of these websites. We have no control over, and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.\nChanges to This Privacy Policy # We may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately, after they are posted on this page.\nContact Us # If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us.\nUpdated: 2021-07-18\n","externalUrl":null,"permalink":"/privacy/","section":"","summary":"acim.net is built and provided by Boban Acimovic. This Service is provided at no cost and is intended for use as is.\nThis page is used to inform website visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.\n","title":"Privacy Policy","type":"page"},{"content":" Disclaimer # This is a personal blog. Any views or opinions represented in this blog are personal and belong solely to the blog owner and do not represent those of people, institutions or organizations that the owner may or may not be associated with in professional or personal capacity, unless explicitly stated.\nAny views or opinions are not intended to malign any religion, ethnic group, club, organization, company, or individual.\nAll content provided on this blog is for informational purposes only. The owner of this blog makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.\nThe owner will not be liable for any errors or omissions in this information nor for the availability of this information. The owner will not be liable for any losses, injuries, or damages from the display or use of this information.\nDownloadable Files and Images # Any downloadable file, including but not limited to pdfs, docs, jpegs, pngs, is provided at the user’s own risk. The owner will not be liable for any losses, injuries, or damages resulting from a corrupted or damaged file.\nFinal note # This blog disclaimer is subject to change at anytime.\n","externalUrl":null,"permalink":"/terms/","section":"","summary":"Disclaimer # This is a personal blog. Any views or opinions represented in this blog are personal and belong solely to the blog owner and do not represent those of people, institutions or organizations that the owner may or may not be associated with in professional or personal capacity, unless explicitly stated.\n","title":"Terms And Conditions","type":"page"}]