<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>wykwit</title>
    <subtitle>Projects, notes, and opinions on software, security, deployments, LLMs...</subtitle>
    <link rel="self" type="application/atom+xml" href="https://www.wykwit.pl/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.wykwit.pl"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-04-17T00:00:00+00:00</updated>
    <id>https://www.wykwit.pl/atom.xml</id>
    <entry xml:lang="en">
        <title>LLM subscriptions</title>
        <published>2026-04-17T00:00:00+00:00</published>
        <updated>2026-04-17T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/llm-subscriptions/"/>
        <id>https://www.wykwit.pl/blog/llm-subscriptions/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/llm-subscriptions/">&lt;p&gt;Another post in my LLM series, this time about LLM inference providers, labs, available subscriptions, and why it might be a worthwhile purchase at the time of writing. I also sprinkle in some LLM updates that you might have missed and round it out with my own perspective.&lt;/p&gt;
&lt;h2 id=&quot;inference-and-how-to-get-it&quot;&gt;Inference and how to get it&lt;a class=&quot;zola-anchor&quot; href=&quot;#inference-and-how-to-get-it&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Inference is the prediction made by the model as to what (output) tokens should follow other (input) tokens under consideration. In simple terms, by LLM inference we mean computations delegated to the model that give some output tokens in return. This inference computation is not cheap and usually constrained by the provider (the company or datacenter that runs the LLM).&lt;/p&gt;
&lt;p&gt;There are a few ways to obtain it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using built-in integrations (like the G00gle Search &quot;AI Overview&quot;)&lt;/li&gt;
&lt;li&gt;using dedicated tools (like Perplexity or DeepSeek apps)&lt;/li&gt;
&lt;li&gt;buying a subscription from the model provider&lt;/li&gt;
&lt;li&gt;accessing models directly through API calls to the model provider&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As we go from top to bottom these options get more expensive, but they do get more flexible too.&lt;/p&gt;
&lt;h2 id=&quot;integrations-and-products&quot;&gt;Integrations and products&lt;a class=&quot;zola-anchor&quot; href=&quot;#integrations-and-products&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;With a built-in integration you have no control over what models are in use, from what provider, what are the model capabilities. You are handed a ready-made product, sometimes only a fancy name, and expected to use it as intended. Search summary is a good example of such integration done right - many people started to rely on it and for certain queries that is more than you need. Other times these &quot;AI&quot; features land anywhere between an annoyance and an obstacle that the user has to fight in order to achieve the result they need. One of many reasons why &quot;AI&quot; gets well-deserved bad rep.&lt;/p&gt;
&lt;p&gt;The situation is a little better with dedicated tools. Usually the choice of a tool is either tied to the provider in the first place or allows for switching the underlying model and selecting some preferences. Here&#39;s a very good example: &lt;a rel=&quot;external&quot; href=&quot;https://t3.chat/&quot;&gt;T3 Chat&lt;/a&gt; is an LLM chat webapp that gives you access to all models for a monthly subscription fee. You get to choose which model you want to use, but the scope of this product subscription is limited to the product itself. You are not buying a subscription for the model inference, you are buying a subscription to access the product. The inference is just a part of it, required to make the product work. Another example that comes to mind is &lt;a rel=&quot;external&quot; href=&quot;https://www.perplexity.ai/&quot;&gt;Perplexity&lt;/a&gt;. They charge a monthly fee for LLM powered websearch, giving you the option to choose which exact model you want to use for generating the answers. They only support a few selected models. The subscription cost is mainly for access to their app, not meant to provide you with raw model inference.&lt;/p&gt;
&lt;h2 id=&quot;the-cost-of-inference&quot;&gt;The cost of inference&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-cost-of-inference&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Buying inference directly can be rather costly depending on the model. The best way to explore this option is through &lt;a rel=&quot;external&quot; href=&quot;https://openrouter.ai/&quot;&gt;OpenRouter&lt;/a&gt; which is a common gateway for accessing different models served by different providers. You can clearly see how individual providers differ with the service quality: different latency, different uptime statistics, reliability, and most importantly - different inference throughput (tokens per second) for the same model. If you&#39;re building a product on top of LLMs, this is the way to go. You pay exactly for what you use. Picking the right model and provider will make all the difference for your project.&lt;/p&gt;
&lt;p&gt;For personal use subscriptions may be the best deal right now. If you&#39;re not using LLMs much it will probably cost you more than paying for inference directly, but then again if you&#39;re not using LLMs much you may as well rely on the other two options discussed previously and avoid any additional costs. There are still many people who keep their subscriptions even though they get nowhere near the usage they pay for. That&#39;s one of the reasons why inference subscriptions can stay so cheap. They are heavily subsidized and many companies see them as an opportunity to sell people another product that isn&#39;t just inference. As long as you don&#39;t fall for this marketing trap, for heavy LLM usage, this comes out to be a really good deal. There are many subscriptions that live on the edge between being a product price and inference price. You should know what you&#39;re paying for and keep your hand on the pulse to drop subscriptions that lose their value. The market now is rather competitive, so there&#39;s plenty of options to choose from.&lt;/p&gt;
&lt;h2 id=&quot;best-deals-last-year&quot;&gt;Best deals last year&lt;a class=&quot;zola-anchor&quot; href=&quot;#best-deals-last-year&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&quot;github-copilot&quot;&gt;GitHub Copilot&lt;a class=&quot;zola-anchor&quot; href=&quot;#github-copilot&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Last year my favorite option was the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/features/copilot/plans&quot;&gt;GitHub Copilot Pro&lt;/a&gt; plan. It&#39;s priced at 10 USD and gives you a monthly quota of &quot;300 premium request tokens&quot; which can be used for calling top models from 0penAI, G00gle, and Anthr0pic. The way it used to work was that it would consume a predefined amount of &quot;premium request tokens&quot; for each started session, so you could pretty much use a model indefinitely for free after that. Now each message consumes some predefined amount of premium request tokens (probably as intended from the start). Still, this amount is defined per model, regardless of the selected reasoning effort. For a single run of GPT-5.4 xhigh, which can take hours to finish and burn a ton of inference tokens, it is still a decent price. Obviously it is worse than what we had last year. Back then it was probably the most cost-effective option of all. It wasn&#39;t as straightforward to use in external tools as it is now, but it was always possible. Between the &quot;premium request tokens&quot; consumption fix and the release of GPT-5.4 that subscription was not worth the price. You could burn through the monthly quota in a matter of minutes trying to use it with Claude Opus.&lt;/p&gt;
&lt;h3 id=&quot;perplexity&quot;&gt;Perplexity&lt;a class=&quot;zola-anchor&quot; href=&quot;#perplexity&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;There was also a brief moment in September last year when you could get a free Perplexity Pro annual subscription. I got on board and I&#39;m getting quite a lot of use from it, often defaulting to the Perplexity mobile app for search. I kinda like it, but to be honest I would never use it if I had to pay for it at all. I set a reminder when I signed up to cancel and delete my account before this promotional subscription runs out. I don&#39;t even know how much exactly it costs now, but whatever it is I wouldn&#39;t say it&#39;s worth the money.&lt;/p&gt;
&lt;h3 id=&quot;z-ai&quot;&gt;Z.AI&lt;a class=&quot;zola-anchor&quot; href=&quot;#z-ai&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;On a different note, another great catch of insane value from last year was the &lt;a rel=&quot;external&quot; href=&quot;https://z.ai/subscribe&quot;&gt;Z.AI GLM Coding Plan&lt;/a&gt;. I fell in love with the &lt;a rel=&quot;external&quot; href=&quot;https://artificialanalysis.ai/models/glm-4-7/&quot;&gt;GLM-4.7&lt;/a&gt; model when I finally tried it in December and I&#39;ve been preaching it since.&lt;/p&gt;
&lt;p&gt;The Lite plan, which is now 18 USD/month, was 3 USD/month back then. I got it, I tried it out, and I signed up for the annual subscription of the Pro plan. If I recall correctly I paid something like 180 USD for it. Now it&#39;s priced at 864 USD annually or 72 USD/month. I kinda wish I got the Max plan back then, because it was only slightly more expensive, but I doubt I could push it to the limit. Even on the Lite plan hitting a limit was very difficult.&lt;/p&gt;
&lt;p&gt;GLM-4.7 is still a wonderful model and I knew I&#39;d be very happy with it even if Z.AI didn&#39;t deliver another one for a year, but they followed with even stronger &lt;a rel=&quot;external&quot; href=&quot;https://z.ai/blog/glm-5&quot;&gt;GLM-5&lt;/a&gt; in February, then GLM-5-Turbo, and then recently &lt;a rel=&quot;external&quot; href=&quot;https://z.ai/blog/glm-5.1&quot;&gt;GLM-5.1&lt;/a&gt; - all extremely good and very underrated. In benchmarks GLM models are second only to GPT-5.4 and Opus 4.6 with high reasoning effort. In practice GLM models are often way better, depending on the task.&lt;/p&gt;
&lt;p&gt;It&#39;s also worth noting how much cheaper GLM models are, how much faster, and how much more transparent. They are &lt;a rel=&quot;external&quot; href=&quot;https://huggingface.co/zai-org/GLM-5.1&quot;&gt;open-weight, MIT-licensed&lt;/a&gt;! The quality of GPT and Claude may degrade over time, we may lose access to these models eventually, but GLM models will stay available, you can download them right now yourself. They are only getting better with time as providers figure out how to run the model more efficiently at higher throughput. That gives me so much more confidence to rely on it, as opposed to constrained private western models.&lt;/p&gt;
&lt;p&gt;Long story short - Z.AI&#39;s GLM models are my favorite and I&#39;m really glad I got in at the right time.&lt;/p&gt;
&lt;h2 id=&quot;fierce-competition-in-china&quot;&gt;Fierce competition in China&lt;a class=&quot;zola-anchor&quot; href=&quot;#fierce-competition-in-china&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are many strong competitors coming from China other than Z.AI. The main one is MiniMax, a company with a very wide offer of generative tools. They timed their previous two LLM releases to match up with Z.AI: &lt;a rel=&quot;external&quot; href=&quot;https://www.minimax.io/news/minimax-m21&quot;&gt;M2.1&lt;/a&gt; released a single day after &lt;a rel=&quot;external&quot; href=&quot;https://z.ai/blog/glm-4.7&quot;&gt;GLM-4.7&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://www.minimax.io/news/minimax-m25&quot;&gt;M2.5&lt;/a&gt; released the same day as GLM-5. About a month ago they released a new &lt;a rel=&quot;external&quot; href=&quot;https://www.minimax.io/news/minimax-m27-en&quot;&gt;M2.7&lt;/a&gt;. I couldn&#39;t find a strong enough use-case for the previous two models, so I wasn&#39;t particularly keeping up with them, and I haven&#39;t yet tried M2.7. They have their own &lt;a rel=&quot;external&quot; href=&quot;https://platform.minimax.io/subscribe/token-plan&quot;&gt;subscription offer&lt;/a&gt;. It&#39;s hard for me to assess the value, since I am not using it myself, but it does look promising.&lt;/p&gt;
&lt;p&gt;I have, however, used a lot of the very impressive &lt;a rel=&quot;external&quot; href=&quot;https://www.kimi.com/blog/kimi-k2-5&quot;&gt;Kimi K2.5&lt;/a&gt; model after it released in late January this year. The Moonshot AI lab is a world leader when it comes to LLM research. For some time between GLM releases their model was leading in the intelligence benchmarks too. Moonshot AI offers subscription plans through &lt;a rel=&quot;external&quot; href=&quot;https://www.kimi.com/code&quot;&gt;Kimi Code membership&lt;/a&gt;. The prices start at 20 USD/month. Back when I tried their lowest subscription tier I&#39;d burn through the quota rather fast. I heard they have increased it since, but I&#39;m not sure how much you can really get out of these plans. There are stronger models out there and better priced subscriptions. Kimi K2.5 itself is rather cheap even when you pay directly for the inference per token. I do recommend trying out the model, but not necessarily through this subscription. Definitely keep an eye out on future releases and the research that this team drops.&lt;/p&gt;
&lt;p&gt;When it comes to research teams the uncontested king is definitely &lt;a rel=&quot;external&quot; href=&quot;https://deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;. They have no subscriptions. They don&#39;t even charge for the use of their app. The LLM itself is also crazy cheap and very good. Everybody is waiting for the next LLM drop from this lab, because you can bet it&#39;s gonna be big. Right now their latest model is the weakest on my list, but this will very likely change with their next highly anticipated release.&lt;/p&gt;
&lt;p&gt;You can&#39;t talk about LLM research without mentioning &lt;a rel=&quot;external&quot; href=&quot;https://qwen.ai/research&quot;&gt;Qwen&lt;/a&gt;, a research team from Alibaba. &lt;a rel=&quot;external&quot; href=&quot;https://huggingface.co/Qwen&quot;&gt;Qwen models&lt;/a&gt; act as a de facto reference point in LLM research. It&#39;s a shame the team didn&#39;t receive enough support within their company and their &lt;a rel=&quot;external&quot; href=&quot;https://techcrunch.com/2026/03/03/alibabas-qwen-tech-lead-steps-down-after-major-ai-push/&quot;&gt;leader had to step down&lt;/a&gt;. Fingers crossed they can start up something even better independently. Alibaba does have a &lt;a rel=&quot;external&quot; href=&quot;https://www.alibabacloud.com/help/en/model-studio/coding-plan&quot;&gt;Coding Plan&lt;/a&gt; subscription, but it seems rather limited and priced at 50 USD/month, so in my eyes not worth considering seriously.&lt;/p&gt;
&lt;p&gt;Xiaomi entered the race not too long ago with their impressive &lt;a rel=&quot;external&quot; href=&quot;https://mimo.xiaomi.com/mimo-v2-pro&quot;&gt;MiMo V2 Pro&lt;/a&gt; model. On &lt;a rel=&quot;external&quot; href=&quot;https://artificialanalysis.ai/models/mimo-v2-pro&quot;&gt;benchmarks&lt;/a&gt; it lands very close to &lt;a rel=&quot;external&quot; href=&quot;https://artificialanalysis.ai/models/minimax-m2-7&quot;&gt;MiniMax M2.7&lt;/a&gt;, which is very good. Xiaomi also introduced a compelling offer of &lt;a rel=&quot;external&quot; href=&quot;https://platform.xiaomimimo.com/#/token-plan&quot;&gt;MiMo Token Plan&lt;/a&gt; subscriptions this month, clearly inspired by the Z.AI GLM Coding Plan offer from December. Even website colors are similar. The quota seems very generous judging by their claims. I&#39;m sure MiMo models will only improve with time too, so this may turn out to be one of those rare hidden gems. It can go both ways. Limits on these plans can change any time too, so it&#39;s not a given that an interesting offer now will stay reliably good a few weeks or months later.&lt;/p&gt;
&lt;p&gt;To wrap up this section, here&#39;s how a leaderboard of these LLMs would look according to &lt;a rel=&quot;external&quot; href=&quot;https://artificialanalysis.ai/&quot;&gt;benchmarks&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GLM-5.1 (Z.AI)&lt;/li&gt;
&lt;li&gt;Qwen 3.6 Plus&lt;/li&gt;
&lt;li&gt;MiniMax M2.7&lt;/li&gt;
&lt;li&gt;MiMo V2 Pro (Xiaomi)&lt;/li&gt;
&lt;li&gt;Kimi K2.5 (Moonshot AI)&lt;/li&gt;
&lt;li&gt;DeepSeek V3.2&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-american-offer&quot;&gt;The American offer&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-american-offer&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/&quot;&gt;OpenCode&lt;/a&gt; became an inference provider too with their &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/docs/zen/#pricing&quot;&gt;pay-as-you-go&lt;/a&gt; service called &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/zen&quot;&gt;OpenCode Zen&lt;/a&gt;. They have also experimented with a subscription model through limited-availability &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/black&quot;&gt;OpenCode Black&lt;/a&gt;. They&#39;ve now introduced &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/go&quot;&gt;OpenCode Go&lt;/a&gt;, which is a cheaper 10 USD/month subscription that enables access to the open-weight models we&#39;ve discussed above. There are &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/docs/go/#usage-limits&quot;&gt;usage limits&lt;/a&gt; in place, but the offer seems more than fair. If you were to pick only one cheap subscription out of all, this should probably be the one.&lt;/p&gt;
&lt;p&gt;All the subscriptions discussed so far can be used directly in OpenCode. Major model labs from the land of the free do not give you such liberty. 0penAI GPT, Anthr0pic Claude, and G00gle Gem1n1 all offer similar types of subscriptions, but only 0penAI encourages people to use it however they want. With the other two it&#39;s all about working around bullshit restrictions to get any meaningful use of it. Reportedly for both GPT and Claude you may get up to 20x worth of tokens for the price.&lt;/p&gt;
&lt;p&gt;I bought &lt;a rel=&quot;external&quot; href=&quot;https://chatgpt.com/pricing&quot;&gt;ChatGPT Plus&lt;/a&gt; for 20 USD/month only to get access to GPT-5.3-Codex on the release day and I&#39;ve kept the subscription since. I use it only for accessing GPT-5.4 Fast in OpenCode and pretty much nothing else at all. Other perks and features of this subscription are completely useless. Still, I feel like I burn through a lot of tokens with GPT-5.4 and no other subscription could really satiate that. It has been the best model available for a while now - especially useful when fixing things or debugging. For quick implementation work or targeted changes I much prefer GLM models, but I still find GPT to complement it pretty well. If another model comes along I might drop this subscription. I don&#39;t see why anybody would pay that much for ChatGPT, but if you want to get some of those sweet subsidized GPT tokens in your tools, then it is a pretty good purchase. From the offers of the three major labs discussed here I&#39;d pick this as number one. Also, Codex TUI is probably the second best tool after OpenCode.&lt;/p&gt;
&lt;p&gt;Claude models are infamous for how expensive they are. Even with a ton of subsidized tokens, those are very expensive tokens. I don&#39;t think they really carry the value that Anthr0pic claims. That&#39;s why I&#39;m skeptical about &lt;a rel=&quot;external&quot; href=&quot;https://claude.com/pricing&quot;&gt;Claude subscription plans&lt;/a&gt;. They are overpriced on two levels. Sure, you get a little bit more Claude Opus use, but if you want the limit to last you for the whole programming session you have to use Claude Sonnet most of the time anyway - and that model is way worse than GLM. I admit Claude Opus can be fun sometimes, but in my opinion Claude models overall are simply overrated. Sure they follow instructions well, but the amount of instructions people feed them to get anything half-decent out is insane to me. I can see why people who over-invest in those complex instructions, MCP configurations, custom skills, and other bloat - why they would prefer a model like Claude. For me this is rarely a top choice when I pick an LLM for the task. &lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=Vspc3ViP2G4&quot;&gt;Anthr0pic has a bad vibe.&lt;/a&gt; Also, Claude Code is probably the worst TUI program ever and Anthr0pic really wants you to use that and nothing else. If you like fighting your tools and have the money to spend this might be a good option for you.&lt;/p&gt;
&lt;p&gt;There is a way to make Claude subscriptions work with OpenCode anyway. You need two things: 1. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ianjwhite99/opencode-with-claude&quot;&gt;opencode-with-claude&lt;/a&gt; plugin for OpenCode and 2. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rynfar/meridian&quot;&gt;meridian&lt;/a&gt; bridge that uses the blessed Claude Code SDK to serve models through a standard API. It&#39;s a little convoluted, but the end result is a very smooth experience. Definitely worth setting up to avoid dealing with the horrible Claude Code and Claude-specific configurations.&lt;/p&gt;
&lt;p&gt;It&#39;s easy to forget that G00gle also has &lt;a rel=&quot;external&quot; href=&quot;https://gemini.google/subscriptions&quot;&gt;G00gle &quot;AI&quot; subscription plans&lt;/a&gt; with Gem1n1. They also offer Claude models through &lt;a rel=&quot;external&quot; href=&quot;https://antigravity.google/&quot;&gt;Antigravity IDE&lt;/a&gt;, the descendant of &lt;a rel=&quot;external&quot; href=&quot;https://windsurf.com/&quot;&gt;Windsurf&lt;/a&gt; and another VSCode fork. Apparently these subscriptions can be bundled with other enterprise purchases, so there&#39;s a chance your organization already has access to higher quotas with Antigravity. Unfortunately, it&#39;s the same story as with Gemini-CLI - their tools are not very good. You may plug this subscription into OpenCode through a custom plugin like &lt;a rel=&quot;external&quot; href=&quot;https://github.com/NoeFabris/opencode-antigravity-auth&quot;&gt;opencode-antigravity-auth&lt;/a&gt;, but honestly it&#39;s not a good experience. This only makes sense if you want to milk some more free inference with the access you already have. If you really want to try out Gem1n1 and Claude along the GPT models I believe you&#39;d be better off paying for a GitHub Copilot plan or Curs0r instead.&lt;/p&gt;
&lt;p&gt;Curs0r exists too with &lt;a rel=&quot;external&quot; href=&quot;https://cursor.com/pricing&quot;&gt;their monthly subscriptions&lt;/a&gt;, but it doesn&#39;t exactly appeal to me. I already have my code editor. I don&#39;t use inline auto-complete either. The Cursor Agent is fine, but for the price it&#39;s not much. The good thing is you can access a variety of models through their service, including their exclusive &lt;a rel=&quot;external&quot; href=&quot;https://news.ycombinator.com/item?id=47452404&quot;&gt;Composer 2 based on Kimi K2.5&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;let-it-all-burn&quot;&gt;Let it all burn&lt;a class=&quot;zola-anchor&quot; href=&quot;#let-it-all-burn&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Mostly around the beginning of the year people were infatuated with the idea of agent orchestration. LLMs can write most of the code. Why can&#39;t they also work autonomously on the programming projects? Well, we tried it and failed. Notably &lt;a rel=&quot;external&quot; href=&quot;https://www.theregister.com/2026/02/13/anthropic_c_compiler/&quot;&gt;Anthr0pic&lt;/a&gt; failed to build a C compiler and &lt;a rel=&quot;external&quot; href=&quot;https://news.ycombinator.com/item?id=46646777&quot;&gt;Curs0r&lt;/a&gt; failed to build a browser. They went all the way and repainted their experiments as a huge success afterwards. It&#39;s quite obviously the opposite, but this kind of trick &quot;can have a strong influence on the weak-minded&quot;.&lt;/p&gt;
&lt;p&gt;Two other independent attempts &lt;a rel=&quot;external&quot; href=&quot;https://beincrypto.com/ralph-gas-meme-coins-creator-economy-decline/&quot;&gt;ended up as crypto-scams&lt;/a&gt;: Geoffrey Huntley&#39;s Ralph Loop, and Steve Yegge&#39;s Gas Town. Those people are truly the worst &lt;strong&gt;charlatans of the AI revolution&lt;/strong&gt;. It was obvious from all their posts that made the rounds on Hacker News, with claims impossible to reproduce. Unfortunately, the Valley seems to love loud characters like that and somehow they get away with it in the end. At least now there&#39;s undeniable proof to show they were full of shit from the very beginning.&lt;/p&gt;
&lt;p&gt;So how does one genuinely burn through all these tokens? Turns out good human guidance is crucial for all of this agentic stuff to work well. That&#39;s why good tools focus on expanding the human ability instead of replacing it. Two great recent examples: &lt;a rel=&quot;external&quot; href=&quot;https://openclaw.ai/&quot;&gt;OpenClaw&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://t3.codes/&quot;&gt;T3 Code&lt;/a&gt;. An LLM-assisted loop of planning, implementing, and reviewing wastes inference like crazy, but yields good results. Preferably involve different LLMs in each step for a little variance. Using custom commands is a good way to make this process more streamlined.&lt;/p&gt;
&lt;h2 id=&quot;subscriptions-summary&quot;&gt;Subscriptions summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#subscriptions-summary&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here&#39;s a list of discussed subscriptions and how I would group them in terms of value at current prices.&lt;/p&gt;
&lt;p&gt;Most subsidized:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;0penAI ChatGPT - 20/100/200 USD&lt;/li&gt;
&lt;li&gt;Anthr0pic Claude - 20/100/200 USD&lt;/li&gt;
&lt;li&gt;MiMo Token Plan - 6/16/50/100 USD&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Strong contenders:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MiniMax Token Plan - 10/20/40/50/80/150 USD&lt;/li&gt;
&lt;li&gt;Z.AI GLM Coding Plan - 18/72/160 USD&lt;/li&gt;
&lt;li&gt;Kimi Code - 20/40/100/200 USD&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most flexible:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OpenCode Go - 10 USD&lt;/li&gt;
&lt;li&gt;GitHub Copilot - 10/40 USD&lt;/li&gt;
&lt;li&gt;Curs0r - 20/60/200 USD&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;what-do-i-use&quot;&gt;What do I use?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-do-i-use&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Personally I mostly make use of my Z.AI Coding Plan which is generous enough that I never really run out of inference for my favorite GLM models. I also keep a ChatGPT Plus subscription for certain things - GPT-5.4 is very capable and useful, but I&#39;m riding the limit almost all the time. American models quickly lead you astray; in personal projects it&#39;s not as fun. If I were to buy another personal subscription, I would &lt;em&gt;go&lt;/em&gt; with OpenCode Go. Every month I also squeeze out whatever little inference I can from the employer-provided Curs0r and GitHub Copilot subscriptions. Unlike personal subscriptions, these run out fast.&lt;/p&gt;
&lt;p&gt;I burn through most of this inference using &lt;a rel=&quot;external&quot; href=&quot;https://opencode.ai/&quot;&gt;OpenCode&lt;/a&gt; (mainly in a TUI-first workflow, but sometimes using the WebUI as well), running multiple sessions in git worktrees managed with my tool &lt;a href=&quot;/projects/bra/&quot;&gt;bra&lt;/a&gt;, and monitoring each project and branch directory with the help of my &lt;a href=&quot;/projects/madgit/&quot;&gt;madgit&lt;/a&gt;. I&#39;ve also built out a dedicated web dashboard to monitor all my subscription quotas: &lt;a href=&quot;/projects/llm-usage/&quot;&gt;llm-usage-monitor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As you&#39;d probably expect - I mostly rely on open-source software, including a lot of my own. Similarly, I prefer to rely on open-weight models, even if not self-hosted. It would be foolish not to bend this a little to make good use of the deals around, but still for me the core must stay open, and not just &quot;open&quot; in name only.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Blog evolution</title>
        <published>2025-11-02T00:00:00+00:00</published>
        <updated>2025-11-02T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/blog-evolution/"/>
        <id>https://www.wykwit.pl/blog/blog-evolution/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/blog-evolution/">&lt;p&gt;For years I&#39;ve been rocking the same minimal design on my blog.
I&#39;ve been creating web content of some sort since I first learnt how to make basic websites back in primary school.
I feel like the form of my personal website became inadequate with passing time
and as my content continues evolving.
It was time for a little make over.
Most importantly, I had to improve meta info for my posts
and unify the style of all pages.
I&#39;ve decided to focus on functional improvements rather than bold visual changes.&lt;/p&gt;
&lt;h2 id=&quot;my-little-blogging-evolution&quot;&gt;My little blogging evolution&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-little-blogging-evolution&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When I first started this blog I had a different goal in mind than today.
I wanted to make my dense notes public on the web so that I could refer to them whenever I needed.
Let&#39;s take &lt;a href=&quot;/blog/static-ip/&quot;&gt;&quot;Static IP&quot; blog post&lt;/a&gt; as an example.
There is almost no introduction, the post starts with a link to relevant Arch Wiki article,
then there&#39;s a few command examples with short descriptions, and that&#39;s it.
If I ever forget how to use the &#39;ip&#39; command (which regularly happens)
I can simply go back to that very post and the list of all the commands I need is right there.
My blog was a collection of notes.
Titles were as short as possible,
I had no need for subtitles or catchy headers,
only enough information for me to find what I knew I had saved.
What little design there was served that purpose very well.
However, it was not very approachable for others.&lt;/p&gt;
&lt;p&gt;Before 2018 my blog was more of a little personal journal and that was... cringy.
Some things are better left off the internet.
Now I write my personal notes on paper, those can be ephemeral.
I publish more deliberately, being concious about the fact that things here may stay alive longer
and are generally available to see for everyone with no restrictions.
I always try to keep some hard technical info in my posts.
I still use the blog to note down things I would like to refer to in the future,
but my old style of strict notes does not work with the things I learn anymore.
I want to share more things I find particularly interesting
and use this platform for more than just stashing notes.
With the shift to more opinionated articles the form does not serve the function well enough anymore.
I once again find the need for subsections, descriptions, and meta info for each page on the blog.&lt;/p&gt;
&lt;p&gt;I published &lt;a rel=&quot;external&quot; href=&quot;https://neocities.org/site/wykwit&quot;&gt;my blog on neocities&lt;/a&gt; over 5 years ago.
&lt;a rel=&quot;external&quot; href=&quot;https://neocities.org/browse&quot;&gt;Neocities websites&lt;/a&gt; were always my inspiration,
and especially for my &quot;about me&quot; page back then.
I really liked the way it turned out - minimal, clean and informative.
However, it did not fit in stylistically with the rest.
Regardless, I liked it so much that it just had to stay.&lt;/p&gt;
&lt;p&gt;One of the redesign goals was to unify the style across all pages on this website:
blog (article list), post (article content), network (links list), and the &quot;about me&quot; page.
I went with the minimalist dark look from my blog,
and adapted the &quot;about me&quot; page to better fit in with that style.&lt;/p&gt;
&lt;h2 id=&quot;design-principles&quot;&gt;Design principles&lt;a class=&quot;zola-anchor&quot; href=&quot;#design-principles&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Core design principles did not change.
I need my website to be readable without JS,
accessible from a terminal browser, very hacker-friendly.
I want to use a dark theme by default.
There should be no unnecessary distractions on the page.
Content is the focus.
If there is JS, it&#39;s only there to help the user,
not as a requirement to view the website.&lt;/p&gt;
&lt;p&gt;Frontend was never my strongest suite,
but recently I came around to using modern hybrid web frameworks
and I completely fell in love with &lt;a rel=&quot;external&quot; href=&quot;https://nuxt.com/&quot;&gt;Nuxt&lt;/a&gt;, which is built on top of &lt;a rel=&quot;external&quot; href=&quot;https://vuejs.org/&quot;&gt;Vue.js&lt;/a&gt;.
I&#39;ve been debating whether to use Nuxt or a different SSG for this website.
I&#39;m sure I want to use Nuxt for other websites in the future,
but for this one a simpler SSG like &lt;a rel=&quot;external&quot; href=&quot;https://www.getzola.org/&quot;&gt;Zola&lt;/a&gt; seemed to be a better fit.
Until now I&#39;ve been using JS to fetch the post content on the blog page,
with links to text-only versions of the post in case the user does not support JS.
I would re-generate JSON with a list of all posts on every publish with a little python script in my website repo.
I could just as well use some SSG by hand or regenerate the website in a continous delivery pipeline on GitLab when I push to master.
Maintainability should not really be a concern with statically generated pages.&lt;/p&gt;
&lt;p&gt;I considered including some Visual Sugar: animations, page fade-in, code syntax highlighting.
There are no long animations, so users don&#39;t have to wait for the content to display for too many millisecons.
Adding syntax higlighting for code snippets was long overdue.&lt;/p&gt;
&lt;p&gt;I was also debating whether or not to include more links on the home page,
to things such as: recent posts, recently updated projects, maybe fediverse activity.
Right now the home page is a simple landing page hub from which you can go to my blog or the &quot;about me&quot; page,
and only from there do you get to posts and other places.
The landing page gets many accidental visits and bot traffic,
so I prefer to have the blog at least one click away from the home page.
On one hand I like how minimal it is, but on the oter hand - it makes sense to better display what I&#39;m doing here.
As of now I haven&#39;t made that move yet.&lt;/p&gt;
&lt;p&gt;Finally - metrics.
I changed my mind about this, because for years I was strongly against it.
I&#39;d never have any tracking on the website,
not even to count the page view.
This time I would prefer to know which pages and posts attract most eyeballs
and how many people are even reading this.
For this I decided to use &lt;a rel=&quot;external&quot; href=&quot;https://umami.is/&quot;&gt;Umami&lt;/a&gt; analytics - it&#39;s very simple, self-hosted, open-source, privacy-respecting, no-cookie-bullshit,
presumably GDPR and PECR compliant, easy to block if you care, and at the same time should give me enough insight for all I need.&lt;/p&gt;
&lt;p&gt;Eventually I might also include a comments section for each article.
If I built out a little dynamic service to gather user feedback,
it would bring even more valuable insight,
and make the website that much more alive.
Still, I don&#39;t want to make any promises and I need to think it through a little more.&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When I first approached the idea of a redesign my imagination was running wild with all the things I could do.
It was on my mind for over two months.
The scope was so broad that no work was ever going to get done.&lt;/p&gt;
&lt;p&gt;Only when I embraced small, focused and purposeful changes, did I make any progress in this effort.
Instead of re-building from nothing, I took what I already had and improved it.&lt;/p&gt;
&lt;p&gt;For now I&#39;m pretty happy with how this website presents itself online.
Migrating to Zola, a proper SSG, was a chance to fix many of it&#39;s previous technical shortcomings.
These improvements compound, even when the effect is not a drastic unrecognizable change.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Scraping</title>
        <published>2025-09-23T00:00:00+00:00</published>
        <updated>2025-09-23T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/scraping/"/>
        <id>https://www.wykwit.pl/blog/scraping/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/scraping/">&lt;p&gt;Web scraping is the process of automatically accessing and collecting information from websites using bots. It&#39;s essential for web search, LLM recommendations, live web monitoring and so on, but it can have a downside of generating unwanted traffic and costs. For this reason some websites use various anti-bot measures and in the web content arms race the scrapers unevitably grow more complex.&lt;/p&gt;
&lt;p&gt;There are three main ways to recognize and mitigate bot traffic:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;displaying captchas for risky browser fingerprints&lt;/li&gt;
&lt;li&gt;blocking or rate-limiting abusive IPs&lt;/li&gt;
&lt;li&gt;making scraping cost more than it&#39;s worth&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the dynamic web it&#39;s not feasible anymore to simply fetch the website text and parse it. Often there is some JS involved that populates the website content. Some of the aforementioned anti-bot measures can be involved too, thus the entire browser has to be utilized in the scraping process to be effective, circumvent protections, and render the target content properly.&lt;/p&gt;
&lt;p&gt;There are two main browser automation toolkits: (1) &lt;a rel=&quot;external&quot; href=&quot;https://www.seleniun.dev/&quot;&gt;selenium&lt;/a&gt; and (2) &lt;a rel=&quot;external&quot; href=&quot;https://playwright.dev/&quot;&gt;playwright&lt;/a&gt;. Both provide some facilities to make the browser appear more like a real user. For selenium there is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ultrafunkamsterdam/undetected-chromedriver&quot;&gt;undetected-chromedriver&lt;/a&gt; and for playwright there are extensions such as &lt;a rel=&quot;external&quot; href=&quot;https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth&quot;&gt;puppeteer-extra-plugin-stealth&lt;/a&gt;. Choice between the two pretty much comes down to personal preference and external tooling support.&lt;/p&gt;
&lt;p&gt;To avoid IP blocking scrapers have to rotate their addresses regularly, utilizing various proxy services. Some of them are pretty shady, for example residential and mobile IP proxies, like the ones from brightdata (previously luminati). The Evil™ Corp pays mobile devs to include their Evil™ SDK within their app that allows other people to use YOUR device as a proxy. Of course it all has to be obfuscated somewhere in the terms of service, but nobody reads a fucking 200 page TOS for a stupid mobile game. The malicious Evil™ SDK ends up in many places where you don&#39;t suspect it: mobile apps, browser extensions, games, the .exe you downloaded last time, and many more. The more you know...&lt;/p&gt;
&lt;p&gt;Even though it&#39;s not hard to build out a scraping setup like this by yourself, it would be much more convenient to have it all bundled in one service. Unsurprisingly, there&#39;s a lot to choose from: scrap-this, scrap-that, com, io, dev, whatever. There are even some designed for plug-and-play use with LLM tools, for example: browserbase, firecrawl.&lt;/p&gt;
&lt;p&gt;Last time I used browserbase to scrape a list of about 200 ecom websites and extract contact info from them. Data like this can later be used for marketing campaigns, so called &quot;lead generation&quot;, robocalls, email spam, phishing, or other cyberattacks. It&#39;s easy with browserbase, because I don&#39;t have to grep for contact links and emails, I can use stagehand and have LLMs locate this data for me, navigate the page even, and in the end extract only what I need. Browserbase exposes playwright API for their browser session, so I can also take screenshots and shapshots of these websites to analyze them more throughly later. Theo&#39;s recommendation once again comes in clutch. I hear more and more about LLM-based scrapers in the browser and other tools, so I suspect this is only going to get easier with time.&lt;/p&gt;
&lt;p&gt;I think the third way of mitigating bot traffic, making it financially unfeasible, is currently the best solution. I am very much rooting for Anubis to win in the battle against the bots and even out the cost of serving the content with the cost of scraping it. There must be a better and less hostile way to obtain a good data set than just wild data harvesting. And there must be better ways to protect your services from it.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>LLM agents</title>
        <published>2025-09-21T00:00:00+00:00</published>
        <updated>2025-09-21T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/llm-agents/"/>
        <id>https://www.wykwit.pl/blog/llm-agents/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/llm-agents/">&lt;p&gt;Getting a little deeper into the good, the bad, and the things I miss after playing around with LLM tools in the terminal for some time now. In &lt;a href=&quot;/blog/llm-tools/&quot;&gt;my previous post&lt;/a&gt; I gave an overview of some tools built around LLMs specifically for programming and which ones I ended up using the most myself. This time I briefly explain how such things are built and then lay down some ideas on what could be improved to make LLM-powered tools aid my processes even better.&lt;/p&gt;
&lt;p&gt;By a &quot;tool&quot; we could mean many different things, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLM agents (tools around LLMs)&lt;/li&gt;
&lt;li&gt;programs that the LLM agent calls (tools for LLMs)&lt;/li&gt;
&lt;li&gt;other programs that we use&lt;/li&gt;
&lt;li&gt;plugins for other programs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s walk through the anatomy of an LLM agent first. It will help us see where each tool type fits in the whole thing. In general agents are built around an inifinite loop with three steps: input (prompt), output (inference), actions (tool calls). We will refer to the code that manages this loop as the LLM harness. It works kinda like a programming language interpreter. First the model is informed about capabilities of the harness - for example it can get a plain text explanation of provided tools along with expected input/output formats for a proper call. The model might be fine-tuned for a more complex format. Sometimes it can be overfit for a particular set of tools, or harness capabilities, which causes interoperability issues. When harness picks up a tool call pattern in the LLM output it makes the call with data passed by the model and in the next loop interation feeds that to the LLM as input. When there are no more tool calls to process, the harness goes back to asking the user for another prompt.&lt;/p&gt;
&lt;p&gt;Agent takes actions by executing tool calls, which can be implemented as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;function calls - using code straight in the agent harness, similar to how naive interpreters work&lt;/li&gt;
&lt;li&gt;tool calls - this is a general term, but it can also mean invoking external commands on the local system - such as bash, grep, find, head, linters and so on&lt;/li&gt;
&lt;li&gt;MCP client calls - using a protocol or framework for making a call to an external server, which shifts responsibility of implementing the former two to the MCP server developer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Model Context Protocol (MCP) functions as a middle man between the place where tool calls are invoked (client, the LLM agent) and where these calls are executed (the MCP server, integrated with some resource). Personally I don&#39;t find a need for it - local agents already have shell access with all the tools they could ask for. I&#39;d rather enhance the capabilities of my shell with additional CLI tools. Sure there are some things that could benefit from restructuring I/O for LLM consumption and that&#39;s where I&#39;d consider plugging MCP if I wanted to connect LLM to the thing. I think it&#39;s a good idea as a conversational interface for your services. I would also consider implementing MCP as a client if I was making my own LLM agent from scratch.&lt;/p&gt;
&lt;p&gt;To finish off my quick agent anatomy course we have to discuss context management. LLMs have a limited context window they can process - information that doesn&#39;t fit in the context is not considered during inference. For the most popular models that window is still rather small if you consider how big source files can get in long running projects. This is the hard part. If you don&#39;t manage the context well the agent will quickly forget what it was doing. Good prompting beats fine-tuning for general tasks - and this is also part of context management. First the LLM harness needs to load up tool definitions; then specific user-defined rules from AGENTS.md. Often the LLM agent tool also comes with baked-in system prompts or prompt templates that tell the model how to behave for the most effective outcome. You will easily find entire prompt template collections online (for example &lt;a rel=&quot;external&quot; href=&quot;https://github.com/danielmiessler/fabric&quot;&gt;danielmiessler/fabric&lt;/a&gt;), and AGENT.md or cursorrules repositories. &quot;Teaching the LLM&quot; is all about effective context management strategies.&lt;/p&gt;
&lt;p&gt;Here&#39;s one example - it&#39;s very effective to include relevant resources in the LLM input - this strategy is called retrieval-augmented generation (RAG):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the user can specify resources or include them directly in their prompt&lt;/li&gt;
&lt;li&gt;the harness can go fetch relevant resources based on user&#39;s prompt and include them as additional input&lt;/li&gt;
&lt;li&gt;the model can request related resources through a dedicated tool call&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RAG is one of the things I like the most about this LLM rush. Embeddings and vector databases can be used for sweet semantic search with applications beyond silly chat bots. RAG also allows the model to cite sources with higher reliability. I like how the need for compressing technical documentation for LLM consumption resulted in some good dense text documentation which is very accessible and helpful for human learning. We got new scrapers, parsers, better OCR, search, and so on - mainly to make documents easier to digest for LLMs, but accidentally also making many resources easier to process by hackers like myself.&lt;/p&gt;
&lt;p&gt;My point is that some tools for LLMs are really cool for people too. Many of them would fit very well in a regular development flow. Nothing prevents you from calling LLMs as a CLI tool or giving your LLM agent the ability to spawn sub-agents. C0gniti0n the Devin company suggests &lt;a rel=&quot;external&quot; href=&quot;https://cognition.ai/blog/dont-build-multi-agents&quot;&gt;it might not be the best idea&lt;/a&gt;, but who the hell would listen to those guys anyway, right? On the other hand Anthr0pic uses &lt;a rel=&quot;external&quot; href=&quot;https://docs.claude.com/en/docs/claude-code/sub-agents&quot;&gt;subagents in Claude Code&lt;/a&gt; and describes LLM workflows that involve multiple workers on their blog, which seems to be a pretty good resource: &lt;a rel=&quot;external&quot; href=&quot;https://www.anthropic.com/engineering/building-effective-agents&quot;&gt;https://www.anthropic.com/engineering/building-effective-agents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might be eager to write your own LLM agent now. You will unevitably find many libraries that claim to be the best for this task, but let me just remind you - &lt;a rel=&quot;external&quot; href=&quot;https://github.com/sigoden/aichat&quot;&gt;aichat&lt;/a&gt; proves you don&#39;t need any external libraries for handling inference from an API. If you are to pick one API to integrate - make it OpenAI-compatible API and use &lt;a rel=&quot;external&quot; href=&quot;https://www.litellm.ai/&quot;&gt;LiteLLM&lt;/a&gt; as a proxy for your target model. You will get logs, stats and cost tracking for free. You can even plug GitHub Copilot as a provider. Of course if you prefer to use LangChain or whatever else - it&#39;s up to you. In the end you might still find yourself using more purposeful tools, such as aichat or Simon Willison&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/simonw/llm&quot;&gt;&quot;llm&quot; LLM tool collection&lt;/a&gt; as building blocks or to enhance your own flow instead of replacing it with agents.&lt;/p&gt;
&lt;p&gt;People have varied opinions when it comes to LLM agents, how they should be run, managed, etc.
This blog post is a good overview and will probably give you some ideas:
&lt;a rel=&quot;external&quot; href=&quot;https://shmck.substack.com/p/claude-code-framework-wars&quot;&gt;https://shmck.substack.com/p/claude-code-framework-wars&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally we get back to where we started this post. I think the missing piece for LLM agents right now is easy knowledge retrieval and self-hosted grounding. This is mainly because managing context is difficult and mostly left for the user. If I were to address this issue, I&#39;d use a specialized agent to help select the scope for the coding agent and prepare a well-formated prompt. I would also use RAG to include additional context about target of the change. Instead of making the agent grep for function usages and references, it could be included in the context. Closer integration with treesitter would also be an interesting change. The LLM wouldn&#39;t have to target files and walk the filesystem anymore - it could target specific classes and functions directly, and have more information retrieved from the vector database after one initial sweep of the codebase. You could also chat with the codebase through RAG after that one initial sweep. This might not be the best approach, but I&#39;m curious to see how it would work in practice.&lt;/p&gt;
&lt;p&gt;Anyway, to recap - an LLM agent is basically a dumb LLM calling a bunch of dumb tools in a loop. Surely that&#39;s worth millions of dollars if not more?&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>madgit</title>
        <published>2025-08-30T00:00:00+00:00</published>
        <updated>2025-08-30T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/madgit/"/>
        <id>https://www.wykwit.pl/blog/madgit/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/madgit/">&lt;p&gt;I decided to give a &lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=-WCg4dCQcLo&quot;&gt;lightning talk during Cebula Camp 2025&lt;/a&gt;. The title I submitted was: mad git - custom commands for fun and profit. These are my notes describing more or less what this is about. For people coming here right after the talk - hi! Sorry the talk was scuffed, public speaking is crazy stressful. I&#39;m glad you&#39;ve decided to check out my little internet corner. I hope you like it here.&lt;/p&gt;
&lt;p&gt;Let me first introduce myself in a single sentence and then I&#39;m gonna move on to the problem statement. This is not going to surprise you: I&#39;m a programmer, dealing mostly with backend webdev and cybersecurity.&lt;/p&gt;
&lt;p&gt;Sometimes I want to read (IYKYK) some code. A lot of code. I go to GitHub and see a user or organization and rarely ever do I end up interested in only one repository. I know we all love git, I&#39;m sure we all love GitHub even more. Maybe instead of clicking through pages of repos I could just clone them all and browse the code directly? But.. what if I want to grab some repos from GitLab (or Forgejo) too? Oh, and I also want to keep my copies up to date!&lt;/p&gt;
&lt;p&gt;At this point most people would just G00gle the answer (and figure out there is an official gh cli tool, wtf?) or generate a bash one-liner with GeePiTy and move on with their lives. But you know, I have that weird muscle memory, so I always end up opening the network tab in dev tools first. Little &#39;curl | jq | git&#39; in a for loop and we&#39;re good.&lt;/p&gt;
&lt;p&gt;This is exactly what I did and for a while I was happy. In a few lines of bash I had a script to clone a list of git links. Updating was super easy too, by the way. I was actually using it more than expected. I&#39;m sure many of you had to write a similar script: walk directories, git pull in all of them. Very easy, very useful, feels good.&lt;/p&gt;
&lt;p&gt;This is not all I wanted to do with these repositories. It is however the first basic building block that I would call over and over again... If I&#39;m gonna call it more than once, then I might as well... (Maybe you already see where this is going.) Might as well rewrite it in Rust. It&#39;s nothing fancy... But I still put it on &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/madgit&quot;&gt;crates.io&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://aur.archlinux.org/packages/madgit&quot;&gt;AUR&lt;/a&gt; for convenience. I called the tool &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.com/wykwit/madgit/&quot;&gt;madgit&lt;/a&gt; - it solves exactly the two of my problems that I stated in the intro. It also allows me to call any arbitrary command in each git repo from a selected directory. There&#39;s many directons this could further go... No promises tho! Check out the project README if you&#39;re curious.&lt;/p&gt;
&lt;p&gt;That&#39;s cool - I solved my little problem and published a tool to address it. We all have little scripts and personal tools like that, they are often underrated productivity boosters. Sometimes they seem so insignificant that we don&#39;t bother sharing. It seems like it&#39;s just not worth the time to clean it up, document and push out. If you&#39;re one of those people - publish with no warranty, but just do it.&lt;/p&gt;
&lt;p&gt;This got me started on a journey to discover more custom commands made by other people. I know there are also other git wrappers, UIs, TUIs and whatever. I don&#39;t want to make a complete list, I just want to share some cool stuff I found. There are two ways that I know of to modify git subcommands without writing a wrapper: (1) alias in the config (&lt;a rel=&quot;external&quot; href=&quot;https://gist.github.com/mwhite/6887990&quot;&gt;here is a gist tutorial&lt;/a&gt; for this) and (2) having a git-[subcommand] executable in your $PATH. I compiled a list of some custom commands below, all of them are available in AUR. There is a pretty good description of how this works here: &lt;a rel=&quot;external&quot; href=&quot;https://nathancraddock.com/blog/custom-git-commands/&quot;&gt;https://nathancraddock.com/blog/custom-git-commands/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is a lot of tools for managing branches and encrypting files, I skipped those.
I also skipped demos and examples, sorry for that, but at least the resources are there.&lt;/p&gt;
&lt;p&gt;STATS&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-cal - github like contributions calendar on terminal&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/denshakhov/git-heatgrid&quot;&gt;git-heatgrid&lt;/a&gt; - visualize git commits as a calendar heatmap&lt;/li&gt;
&lt;li&gt;git-hours - count the time spent on code via git&lt;/li&gt;
&lt;li&gt;git-punchcard - show punchcard graphs with git commit activity.&lt;/li&gt;
&lt;li&gt;git-quick-stats - simple and efficient way to access various statistics in git repository&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/kamranahmedse/git-standup&quot;&gt;git-standup&lt;/a&gt; - recall what you did on the last working day&lt;/li&gt;
&lt;li&gt;git-summary - script to print a summary of git author contributions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CHANGES&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-chglog - git changelog generator&lt;/li&gt;
&lt;li&gt;git-delta - syntax-highlighting pager for git and diff output&lt;/li&gt;
&lt;li&gt;git-file-history - easily view the history of a file in a git repository&lt;/li&gt;
&lt;li&gt;git-playback - a git command to play back or step through the history of a git-controlled file.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/mhagger/git-when-merged&quot;&gt;git-when-merged&lt;/a&gt; - determine when a particular commit was merged into a git branch&lt;/li&gt;
&lt;li&gt;git-who - git blame for file trees&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;REBASE&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-fiddle - edit commit messages, authors, and timestamps during git-rebase&lt;/li&gt;
&lt;li&gt;git-filter-repo - quickly rewrite git repository history (filter-branch replacement)&lt;/li&gt;
&lt;li&gt;git-imerge - incremental merge for git&lt;/li&gt;
&lt;li&gt;git-machete - git repository organizer &amp;amp; rebase/merge workflow automation tool&lt;/li&gt;
&lt;li&gt;git-revise - a git subcommand to efficiently update, split, and rearrange commits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IDENTITY&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-identity - manage your identity in git&lt;/li&gt;
&lt;li&gt;git-switcher - git profile switcher switch between your git profiles easily&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/gesquive/git-user&quot;&gt;git-user&lt;/a&gt; - git plugin that allows you to save multiple user profiles and set them as project defaults&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CLEANUP&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-debubble - clean up merge bubbles in a git repository&lt;/li&gt;
&lt;li&gt;git-delete-merged-branches - command-line tool to delete merged git branches.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/imsky/git-fresh&quot;&gt;git-fresh&lt;/a&gt; - keep your repo fresh with one command.&lt;/li&gt;
&lt;li&gt;git-gone - prune stale local git branches&lt;/li&gt;
&lt;li&gt;git-superprune - a git command to prune remote branches that have already been merged&lt;/li&gt;
&lt;li&gt;git-trim - trims your git remote tracking branches&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/alerque/git-warp-time&quot;&gt;git-warp-time&lt;/a&gt; - reset file timestamps to repo state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TOOLBOXES&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git-commands - fuzzy search git commands with fzf&lt;/li&gt;
&lt;li&gt;git-extensions - simple handy extensions for git&lt;/li&gt;
&lt;li&gt;git-extras - repo summary, commit counting, repl, changelog population and more&lt;/li&gt;
&lt;li&gt;git-toolbelt - a suite of useful git commands that aid with scripting or every day command line usage&lt;/li&gt;
&lt;li&gt;git-town - generic, high-level git workflow support&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/simeg/git-x&quot;&gt;git-x&lt;/a&gt; - cli extensions for git that simplify common workflows&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/gruntwork-io/git-xargs&quot;&gt;git-xargs&lt;/a&gt; - making updates across multiple github repositories with a single command&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Checking out those git custom commands feels like figuring out nvim plugins again. Maybe some of this is helpful to you. At the end of the day... It&#39;s not about the repos we cloned, it&#39;s about the journey... It&#39;s about the &quot;shitty scripts we threw together and then immediately thrashed&quot; along the way.&lt;/p&gt;
&lt;p&gt;Happy hacking everyone!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Deployments</title>
        <published>2025-07-27T00:00:00+00:00</published>
        <updated>2025-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/deployments/"/>
        <id>https://www.wykwit.pl/blog/deployments/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/deployments/">&lt;p&gt;Imagine a user wants to use your app, so they look it up on the internet and find your domain. They go to your domain and you want to serve them your webapp. For any of that to work, you need a few things prepared first on the deployment side: (1) registered domain, (2) DNS records set, (3) have a network-accessible server or a proxy/load-balancer/firewall, (4) host or container for you app. Only if all that works smoothly can you resolve the request with your app and reply with a response. In this post we&#39;re gonna look at some solutions for steps 3 and 4.&lt;/p&gt;
&lt;p&gt;Your app has to run somewhere, it has to be executed on some machine that is also in some way accessible to your users. The process of putting it there, especially for production use, is exactly what we call deployment. There are a few approaches to getting that done.&lt;/p&gt;
&lt;p&gt;The traditional approach is to spin up a server, either on real hardware by yourself or as a rented VPS, install all the software you need on that server, and then expose it to the internet. This is a very good and easy approach. You get to understand what happens at every step of the way. The pricing is clear and limitations of this setup are rather obvious. It&#39;s difficult to scale, Continuous Deployment can be tricky, and sharing the same server for multiple projects is not necessarily clean.&lt;/p&gt;
&lt;p&gt;To build on top of that, you could use containers, for example with docker compose, to run multiple projects on one host. The advantage of this is that your system configuration is now confined to a container, so there can be no issues with shared libraries or conflicting dependencies between different projects. This is a sweet spot for ease of use with small projects. The setup is usually smooth and once it&#39;s done - deployments become very easy. All you have to do is rebuild and push your container, then bump the image tag on your host to re-deploy. Scaling would be limited to the power of your host, unless you apply another solution...&lt;/p&gt;
&lt;p&gt;You could use docker swarm mode, which lets you utilize multiple hosts clustered together to serve docker images cooperatively. This is all fine and you will find many different solutions built on top of that. Some neat self-hosted solutions for deployment management with Docker Swarm I would like to mention: &lt;a rel=&quot;external&quot; href=&quot;https://coopcloud.tech/&quot;&gt;Co-op Cloud&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://caprover.com/&quot;&gt;CapRover&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://coolify.io/&quot;&gt;Coolify&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://dokploy.com/&quot;&gt;Dokploy&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://swarmpit.io/&quot;&gt;Swarmpit&lt;/a&gt;. The original idea for this post was to go through these, compare them, and perhaps conclude on what I want to use more. Unfortunately, they are all too cool, so instead I suggest you check them all out by yourself. Personally I use Coolify and Co-op Cloud the most.&lt;/p&gt;
&lt;p&gt;There is another common approach to deployments: using Kubernetes, or k8s for short. It&#39;s probably the best solution for modern distributed computing, scaling at a different magnitude. It was designed and released by Google and is now widely supported in the world of enterprise open-source; notably with RedHat&#39;s OpenShift products being built on top of it. Kubernetes is a beast that deserves a dedicated blog post or even a few. This solution is complicated enough to create a dedicated role in the industry. DevOps, which was originally meant to be Development+Operations, became more of a modern infrastructure administration role centered around a software development model spawned from the adoption of Kubernetes for deployments. Cloud, microservices, IaaC, CI/CD pipelines, containers, and more. These topics were heavily hyped up not too long ago - it was a big one just before LLMs and cryptocurrencies took over the news. All of it is easy enough for a motivated developer to understand and operate, but time-consuming and annoying enough to warrant getting another person employed just to take care of it. Many places build out their own pipelines and custom UIs just to make these things easier to operate.&lt;/p&gt;
&lt;p&gt;For certain workloads there is a better way. With each approach discussed we&#39;ve been abstracting away from the bare metal machine running our code. The next step is to go serverless, or in other words, to completely forget about the underlying servers running our deployments. Kubernetes, Docker Swarm, VPS administration - with this approach none of these are our concern anymore. Unlike previous options, this one is pretty much always bound to some managed solution. Our app code will run on ephemeral virtual machines spinned up on demand by our cloud provider. That way the infrastructure we rent out can scale anywhere, even down to zero (free beer!). Some interestng providers, besides the big three of cloud, that can offer this are: Cloudflare, Fly.io, Netlify, Vercel. You will likely need a managed database to match. Lately I really like to use &lt;a rel=&quot;external&quot; href=&quot;https://turso.tech&quot;&gt;Turso&lt;/a&gt; for this, so even though it can be kinda a controversial choice, I&#39;d still recommend that. I&#39;m skipping over the details of &quot;serverless functions&quot; and instead I leave that part of research as an exercise for the reader. Serverless is really great if you don&#39;t want to get deep into the infrastructure rabbit hole and still want to deliver good and scalable experience for your users. This is what truly makes developer&#39;s life easier. We get great UIs, great management options, logs, easy and fast rollback features, easy setup, scaling, all the good stuff. If you need a better explanation of what serverless is and how it&#39;s different from a k8s deployment, here&#39;s a really good video by Theo (t3.gg) that I highly recommend watching: &lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=_VQl_HTk9PM&quot;&gt;https://www.youtube.com/watch?v=_VQl_HTk9PM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To summarize, the common options are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;deploying software directly on a server&lt;/li&gt;
&lt;li&gt;deploying through docker on a server&lt;/li&gt;
&lt;li&gt;using docker swarm, perhaps through some other UI&lt;/li&gt;
&lt;li&gt;using kubernetes, again perhaps through a dedicated UI&lt;/li&gt;
&lt;li&gt;using serverless deployment solutions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And finally here&#39;s my recommendations on what to pick:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you are working on a modern webapp - go with serverless deployment using Cloudflare or Vercel.&lt;/li&gt;
&lt;li&gt;If you&#39;re working on a research project, especially in early stages, consider the simplest of options: 1 and 2.&lt;/li&gt;
&lt;li&gt;For almost anything else Docker Swarm directly on your VPS is probably the right choice, especially with additional open-source tooling. Personally, that would be my preferred choice.&lt;/li&gt;
&lt;li&gt;If you need to scale over multiple machines or run a big enterprise - Kubernetes is for you.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Happy DevOpsing!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>LLM tools</title>
        <published>2025-07-05T00:00:00+00:00</published>
        <updated>2025-07-05T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/llm-tools/"/>
        <id>https://www.wykwit.pl/blog/llm-tools/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/llm-tools/">&lt;p&gt;Back in January I finally gave Cursor IDE an honest go and it sold me on the idea of finally using LLMs for programming. Since then I&#39;ve tried multiple different tools, and even though I still hardly use generated code in my projects, I now see many ways in which this technology can be useful day-to-day.&lt;/p&gt;
&lt;p&gt;The most basic tool with the widest adoption is a chat interface. Think: ChatGPT, t3.chat, aistudio. You get to talk to your model of choice directly, ask questions, give out tasks, and so on. I find it especially useful for summarization and search. Summarization is one task that LLMs are actually good at. Proper web search options, such as deep research and search grounding, which provides links to other sources, go a long way too. Searching for something using vague context description is great for exploring. Unlike a traditional search engine, you don&#39;t need a very specific query anymore.&lt;/p&gt;
&lt;p&gt;Generating self-contained code examples is where I find most value of LLM tools for software development. Small code snippets are easy to verify and save a lot of research time. Instead of reading through docs and library source code, you can generate a personalized example and see if it works for your problem. I usually choose to adapt and transform the code myself, so I still get to do some thinking. The LLM is just there to help me find a working solution faster. Some people choose to go further...&lt;/p&gt;
&lt;p&gt;Around February I went through a list of VSCode extensions and VSCode-based editors which enable comfortable LLM usage for development. All these options were really very similar. Open-source: AIDE, Cline, Continue, PearAI, Sourcegraph Cody, Tabby, Void. Proprietary: Codi, Cursor, GitHub Copilot, Qodo, Supermaven, Tabnine, Trae, Windsurf. I was looking for something I could use on my own terms: offline and with open-source models. Even with paid tools, I was quite disappointed. With Cursor everything goes through their servers before hitting any model, so they clearly don&#39;t care about self-hosted models. From the open-source selection - Continue seemed interesting. It even got &lt;a rel=&quot;external&quot; href=&quot;https://ollama.com/blog/continue-code-assistant&quot;&gt;featured on Ollama blog&lt;/a&gt;. After trying it out myself it quickly felt lacking in comparison to a full-blown editor, but so did other solutions I tried. Perhaps trying to fit an LLM in the constraints of an existing editor was not such a good idea afterall.&lt;/p&gt;
&lt;p&gt;Cursor does many things right and accomodates a wide range of users. It&#39;s very good at picking up context and displaying suggested changes. You could think that is exactly what makes it distinctly better than the rest. I certainly thought so at first. There is more: Cursor has amazing autocomplete, well integrated inline editing (Ctrl+K), and a Composer mode for conversational development flow closer to a chat experience. That&#39;s like fitting three tools into one, each covering a different prediction distance, each of them scratching a slightly different itch. I believe that is what makes the Cursor experience so good. Out of these three, autocomplete was the first application of LLMs for coding (the other two require instruct model tuning, which came later). It covers the shortest prediction distance, so it&#39;s usually rather accurate. It helps with tedious and repeatable edits and typing out boring parts of the code. Then again, so does learning vim. I take pleasure in typing and do it fast enough not to really need completion suggestions for the parts that I already know how to code. When it comes to parts that I&#39;m not yet sure about, I would rather stop and think the problem through, than have an invasive completion suggestion pop up to skew my direction of thinking. Anyway, out of the three editing modes, only this one really needs to exist within the editor.&lt;/p&gt;
&lt;p&gt;Inline editing is a pretty cool idea. It can both handle your tedious edits when you don&#39;t want to bother coming up with a good macro, and can handle small-scale changes, generating snippets of code in-place. It is also not very invasive - it only works when the user requests it. Finally Composer, with the conversational approach, has the furthest prediction distance. The LLM has to find a proper place to make the edit and then attempt to make a prediction far into the future, to generate a change that is possibly very distant from the present code. It makes this mode prone to mistakes. Generally speaking, the more autonomy you give to the LLM and more complex the instruction, the lower quality and accuracy goes. These two modes don&#39;t have to live in the editor. Let&#39;s discuss another family of LLM tools - agents.&lt;/p&gt;
&lt;p&gt;Meet &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Aider-AI/aider&quot;&gt;Aider&lt;/a&gt; - the first proper LLM agent for the terminal. It is Apache licensed and written in Python. Aider introduces a few chat modes: one lets you quickly ask questions about your codebase and plan out changes, another lets you apply changes to files right in your filesystem, and then there is a third one that kinda combines the previous two. It&#39;s kind of like Cursor&#39;s Composer, but better. It works with many different providers and any LLM model you could think of. It does conventional commits after each change, so you can thoroughly and comfortably review them. Aider also has a watch mode, which reacts to file changes in a repository and acts on special comments that you can place anywhere. For example you could write a function declaration and right above it a comment &quot;Implement this function. AI!&quot; and Aider should create a matching function definition or fill out the function body. I like the Aider workflow even more than the Cursor experience. The ability to use different models and to seamlessly switch between them, different tools, chat modes - all of this makes Aider stand out as one of the top LLM tools for development. There is a model benchmark section in Aider docs, in case you&#39;re wondering which LLMs give best results: &lt;a rel=&quot;external&quot; href=&quot;https://aider.chat/docs/leaderboards/&quot;&gt;https://aider.chat/docs/leaderboards/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A complementary terminal tool, also very powerful and flexible, is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/sigoden/aichat&quot;&gt;aichat&lt;/a&gt; - written in Rust and available in official Arch Linux extra repos. I haven&#39;t used it much yet, but I see huge potential for creating quick terminal commands and personal workflows on top of it. I like two concepts in particular: user-defined roles, a collection of system prompts stored in a directory; and macros, which expand to longer bits of pre-defined text which you can re-use in your prompts. Configuration options are very extensive. There are also some web interfaces that aichat can expose for you, like an openai-compatible api proxy, very useful for testing and development.&lt;/p&gt;
&lt;p&gt;After Aider, all major players released their versions of LLM tools for the terminal. First we got Claude Code, some people swear by it, but it is closed source and closely tied to Anthropic, so no way in hell I will ever run it. Then &lt;a rel=&quot;external&quot; href=&quot;https://github.com/openai/codex&quot;&gt;OpenAI Codex&lt;/a&gt; came out, open-source project in TS with an ongoing official Rust rewrite, unfortunately completely unusable in my experience. Finally, recently released &lt;a rel=&quot;external&quot; href=&quot;https://github.com/google-gemini/gemini-cli&quot;&gt;Gemini-CLI&lt;/a&gt;, also open-source and in TS, has a good vibe, but lacks basic features compared to alternatives and is also tightly coupled with G00gle&#39;s LLMs. To be fair, none of them are worth wasting time on. If you&#39;re looking for something that&#39;s more fresh and simple than Aider, I have another tool to recommend.&lt;/p&gt;
&lt;p&gt;Lately my go-to LLM terminal tool is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/sst/opencode&quot;&gt;sst/opencode&lt;/a&gt;. This FOSS tool has the cleanest interface I&#39;ve seen so far. You can&#39;t deny it beauty and simplicity. It&#39;s also written in TS, but very fast and responsive. I wish it had more advanced features exposed to the user, but defaults are more than good enough, and you can still plug in any model with almost any provider. I often prefer it over opening the web chat interface (I still do that for search). There is a handful of tools built-in and included for the LLM to use: running general shell commands, fetching web content, keeping track of a TODO list (works great for making the LLM implement everything you ask for step-by-step), searching for files by pattern or with grep, basic file operations like listing, reading, writing, editing. That&#39;s really all you need for effective agentic work and opencode is great at it.&lt;/p&gt;
&lt;p&gt;Having so many LLM agent tools, you may think about running multiple agents in parallel for easy agent/model comparisons and quick re-rolls of changes per prompt. That&#39;s exactly where &lt;a rel=&quot;external&quot; href=&quot;https://github.com/devflowinc/uzi&quot;&gt;uzi&lt;/a&gt; comes in. It&#39;s a fairly simple project that lets you orchestrate local agents. It can run multiple agents in separate tmux sessions, each working in their own git workspace, on a separate branch. You can control multiple at once by passing stdin directly through tmux, all managed by uzi. Personally I&#39;d take a different approach and use Docker or &lt;a rel=&quot;external&quot; href=&quot;https://dev.l1x.be/posts/2020/12/13/diving-into-firecracker-with-alpine/&quot;&gt;firecracker VMs&lt;/a&gt; for each agent, but then again - that might be more hassle than it&#39;s worth.&lt;/p&gt;
&lt;p&gt;Regardless of the interface, there&#39;s still a serious issue with LLM generated code. The way LLMs write makes single files read really good, but only in separation. Whenever changes are contained within one file, one class, one function - the results are usually more than satisfactory. Once the logic is spread throughout different files, that&#39;s when everything falls apart. Again, in separation all new changes look fine, but they lack any design. The LLM does not really think and that lack of thought shows greatly in resulting interfaces, object relations, module separation, and all those other design decisions that human programmers with experience make intuitively on a whim. Generated code looks good on surface, but is very hard to work with later on. LLM agents are also not fully capable of utilizing existing code well for the same reason - they don&#39;t have complete enough understanding. Best they can do is explain bits of code, explain their goal out loud, and if those two match, make a decision to use a certain method. LLMs are thus happy to repeat themselves - it&#39;s easier for them to process and is therefore cheaper. It&#39;s far from how real programmers work. &lt;a rel=&quot;external&quot; href=&quot;https://www.pbm.com/~lindahl/real.programmers.html&quot;&gt;Real programmers don&#39;t use Pascal&lt;/a&gt;. Utilizing LLM tools well is a new skill to learn. They can enhance our work, but they need a competent human to drive them properly to really be useful.&lt;/p&gt;
&lt;p&gt;There is a lot more to talk about: building tools around LLMs, building tools for LLMs, dense documentation, retrieval-augmented generation, fine-tuning, big models calling specialized models, transpilation, interesting tasks for LLMs... I will most likely come back to these topics later. For now - I&#39;m excited to still have a lot to learn.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AccelProfile</title>
        <published>2025-02-17T00:00:00+00:00</published>
        <updated>2025-02-17T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/accelprofile/"/>
        <id>https://www.wykwit.pl/blog/accelprofile/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/accelprofile/">&lt;p&gt;Default mouse acceleration settings on X11 are anoying as hell, especially when you just launch your i3-wm and realize mouse movements are way off.
On most DEs you can change it from within settings, but with a WM you&#39;re on your own.&lt;/p&gt;
&lt;p&gt;ArchWiki article on this topic: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Mouse_acceleration&quot;&gt;https://wiki.archlinux.org/title/Mouse_acceleration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Quick fix: &lt;code&gt;/etc/X11/xorg.conf.d/40-libinput.conf&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Section &amp;quot;InputClass&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Identifier &amp;quot;libinput pointer catchall&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MatchIsPointer &amp;quot;on&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MatchDevicePath &amp;quot;/dev/input/event*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Driver &amp;quot;libinput&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Option &amp;quot;AccelProfile&amp;quot; &amp;quot;flat&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EndSection&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second fix is for touchpad tap to click. Whether I like to have it enabled depends on a device.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Section &amp;quot;InputClass&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Identifier &amp;quot;libinput touchpad catchall&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MatchIsTouchpad &amp;quot;on&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MatchDevicePath &amp;quot;/dev/input/event*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Driver &amp;quot;libinput&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Option &amp;quot;Tapping&amp;quot; &amp;quot;on&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EndSection&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&#39;re welcome.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Window$ setup</title>
        <published>2025-02-04T00:00:00+00:00</published>
        <updated>2025-02-04T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/windows-setup/"/>
        <id>https://www.wykwit.pl/blog/windows-setup/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/windows-setup/">&lt;p&gt;How to make this piece of shit usable for a UNIX hacker, or even usable at all? The default answer used to be &lt;a rel=&quot;external&quot; href=&quot;https://www.cygwin.com/&quot;&gt;cygwin&lt;/a&gt;, but more recently it&#39;s been &lt;a rel=&quot;external&quot; href=&quot;https://learn.microsoft.com/en-us/windows/wsl/about&quot;&gt;WSL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My setup for &quot;work&quot; on &quot;Window$&quot; would look more or less like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WSL2 (for the Linux kernel, otherwise WSL1 runs through a compatibility layer)&lt;/li&gt;
&lt;li&gt;Debian&lt;/li&gt;
&lt;li&gt;bash&lt;/li&gt;
&lt;li&gt;tmux&lt;/li&gt;
&lt;li&gt;neovim&lt;/li&gt;
&lt;li&gt;alacritty&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can set up alacritty to go right into WSL2+Debian+bash on launch by default. Consult &lt;a rel=&quot;external&quot; href=&quot;https://alacritty.org/config-alacritty.html#s69&quot;&gt;alacritty docs&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;WSL exposes Window$ filesystem, so there&#39;s really no need to leave the terminal ever again, but if you have to - graphical programs also work under WSL. Just launch alacritty full-screen and enjoy the familiar and comfy Debian. In terms of usability it&#39;s a HUGE improvement, but there is one disadvantage: RAM by default is split 50-50 between WSL2 and host, which means Window$ will still eat up half of it, unfortunately.&lt;/p&gt;
&lt;p&gt;If you somehow can&#39;t get admin access on the machine to install whatever you want, there&#39;s a different setup you can try.&lt;/p&gt;
&lt;p&gt;From M$-Store you can install:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Window$ Terminal&lt;/li&gt;
&lt;li&gt;Powershell (7)&lt;/li&gt;
&lt;li&gt;neovim&lt;/li&gt;
&lt;li&gt;python&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Window$ Terminal is pretty good and Powershell 7 is better than cmd.exe or Window$ Powershell 5. Not ideal, but you can get by if you stick to neovim-based workflow. You can try to build out a different kind of shell with Python-based xonsh, but results may vary.&lt;/p&gt;
&lt;p&gt;There are some tweaks that can also make the WM experience a little less painful.&lt;/p&gt;
&lt;p&gt;Settings to change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disable personalized ads, disable news.&lt;/li&gt;
&lt;li&gt;Change Alt+Tab behaviour.&lt;/li&gt;
&lt;li&gt;Change window snapping behaviour.&lt;/li&gt;
&lt;li&gt;Move Start Menu to the left.&lt;/li&gt;
&lt;li&gt;Disable Search Bar.&lt;/li&gt;
&lt;li&gt;Disable Copilot.&lt;/li&gt;
&lt;li&gt;Disable notification pop-ups.&lt;/li&gt;
&lt;li&gt;Hide tray icons.&lt;/li&gt;
&lt;li&gt;Create more virtual desktops.&lt;/li&gt;
&lt;li&gt;Disable default lid action.&lt;/li&gt;
&lt;li&gt;Disable desktop icons.&lt;/li&gt;
&lt;li&gt;Pin terminal to taskbar.&lt;/li&gt;
&lt;li&gt;Display taskbar on main display only.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using this OS is truly an exercise in patience. My x220 (over a decade old laptop, CPU only has 2 cores) with Arch Linux felt much snappier than a modern top-end ThinkPad running W11. On paper the host machine was multiple times more powerful, but in practice it felt multiple times less performant, with huge loading times and latency for almost any basic action. Only in WSL2 terminal felt fine, but I&#39;m pretty sure installing any distro straight on the device would feel even better. With a native GNU/Linux install you could also leverage a proper window manager... User experience on Window$ is absolutely horrible, but still there&#39;s one thing I actually liked about this system and that is virtualization. WSL2 integration is done fairly well and GUI integration especially is quite impressive. Guest OS runs great, no complaints there. Hyper-V overall is pretty cool, although I find no reason to pick that over Linux KVM. It&#39;s nice to see at least some things done well over on Window$.&lt;/p&gt;
&lt;p&gt;With each release since Window$ 7 (hell, maybe even XP) the experience for a consumer has only been getting worse. Window$ Server holds up better, because it doesn&#39;t include as much bloatware by default, but even then - it&#39;s not great. If you&#39;re stuck with it then I truly pity you, but if you just can&#39;t decide what to switch to - I wrote a post about Linux Distros a while back, maybe it will help you decide where to start.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Python tooling</title>
        <published>2024-11-11T00:00:00+00:00</published>
        <updated>2024-11-11T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/python-tooling-2024/"/>
        <id>https://www.wykwit.pl/blog/python-tooling-2024/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/python-tooling-2024/">&lt;p&gt;Python tooling currently is a mess. Other modern programming languages, like Go or Rust, have a unified standard tooling to cover all bases. Meanwhile Python suffers from tool overload. For every aspect of working with a project there&#39;s at least a few different tools you can choose from. While development tools are greatly improving, it seems like project management has gotten a little more complicated.&lt;/p&gt;
&lt;p&gt;Good overview is presented here: &lt;a rel=&quot;external&quot; href=&quot;https://alpopkes.com/posts/python/packaging_tools/&quot;&gt;https://alpopkes.com/posts/python/packaging_tools/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another interesting insight is presented here: &lt;a rel=&quot;external&quot; href=&quot;https://chriswarrick.com/blog/2024/01/15/python-packaging-one-year-later/&quot;&gt;https://chriswarrick.com/blog/2024/01/15/python-packaging-one-year-later/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&#39;s a &quot;very short&quot; list of development tools for Python:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pip - managing python packages&lt;/li&gt;
&lt;li&gt;venv - isolated virtual environments&lt;/li&gt;
&lt;li&gt;pyenv - managing python versions&lt;/li&gt;
&lt;li&gt;setuptools - building packages&lt;/li&gt;
&lt;li&gt;twine - publishing packages&lt;/li&gt;
&lt;li&gt;poetry - complete project management&lt;/li&gt;
&lt;li&gt;hatch - project management, again&lt;/li&gt;
&lt;li&gt;rye - different project management, again&lt;/li&gt;
&lt;li&gt;maturin - project management for Rust packages&lt;/li&gt;
&lt;li&gt;pyinstaller - freezing into binaries&lt;/li&gt;
&lt;li&gt;pytest - testing framework&lt;/li&gt;
&lt;li&gt;black - simple linter&lt;/li&gt;
&lt;li&gt;isort - import linter&lt;/li&gt;
&lt;li&gt;flake8 - extensible linter&lt;/li&gt;
&lt;li&gt;ruff - linter and code formatter (+LSP, very cool!)&lt;/li&gt;
&lt;li&gt;autopep8, pyflakes, pylint, ... - more linters&lt;/li&gt;
&lt;li&gt;mypy - type checker&lt;/li&gt;
&lt;li&gt;jedi - autocompletion, static analysis&lt;/li&gt;
&lt;li&gt;pyright - static type checker (+LSP)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For some tools there might be more alternatives available too... In short - tool overload.&lt;/p&gt;
&lt;p&gt;Let&#39;s first cover dependency management, then project management, and lastly development tools like linters and static checkers. I&#39;ll mention my personal choices for each.&lt;/p&gt;
&lt;p&gt;The most basic tools are &lt;a rel=&quot;external&quot; href=&quot;https://pip.pypa.io/en/stable/&quot;&gt;pip&lt;/a&gt; (a package manager) and &lt;a rel=&quot;external&quot; href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;venv&lt;/a&gt; (virtual environment to contain and separate packages). They are very useful and probably enough for simple development purposes, but not quite enough for building and distributing packages. You can use them along with &#39;requirements.txt&#39; file for project dependency management.&lt;/p&gt;
&lt;p&gt;Now for some people, getting the Python version right is also an issue. I don&#39;t see why you wouldn&#39;t just use the lastest version offered by your distro, but I guess some poeople are still stuck with inferior operating systems or are constrained by the deployment environment. This is where &lt;a rel=&quot;external&quot; href=&quot;https://github.com/pyenv/pyenv&quot;&gt;pyenv&lt;/a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https://conda.org/&quot;&gt;conda&lt;/a&gt; comes in. I haven&#39;t used either much myself, but I mention them here for completeness.&lt;/p&gt;
&lt;p&gt;There used to be a common and simple tool for package building - &lt;a rel=&quot;external&quot; href=&quot;https://setuptools.pypa.io/en/latest/index.html&quot;&gt;setuptools&lt;/a&gt; - but right now it&#39;s quite a mess. You would set your metadata and configure the build in a &#39;setup.py&#39; file, then you could build the project by executing that file. This offered a lot of flexibility, since a regular python file realistically can contain any code you would need. The downside is that it&#39;s difficult to parse for external tools.&lt;/p&gt;
&lt;p&gt;Then &#39;pyproject.toml&#39; configuration got introduced with &lt;a rel=&quot;external&quot; href=&quot;https://peps.python.org/pep-0518/&quot;&gt;PEP-518&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many build tools make use of the &#39;pyproject.toml&#39;, including setuptools, which is not as dominant anymore. Recently my favorite is &lt;a rel=&quot;external&quot; href=&quot;https://python-poetry.org/&quot;&gt;poetry&lt;/a&gt;. It&#39;s a complete project management tool, which by now plays very well with &#39;pyproject.toml&#39;, and takes care of pretty much everything: dependency management, virtual environments, package builds, package distribution, etc. I find it very easy and pleasant to use. It doesn&#39;t fuck up my project structure and nicely integrates with other tools, for example &lt;a rel=&quot;external&quot; href=&quot;https://pytest.org/&quot;&gt;pytest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another project management tool, &lt;a rel=&quot;external&quot; href=&quot;https://rye.astral.sh/&quot;&gt;rye&lt;/a&gt;, embraces a slightly different vision. It also covers most bases, but it uses a specific set of specialised utilities to accomplish that. Their choice of tooling is opinionated, but very solid and also quite interesting. For example: they use &lt;a rel=&quot;external&quot; href=&quot;https://docs.astral.sh/uv/&quot;&gt;uv&lt;/a&gt; instead of pip. I believe rye, uv, ruff were all written in Rust by the same original author (they are all part of &lt;a rel=&quot;external&quot; href=&quot;https://astral.sh/&quot;&gt;astral.sh&lt;/a&gt;). On &lt;a rel=&quot;external&quot; href=&quot;https://rye.astral.sh/philosophy/&quot;&gt;their &quot;philosophy&quot; page&lt;/a&gt; you can read how exactly rye is different from other project management tools and why.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://pyinstaller.org/en/stable/&quot;&gt;PyInstaller&lt;/a&gt; is useful when you want to distribute your program for a platform that might not have the appropriate python version already available in the PATH. You freeze your project along with dependencies into a single binary file and run it on your target. It&#39;s pretty cool for some use cases.&lt;/p&gt;
&lt;p&gt;When it comes to development, Python doesn&#39;t have a strict style. However, especially when you&#39;re working with others, you would probably like to automatically enforce a uniform and clean style that doesn&#39;t make your eyes bleed. That&#39;s exactly what a linter does. There&#39;s more than a couple of those you can choose from for Python. &lt;a rel=&quot;external&quot; href=&quot;https://black.readthedocs.io/en/stable/&quot;&gt;Black&lt;/a&gt; is a pretty simple yet solid choice. Just for the purpose of sorting your imports correctly there is &lt;a rel=&quot;external&quot; href=&quot;https://pycqa.github.io/isort/&quot;&gt;isort&lt;/a&gt;. Extensible and powerful &lt;a rel=&quot;external&quot; href=&quot;https://flake8.pycqa.org/en/latest/&quot;&gt;flake8&lt;/a&gt; is a popular linter too. It&#39;s very good, but not very fast. That&#39;s where &lt;a rel=&quot;external&quot; href=&quot;https://docs.astral.sh/ruff&quot;&gt;ruff&lt;/a&gt; comes in, offering parity with all the three at faster execution time. Speaking of Python style, the classic style guide is &lt;a rel=&quot;external&quot; href=&quot;https://peps.python.org/pep-0008/&quot;&gt;PEP-8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python is a dynamic language, which means that variables don&#39;t have strictly assigned types. Nonetheless, we can enforce type consistency through static analysis with a type checker such as &lt;a rel=&quot;external&quot; href=&quot;https://www.mypy-lang.org/&quot;&gt;mypy&lt;/a&gt;. Static typing makes it easier to catch some errors before reaching the faulty program state. Static analysis can extend beyond that to catch all sorts of mistakes and provide helpful hints about the correctess of the program. Good tool examples are &lt;a rel=&quot;external&quot; href=&quot;https://github.com/microsoft/pyright&quot;&gt;pyright&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/davidhalter/jedi&quot;&gt;jedi&lt;/a&gt;, which can also provide completions and help effectively browse the code through LSP integrations. You don&#39;t even have to provide any type hints yourself to make good use of a static analysis tool such as pyright. In case you want to get a refresher on Python type hints anyway, they were described in &lt;a rel=&quot;external&quot; href=&quot;https://peps.python.org/pep-0484/&quot;&gt;PEP-484&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;LSP&lt;/a&gt; is a protocol that allows for integrating tools with IDEs or editors such as Neovim. LSP tools help out a whole bunch during source code editing. I myself use aforementioned ruff and pyright that way.&lt;/p&gt;
&lt;p&gt;In the end you have to reach for multiple tools to get what &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/cargo/commands/index.html&quot;&gt;cargo&lt;/a&gt; gives you by default for Rust. For now &lt;em&gt;poetry+ruff+pyright&lt;/em&gt; feels comfy enough to me, but it was quite a journey to get there. I&#39;m sure Python tooling is going to evolve further, hopefully for the better.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>OpenVPN</title>
        <published>2024-11-10T00:00:00+00:00</published>
        <updated>2024-11-10T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/openvpn/"/>
        <id>https://www.wykwit.pl/blog/openvpn/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/openvpn/">&lt;p&gt;As I mentioned in my previous post on VPNs, it&#39;s pretty easy to set up an OpenVPN server. This is my quick setup guide and pretty much what I use on my Debian VPS. I have PKI set up on a different local machine and that&#39;s where I generate my client configs. Once set up you only need a single .ovpn file for a client to connect.&lt;/p&gt;
&lt;p&gt;Config files for openvpn server go to: &lt;code&gt;/etc/openvpn/server&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Files you want to have there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;avpn.conf&lt;/li&gt;
&lt;li&gt;ca.crt&lt;/li&gt;
&lt;li&gt;avpn.crt&lt;/li&gt;
&lt;li&gt;avpn.key&lt;/li&gt;
&lt;li&gt;ta.key&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &#39;avpn&#39; part is simply a name for my config, so you can change it with no problem, just be consistent.&lt;/p&gt;
&lt;p&gt;Install the proper package, move config files, then enable &#39;openvpn-server@avpn&#39; service. Update your DNS entries for the VPN access too. Setup with cloud-init and my server conf follows.&lt;/p&gt;
&lt;p&gt;cloud-init&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;#cloud-config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;package_update&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;package_upgrade&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;packages&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; openvpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ufw&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ca-certificates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;runcmd&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ufw allow 1194/udp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ufw allow 22/tcp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ufw enable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    cat &amp;lt;&amp;lt;&amp;#39;EOF&amp;#39; &amp;gt; /root/openvpn-ready.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    #!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    CONFIG_FILE=&amp;quot;/etc/openvpn/server/avpn.conf&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    if [ -f &amp;quot;$CONFIG_FILE&amp;quot; ]; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      systemctl enable --now openvpn-server@avpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      systemctl status openvpn-server@avpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      echo &amp;quot;OpenVPN service enabled&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      echo &amp;quot;Please copy your configuration to $CONFIG_FILE and run this script again.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; chmod +x /root/openvpn-ready.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;final_message&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;Cloud-Init finished. Copy your OpenVPN configuration files to /etc/openvpn/server/avpn.conf and run /root/openvpn-ready.sh&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;avpn.conf&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;port 1194&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proto udp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dev tun&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ca	/etc/openvpn/server/ca.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cert	/etc/openvpn/server/avpn.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;key	/etc/openvpn/server/avpn.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;topology subnet&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;server 10.8.0.0 255.255.255.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;keepalive 10 120&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dh none&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ecdh-curve secp384r1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tls-crypt /etc/openvpn/server/ta.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;auth-nocache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cipher AES-256-GCM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data-ciphers AES-256-GCM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;auth SHA512&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;persist-key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;persist-tun&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;verb 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;client-to-client&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;explicit-exit-notify 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Below is a script that I use to generate my client keys and .ovpn config files. Omit spaces within tags.&lt;/p&gt;
&lt;p&gt;add-vpn-client.sh&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5C2E7;font-style: italic;&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;client-&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;$1&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F38BA8;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span&gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;export&lt;/span&gt;&lt;span&gt; EASYRSA&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span&gt;$PWD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;easyrsa&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; gen-req&lt;/span&gt;&lt;span&gt; $name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; nopass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;easyrsa&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; sign-req client&lt;/span&gt;&lt;span&gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;mkdir&lt;/span&gt;&lt;span&gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cp&lt;/span&gt;&lt;span&gt; $EASYRSA&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/pki/private/&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;.key ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cp&lt;/span&gt;&lt;span&gt; $EASYRSA&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/pki/issued/&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;.crt ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;chmod&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; go+r -R&lt;/span&gt;&lt;span&gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F38BA8;font-style: italic;&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;writing .ovpn config&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;touch&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;client&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;remote vpn.wykwit.pl 1194&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;proto udp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;dev tun&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;ca   [inline]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;cert [inline]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;key  [inline]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;tls-crypt [inline]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;ecdh-curve secp384r1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;cipher AES-256-GCM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;auth SHA512&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; ca &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ca.crt&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; /ca &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; cert &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;.crt&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; /cert &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; key &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;.key&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; /key &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; tls-crypt &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ta.key&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; ./&lt;/span&gt;&lt;span&gt;$name&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;/avpn.ovpn&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;lt; /tls-crypt &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setting up PKI with Easy-RSA is described very well on ArchWiki: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Easy-RSA&quot;&gt;https://wiki.archlinux.org/title/Easy-RSA&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Scientific method</title>
        <published>2024-11-09T00:00:00+00:00</published>
        <updated>2024-11-09T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/scientific-method/"/>
        <id>https://www.wykwit.pl/blog/scientific-method/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/scientific-method/">&lt;p&gt;Scientific method is OP and can be applied to many more things than just pure science. Methods of engineering design are very similar, only applied to a different problem. It&#39;s really a flexible and useful framework to inteligently approach any problem and work out a satisfying conclusion. For example TDD can be seen as the embodiment of scientific method applied to software engineering, where instead of modifying the hypothesis to match your observations about the world, you modify the world to make observations match your hypothesis. I find it useful to remind myself steps of the scientific method from time to time.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| step | scientific method | engineering design |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|------|-------------------|--------------------|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 1    | question          | problem definition |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 2    | observation       | research           |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 3    | hypothesis        | planning &amp;amp; design  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 4    | experiment        | prototype          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 5    | analysis          | evaluation         |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 6    | conclusion        | improvement        |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 7    | report &amp;amp; repeat   | report &amp;amp; repeat    |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Distros</title>
        <published>2024-10-07T00:00:00+00:00</published>
        <updated>2024-10-07T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/distros/"/>
        <id>https://www.wykwit.pl/blog/distros/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/distros/">&lt;p&gt;Linux is a kernel. Linux-based operating systems bundle all kind of software, mostly open-source or FOSS (often coming from the GNU project), to create a friendly environment for the user. They are commonly called Linux distributions or &quot;distros&quot; for short. The big difference between them is in how exactly they distribute the software. We use packages and package managers for that.&lt;/p&gt;
&lt;p&gt;Debian family uses .deb packages and the &quot;apt&quot; package manager.&lt;/p&gt;
&lt;p&gt;RedHat family uses .rpm packages and &quot;dnf&quot; or &quot;yum&quot; as a package manager.&lt;/p&gt;
&lt;p&gt;Arch Linux uses .tar.zst packages (compressed tarballs) and the &quot;pacman&quot; package manager.&lt;/p&gt;
&lt;p&gt;There is a list of common operations along with a comparison of commands for major distros in the pacman/Rosetta article on ArchWiki: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Pacman/Rosetta&quot;&gt;https://wiki.archlinux.org/title/Pacman/Rosetta&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is also a small difference in what distros bundle in their installations by default. Most of the time that&#39;s not very important, since you can customize any distro to operate, look and feel exactly the way you like. From user perspective most modern distros are really very similar. The other big difference lies in your choice of a Desktop Environment (or a Window Manager), but that&#39;s a topic for a different article.&lt;/p&gt;
&lt;p&gt;One sentence description for all significant Linux distributions follows.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Debian             -&amp;gt; major distribution using the .deb package format and apt package manager&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Ubuntu           -&amp;gt; major family of commercial distributions by Canonical Ltd.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Linux Mint     -&amp;gt; major desktop distribution for end users, pretty beginner friendly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Pop! OS        -&amp;gt; desktop distribution shipped with System76 machines, preinstalled drivers etc.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - LMDE             -&amp;gt; it&amp;#39;s Linux Mint without Ubuntu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Kali Linux       -&amp;gt; major pentesting distribution with a lot of offensive security tools&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Tails            -&amp;gt; amnesic distribution focused on privacy and anonymity with Tor deeply integrated&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Whonix           -&amp;gt; virtualized distribution focused on anonymity that routes all traffic through Tor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Raspberry Pi OS  -&amp;gt; default distribution for Raspberry Pi devices&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- RedHat             -&amp;gt; major distro family using .rpm format for package management&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Fedora           -&amp;gt; testing ground for RHEL, latest and greatest, operated by the community&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Qubes OS       -&amp;gt; operating system that provides security through isolation with xen virtualization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - CentOS Stream    -&amp;gt; second stage of the RHEL testing ground, used to be common enterprise linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - RHEL             -&amp;gt; the industry standard enterprise linux solution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Alma Linux     -&amp;gt; compatible alternative to RHEL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Rocky Linux    -&amp;gt; another compatible alternative to RHEL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - Oracle Linux   -&amp;gt; the enterprise linux solution endorsed by Oracle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - openSUSE         -&amp;gt; European equivalent to RedHat which also offers enterprise options&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - SLES           -&amp;gt; SUSE Linux Enterprise Server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - SLED           -&amp;gt; SUSE Linux Exterprise Desktop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Arch Linux         -&amp;gt; community-driven, simple, lightweight, flexible, fast, power-users delight&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Arch Linux ARM   -&amp;gt; Arch Linux for ARM architectures&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Arch Linux 32    -&amp;gt; Arch Linux for 32-bit CPUs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Artix Linux      -&amp;gt; Arch Linux without systemd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Asahi Linux      -&amp;gt; Arch Linux on Apple silicon&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - BlackArch        -&amp;gt; Arch Linux with pentesting tools&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - EndeavourOS      -&amp;gt; Arch Linux for newbies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Manjaro          -&amp;gt; the Ubuntu of Arch Linux family&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Parabola         -&amp;gt; fully FOSS and libre distribution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - SteamOS          -&amp;gt; distribution exclusively for gaming with Steam, by Valve&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Slackware          -&amp;gt; the oldest distribution still in use, solid and reliable, but not very modern&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Gentoo             -&amp;gt; highly customizable source-based distribution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- NixOS              -&amp;gt; reproducible, declarative and reliable distribution for advanced users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Alpine Linux       -&amp;gt; truly minimal, small, simple, secure, very fast, utilizing musl libc and busybox&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - postmarketOS     -&amp;gt; alternative operating system for mobile devices&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- OpenWrt            -&amp;gt; small yet powerful distribution for routers, firewalls, and other embedded devices&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Android            -&amp;gt; major operating system for smartphones and other mobile devices&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For beginners I would recommend: LMDE, Linux Mint, Fedora. Advanced users will probably have their own preference, but personally I can definitely recommend Arch Linux. On a server I would primarly use: Alpine Linux, Debian, or any of the RHEL-based distros.&lt;/p&gt;
&lt;p&gt;If you&#39;re not using GNU/Linux already, you should definitely try it!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Upskill</title>
        <published>2024-08-15T00:00:00+00:00</published>
        <updated>2024-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/upskill/"/>
        <id>https://www.wykwit.pl/blog/upskill/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/upskill/">&lt;p&gt;It&#39;s good to brush up on your computer-magician skills from time to time.&lt;/p&gt;
&lt;p&gt;Platforms with programming challenges are great for this. You can quickly solve a short task to regain some confidence in your fundemantal knowledge. One such platform is &lt;a rel=&quot;external&quot; href=&quot;https://www.codewars.com/&quot;&gt;Codewars&lt;/a&gt;, which lets you solve simple tasks in a variety of programming languages. Solutions are tested on the platform and sometimes are constrained in terms of execution time, although the testing isn&#39;t as through as you might expect for competitive programming. The second platform I like is &lt;a rel=&quot;external&quot; href=&quot;https://codeforces.com/&quot;&gt;Codeforces&lt;/a&gt;, which aggregates tasks from various competitions. That&#39;s where you can really test your knowledge of algorithms. Then there&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt;, a collection of challenges often relating to some mathematical concepts.&lt;/p&gt;
&lt;p&gt;Capture The Flag is a different class of challenges. On &lt;a rel=&quot;external&quot; href=&quot;https://ctftime.org/&quot;&gt;CTFtime&lt;/a&gt; you can find a list of upcoming CTF competitions, archive of past events, and many useful writeups. You will never run out of new tasks to solve. I particularly like &lt;a rel=&quot;external&quot; href=&quot;https://cryptohack.org/&quot;&gt;Cryptohack&lt;/a&gt;, a CTF platform filled with challenges around the topic of cryptography. For a more structured approach to CybSec training, &lt;a rel=&quot;external&quot; href=&quot;https://www.hackthebox.com/&quot;&gt;HackTheBox&lt;/a&gt; is probably the best choice. They offer a huge library of virtual labs and learning environments to break in quite a realistic fashion.&lt;/p&gt;
&lt;p&gt;Nonetheless, the best way to upskill is to take up a personal project and to see it through. I always favor this over courses and dull exercises. Not to say that courses are bad, but I believe books and official documentation are the best learning resources, especially effective with practice.&lt;/p&gt;
&lt;p&gt;Learning new programming languages or different technologies can also be very refreshing. Picking up a foreign language is great too. When you&#39;re tired of tech it might be a good idea to delve into literature from other scientific fields and hopefully come back with a new perspective. There&#39;s so many interesting topics to study, it&#39;s impossible not to get drawn into something when walking through a library.&lt;/p&gt;
&lt;p&gt;Never stop learning!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>New installations</title>
        <published>2024-04-29T00:00:00+00:00</published>
        <updated>2024-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/new-installations/"/>
        <id>https://www.wykwit.pl/blog/new-installations/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/new-installations/">&lt;p&gt;Installation guide on ArchWiki describes basics in more details.
This list is just an overview, in practice the basic installation is mostly covered by &#39;archinstall&#39;.
In the past I wrote a post about partitioning for fully encrypted installations, check it out first if that&#39;s what you&#39;re aiming for.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;partition the hard drive&lt;/li&gt;
&lt;li&gt;format partitions&lt;/li&gt;
&lt;li&gt;mount all the partitions&lt;/li&gt;
&lt;li&gt;$ pacstrap -ci /mnt base&lt;/li&gt;
&lt;li&gt;$ genfstab -U /mnt &amp;gt;&amp;gt; /mnt/etc/fstab&lt;/li&gt;
&lt;li&gt;arch-chroot into the new installation&lt;/li&gt;
&lt;li&gt;install kernel, run $ mkinitcpio -P&lt;/li&gt;
&lt;li&gt;set up a bootloader like grub or systemd-boot&lt;/li&gt;
&lt;li&gt;install additional packages: vim tmux networkmanager&lt;/li&gt;
&lt;li&gt;set up a user account with sudo privileges&lt;/li&gt;
&lt;li&gt;reboot&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At this point you should have a basic working system installation, but there is a lot more to do.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;set hostname, locales, keymaps, timezone&lt;/li&gt;
&lt;li&gt;install additional drivers (microcode, nvidia, r8168) and load kernel modules you might need&lt;/li&gt;
&lt;li&gt;regenerate mirrorlist with reflector&lt;/li&gt;
&lt;li&gt;set up a desktop manager (lightdm) with a greeter (lightdm-gtk-greeter)&lt;/li&gt;
&lt;li&gt;install a desktop environment (cinnamon) or a window manager (i3, sway)&lt;/li&gt;
&lt;li&gt;install some AUR helper (paru, yay)&lt;/li&gt;
&lt;li&gt;install your preferred set of packages&lt;/li&gt;
&lt;li&gt;enable your preferred set of services&lt;/li&gt;
&lt;li&gt;add your user to preferred groups&lt;/li&gt;
&lt;li&gt;set up a firewall (ufw, gufw)&lt;/li&gt;
&lt;li&gt;restore your dotfiles and custom configurations&lt;/li&gt;
&lt;li&gt;change themes (mint-l-theme) and icons (papirus-icon-theme)&lt;/li&gt;
&lt;li&gt;tweak your desktop environment settings just right&lt;/li&gt;
&lt;li&gt;change your input method to fcitx with mozc&lt;/li&gt;
&lt;li&gt;disable actions on lid close (/etc/systemd/logind.conf) and automatic suspend&lt;/li&gt;
&lt;li&gt;install vim-plug and vim plugins&lt;/li&gt;
&lt;li&gt;monitor filesystem integrity with AIDE&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For some of these topics you can find helpful info on my blog.&lt;/p&gt;
&lt;p&gt;Here&#39;s the reflector command that you can use for refreshing your mirrorlist:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ reflector --verbose --latest 100 --fastest 30 --protocol https --sort rate --save /etc/pacman.d/mirrorlist&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a bonus, here&#39;s my &lt;code&gt;lightdm-gtk-greeter.conf&lt;/code&gt;. I couldn&#39;t decide where else to store it.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[greeter]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;background = /usr/share/backgrounds/lain-on-black.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;user-background = false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theme-name = Mint-L-Dark-Red&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;icon-theme-name = Papirus-Dark&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;font-name = Liberation Sans 12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;indicators = ~power;~spacer;~separator;~clock;~separator;~spacer;~session&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;clock-format = %H:%M:%S - %a %d %h %Y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;position = 5%,start -5%,end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a11y-states = ~contrast&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hide-user-image = true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>LLMs</title>
        <published>2023-11-27T00:00:00+00:00</published>
        <updated>2023-11-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/llms/"/>
        <id>https://www.wykwit.pl/blog/llms/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/llms/">&lt;p&gt;Large Language Models popped off with the release of ChatGPT, a service that launched almost exactly a year ago as a research preview at the end of November 2022 and quickly took internet by the storm. It gained over a million users in just a few days, and reached over a 100 mln users in a few weeks. They&#39;ve caused a lot of fuzz which definitely accelerated the evolution of AI, and we&#39;ve seen a lot of developments in that space over just this last year. While there is also a lot of valid criticism regarding AI, and plenty that I could pour out in that direction myself, LLMs sure are a damn useful tool. In simple terms, LLM provides text completions by predicting what the next word should be based on what it has seen previously - in mainly the context given, but also the training data. It would be pretty cool if we could run our own local instance of some open-source LLM, right?&lt;/p&gt;
&lt;p&gt;Unfortunately there isn&#39;t much open-source in OpenAI&#39;s LLM solution like ChatGPT, but it will still serve a helpful example to better understand how it all works. With ChatGPT we use a web frontend for interaction with the language model like GPT-3.5 or GPT-4. You can also interact with available models through the API. GPT-3.5 itself is &quot;a series of models&quot; that consists of: &#39;code-davinci-002&#39; (base model), &#39;text-davinci-002&#39; (InstructGPT model based on the previous one), &#39;text-davinci-003&#39; (an improvement over the previous one), &#39;gpt-3.5-turbo&#39; (another improvement, optimized for chat). InstructGPT and other chat models are useful because of the fine-tuning towards instruction following and proper AI alignment. After the model has been trained for valid completions, there&#39;s an additional training step to teach it the pattern for interaction - that step is called fine-tuning. With open-source LLMs people can fine-tune the model to their specific need. The AI alignment is a preprogrammed bit of context that tells the model how to behave. In case of ChatGPT it is the invisible prompt that tells the model to play the role of a helpful chat assistant. All of this together makes LLMs useful for various tasks besides just text completions (which was needed for that software to take over mainstream). Without alignment the base GPT will not provide a dialogue by itself, but could be used successfully for code completion tasks. Below the interface, whether WebUI or API, there is a plethora of models to choose from, and that&#39;s the most interesting part. The &quot;deprecations&quot; page in OpenAI docs lists a whole graveyard of GPT-3 models with the naming convention of &quot;[class]-{ada,babbage,curie,davinci}-[suffix]&quot;. They can all behave slightly differently. Following OpenAI, other tech giants such as G00gle, Micro$$oft, and Faceb00k have been toying with this tech too. A particularly interesting model was LLaMA by Meta AI (Faceb00k).&lt;/p&gt;
&lt;p&gt;Open-sourcing LLMs started off with LLaMA, which was leaked on 4chan soon after release. Source code for inference was already published, but the leak contained model&#39;s weights (the result of model learning) which allowed the community to skip the access application process with the corp. It was easier for people to run it on their own machines and to fine-tune the model further. The significantly smaller 13B parameter model of LLaMA was exceeding the 175B parameter model of GPT-3 in performance. As with all things open-source, advancements were quickly made by the community. This laid ground for the de-facto standard platform of open-source LLMs. Llama2 was released a few months later, you can learn all about it here: &lt;a rel=&quot;external&quot; href=&quot;https://ai.meta.com/llama/get-started/&quot;&gt;https://ai.meta.com/llama/get-started/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is how Facebook itself praises perks of open-source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crowd sourced optimization: The open source community has really embraced our models. To date, the community has fine-tuned and released over 7,000 derivatives on Hugging Face. On average, across standard benchmarks, these have improved performance on common benchmarks by nearly 10% with remarkable improvements of up to 46% for benchmark datasets like TruthQA.&lt;/li&gt;
&lt;li&gt;Developer community: There are now over 7,000 projects on GitHub built on or mentioning Llama. New tools, deployment libraries, methods for model evaluation, and even “tiny” versions of Llama are being developed to bring Llama to edge devices and mobile platforms. Additionally, the community has expanded Llama to support larger context windows, added support for additional languages, and so much more.&lt;/li&gt;
&lt;li&gt;Hardware support: The hardware community has fully embraced Llama as a key model architecture. Major hardware platforms AMD, Intel, Nvidia, and Google have boosted the performance of Llama 2 through hardware and software optimizations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the platforms mentioned above is Hugging Face, which hosts a huge library of different models and datasets. Some of the models that I think might be worth checking out are: Mistral, Vicuna, WizardLM. HuggingFace also has a model leaderboard, so you can compare different open-source LLMs and pick something out by yourself: &lt;a rel=&quot;external&quot; href=&quot;https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard&quot;&gt;https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Besides fine-tuning the model and feeding it a good prompt, there there are still some parameters that you can change when you run the model. Check out this article for an idea: &lt;a rel=&quot;external&quot; href=&quot;https://rentry.org/llm-settings&quot;&gt;https://rentry.org/llm-settings&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you do finally run the model, really the most important thing to make good use of it is feeding it effective prompts. The model will respond better or worse depending on the way you express yourself. This sparked interest in &quot;prompt engineering&quot; - figuring out how to communicate with ready-made models effectively to make them do the right job and achieve desired outcomes. This could be very useful to you as an operator.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://platform.openai.com/docs/guides/prompt-engineering/&quot;&gt;https://platform.openai.com/docs/guides/prompt-engineering/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/&quot;&gt;https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.promptingguide.ai/&quot;&gt;https://www.promptingguide.ai/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://learnprompting.org/docs/intro&quot;&gt;https://learnprompting.org/docs/intro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, finally, how do you actually run this stuff?&lt;/p&gt;
&lt;p&gt;With something like &lt;a rel=&quot;external&quot; href=&quot;https://ollama.ai/&quot;&gt;ollama&lt;/a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https://localai.io/&quot;&gt;LocalAI&lt;/a&gt;, it&#39;s pretty simple and painless. You can easily interact with the LLM from your terminal or the HTTP API that is usually similar to the one from OpenAI (so maybe check out their docs too?). Both of these open-source projects have decent documentation.&lt;/p&gt;
&lt;p&gt;From the website of LocalAI:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LocalAI acts as a drop-in replacement REST API that’s compatible with OpenAI API specifications for local inferencing. It allows you to run LLMs, generate images, audio (and not only) locally or on-prem with consumer grade hardware, supporting multiple model families that are compatible with the ggml format. Does not require GPU.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;An example of installing and running &#39;ollama&#39; with &#39;mistral&#39; model:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# pacman -S ollama&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ollama serve &amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ollama pull mistral&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ollama run mistral&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also install a local WebUI and plug into your locally deployed API. There are plenty open-source options to choose from, for example &lt;a rel=&quot;external&quot; href=&quot;https://big-agi.com/&quot;&gt;big-AGI&lt;/a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https://cheshirecat.ai/&quot;&gt;Cheshire Cat&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Where to go next? Here are two deligthful pieces with a ton of links to other sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.borealisai.com/research-blogs/a-high-level-overview-of-large-language-models/&quot;&gt;https://www.borealisai.com/research-blogs/a-high-level-overview-of-large-language-models/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://flyte.org/blog/getting-started-with-large-language-models-key-things-to-know&quot;&gt;https://flyte.org/blog/getting-started-with-large-language-models-key-things-to-know&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No AI was harmed in the making of this blog post.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>VPN security</title>
        <published>2023-10-20T00:00:00+00:00</published>
        <updated>2023-10-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/vpn-security/"/>
        <id>https://www.wykwit.pl/blog/vpn-security/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/vpn-security/">&lt;p&gt;VPN stands for a Virtual Private Network and it&#39;s purpose is to connect together computers that are in different physical networks. This allows them to access and share resources as if they were all in the same LAN and even reach devices behind NAT. With proper routing they can also provide an exit to the internet somewhere else from the original point of connection and therefore serve as a proxy for connected devices.&lt;/p&gt;
&lt;p&gt;The proxy feature was not the point of a VPN, but because of heavy advertising online, many people started to see it that way. There are a few problems with using commercial VPNs as a proxy for the sake of security; I&#39;ll go through them briefly.&lt;/p&gt;
&lt;p&gt;Commercial VPN providers claim it is more secure to use a VPN, because then your connection is encrypted. The truth is, if you&#39;re using HTTPS (and you most likely are - see the lock icon in the URL bar), then your connection is encrypted by default anyway. As long as the Certificate Authority (CA) is not compromised, the connection between you and the website is private. People on your network will not be able to &quot;steal your passwords&quot; easily. They might be able to see what you connect to, what website you are talking to, but they will not see what you &quot;talk about&quot; with the online service. Snooping on the traffic used to be possible back in the plain HTTP days, but now it&#39;s only viable if your machine trusts a compromised CA. On your work machine that could be the case: it might be set up to trust a CA of your employer so they would be able to see what you&#39;re doing. When you click on the padlock in the url bar you can see details that will tell you who the CA is, so you can know whether certificates in use were compromised by your employer. VPN will not help you if the CA is compromised for real by someone malicious. The advertisement claim is about MITM attacks in an outdated scenario and for the criminal it won&#39;t work out as easily as they claim anymore. Yes, a VPN will make a MITM attack harder, but MITM in of itself is not really that useful, and definitely not as powerful as they claim, thanks to the common use of encryption nowadays. Check out my post on ARP to see an example of a MITM attack.&lt;/p&gt;
&lt;p&gt;As I said, people on the same network might not see what you&#39;re talking about, but they can see what server you&#39;re trying to talk to. When you connect to a VPN you only talk to one server and the rest of your traffic goes out to the internet from there. People on your network might not see who you&#39;re talking to besides the VPN server, but the VPN server does! And everyone still knows what VPN server you were connected to! If this is a commercial VPN, the provider most likely has a KYC (know your client) policy that makes it way easier to indentify you than if you were simply connecting to the endpoint directly. They might claim to never store logs, but: someone might still monitor that traffic, perhaps collect it and analyze it in a different way, exit nodes might be under heavier surveilance than your regular connection, with servers under foreign jurisdiction you can&#39;t always be sure what is going on there and how much the provider can or can&#39;t tell you about it. At the end of the day, you don&#39;t know what&#39;s going on with your traffic at the provider&#39;s side and there is no way for them to prove what is really happening with it. The only way to ensure security and privacy is through encryption end-to-end. For anonymity VPN is not a very good idea. The key question is: who do you trust more - your ISP or the VPN provider? Maybe in your case it makes sense to access the internet with a connection originating from a different country. Commercial VPN advertisements often mention bypassing geoblocks. If that is your goal, you might want to read more about Tor or check out my previous post on piracy.&lt;/p&gt;
&lt;p&gt;Commercial VPN providers also claim to hide your IP address and thus make you anonymous. That&#39;s not how it works. Anonymity is more about how you use the service than what exact service you use. If you want to be more anonymous you should use Tor instead of commercial VPNs. The VPN provider can most likely identify you already. They know the account you use to connect, they can see all the details such as where you connect from, when, for how long, the details of your payment method, your browsing patterns, perhaps your web browser fingerprint, and perhaps a lot more details in case they have a stronger KYC policy. That&#39;s not even the biggest issue here. When you&#39;re using the VPN as a proxy with the same IP address during the whole session - everything you do during that session is still interconnected. If you deanonymize yourself by logging into any account, you deanonymize the whole session. Tracking by IP is also not the only option for anonymity adversaries. Devices we use and the software we choose can also be used to fingerprint and track us, even between different connections and websites, while being much more reliable and precise. Let&#39;s just say that anonymity and online tracking is a wide topic. Your anonymity will crumble if you manage your online identities wrong and no VPN can help with that. Ideally you would like to have a common fingerprint and use a different exit node for each connection. That&#39;s what Tor aims to accomplish. It&#39;s what it does for free.&lt;/p&gt;
&lt;p&gt;In summary, commercial VPN gives a false sense of security and you more than likely do not need it. Nevertheless, you might want to set up a VPN for a lot of different reasons, but not necesarilly for the sake of &quot;security&quot;. In future post I might explain how to do it. There are many VPN technologies to choose from.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PPTP - unsecure 90s protocol spawned by Micro$$oft, avoid this one&lt;/li&gt;
&lt;li&gt;L2TP - another 90s protocol, to be used in tandem with IPsec, be careful with this one&lt;/li&gt;
&lt;li&gt;OpenVPN - popular open-source solution, both protocol and server software, requires additional client software, but everything about it is fairly easy to set up and works great&lt;/li&gt;
&lt;li&gt;IKEv2 - strongSwan, Openswan, Libreswan - family of FOSS servers implementing IPsec, IKEv2, very cool&lt;/li&gt;
&lt;li&gt;SSTP - another protocol spawned by Micro$$oft, supported OOTB on Window$$, uses SSL/TLS on port 443 by default&lt;/li&gt;
&lt;li&gt;WireGuard - modern, fast and simple, secure protocol, included in the Linux kernel, but with wide support for all the platforms. If you&#39;re wondering what you should use, this is what you should use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are some commercial VPN server solutions too, but I am convinced that WireGuard trumps them all.
If you want to deploy a server quick and easy then OpenVPN is also a pretty good choice.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Piracy</title>
        <published>2023-09-10T00:00:00+00:00</published>
        <updated>2023-09-10T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/piracy/"/>
        <id>https://www.wykwit.pl/blog/piracy/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/piracy/">&lt;h2 id=&quot;0-piracy-is-good&quot;&gt;0. PIRACY IS GOOD&lt;a class=&quot;zola-anchor&quot; href=&quot;#0-piracy-is-good&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I hope if you&#39;re reading this you already understand that.&lt;/p&gt;
&lt;h2 id=&quot;1-block-ads&quot;&gt;1. BLOCK ADS&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-block-ads&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is no joke, this is extremely common vector of attack that gets people infected with malware or fall for phishing and lose access to their accounts.
Also, ads are annoying.
Fuck advertisers.&lt;/p&gt;
&lt;p&gt;Use the best adblocker there is:
&lt;a rel=&quot;external&quot; href=&quot;https://ublockorigin.com/&quot;&gt;https://ublockorigin.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Find the uBlock Origin extension for your browser and install it (that&#39;s two clicks to be much safer online).
The website above will help.
You can use it both on Chrome and Firefox, but ad-blocking generally works better on Firefox.
Google is a business selling ads, obviously it&#39;s in their incentive for ad-blockers to be less effective.&lt;/p&gt;
&lt;h2 id=&quot;2-search-and-you-shall-find&quot;&gt;2. SEARCH AND YOU SHALL FIND&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-search-and-you-shall-find&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Again, searching on Google will not be very effective, since their search engine is heavily censored.
You know, to comply with demands of industry giants that advertise there and spend big money. Also DMCA.&lt;/p&gt;
&lt;p&gt;A meta search engine like SearXNG would be more effective, but it&#39;s a little more advanced.
Find a working instance and search from there: &lt;a rel=&quot;external&quot; href=&quot;https://searx.space/&quot;&gt;https://searx.space/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;DuckDuckGo should give decent results for casual searches and it&#39;s even easier to use than Google, since it doesn&#39;t include ad spam in top results: &lt;a rel=&quot;external&quot; href=&quot;https://duckduckgo.com/&quot;&gt;https://duckduckgo.com/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-streaming&quot;&gt;3. STREAMING&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-streaming&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now that you have WORKING AD BLOCKING set up and you know how to effectively search the web, it&#39;s time to finally watch something.&lt;/p&gt;
&lt;p&gt;Here&#39;s a list of a few websites you can use for streaming movies and series.
Very simple to use.
Just be cautious. Don&#39;t fall for scams and don&#39;t fall for phishing.
Exact domains can change with time as they get shut down, but at least you know what to look for.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://fmovies.to/ - favourite for getting movies easy and quick&lt;/li&gt;
&lt;li&gt;https://susflix.tv/&lt;/li&gt;
&lt;li&gt;https://gogoanime.tv/&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are lists of links too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.reddit.com/r/FREEMEDIAHECKYEAH/wiki/index/&quot;&gt;https://www.reddit.com/r/FREEMEDIAHECKYEAH/wiki/index/&lt;/a&gt; - Piracy Wiki on Reddit&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.reddit.com/r/FREEMEDIAHECKYEAH/wiki/video/&quot;&gt;https://www.reddit.com/r/FREEMEDIAHECKYEAH/wiki/video/&lt;/a&gt; - list of video streaming sites from that Wiki&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://shakil-shahadat.github.io/awesome-piracy/&quot;&gt;https://shakil-shahadat.github.io/awesome-piracy/&lt;/a&gt; - huge list of resources and websites related to piracy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you choose to create an account on any of the piracy websites - don&#39;t use anything that could be related to you.
Use a completely random password or some simple throw-away that you&#39;ve never used anywhere before.
You can be identified by the password you use, not only by e-mail or username. Don&#39;t reuse passwords.&lt;/p&gt;
&lt;p&gt;For music you could use a modded Spotify app for free or download your music from elsewhere.
Again, see the resources above.
If you find the modded .apk I would advise to scan it on &lt;a rel=&quot;external&quot; href=&quot;https://www.virustotal.com/&quot;&gt;virustotal.com&lt;/a&gt; before installing it on your phone.&lt;/p&gt;
&lt;p&gt;Don&#39;t ever pay for streaming.&lt;/p&gt;
&lt;h2 id=&quot;4-downloading&quot;&gt;4. DOWNLOADING&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-downloading&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can download anything you can stream and more.
When you&#39;re streaming something you&#39;re actually downloading the media piece by piece while displaying each piece as it is ready to be played.
If you save these pieces when you recieve them - you can effectively just download the media file.
Some of the streaming sites mentioned above will give you an option of direct download for simplicity.
For others, like YouTube, you may have to use a specific downloader, for example: &lt;a rel=&quot;external&quot; href=&quot;https://github.com/yt-dlp/yt-dlp&quot;&gt;yt-dlp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To download a YouTube video:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yt-dlp [link]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To download audio only:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yt-dlp -x [link]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find direct download links to most things with enough effort.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://chomikuj.pl/&quot;&gt;https://chomikuj.pl/&lt;/a&gt; - Polish file storage and file sharing website. You pay a little bit for the data transfer, but there is a lot you can find there, especially if you&#39;re looking for something in Polish language.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://sci-hub.st/&quot;&gt;https://sci-hub.st/&lt;/a&gt; - Scientific papers unlocked.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://libgen.rs/&quot;&gt;https://libgen.rs/&lt;/a&gt; - Library Genesis is a huge collection that contains non-fiction books, fiction, scientific articles, and overall a lot of useful stuff. Their files are also available through torrent download and on IPFS.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://annas-archive.org/&quot;&gt;https://annas-archive.org/&lt;/a&gt; - Amazing website that allows you to search through a vast library including Sci-Hub, LibGen and Z-Library resources.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4b-torrents&quot;&gt;4b. TORRENTS&lt;a class=&quot;zola-anchor&quot; href=&quot;#4b-torrents&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The rest of this section will be all about torrents.&lt;/p&gt;
&lt;p&gt;There&#39;s one simple catch when it comes to torrents - it&#39;s a peer-to-peer network, which means it only works when people who download also upload the same content for others to use.
Uploading is where the copyright infringement lies.
In short, downloading should be legal, uploading may not be.
In your torrent client settings you can set limits for upload or use a proxy/vpn to hide yourself a little bit;
although in some countries, as long as you don&#39;t pirate movies produced in that country, you&#39;re probably better off just using your raw connection without a foreign VPN.&lt;/p&gt;
&lt;p&gt;You need a torrent client to open .torrent files or open &quot;magnet links&quot; to download stuff.&lt;/p&gt;
&lt;p&gt;My favorite torrent client is Transmission: &lt;a rel=&quot;external&quot; href=&quot;https://transmissionbt.com/&quot;&gt;https://transmissionbt.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will need trackers to track the peers that seed (upload) the file you want to get.
The list of trackers that your torrent client will use is usually included with the .torrent file or magnet link.
There are private trackers that may provide better service or have some rare content available, but I won&#39;t go into details on this.&lt;/p&gt;
&lt;p&gt;Here&#39;s a list of a few websites where you can get your magnet links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://ext.to/&quot;&gt;https://ext.to/&lt;/a&gt; - torrent aggregator with multiple sources&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://thepiratebay.org/&quot;&gt;https://thepiratebay.org/&lt;/a&gt; - a classic, giant of the internet history, one and only, The Pirate Bay&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://1337x.to/&quot;&gt;https://1337x.to/&lt;/a&gt; - good source for movies and series&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://nyaa.si/&quot;&gt;https://nyaa.si/&lt;/a&gt; - best quality anime and all that nerd weeb shit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I say &quot;best quality anime&quot; I actually mean it.
It&#39;s usually better than any streaming.
The highest quality, best encoded, best looking releases you can find are over there.
You&#39;re welcome.&lt;/p&gt;
&lt;h2 id=&quot;5-stay-informed&quot;&gt;5. STAY INFORMED&lt;a class=&quot;zola-anchor&quot; href=&quot;#5-stay-informed&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;News website that covers piracy-related topics and more: &lt;a rel=&quot;external&quot; href=&quot;https://torrentfreak.com/&quot;&gt;https://torrentfreak.com/&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Common Lisp resources</title>
        <published>2023-08-12T00:00:00+00:00</published>
        <updated>2023-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/cl-resources/"/>
        <id>https://www.wykwit.pl/blog/cl-resources/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/cl-resources/">&lt;p&gt;Common Lisp is a lisp dialect with an official ANSI specification (X3J13), but multiple different implementations.
The one I primarly use is ECL, but I&#39;m also using SBCL sometimes, which is the most popular choice.
There should be no difference regardless of which implementation you go with.&lt;/p&gt;
&lt;p&gt;Lisp is a wonderful language, and below is a list of resources for learning more about Common Lisp, also for my future reference.&lt;/p&gt;
&lt;p&gt;Common Lisp HyperSpec:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://clhs.lisp.se/&quot;&gt;http://clhs.lisp.se/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.lispworks.com/documentation/lw50/CLHS/Front/Contents.htm&quot;&gt;http://www.lispworks.com/documentation/lw50/CLHS/Front/Contents.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Common Lisp Cookbook:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://lispcookbook.github.io/cl-cookbook/&quot;&gt;https://lispcookbook.github.io/cl-cookbook/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Common Lisp Style Guide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://lisp-lang.org/style-guide/&quot;&gt;https://lisp-lang.org/style-guide/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quickdocs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://quickdocs.org/&quot;&gt;https://quickdocs.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quickref, index of libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://quickref.common-lisp.net/index-per-library.html&quot;&gt;https://quickref.common-lisp.net/index-per-library.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Book &quot;Practical Common Lisp&quot; by Peter Seibel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://gigamonkeys.com/book/&quot;&gt;https://gigamonkeys.com/book/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Book &quot;Common Lisp the Language, 2nd Edition&quot; by Guy L. Steele Jr.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node1.html&quot;&gt;https://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node1.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Book &quot;On Lisp&quot; by Paul Graham:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.paulgraham.com/onlisp.html&quot;&gt;http://www.paulgraham.com/onlisp.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Book &quot;Let Over Lambda&quot; by Douge Hoyte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://letoverlambda.com/&quot;&gt;https://letoverlambda.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Road to Common Lisp: &lt;a rel=&quot;external&quot; href=&quot;https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/&quot;&gt;https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Common Lisp Wikibook: &lt;a rel=&quot;external&quot; href=&quot;https://en.wikibooks.org/wiki/Common_Lisp/First_steps/Experienced_tutorial&quot;&gt;https://en.wikibooks.org/wiki/Common_Lisp/First_steps/Experienced_tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Common Lisp in Practice: &lt;a rel=&quot;external&quot; href=&quot;https://atomized.org/blog/2020/07/06/common-lisp-in-practice/&quot;&gt;https://atomized.org/blog/2020/07/06/common-lisp-in-practice/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sean&#39;s Lisp Tutorial: &lt;a rel=&quot;external&quot; href=&quot;https://cs.gmu.edu/~sean/lisp/LispTutorial.html&quot;&gt;https://cs.gmu.edu/~sean/lisp/LispTutorial.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Successfull Lisp PDF: &lt;a rel=&quot;external&quot; href=&quot;https://www.ebixio.com/online_docs/SuccessfulLisp.pdf&quot;&gt;https://www.ebixio.com/online_docs/SuccessfulLisp.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;lisp-lang website: &lt;a rel=&quot;external&quot; href=&quot;https://lisp-lang.org/learn/&quot;&gt;https://lisp-lang.org/learn/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;lisp-stat website: &lt;a rel=&quot;external&quot; href=&quot;https://lisp-stat.dev/docs/tutorials/basics/&quot;&gt;https://lisp-stat.dev/docs/tutorials/basics/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>samba</title>
        <published>2022-09-29T00:00:00+00:00</published>
        <updated>2022-09-29T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/samba/"/>
        <id>https://www.wykwit.pl/blog/samba/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/samba/">&lt;p&gt;All things micro$$oft suck ass. AD and SMB are no exceptions.&lt;/p&gt;
&lt;p&gt;Active Directory (AD) is &quot;a directory service for Window$$ domain networks&quot;, essentially used for identity management.
You can think of it as a Window$$-centric authentication and authorization service.
SMB is a file sharing protocol pushed out with Window$$ OS.
Samba is the interoperability suite to utilize this insanity on some sane OS.&lt;/p&gt;
&lt;p&gt;As per usual, more info on ArchWiki:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Samba&quot;&gt;https://wiki.archlinux.org/title/Samba&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Extensive docs are out there, too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf&quot;&gt;https://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If all you need to do is access files over SMB, your best bet is to use &lt;a rel=&quot;external&quot; href=&quot;https://archlinux.org/packages/extra/x86_64/gvfs-smb/&quot;&gt;gvfs-smb&lt;/a&gt;
and save yourself a headache of trying to figure out how it all works.
Using GVfs allows you to connect and nicely browse shares with file managers like Nemo or Nautilus.
You have to know the IP address or DNS name of your share.
Simply type it in with &quot;smb://&quot; protocol prefix as a location in Nemo and you&#39;ll be prompted for credentials to access the share.
SMB also allows for sharing printers somehow, but I&#39;ve never tried it.&lt;/p&gt;
&lt;p&gt;If you need to play with AD a little bit more, read on.
Then refer to this ArchWiki page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Active_Directory_integration&quot;&gt;https://wiki.archlinux.org/title/Active_Directory_integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few configuration details you&#39;d like to note down: NetBIOS domain name, DNS domain name, Kerberos realm, DC1 (hostname/IP), DC2, etc.&lt;/p&gt;
&lt;p&gt;To set up your DNS - change &lt;code&gt;/etc/resolv.conf&lt;/code&gt; according to the template:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nameserver [DC1 IP]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nameserver [DC2 IP]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;search [internal.domain.tld]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test it with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ nslookup -type=SRV _kerberos._tcp.internal.domain.tld.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ nslookup -type=SRV _ldap._tcp.internal.domain.tld.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ nslookup dc1.internal.domain.tld.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Kerberos it may be neccessary to modify &lt;code&gt;/etc/krb5.conf&lt;/code&gt; if authentication doesn&#39;t work properly.&lt;/p&gt;
&lt;p&gt;Configuring samba cosists of a few steps, but I won&#39;t go into details: basic config, disabling printers, UID/GID mapping config, NSS config for UID/GID mapping.
You may need to run these services: &#39;smb.service&#39;, &#39;nmb.service&#39;, (optional) &#39;winbind.service&#39;.
Again, consult references linked above for more information.&lt;/p&gt;
&lt;p&gt;To join a domain try:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ net ads join -U [username]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ samba-tool domain join [internal.domain.tld] MEMBER -U [username]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few commands for testing:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ net ads info&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ net ads lookup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ net ads status -U [username]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ wbinfo -u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ wbinfo -g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ wbinfo --ping-dc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now some more SMB commands...&lt;/p&gt;
&lt;p&gt;In case you didn&#39;t like gvfs-smb that I suggested, you may have shot at using smbclient.&lt;/p&gt;
&lt;p&gt;Listing:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ smbclient -L &amp;quot;\\12.23.34.45&amp;quot; -U [username]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Connecting:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ smbclient &amp;quot;//12.23.34.45/DIRECTORY&amp;quot; -U [username]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I honestly don&#39;t know about the slashes here.
Micro$$oft is always going backwards so they prefer backslashes.
Anything else would escape on a backslash.
How does it mix in your shell? IDK, just try it I guess? ¯\_(ツ)_/¯&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SELinux</title>
        <published>2022-07-25T00:00:00+00:00</published>
        <updated>2022-07-25T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/selinux/"/>
        <id>https://www.wykwit.pl/blog/selinux/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/selinux/">&lt;p&gt;SELinux is a Linux Security Module (LSM). When the kernel does something like a permission check and it passes OK, the security module is queried right after to provide additional security checks. You will find SELinux on RedHat based distributions and Android. Another popular option is AppArmor, used for example in Ubuntu. There can only be one LSM is use at a time, so you won&#39;t ever use both of them at once.&lt;/p&gt;
&lt;p&gt;SELinux provides additional context associated with certain paths to provide an extended permission model.&lt;/p&gt;
&lt;p&gt;Directory listing with SELinux context:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ls -laRZ .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;List possible context values:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ semanage fcontext -l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Refresh assigned context values:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ restorecon -Rv .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Change context:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ chcon&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To automatically refresh context values and relabel the system on reboot:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ touch /.autorelabel&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>arduino-cli</title>
        <published>2022-05-28T00:00:00+00:00</published>
        <updated>2022-05-28T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/arduino-cli/"/>
        <id>https://www.wykwit.pl/blog/arduino-cli/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/arduino-cli/">&lt;p&gt;Arduino CLI is pretty convenient and definitely better than the default Arduino IDE.&lt;/p&gt;
&lt;p&gt;Documentation is here: &lt;a rel=&quot;external&quot; href=&quot;https://arduino.github.io/arduino-cli/&quot;&gt;https://arduino.github.io/arduino-cli/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Generate configuration:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli config init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add custom boards to arduino-cli.yaml by modifying the additional_urls list:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;board_manager&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;  additional_urls&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;http://digistump.com/package_digistump_index.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update index and install the core:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli core update-index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli core search digistump&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli core install digistump:avr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Identify your Fully Qualified Board Name:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli board listall&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compile and upload:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli compile -b digistump:avr:digispark-tiny sth.ino&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arduino-cli upload -b digistump:avr:digispark-tiny sth.ino&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the upload to work with digispark-tiny board you will need to install micronucleus bootloader first.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yay -S micronucleus&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In case you need it, here&#39;s a digispark troubleshooting page:
&lt;a rel=&quot;external&quot; href=&quot;http://digistump.com/wiki/digispark/tutorials/linuxtroubleshooting&quot;&gt;http://digistump.com/wiki/digispark/tutorials/linuxtroubleshooting&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AIDE</title>
        <published>2022-05-05T00:00:00+00:00</published>
        <updated>2022-05-05T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/aide/"/>
        <id>https://www.wykwit.pl/blog/aide/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/aide/">&lt;p&gt;AIDE stands for Advanced Intrusion Detection Environment and it keeps track of system integrity by holding a database of file details. This can help you catch unauthorized file modifications and other tampering attempts which could be caused by malware, misbehaving software or bad actors on your server.&lt;/p&gt;
&lt;p&gt;The weak point of this solution is the dependence on trusted AIDE database. It is created with the initial scan, so if your system has been infected beforehand - AIDE will be of no help.&lt;/p&gt;
&lt;p&gt;The database should be updated periodically to keep single check runs nice and clean. Keeping track of the AIDE database integrity is on the administrator. It is still much easier to track integrity of only one file by hand instead of the whole system, so AIDE turns out to be quite useful nonetheless.&lt;/p&gt;
&lt;p&gt;On Debian the default main configuration is located at &lt;code&gt;/etc/aide/aide.conf&lt;/code&gt; with more configuration files under &lt;code&gt;/etc/aide/aide.conf.d/&lt;/code&gt;. Database locations are defined in the main configuration file. These paths are not baked into the binary, so you have to pass a &#39;--config&#39; parameter when using AIDE on Debian.&lt;/p&gt;
&lt;p&gt;On Arch Linux the default configuration is located at &lt;code&gt;/etc/aide.conf&lt;/code&gt; and the path is automatically recognized.
You can confirm default locations with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ aide --version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re using Arch Linux instead of Debian, simply omit the &lt;code&gt;--config&lt;/code&gt; parameter in the commands below.&lt;/p&gt;
&lt;p&gt;To initiate the database:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ aide --config /etc/aide/aide.conf --init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will perform initial scan and drop a new database file.
Updates work similarly, but they will produce a longer report, because they also run checks.&lt;/p&gt;
&lt;p&gt;Every time you update the database you have to manually replace the old version with the new one. For Debian:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mv /var/lib/aide/aide.db{.new,}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To perform the update:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ aide --config /etc/aide/aide.conf --update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To run a check you can issue:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ aide --config /etc/aide/aide.conf --check | tee aide.out&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output might be longer than you think, but you can inspect the &lt;code&gt;aide.out&lt;/code&gt; file later.&lt;/p&gt;
&lt;p&gt;Every action outputs multiple hashes of your database.
AIDE will check the integrity of your files, but the database it uses must be trusted.
Makes sure these checksums don&#39;t change unexpectedly, as it is crucial for the integrity.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>CBC bitflip</title>
        <published>2021-12-30T00:00:00+00:00</published>
        <updated>2021-12-30T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/cbc-bitflip/"/>
        <id>https://www.wykwit.pl/blog/cbc-bitflip/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/cbc-bitflip/">&lt;p&gt;Advanced Encryption Standard (AES) is a well-known encryption standard and a common name for the symmetric block cipher called Rijndael - originally named after the surnames of researchers who proposed it: Joan Daemen and Vincent Rijmen.&lt;/p&gt;
&lt;p&gt;The core encryption algorithm can be applied to blocks of 128 bits with a key of 128, 192, 256 bits. Besides the core encryption algorithm there are multiple modes of operation, which define how to apply the algorithm to multiple blocks. Let&#39;s have a quick look at two very basic ones.&lt;/p&gt;
&lt;p&gt;Electronic Code Book (ECB) mode is the simplest. Plaintext is split into blocks and each one of them is encrypted in the same way. &quot;ECB Penguin&quot; image shows very well why this is not ideal. Two blocks of plaintext that are the same will give the same output. If we can control some part of the input and we can see the encryption output, we can recover parts of the plaintext without knowing the key. By carefully aligning blocks we can guess and match the encrypted part character by character.&lt;/p&gt;
&lt;p&gt;Cipher Block Chaining (CBC) mode is only slightly more complicated. In this mode each block of plaintext is XOR-ed with previous ciphertext before encryption. IV is the initialization vector. The scheme looks something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_1 ^ IV)  ---[block encryption]---&amp;gt; C_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_2 ^ C_1) ---[block encryption]---&amp;gt; C_2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_3 ^ C_2) ---[block encryption]---&amp;gt; C_3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_n ^ C_(n-1)) ---[block encryption]---&amp;gt; C_n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has an interesting property. Again, if we control some part of the input and we can see the encryption output, we can manipulate the decryption output by modifying the ciphertext without knowing the key.&lt;/p&gt;
&lt;p&gt;Let M be the malicious input.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;encryption:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_1 ^ IV)  ---[block encryption]---&amp;gt; C_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_2 ^ C_1) ---[block encryption]---&amp;gt; C_2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_3 ^ C_2) ---[block encryption]---&amp;gt; C_3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(P_4 ^ C_3) ---[block encryption]---&amp;gt; C_4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;modification:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C_2 ^ M = C_M&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ciphertext:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[C_1, C_M, C_3, C_4]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;decryption:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C_1 ---[block decryption]---&amp;gt; (P_1 ^ IV) ---[^ IV]---&amp;gt; P_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C_M ---[block decryption]---&amp;gt; (block of random bullshit)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C_3 ---[block decryption]---&amp;gt; (P_3 ^ C_2) ---[^ C_M]---&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; (P_3 ^ C_2 ^ C_M) = (P_3 ^ C_2 ^ (C_2 ^ M)) = P_3 ^ M = P_M&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C_4 ---[block decryption]---&amp;gt; (P_4 ^ C_3) ---[^ C_3]---&amp;gt; P_4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have modified some block of plaintext.&lt;/p&gt;
&lt;p&gt;If we can also control the IV we can fix up the blocks we&#39;ve broken on the way. Oftentimes we don&#39;t care though. You may hit some unfortunate bytes once the block of garbage decrypts, but sometimes it&#39;s enough to resolve it by messing with the block some more instead of fixing up the decryption output all the way.&lt;/p&gt;
&lt;p&gt;This attack is pretty simple in principle, the harder part is to find where exactly to apply it.&lt;/p&gt;
&lt;p&gt;I&#39;ll just hint that there are more attacks on this mode of operation.
An interesting example is a padding oracle attack, but that&#39;s a topic for another post.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Partitioning</title>
        <published>2021-10-11T00:00:00+00:00</published>
        <updated>2021-10-11T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/partitioning/"/>
        <id>https://www.wykwit.pl/blog/partitioning/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/partitioning/">&lt;p&gt;Partitioning is the most tedious part of the OS installation process. Everything else is either very fast to set up or can easily be automated. Even with declarative systems, they mostly assume you already have prepared your hard drives before applying the configuration. Partitioning cannot be mutated as easily as configuration, therefore it requires proper planning and a lot of attention. I tend to think about it more than I should.&lt;/p&gt;
&lt;p&gt;Needless to say, I want my stuff encrypted. My basic setup follows this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS&quot;&gt;https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With coreboot (or libreboot) I can encrypt the entire drive without leaving the boot partition readable. My GRUB payload has LUKS and LVM support compiled in. It can decrypt the drive and boot straight away or load another GRUB config file from the decrypted drive.&lt;/p&gt;
&lt;p&gt;Check out guides on Libreboot&#39;s website before commit 48b04d0993 to see how that&#39;s done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://notabug.org/libreboot/lbwww/src/8844c201ef0d1ab856fed2aa5148b89100fffe0d/site/docs/gnulinux&quot;&gt;https://notabug.org/libreboot/lbwww/src/8844c201ef0d1ab856fed2aa5148b89100fffe0d/site/docs/gnulinux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The parabola one was especially helpful when I was first setting it up. Currently it is available here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.parabola.nu/Installing_Parabola_on_Libreboot_with_full_disk_encryption_(including_/boot)&quot;&gt;https://wiki.parabola.nu/Installing_Parabola_on_Libreboot_with_full_disk_encryption_(including_/boot)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately not all my machines are officially supported by the coreboot project. In such a case the UEFI boot must suffice. That usually means leaving out an unencrypted EFI boot partition which makes the GRUB config and possibly the kernel vulnerable to tampering. Unless we also properly set up Secure Boot... I won&#39;t.&lt;/p&gt;
&lt;p&gt;Just be wary - when someone gains physical access to the machine, although they won&#39;t be able to read the valuable content of the drive right away, they could still do a lot of harm. If that happens to you - do not boot from that drive again. Boot from some other safe media, nuke all readable content on the drive, then regenerate it from within the system.&lt;/p&gt;
&lt;p&gt;We will use fdisk cli for partitioning, however if you prefer a graphical utility - GParted is a nice one.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ fdisk /dev/sda&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we choose &quot;g&quot; to create new GPT partition label, then &quot;n&quot; to create a new partition. The boot partition should span a few hundred MB (300M should be enough). Use &quot;t&quot; to change it&#39;s type to &quot;EFI System&quot; - option 1. Next is the general partition for LUKS which should cover all available space left on the drive. Write changes with &quot;w&quot;.&lt;/p&gt;
&lt;p&gt;Format the boot partition with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mkfs.fat -F32 /dev/sdxY&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Format the general LUKS partition with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cryptsetup -v --iter-time 600 --type luks1 luksFormat /dev/sdXY&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The type flag was needed for GRUB compatibility. If your bootloader is fresh and shiny you may skip it. The iteration time is set to 2 seconds by default. I prefer to set it lower, like 600ms in the example above.&lt;/p&gt;
&lt;p&gt;Options and defaults are described here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Dm-crypt/Device_encryption#Encryption_options_for_LUKS_mode&quot;&gt;https://wiki.archlinux.org/title/Dm-crypt/Device_encryption#Encryption_options_for_LUKS_mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basic LVM setup:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cryptsetup luksOpen /dev/sdxY cryptlvm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pvcreate /dev/mapper/cryptlvm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ vgcreate vgrp /dev/mapper/cryptlvm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ lvcreate -l 100%FREE vgrp -n root&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mkfs.ext4 /dev/vgrp/root&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point you can mount your partitions and install the system or whatever.
In the end we get to something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drive -&amp;gt; LUKS -&amp;gt; LVM -&amp;gt; ext4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to tell our kernel how to deal with this. Therefore in &lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt; we set:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run mkinitcpio:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mkinitcpio -P&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also need to set kernel parameters:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; cryptdevice=UUID=[device-UUID]:cryptlvm root=/dev/vgrp/root&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How to do that depends on a bootloader. For GRUB we can simply modify grub.cfg (on the boot partition or in cbfs).
For systemd-boot we would put those parameters on the &quot;options&quot; line of a proper &lt;code&gt;/boot/loader/entries/*.conf&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Of course we can use something else instead of the good old ext4 filesystem. My first pick would be btrfs which offers some cool features like subvolumes and snapshots. I don&#39;t feel like fully explaining it now though (maybe in a btrfs post?). Long story short - subvolumes could suffice for partitions and the LVM layer may not be needed, since btrfs is flexible enough by itself.&lt;/p&gt;
&lt;p&gt;For automatic snapshots on btrfs:
Snapshot destination should be in a different subvolume than the directory you are snapshotting.
I also highly recommend putting /home on a different subvolume or on a different partition altogether.
Therefore you need at least 3 subvolumes: root, home, snapshots. Snapshot root and home separately.
Check out snapper and snap-pac (both available in Arch Linux community repo).&lt;/p&gt;
&lt;p&gt;Here&#39;s an example of kernel parameters for root on a btrfs subvolume:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; cryptdevice=[device-partition]:cryptroot root=/dev/mapper/cryptroot rootfstype=btrfs rootflags=subvol=/@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you decrypt with coreboot payload, you may want to add a keyfile and additional kernel parameters. This should be described in at least one of the articles I linked at the top.&lt;/p&gt;
&lt;p&gt;Some people also like to partition off swap space, although you can simply use a swapfile. This is not necessary, but if you&#39;ll want to hibernate your system or you&#39;ve ever run out of RAM - look into setting up swap next.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>epnel algo</title>
        <published>2021-10-05T00:00:00+00:00</published>
        <updated>2021-10-05T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/epnel-algo/"/>
        <id>https://www.wykwit.pl/blog/epnel-algo/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/epnel-algo/">&lt;p&gt;Recently I had a technical interview for a junior positon with a following task: given a string, find the length of the longest substring without repeating characters. Fairly simple, but due to stress I wasn&#39;t able to properly solve it and completely failed the interview as a result. The problem and it&#39;s solutions are described here:
&lt;a rel=&quot;external&quot; href=&quot;https://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/&quot;&gt;https://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make up for that epic fail I decided to implement the solution in my own esoteric language that I wrote sometime in high-school - epnel. Below is a valid Python solution, adapted for easy translation.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;abcabcbbc&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;abcabcbbacbd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;ddabcdedd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;for&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; in&lt;/span&gt;&lt;span&gt; inputs&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	d&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;font-style: italic;&quot;&gt; dict&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	for&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; c&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color: #FAB387;font-style: italic;&quot;&gt; enumerate&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;		if&lt;/span&gt;&lt;span&gt; c&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; in&lt;/span&gt;&lt;span&gt; d&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			nb&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;			if&lt;/span&gt;&lt;span&gt; nb&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; nb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;		d&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		nr&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;		if&lt;/span&gt;&lt;span&gt; nr&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; nr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FAB387;font-style: italic;&quot;&gt;	print&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find the epnel language on my GitLab: &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.com/wykwit/epnel&quot;&gt;https://gitlab.com/wykwit/epnel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The curiosity that is epnel was also written in Python, but it doesn&#39;t provide much IO functionality. For that purpose, we can use the host language again.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;import&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;abcabcbbc&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;abcabcbbacbd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;ddabcdedd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# convert input string to an integer for epnel to handle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;convert_input&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; lambda&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;font-style: italic;&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;from_bytes&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;font-style: italic;&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;big&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# main epnel code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;algorithm&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;= 0 &lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# apply algorithm to each input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;for&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; in&lt;/span&gt;&lt;span&gt; inputs&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	s&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; algorithm&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;convert_input&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	p&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;Parser&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;	# and because we want to have a clean start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span&gt;interpreter&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span&gt;symbol_table&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;clear&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	r&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;interpret&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FAB387;font-style: italic;&quot;&gt;	print&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mind that it doesn&#39;t matter whether we traverse the string from the beggining or from the end - we should get the same result, therefore endianness in our conversion shouldn&#39;t matter. What we need now is an actual algorithm to plug into the code above. Let&#39;s start off with a simple example and translate the loop first.&lt;/p&gt;
&lt;p&gt;All variables (previously undefined symbols) have a value of zero by default. Our sample input string translates to 1796423792463439880801, we can set it like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. in 1796423792463439880801&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are no indentation rules in epnel. Sometimes I myself am not sure what would make most sense. The only requirement is that all parameters should be separated with at least a single whitespace, everything else is up to the programmer. I try to make my examples clean, but it&#39;s perfectly fine to simply have everything in a single line.&lt;/p&gt;
&lt;p&gt;Once we have a loop, we would want that loop to execute some body. For now we can simply count the number of iterations to make sure our loop works right.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;, body . r + r 1 !&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the actual loop would look something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;, loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ? &amp;gt; in 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | . c &amp;amp; in 255&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | . i + i 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | . in / in 256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | loop !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  loop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define a loop and call it in the last parameter of the definition. First statement we execue is a check on whether there is still some input to handle. This condition will end recursion. Then we assign current character to a variable and execute our body. Before we recursively call the loop again, we increment our loop counter and remove the character we&#39;ve just looked at. Finally we finish the loop off with a couple of exclamation marks to fill remaining parameters with boolean false.&lt;/p&gt;
&lt;p&gt;We can chain these three blocks with ampersands (binary and) and wrap with another binary or to get a clean result.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| &amp;amp; . in 1796423792463439880801&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;amp; , body . r + r 1 !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;amp; , loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ? &amp;gt; in 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | . c &amp;amp; in 255&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | . i + i 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | . in / in 256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | loop !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save the file as loop.e and we get a following result when we run it.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ epnel loop.e &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our input string consists of 9 characters, so this matches our expectations. Apparently the loop works.&lt;/p&gt;
&lt;p&gt;We can now move on to translate the loop&#39;s body, which consists of a conditional statement and a few assignments. This is simple enough, but in our reference we are using a dictionary (hashmap) which doesn&#39;t have an obvious translation to epnel. Since we deal with characters that fit in one byte, we don&#39;t really need a dictionary (hashmap) - an array should suffice. Still, how do we solve this in epnel? We can use regular assignments and the (most confusing) epnel dereference operator. Assignments in epnel could overwrite numeric values and additionally confuse some code (which is awesome btw). Just to stay on the safe side, we can denote a variable to be our offset into negative numbers, which are not used in the algorithm.&lt;/p&gt;
&lt;p&gt;For more details on assignments check out README in the epnel repo. Dereference is called &quot;number reassignment&quot;. Play around with the REPL a little to figure out how exactly it works.&lt;/p&gt;
&lt;p&gt;In the end - the body translates neatly.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;, body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | ? = : + d c 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ! &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | . nb + : + d c 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ? &amp;gt; nb b . b nb !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | . + d c i&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | | . nr + - i b 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ? &amp;gt; nr r . r nr !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final solution takes way more than 10 LOC and is more complex in practice, but theoreticaly the underlaying algorithm is also linear (and it looks cool).&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;import&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;abcabcbbc&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;abcabcbbacbd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;ddabcdedd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# convert input string to an integer for epnel to handle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;convert_input&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; lambda&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;font-style: italic;&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;from_bytes&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;font-style: italic;&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;big&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# main epnel code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;algorithm&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;| &amp;amp; | . in &lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    | . d - ! 9999&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  &amp;amp; , body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | ? = : + d c 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        ! &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        | . nb + : + d c 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;          ? &amp;gt; nb b . b nb !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | . + d c i&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | | . nr + - i b 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;          ? &amp;gt; nr r . r nr !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  &amp;amp; , loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      ? &amp;gt; in 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | . c &amp;amp; in 255&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | . i + i 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | . in / in 256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      | loop !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;      !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# apply algorithm to each input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;for&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; in&lt;/span&gt;&lt;span&gt; inputs&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	s&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; algorithm&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;convert_input&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	p&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;Parser&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;	# and because we want to have a clean start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span&gt;interpreter&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span&gt;symbol_table&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;clear&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	r&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;/span&gt;&lt;span&gt; epnel&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;interpret&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FAB387;font-style: italic;&quot;&gt;	print&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks even more cool when you get rid of indendation and rename variables that are too descriptive.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:) | &amp;amp; . x 1796423792463439880801 &amp;amp; . d - ! 9999 &amp;amp; , l ? &amp;gt; x 0 | . c &amp;amp; x 255 | | ? = : + d c 0 ! | . _b + : + d c 1 ? &amp;gt; _b b . b _b ! | . + d c i | ? &amp;gt; + - i b 1 r . r + - i b 1 ! ! | . i + i 1 | . x / x 256 | l ! ! l ! r &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s how problem-solving in epnel works. That is, if you can come up with the algorithm on time, of course.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>email regex</title>
        <published>2019-12-19T00:00:00+00:00</published>
        <updated>2019-12-19T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/email-regex/"/>
        <id>https://www.wykwit.pl/blog/email-regex/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/email-regex/">&lt;p&gt;email regex - when you need to find email addresses in a long document or validate html forms&lt;/p&gt;
&lt;p&gt;This was also one of &lt;a rel=&quot;external&quot; href=&quot;https://codein.withgoogle.com/&quot;&gt;Google Code-In&lt;/a&gt; tasks.&lt;/p&gt;
&lt;p&gt;Basic regex syntax:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\s - matches a whitespace&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;() - matched group&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[] - matches any range of characters in the brackets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[a-zA-Z0-9] – matches alphanumeric characters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[]+ - matches given range multiple times&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(L|R) – a group with alternation, matches either left or right side expressed inside the parentheses&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[]* - matches given range zero or more times&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[]? - matches given range once or not at all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;According to &lt;a rel=&quot;external&quot; href=&quot;https://tools.ietf.org/html/rfc5322#section-3.4.1&quot;&gt;RFC5322 section 3.4.1&lt;/a&gt; the e-mail address is specified as follows (in ABNF):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;addr-spec      =    local-part &amp;quot;@&amp;quot; domain&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;local-part     =    dot-atom / quoted-string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;domain         =    dot-atom / domain-literal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;domain-literal =    [CFWS] &amp;quot;[&amp;quot; *([FWS] dtext) [FWS] &amp;quot;]&amp;quot; [CFWS]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dtext          =    %d33-90 / %d94-126 ; printable ASCII not including &amp;quot;[&amp;quot;, &amp;quot;]&amp;quot;, or &amp;quot;\&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The obsolete alternate parts were omitted.&lt;/p&gt;
&lt;p&gt;dot-atom may not begin with a dot, it consists of:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;any alphanumeric character or any of &amp;quot;!#$%&amp;amp;&amp;#39;*+-/=?^_`{|}~.&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Domain name syntax is specified elsewhere,
for simplicity let&#39;s assume only alphanumeric characters and dashes are allowed in domain-names.
Domain names may also consist of subdomains, so we should match dots too.
quoted-strings in a local-part of the email address
and domain-literal in the domain part is rarely used, especially in web-forms etc.&lt;/p&gt;
&lt;p&gt;In practice matching a following pattern should be sufficient (in EBNF):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;email-address =    dot-atom, &amp;quot;@&amp;quot;, domain&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;domain        =    alphanumeric, {[&amp;quot;.&amp;quot; | &amp;quot;-&amp;quot;], alphanumeric}, &amp;quot;.&amp;quot;, alphanumeric, {alphanumeric}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dot-atom      =    (legal-char - &amp;quot;.&amp;quot;), {legal-char}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;legal-char    =    alphanumeric | ? any of &amp;quot;!#$%&amp;amp;&amp;#39;*+-/=?^_`{|}~.&amp;quot; ?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore a following regex should match most of e-mail address names in a practical scenario:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;([#-&amp;#39;\/-9A-Z^-~!*+=?-][#-&amp;#39;--9A-Z^-~!*+=?]*@[a-zA-Z0-9]([.-]?[a-zA-Z0-9]+)*\.[a-zA-Z]+)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some additional explanations regarding this regex:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@&lt;/code&gt; - matches a literal &quot;@&quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\.&lt;/code&gt; - matches a literal &quot;.&quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a-zA-Z0-9-.]+&lt;/code&gt; - matches any alphanumeric character, &quot;.&quot; or &quot;-&quot; multiple times (to get the domain name and subdomain names)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first part matches a dot-atom (any legal character excluding a dot followed by any number of legal characters).
Parts are separated by a &quot;@&quot;.
Then the second part matches alphanumeric characters divided by dots or dashes.
The string must end with alphanumeric top-level domain.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ARP</title>
        <published>2019-12-18T00:00:00+00:00</published>
        <updated>2019-12-18T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/arp/"/>
        <id>https://www.wykwit.pl/blog/arp/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/arp/">&lt;p&gt;ARP stands for Address Resolution Protocol. It&#39;s purpose is to resolve IP addresses in local networks (LAN) to MAC addresses used for direct communication. Every network card has a unique MAC address, so it&#39;s convenient to know which hardware you are supposed to communicate with, when you&#39;re addressing some IP.&lt;/p&gt;
&lt;p&gt;It&#39;s analogous to DNS, but on a lower level. DNS resolves domain names to IP addresses - it works both in LAN and in the Wild Internet. ARP resolves IP addresses to MAC addresses, but from what I know it is used in LAN only. It doesn&#39;t make much sense to use MAC addresses outside of LAN, because you can&#39;t access hardware that is not in the range of your antenna. Therefore IP&#39;s usually suffice.&lt;/p&gt;
&lt;p&gt;If we want to mess with our LAN, it makes sense to mess with MAC addresses too. Computers usually resolve IP&#39;s on LAN by first looking through their local ARP table. If the target is not found, they send an ARP request to the broadcast address that looks somewhat like &quot;Who has 192.168.50.69? Tell 192.168.50.143&quot;. Every computer on the network is subscribed to the broadcast, so then the holder of the IP would respond to us directly: &quot;192.168.50.69 is at [MAC addr]&quot;. This is all we need to know to start a communication.&lt;/p&gt;
&lt;p&gt;This is also how scanning for IP&#39;s on LAN works.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ nmap -sP 192.168.1.1/24&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;/img/blog/arp/arp-flood-wireshark.webp&quot; title=&quot;full size&quot;&gt;&lt;img src=&quot;https://www.wykwit.pl/processed_images/arp-flood-wireshark.4f1c66211440c40f.webp&quot; srcset=&quot;https://www.wykwit.pl/processed_images/arp-flood-wireshark.4f1c66211440c40f.webp 720w, https://www.wykwit.pl/processed_images/arp-flood-wireshark.4bd9a86baea2d884.webp 866w&quot; sizes=&quot;(min-width: 40rem) min(64rem, 100vw - 2.5rem), calc(100vw - 2rem)&quot; width=&quot;866&quot; height=&quot;421&quot; alt=&quot;ARP flood in WireShark&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you issue this command, nmap floods your network with ARP requests for every possible IP in your specified range.
Sooner or later someone will respond.
Blocking ARP requests usually breaks TCP/IP connection, so there&#39;s a high chance victim machine would reply.&lt;/p&gt;
&lt;p&gt;Let&#39;s see if we can somehow manipulate ARP.
For that purpose we will use &lt;a rel=&quot;external&quot; href=&quot;https://sectools.org/tool/dsniff/&quot;&gt;dsniff&lt;/a&gt;,
which includes tools like arpspoof or dnsspoof.
To demonstrate how this works I&#39;ve MITM&#39;ed my friend&#39;s laptop.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/img/blog/arp/mitm-laptop.webp&quot; title=&quot;full size&quot;&gt;&lt;img src=&quot;https://www.wykwit.pl/processed_images/mitm-laptop.ae06299496317b0a.webp&quot; srcset=&quot;https://www.wykwit.pl/processed_images/mitm-laptop.ae06299496317b0a.webp 720w, https://www.wykwit.pl/processed_images/mitm-laptop.55349b78eb95e263.webp 1280w&quot; sizes=&quot;(min-width: 40rem) min(64rem, 100vw - 2.5rem), calc(100vw - 2rem)&quot; width=&quot;1280&quot; height=&quot;960&quot; alt=&quot;Successful MITM attack on a friend&#39;s laptop&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On the photo you can see my laptop sending out malicious packets
and my friend&#39;s laptop displaying attacker-controlled website when they try to access a legitimate domain.
Now how did we pull this off? It&#39;s actually very simple.&lt;/p&gt;
&lt;p&gt;First we need to know the IP of our victim and our gateway.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip a show dev wlp2s0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or on windows simply:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ipconfig&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are on the same network, so we can execute the attack.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ arpspoof -i wlp2s0 -t 10.14.75.17 -r 10.14.72.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where 10.14.75.17 is my friend&#39;s IP and 10.14.72.1 is the gateway.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/img/blog/arp/arpspoof.webp&quot; title=&quot;full size&quot;&gt;&lt;img src=&quot;https://www.wykwit.pl/processed_images/arpspoof.40a4490e204f8ce9.webp&quot; srcset=&quot;https://www.wykwit.pl/processed_images/arpspoof.40a4490e204f8ce9.webp 720w, https://www.wykwit.pl/processed_images/arpspoof.500419f1d8c0bb5c.webp 803w&quot; sizes=&quot;(min-width: 40rem) min(64rem, 100vw - 2.5rem), calc(100vw - 2rem)&quot; width=&quot;803&quot; height=&quot;561&quot; alt=&quot;Running arpspoof&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It seems to work. The gateway thinks we are the victim computer and victim treats our computer as the gateway. We&#39;ve fooled them. The connection now goes from the victim computer to our machine instead of the real gateway. This is called a man-in-the-middle (MITM) attack, because our machine is now in the middle of the connection between victim and the internet. The technique used is known as ARP spoofing or ARP poisoning, because we&#39;ve spoofed some ARP requests to poison the ARP table of victim and gateway, and redirect their traffic through our machine.&lt;/p&gt;
&lt;p&gt;Here&#39;s a nice &lt;a rel=&quot;external&quot; href=&quot;https://commons.wikimedia.org/wiki/File:ARP_Spoofing.svg&quot;&gt;graph from Wikipedia&lt;/a&gt; to visualise how the connection looks like during the attack.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/img/blog/arp/arp-poisoning-graph.webp&quot; title=&quot;full size&quot;&gt;&lt;img src=&quot;https://www.wykwit.pl/processed_images/arp-poisoning-graph.cbe4d1b2c3691f39.webp&quot; srcset=&quot;https://www.wykwit.pl/processed_images/arp-poisoning-graph.cbe4d1b2c3691f39.webp 720w, https://www.wykwit.pl/processed_images/arp-poisoning-graph.44fdeb760b672110.webp 1005w&quot; sizes=&quot;(min-width: 40rem) min(64rem, 100vw - 2.5rem), calc(100vw - 2rem)&quot; width=&quot;1005&quot; height=&quot;768&quot; alt=&quot;ARP poisoning graph from Wikipedia&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the sake of demonstration we set up a simple website.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ vim index.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ python2 -m SimpleHTTPServer 80&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And spoof DNS, so that example.com points to our IP address.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ echo &amp;quot;10.14.75.206\texample.com&amp;quot; &amp;gt;&amp;gt; hosts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ dnsspoof -i wlp2s0 -f hosts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when we go to example.com from the victim computer,
we ask our gateway what is the IP of example.com.
We act as the gateway, so we repond with our own IP address.
The victim goes to our IP instead of the real one and sees our website.&lt;/p&gt;
&lt;p&gt;As you can see, arpspoof attack is really powerfull.
In the MITM scenario we can sniff and manipulate victim&#39;s traffic however we want.
Hopefully you now understand the principle of how this attacks work.&lt;/p&gt;
&lt;p&gt;This post was made for &lt;a rel=&quot;external&quot; href=&quot;https://codein.withgoogle.com/&quot;&gt;Google Code-In&lt;/a&gt; and screenshots were requested as a part of the task.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>fcitx-mozc</title>
        <published>2019-11-30T00:00:00+00:00</published>
        <updated>2019-11-30T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/fcitx-mozc/"/>
        <id>https://www.wykwit.pl/blog/fcitx-mozc/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/fcitx-mozc/">&lt;p&gt;There is a difference between an input source (keyboard layout) and an input method. When you browse your DE settings, they only really let you change the input source. If you&#39;d want to type in Japanese for example, even if you change your input source to JP it only changes the keyboard layout. You needn&#39;t mess with the settings in that regard. All you have to do is change your input method. Perhaps you already know: to type in Japanese, you need a &quot;Japanese IME&quot;. Fcitx is an input method framework and Mozc is a Japanese Input Method Editor. Plug Mozc into Fcitx and you&#39;ll be good to go.&lt;/p&gt;
&lt;p&gt;The ArchWiki article on fcitx is way too long: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/index.php/Fcitx&quot;&gt;https://wiki.archlinux.org/index.php/Fcitx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And the article on Mozc refers to the previous one: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/index.php/Mozc&quot;&gt;https://wiki.archlinux.org/index.php/Mozc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The setup is not even that complicated, it just looks like a lot of work.
Here&#39;s what you really have to do:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pacman -S fcitx-im fcitx-mozc fcitx-configtool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cp /etc/xdg/autostart/fcitx-autostart.desktop ~/.config/autostart/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gtk-query-immodules-3.0 --update-cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gtk-query-immodules-2.0 --update-cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ echo &amp;quot;GTK_IM_MODULE=fcitx\nQT_IM_MODULE=fcitx\nXMODIFIERS=@im=fcitx&amp;quot; &amp;gt;&amp;gt; ~/.pam_environment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure you have installed necessary fonts for your language:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pacman -S otf-ipafont ttf-hanazono&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, open up fcitx-configtool and under &quot;Input Method&quot; tab press the little &quot;+&quot; icon in the bottom left corner. Uncheck the &quot;Only Show Current Language&quot; checkbox and search for &quot;Mozc&quot;. Choose it and confirm with the &quot;OK&quot; button. I don&#39;t usually like GUI tools, but that one is quite handy &amp;amp; quick. You may explore other options too.&lt;/p&gt;
&lt;p&gt;Everything should work properly once you relogin.&lt;/p&gt;
&lt;p&gt;The default shortcut for changing between input methods in fcitx is Ctrl+Space. If you&#39;re normally typing in English, but want to write something in Japanese, you would just press Ctrl+Space, write whatever you want with mozc in Japanese, and then press Ctrl+Space again to get back to your default keyboard setup.&lt;/p&gt;
&lt;p&gt;簡単ですね&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>EBNF</title>
        <published>2019-11-20T00:00:00+00:00</published>
        <updated>2019-11-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/ebnf/"/>
        <id>https://www.wykwit.pl/blog/ebnf/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/ebnf/">&lt;p&gt;BNF stands for Backus-Naur Form which is a notation (or you could say: a metasyntax language) designed for description of &lt;i&gt;context-free grammars&lt;/i&gt;.
Many extensions and augmentations exist like EBNF (Extended BNF), ABNF (Augmented BNF) or TBNF (Translational BNF).&lt;/p&gt;
&lt;p&gt;EBNF is the easiest one to read for humans.
Another interesting one is a more complex TBNF,
I&#39;d say it&#39;s an Extended BNF Extended - it lets you define a structure of the Abstract Syntax Tree and the output Intermediate Code.
Seems powerful, but personally I didn&#39;t delve into it; for now EBNF will make do.&lt;/p&gt;
&lt;p&gt;It generally is a useful tool for language and protocol specification description.
You can even use *BNF flavours to generate lexers and parsers automatically (see: &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Yacc&quot;&gt;Yacc&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;EBNF is more or less defined like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Notation   Description&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    =     - definition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ,     - concatenation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ;     - termination of an expression&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |     - alternation (OR)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; [ ... ]  - option, element may be present once or not at all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; { ... }  - repetition, element omited or repeated&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ( ... )  - grouping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;quot; ... &amp;quot;  - literal strings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; (*   *)  - comments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ? ... ?  - special sequence, describes something outside of the EBNF grammar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -     - exception, can be used to exclude something from a rule&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    *     - literal repetition (assert 4*&amp;quot;A&amp;quot; == &amp;quot;AAAA&amp;quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&#39;s a wikipedia article with some examples: &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form#Examples&quot;&gt;https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form#Examples&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another great practical example is the Go Programming Language Specification: &lt;a rel=&quot;external&quot; href=&quot;https://golang.org/ref/spec&quot;&gt;https://golang.org/ref/spec&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go&#39;s formal specification played a huge part in the programming language&#39;s adoption and even before that - it was crucial for the first implementation.&lt;/p&gt;
&lt;p&gt;Reading *BNF is quite intuitive. Writing it, however, is a tedious task.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Coreboot</title>
        <published>2019-07-03T00:00:00+00:00</published>
        <updated>2019-07-03T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/coreboot/"/>
        <id>https://www.wykwit.pl/blog/coreboot/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/coreboot/">&lt;p&gt;Last time I wrote about libreboot updating, this time I&#39;ll write about the coreboot.&lt;/p&gt;
&lt;p&gt;The difference between coreboot and libreboot is that the open-source coreboot may need some binary blobs to run properly on some devices, while libreboot embraces the GNU free-software philosophy and refuses to run anything proprietary. Needless to say, coreboot supports way more devices than libreboot. See the &lt;a rel=&quot;external&quot; href=&quot;https://www.coreboot.org/&quot;&gt;coreboot.org&lt;/a&gt; website for more info.&lt;/p&gt;
&lt;p&gt;I was working with a ThinkPad X220, but the overall process is usually the same. You&#39;ll need some way to reprogram the SOIC chip with the firmware. On an X220 the firmware resides on a SOIC-8 chip to which you can connect with a SOIC clip like Pamona 5250 or similar. On the other end of the wire you connect a flasher, for example a RaspberryPi (that&#39;s what I used). Long story short: disassemble your laptop, find a proper chip on your motherboard, connect it with a clip to the RaspberryPi GPIO, then you can flash. The coreboot wiki will tell you where on your motherboard the chip is located. Don&#39;t get confused: &quot;SOIC clip, SOIC flasher, SPI flasher, SPI programmer&quot; are all just fancy words for the same, basically.&lt;/p&gt;
&lt;p&gt;The best guide on how to do all this is: &lt;a rel=&quot;external&quot; href=&quot;https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi&quot;&gt;https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To check the GPIO pinout of your particular RaspberryPi:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pinout&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A little dot on a SOIC chip indicates pin 1, refer to the github page I linked above.&lt;/p&gt;
&lt;p&gt;For a SOIC-8, that&#39;s the connection you can use:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;pin&lt;/th&gt;&lt;th style=&quot;text-align: left&quot;&gt;desc&lt;/th&gt;&lt;th style=&quot;text-align: left&quot;&gt;RaspberryPi&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;CS&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(24) GPIO08&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;MISO&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(21) GPIO09&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;empty&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;GND&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(20) GND&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;5&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;MOSI&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(19) GPIO10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;6&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;CLK&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(23) GPIO11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;7&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;empty&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;8&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;3.3V&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;(17) 3.3 V&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;You may clean the chip with alcohol before you start. It helps with connection and let&#39;s you visually check the exact version of your chip.&lt;/p&gt;
&lt;p&gt;Make sure you&#39;ve properly connected your clip.&lt;/p&gt;
&lt;p&gt;Use the latest flashrom.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ git clone https://review.coreboot.org/flashrom.git &amp;amp;&amp;amp; cd flashrom &amp;amp;&amp;amp; make&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may have to modprobe some spi stuff. (don&#39;t quote me on this one)&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ modprobe spi-{bcm2835aux,gpio,nor}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m assuming you are using the RPi GPIO as your SPI programmer. To check the connection:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -V&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The common misconception is that you shouldn&#39;t use AC power adapter when flashing, but the truth is some chips won&#39;t power up without it. Check it out if the flashrom wierdly doesn&#39;t cooperate. Again, refer to the github page I linked above.&lt;/p&gt;
&lt;p&gt;If the connection was fine, you&#39;ll now have a list of chips your motherboard is likely using.
Confirm that with the print on the chip casing.
Dump the rom image a few times (you can use different -c value) and compare SHA2 checksums.
If they&#39;re matching, you&#39;re good to go.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -c [chip] -r test-01.img&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -c [chip] -r test-02.img&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sha256sum test-*.img&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note some informations about your chip, particularly the chip size:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -c [chip] -V&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take one of those dumps, it&#39;s your ROM backup now.
We will extract binary blobs and deactivate Intel ME with a program called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/corna/me_cleaner&quot;&gt;me_cleaner&lt;/a&gt;.
You can copy that backup and do the rest on your main machine.
We will come back to the RPi when we have a coreboot rom image done and ready to flash (NOT YET).&lt;/p&gt;
&lt;p&gt;We will flash with a following command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -c [chip] -w [path/to/coreboot.rom]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you flash any coreboot image (unless explicitly set otherwise) you will be able to use the internal programmer
and apply instructions from &lt;a href=&quot;/blog/libreboot/&quot;&gt;my &quot;Libreboot updating&quot; post&lt;/a&gt; in the future; for example to change the configuration.&lt;/p&gt;
&lt;p&gt;Now, on how to build a coreboot image...
Wiki and even the download page will tell you to build from git, but that&#39;s just bullshit - it won&#39;t compile.
At least it wouldn&#39;t for me...
Instead, get the latest RELEASE from &lt;a rel=&quot;external&quot; href=&quot;https://www.coreboot.org/downloads.html&quot;&gt;coreboot.org/downloads.html&lt;/a&gt;.
Download both source and blobs, then merge folders and open up a terminal:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ make menuconfig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ make crossgcc-i386&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most important settings are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;General setup:
&lt;ul&gt;
&lt;li&gt;Allow use of binary-only repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mainboard:
&lt;ul&gt;
&lt;li&gt;Vendor: Lenovo&lt;/li&gt;
&lt;li&gt;Model: ThinkPad X220&lt;/li&gt;
&lt;li&gt;ROM chip size: 8 MB (flashrom told you that)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Chipset:
&lt;ul&gt;
&lt;li&gt;Ignore vendor programmed fuses that limit max. DRAM frequency&lt;/li&gt;
&lt;li&gt;Add Intel descriptor.bin file&lt;/li&gt;
&lt;li&gt;Add Intel ME/TXE firmware&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Generic Drivers:
&lt;ul&gt;
&lt;li&gt;PS/2 keyboard init&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Payload:
&lt;ul&gt;
&lt;li&gt;(set anything you like, but make sure you&#39;ll be able to boot when you flash the rom image)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we will need me_cleaner, you can install it from AUR:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -S me_cleaner-git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s add the blobs and neutralize Managment Engine:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ me_cleaner -Srtd [path/to/clean_rom.img] -D [descriptor.bin] -M [me.bin] -O [output_rom.img]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Place descriptor.bin and me.bin in your coreboot directory under &#39;3rdparty/blobs/mainboard/[vendor]/[model]/&#39; like so:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cp *.bin 3rdparty/blobs/mainboard/lenovo/x220/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should be sufficient to start a system.&lt;/p&gt;
&lt;p&gt;You might still want to add other blobs, though. For instance - Intel Gigabit Engine may be necessary for some boards to use the ethernet.&lt;/p&gt;
&lt;p&gt;Build the final image:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ make&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output is build/coreboot.rom in the coreboot directory.&lt;/p&gt;
&lt;p&gt;Copy it over to your raspberry pi and finally flash!&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ./flashrom -p linux_spi:dev=/dev/spidev0.0 -c [chip] -w [path/to/coreboot.rom]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the program prints &quot;VERIFIED&quot;, you can safely unplug the clip, assemble your machine and boot.&lt;/p&gt;
&lt;p&gt;Rebuild coreboot as many times as you like, tweak and personalise to your heart&#39;s content.
Now, anytime you want to reflash coreboot, use the internal programmer - no need to disassemble your machine anymore!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>CoreWar resources</title>
        <published>2019-06-28T00:00:00+00:00</published>
        <updated>2019-06-28T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/corewar-resources/"/>
        <id>https://www.wykwit.pl/blog/corewar-resources/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/corewar-resources/">&lt;p&gt;CoreWar is a fascinating game. I don&#39;t have enough knowledge nor time to write a proper post about it, but I&#39;ve had this list of resources lying around on my hard-drive for some time. From here you should depart on a journey to discover by yourself what lies beyond the core.&lt;/p&gt;
&lt;p&gt;The original articles written by the game author:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.koth.org/info/akdewdney/First.htm&quot;&gt;http://www.koth.org/info/akdewdney/First.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.koth.org/info/akdewdney/Second.htm&quot;&gt;http://www.koth.org/info/akdewdney/Second.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.koth.org/info/akdewdney/Third.htm&quot;&gt;http://www.koth.org/info/akdewdney/Third.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.koth.org/info/akdewdney/Last.htm&quot;&gt;http://www.koth.org/info/akdewdney/Last.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some hubs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://techtinkering.com/2009/04/30/an-introduction-to-corewar/&quot;&gt;https://techtinkering.com/2009/04/30/an-introduction-to-corewar/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.atspace.com/top10.html&quot;&gt;http://corewar.atspace.com/top10.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/&quot;&gt;http://corewar.co.uk/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.corewar.info/&quot;&gt;http://www.corewar.info/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.atspace.com/&quot;&gt;http://corewar.atspace.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://labarga.atspace.com/&quot;&gt;http://labarga.atspace.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;ftp://ftp.koth.org/pub/corewar/&quot;&gt;ftp://ftp.koth.org/pub/corewar/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://vyznev.net/corewar/&quot;&gt;http://vyznev.net/corewar/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.shadowmagic.org.uk/corewar/&quot;&gt;http://www.shadowmagic.org.uk/corewar/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://users.obs.carnegiescience.edu/birk/COREWAR/&quot;&gt;https://users.obs.carnegiescience.edu/birk/COREWAR/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://moscova.inria.fr/~doligez/corewar/&quot;&gt;http://moscova.inria.fr/~doligez/corewar/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://grabun.pl/&quot;&gt;http://grabun.pl/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://inversed.ru/index.htm&quot;&gt;http://inversed.ru/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://www.corewars.org/&quot;&gt;http://www.corewars.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Warriors&#39; source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/adamowski/pzpr2.htm&quot;&gt;http://corewar.co.uk/adamowski/pzpr2.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://inversed.ru/Tiny_Stone_Challenge.htm&quot;&gt;http://inversed.ru/Tiny_Stone_Challenge.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://users.obs.carnegiescience.edu/birk/COREWAR/94/&quot;&gt;https://users.obs.carnegiescience.edu/birk/COREWAR/94/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://icl.corewar.eu/&quot;&gt;http://icl.corewar.eu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redcode references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/adamowski/pzpr3.htm&quot;&gt;http://corewar.co.uk/adamowski/pzpr3.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://vyznev.net/corewar/guide.html&quot;&gt;http://vyznev.net/corewar/guide.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/standards/icws94.htm&quot;&gt;http://corewar.co.uk/standards/icws94.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CoreWar tutorials:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/adamowski/pzpr5.htm&quot;&gt;http://corewar.co.uk/adamowski/pzpr5.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/ryba/cws88.htm&quot;&gt;http://corewar.co.uk/ryba/cws88.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/strategy.htm&quot;&gt;http://corewar.co.uk/strategy.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/biblio.htm&quot;&gt;http://corewar.co.uk/biblio.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Trivia:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/ryba/index.htm&quot;&gt;http://corewar.co.uk/ryba/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.co.uk/history.htm&quot;&gt;http://corewar.co.uk/history.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://groups.google.com/forum/#!forum/rec.games.corewar&quot;&gt;https://groups.google.com/forum/#!forum/rec.games.corewar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://codu.org/logs/_corewars&quot;&gt;http://codu.org/logs/_corewars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://corewar.eu/forum/index.php&quot;&gt;http://corewar.eu/forum/index.php&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hills:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http://sal.discontinuity.info/&quot;&gt;http://sal.discontinuity.info/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See you on the hill, warrior!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Libreboot</title>
        <published>2019-06-13T00:00:00+00:00</published>
        <updated>2019-06-13T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/libreboot/"/>
        <id>https://www.wykwit.pl/blog/libreboot/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/libreboot/">&lt;p&gt;A quick libreboot cheat-note, useful when you want to update (even if it&#39;s just your background or config).&lt;/p&gt;
&lt;p&gt;Use tools from the libreboot package, from their offcial website: &lt;a rel=&quot;external&quot; href=&quot;https://libreboot.org/&quot;&gt;libreboot.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My version is: r20160907&lt;/p&gt;
&lt;p&gt;For flashing you should boot with a following kernel parameter:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; iomem=relaxed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify flashrom (it&#39;ll tell you whether it&#39;s working properly or not):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ flashrom -p internal -V&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dump current rom:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ flashrom -p internal -r [path/to/file]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Read rom content:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cbfstool [romfile] print&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Extract file from rom:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cbfstool [romfile] extract -n [filename] -f [filename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace a file in rom:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cbfstool remove -n [filename]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cbfstool add -n [filename] -f [path/to/file] -t raw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Flash updated rom:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ flash update [path/to/rom]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s about it. If you don&#39;t have libreboot installed yet, see the installation guide and documentation first: &lt;a rel=&quot;external&quot; href=&quot;https://libreboot.org/docs/&quot;&gt;https://libreboot.org/docs/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before you install, make sure your device is on the list of supported hardware: &lt;a rel=&quot;external&quot; href=&quot;https://libreboot.org/docs/hardware/&quot;&gt;https://libreboot.org/docs/hardware/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you&#39;re not sure why you&#39;d want to run libreboot, here&#39;s a quote from the project&#39;s website:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Many people use non-free proprietary boot firmware, even if they use GNU+Linux. Non-free BIOS/UEFI firmware often contains backdoors, can be slow and have severe bugs. Development and support can be abandoned at any time. By contrast, libreboot is fully free software, where anyone can contribute or inspect its code. [...] Libreboot is faster, more secure and more reliable than most non-free firmware. Libreboot provides many advanced features, like encrypted /boot/, GPG signature checking before booting a Linux kernel and more!&quot;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Moving partitions</title>
        <published>2019-04-21T00:00:00+00:00</published>
        <updated>2019-04-21T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/moving-partitions/"/>
        <id>https://www.wykwit.pl/blog/moving-partitions/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/moving-partitions/">&lt;p&gt;Moving partitions between different disks or devices. For example: moving /home into a bigger hard-drive.&lt;/p&gt;
&lt;p&gt;First move the files. You&#39;ll need higher privilege to keep the permission settings.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cp -av [source] [dest]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or with rsync (won&#39;t copy files you already have copied), generally faster.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ rsync -aHAXv [source] [dest]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Carefully with trailing slashes, rsync uses BSD convention whilst cp uses GNU convention.&lt;/p&gt;
&lt;p&gt;That&#39;s it, if the copy (backup) was all you wanted.&lt;/p&gt;
&lt;p&gt;Now we need our new partition to be mounted instead of the old one.
We&#39;ll achieve that by modifying the &lt;code&gt;/etc/fstab&lt;/code&gt; file, which tells the system where which partitions should be mounted at boot time.
That is, assuming your partition isn&#39;t encrypted.
Then it&#39;s a whole different story and you probably already know best whether you should tinker with &lt;code&gt;/etc/fstab&lt;/code&gt; or rather &lt;code&gt;/etc/crypttab&lt;/code&gt;.
Let&#39;s have a look at our fstab first.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/fstab&lt;/code&gt; entry consists of device name or UUID, mountpoint, filesystem type, then options, dump value and pass value.
Dump value determines how often the partition should be backed-up by the &quot;dump&quot; program, which we don&#39;t use, really. Keep that 0.
Pass value is &quot;a number indicating the order in which the fsck program will check the devices for errors at boot time;
this is 1 for the root file system and either 2 (meaning check after root) or 0 (do not check) for all other devices.&quot;
More details here: &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Fstab&quot;&gt;https://en.wikipedia.org/wiki/Fstab&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This file is very important so back it up before modifying.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cp /etc/fstab /etc/fstab.old&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we have to do now is modify the proper entry. To obtain necessary information:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ lsblk -o NAME,SIZE,LABEL,UUID,MOUNTPOINT,FSTYPE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now simply edit the fstab - that&#39;s the easiest way. You could leverage genfstab utility, but that would require additional effort.
It&#39;s a good practice to leave a comment with partition name and label just above the entry.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# /dev/sda2 LABEL=home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;UUID=2d32c55e-942f-4b45-8694-07029f2583f6	/home		btrfs		defaults	0 2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it, you&#39;re done. Now reboot and if everything is working - you can delete the /etc/fstab.old backup file.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>TTY ricing</title>
        <published>2019-02-01T00:00:00+00:00</published>
        <updated>2019-02-01T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/tty-ricing/"/>
        <id>https://www.wykwit.pl/blog/tty-ricing/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/tty-ricing/">&lt;p&gt;This is just a post I saved from /g/, thread 66847569;
meaning this is not my original content.
I thought it was interesting enough to repost here,
since there wasn&#39;t many other instructions on how to do this.
Thanks, Anonymous!&lt;/p&gt;
&lt;p&gt;Anonymous Mon 23 Jul 2018 16:40:02 No.66851929:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;66851873&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--- tty ricing guide ---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- install fbsplash or splashutils depending on the distro&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- you&amp;#39;re gonna need to configure and recompile the kernel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;enable required kernel options, see https://wiki.gentoo.org/wiki/Fbsplash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ignore the rest of the article&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- install some themes you can use as templates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;splash-themes-gentoo or bootsplash-themes or fbsplash-theme-natural-arch or whatever&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;you can try out some themes like so&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;splash_manager -c set --theme=THEME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;that will set the theme on your current tty, to set the theme on another tty, use&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;splash_manager -c set --theme=THEME --tty=N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;you can&amp;#39;t apply themes that don&amp;#39;t match your resolution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- make your own theme, it&amp;#39;s ez&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;use a bg img that&amp;#39;s in your res, put it in themedir/images, name it &amp;quot;verbose-&amp;lt;your res&amp;gt;.png&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edit the file named &amp;quot;&amp;lt;your res&amp;gt;.cfg&amp;quot; in themedir appropriately&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;just use another theme as a template, you don&amp;#39;t need any guide or whatever to do this&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;if something isn&amp;#39;t obvious, look at &amp;lt;slash&amp;gt;usr/share/doc/splashutils-1.5.4.4-r7/theme_format&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- make a simple init script/systemd unit to set your login theme and tty colors on startup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(you can set a different theme in .bash_profile for post login if you want)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- setting the console (tty) font differs between distros, see your distro wiki or whatever&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- don&amp;#39;t forget to put some cool ascii in &amp;lt;slash&amp;gt;etc/issue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;here&amp;#39;s how I did it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- &amp;lt;slash&amp;gt;etc/tty_theme - file where I keep the names of the themes I&amp;#39;m using:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export TTY_LOGIN_THEME=login_theme&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export TTY_THEME=post_login_theme&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- my openrc script where I set the login theme and colors: http://ix.io/1dCa&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- relevant stuff from .bash_profile (setting the post login theme):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. &amp;lt;slash&amp;gt;etc/tty_theme&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ &amp;quot;$TERM&amp;quot; = &amp;quot;linux&amp;quot; ] &amp;amp;amp;&amp;amp;amp; [ -z $SSH_TTY ] &amp;amp;amp;&amp;amp;amp; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; sudo splash_manager -c set --theme=$TTY_THEME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- .bash_logout so when you log out it resets the login theme:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ &amp;quot;$TERM&amp;quot; = &amp;quot;linux&amp;quot; ] &amp;amp;amp;&amp;amp;amp; [ -z $SSH_TTY ] &amp;amp;amp;&amp;amp;amp; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; sudo splash_manager -c set --theme=&amp;quot;$TTY_LOGIN_THEME&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Anonymous Mon 23 Jul 2018 16:41:22 No.66851939:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;66851929&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;had to put &amp;lt;slash&amp;gt; instead of / because 4chan/cloudflare won&amp;#39;t let me post if there&amp;#39;s unix file paths&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;use this for tty scrots https://github.com/maandree/scrotty&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SQL</title>
        <published>2018-12-24T00:00:00+00:00</published>
        <updated>2018-12-24T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/sql/"/>
        <id>https://www.wykwit.pl/blog/sql/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/sql/">&lt;p&gt;Typically login with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mysql -p -u [username] [databasename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the -p flag you&#39;ll be prompted to input password; databasename is optional.&lt;/p&gt;
&lt;p&gt;To show databases available for you:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; show databases;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use the database:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; use [databasename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly you can show tables in a database:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; show tables;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And describe it&#39;s fields:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; desc [tablename];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To find out how to use mysql I highly suggest reading through MariaDB Documentation and Tutorials:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://mariadb.com/kb/en/library/documentation/&quot;&gt;https://mariadb.com/kb/en/library/documentation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://mariadb.com/kb/en/library/training-tutorials/&quot;&gt;https://mariadb.com/kb/en/library/training-tutorials/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Importing data to the database is fairly simple with well formatted input, but you need to have the database first:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; CREATE DATABASE [databasename];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Database dumps consist of executable commands, so you simply redirect the dumpfile as input:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mysql -p -u [username] [database_name] &amp;lt; [dumpfile]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have some .txt files (like on &lt;i&gt;&lt;em&gt;matura&lt;/em&gt;&lt;/i&gt;) you have to create tables yourself accordingly, and then you can load the data:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; CREATE TABLE [tablename] ([columnname] [options_and_datatype], [...]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; LOAD DATA LOCAL INFILE &amp;#39;[filename.txt]&amp;#39; INTO TABLE [tablename] COLUMNS TERMINATED BY &amp;#39;\t&amp;#39; LINES TERMINATED BY &amp;#39;\r\n&amp;#39; IGNORE 1 LINES ([columnname], @[variable], [...]) SET [columnname] = [expressions];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mind that in the second statement after the tablename you can skip the rest.&lt;/p&gt;
&lt;p&gt;Realistically you&#39;d want to create some users and grant them privileges to work on certain databases. Here&#39;s how to do it:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; CREATE USER &amp;#39;[username]&amp;#39;@&amp;#39;[host]&amp;#39; IDENTIFIED BY &amp;#39;[password]&amp;#39;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; GRANT [privilege] ON [databasename].[tablename] TO &amp;#39;[username]&amp;#39;@&amp;#39;[host]&amp;#39;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Databasename and/or tablename can be a &#39;*&#39; wildcard (for all).&lt;/p&gt;
&lt;p&gt;You can delete users just like you delete databases:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; DROP USER &amp;#39;[username]&amp;#39;@&amp;#39;[host]&amp;#39;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To show user&#39;s privileges:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; SHOW GRANTS FOR &amp;#39;[username]&amp;#39;@&amp;#39;[host]&amp;#39;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Users are saved in &#39;mysql&#39; database - table &#39;user&#39;. So to list all users:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; SELECT * FROM mysql.user;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Talking about privileges, I could explain the basic SQL syntax, but I won&#39;t.
Available privileges: SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, ALL, GRANT OPTION.
Privileges for basic queries let you execute those queries.
To learn more about privileges specifically: &lt;a rel=&quot;external&quot; href=&quot;https://mariadb.com/kb/en/library/grant/&quot;&gt;https://mariadb.com/kb/en/library/grant/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SELECT is probably the most important query. Basic syntax:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; SELECT [columnname] FROM [databasename];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Complex query:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; SELECT [columna] AS a, [columnb], [FUNC]([columnc]) AS c FROM [databasename] JOIN [otherdatabase] USING ([commoncolumnname]) WHERE [expr] GROUP BY [columnd] ORDER BY a DESC LIMIT 1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s worth mentioning that you can nest SELECT queries, just wrap them in parenthesis.&lt;/p&gt;
&lt;p&gt;At that point you might want to learn SQL syntax and database manipulation.&lt;/p&gt;
&lt;p&gt;Another important feature of SQL are built-in functions which let you execute conditional statements, manipulate data inline, etc. Example functions: SUM, COUNT, MAX, IF, LEFT, SUBSTR.&lt;/p&gt;
&lt;p&gt;MariaDB is capable of encrypting and decrypting AES and DES, it can compress and uncompress, and it can hash stuff with MD5, SHA1 and SHA2. For example:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; SELECT SHA2(&amp;quot;[VAL]&amp;quot;, [HASH_SIZE]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is all I&#39;ve wanted to write down regarding SQL.
I highly suggest you read the docs, both MariaDB and PostgreSQL are wonderfully documented (and they&#39;re both great software).
For something less specific - w3schools has a tutorial on SQL: &lt;a rel=&quot;external&quot; href=&quot;https://www.w3schools.com/sql/default.asp&quot;&gt;https://www.w3schools.com/sql/default.asp&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ATmega328P</title>
        <published>2018-12-20T00:00:00+00:00</published>
        <updated>2018-12-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/atmega328p/"/>
        <id>https://www.wykwit.pl/blog/atmega328p/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/atmega328p/">&lt;p&gt;ATmega328 is a popular microcontroller from the AVR family, it&#39;s cheap and useful - just the way we like it. It is commonly found in arduinos. Having one you can make an arduino yourself. The foundation of an arduino is it&#39;s bootloader. So... the first step to make your very own arduino is to properly plug the atmega chip and flash it with an arduino bootloader. And that&#39;s exactly what I did just a moment ago! Let me explain HOW.&lt;/p&gt;
&lt;p&gt;As always in electronics, look up the datasheet. There you can find your chip&#39;s pinout. Plug GND to GNDs and 5V in into VCC (and AVCC, and AREF) normally and to RESET through a 10k Ohm resistor. If you have a crystal plug it between the XTAL pins and then to GND through 22 pF caps. More datails here: &lt;a rel=&quot;external&quot; href=&quot;https://www.arduino.cc/en/Main/Standalone&quot;&gt;https://www.arduino.cc/en/Main/Standalone&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To program the chip you will need 6 pins. We already have VCC, GND and RESET. 3 more to go: SCK, MOSI and MISO. I&#39;m still a newbie in electronics, so I can&#39;t really explain to you what all this means and does, but basically we need those pins plugged into corresponding pins on our programmer. The easiest way is to use a different arduino, but you could also try it with RaspberryPi GPIO (&lt;s&gt;comming up next!&lt;/s&gt; there are multiple tutorials online) or buy a dedicated programmer. I settled for the easiest way, nearly every arduino board has 6 male ICSP pins just perfect for our purpose. And there&#39;s an example sketch available in the arduino IDE - ArduinoISP. It&#39;s well documented, I suggest you read through all the comments in that code. It could have saved me a lot of time.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;from the ArduinoISP sketch&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// Pin 10 is used to reset the target microcontroller.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// By default, the hardware SPI pins MISO, MOSI and SCK are used to communicate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// with the target. On all Arduinos, these pins can be found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// on the ICSP/SPI header:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;//               MISO °. . 5V (!) Avoid this pin on Due, Zero...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;//               SCK   . . MOSI&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;//                     . . GND&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just connect those with corresponding pins on your AVR and you&#39;re ready to go.&lt;/p&gt;
&lt;p&gt;Theoretically it&#39;s enough to compile and upload that sketch onto your working arduino, then select proper target (for example &quot;Arduino Nano&quot; board with &quot;ATmega328P&quot; processor) and then use the &quot;Burn Bootloader&quot; option from the IDE. Like in here: &lt;a rel=&quot;external&quot; href=&quot;https://www.arduino.cc/en/Tutorial/ArduinoISP&quot;&gt;https://www.arduino.cc/en/Tutorial/ArduinoISP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But that did not work for me... I switched on verbose output in arduino IDE&#39;s preferences and after quite some time of fruitless work I asked for help on IRC (#avrs @freenode).&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;wykwit&amp;gt; I&amp;#39;m always getting the Device signature = 0x000000 with atmega328p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;wykwit&amp;gt; what could I be doing wrong?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;polprog&amp;gt; make sure the connections are ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;Emil&amp;gt; wykwit: you need 6 pins for spi programming&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;Emil&amp;gt; vcc, gnd, rst, sck, mosi, miso&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;Emil&amp;gt; Depending on the burned fuses, you might need a crystal of appropriate frequency on the xtal pins&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;Emil&amp;gt; you also might need to use the low speed programming if first if you have the div/8 fuse burned (by default it is)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;wykwit&amp;gt; lowering the SPI_CLOCK in ArduinoISP script worked just fine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;wykwit&amp;gt; thanks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;polprog&amp;gt; wykwit: yeah thats a good trick. works 9 outta ten times ;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should REALLY CAREFULLY read the comments in the sketch and adjust values accordingly, so everything works fine for you. Pay attention especially to SPI_CLOCK and BAUDRATE settings.&lt;/p&gt;
&lt;p&gt;I suppose the first flash could work with the default SPI_CLOCK and BAUDRATE of 1000000 (3rd option). Try it out. I finally flashed with SPI_CLOCK set to (1000000/32) and a default BAUDRATE of 19200.&lt;/p&gt;
&lt;p&gt;You could probably get those magic values from the datasheet, but the datasheet is more than 600 pages long, so I just dug some values up from the internets and experimented.&lt;/p&gt;
&lt;p&gt;For those who are curious about The Real toolchain and how all of this works under the hood I highly suggest reading documentation at: &lt;a rel=&quot;external&quot; href=&quot;http://www.nongnu.org/avr-libc/&quot;&gt;http://www.nongnu.org/avr-libc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now I&#39;ll have to look into fuses. I hear they are important, but we automatically set them when flashing arduino bootloader.&lt;/p&gt;
&lt;p&gt;If you want to keep hacking your ATmega328 with the arduino IDE this chart might be helpfull: &lt;a rel=&quot;external&quot; href=&quot;https://www.arduino.cc/en/Hacking/PinMapping168&quot;&gt;https://www.arduino.cc/en/Hacking/PinMapping168&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now you can simply keep uploading new sketches through your current arduino setup with the &quot;Upload Using Programmer&quot; option.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AUR</title>
        <published>2018-04-30T00:00:00+00:00</published>
        <updated>2018-04-30T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/aur/"/>
        <id>https://www.wykwit.pl/blog/aur/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/aur/">&lt;p&gt;AUR - Arch User Repository&lt;/p&gt;
&lt;p&gt;Something every Arch Linux user MUST be familiar with.
In this post, I&#39;ll describe how to install yaourt, a pacman wrapper with AUR support, from the AUR.
That way you&#39;ll know how to work with AUR and you&#39;ll have a tool which will relieve you from ever doing that AUR stuff manually again.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://aur.archlinux.org/packages/yaourt/&quot;&gt;https://aur.archlinux.org/packages/yaourt/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Update: yaourt is not the coolest kid in town anymore.
Instead check out &lt;a rel=&quot;external&quot; href=&quot;https://aur.archlinux.org/packages/yay/&quot;&gt;yay&lt;/a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https://aur.archlinux.org/packages/paru/&quot;&gt;paru&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First of all: dependencies.
Dependencies are packages needed for a certain package to work.
We need to resolve them manually, installing them before yaourt.
They&#39;re always listed on the packages page.
To install packages, marking them as dependencies we&#39;ll use:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pacman -S --asdeps [packagename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may have some of package&#39;s dependencies already installed on your system.
To skip reinstallation process use &#39;--needed&#39; flag.
So for our yaourt we would issue a following command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# pacman -S --needed --asdeps diffutils gettext pacman rsync&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that one of yaourt&#39;s dependencies, namely package-query, is not in the official repositories
and that&#39;s why I didn&#39;t include it in the command above.
It is (also) available in the AUR!
We have to install package-query before we can proceed.
Fortunately all it&#39;s dependecies are in the repos.
Now we&#39;ll install our first package from AUR - package-query!&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://aur.archlinux.org/packages/package-query/&quot;&gt;https://aur.archlinux.org/packages/package-query/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For that we&#39;ll need a PKGBUILD.
It is a file describing build and installation process of which proper programs then take care.
Historically AUR was just a database for those PKGBUILDs.
Now it&#39;s a little bit more complex; links we&#39;d need are in the upper right corner of the AUR package page.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=package-query -o PKGBUILD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ makepkg -si&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;makepkg will make a package, -s flag will (once again) check for dependencies
and resolve them with pacman, and -i flag will install the package (with pacman) when it&#39;s ready.
As you issue these commands the package should be installed.&lt;/p&gt;
&lt;p&gt;Now you can repeat the process for yaourt, safely omitting -s flag; we&#39;ve already taken care of dependencies.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=yaourt -o PKGBUILD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ makepkg -i&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything went right you&#39;ll have working yaourt installed now.
From the user perspective it works just like pacman, but includes AUR.
Now you can install AUR packages with just a:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -S [packagename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Search through AUR and repositories with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -Ss [search term]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And update everything, including AUR packages with just a:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -Syua&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, when you query for orphans (unused packages):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -Qdt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yaourt will ask you if you want to remove them, which of course you do. Pretty convenient.&lt;/p&gt;
&lt;p&gt;You can work with yaourt like you would with pacman (it&#39;s just a wrapper). For instance, to remove something:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ yaourt -Rncsuv [packagename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will give exactly the same result as:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pacman -Rncsuv [packagename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hope you like your new toys. Have fun!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GPG keys</title>
        <published>2018-03-21T00:00:00+00:00</published>
        <updated>2018-03-21T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/gpg-keys/"/>
        <id>https://www.wykwit.pl/blog/gpg-keys/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/gpg-keys/">&lt;p&gt;So you&#39;ve encountered &quot;unknown public key&quot; error message. What to do?&lt;/p&gt;
&lt;p&gt;First search for the unknown key. Additionally you can explicitly specify the keyserver, for example keyserver.ubuntu.com&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --keyserver keyserver.ubuntu.com --search XXXXXXXXXXXXXXXX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see a key that is reliable just type in its number and it&#39;ll be imported. Error should be gone.&lt;/p&gt;
&lt;p&gt;GPG keys are usually used to sign and/or encrypt e-mails. To generate you own keys type in the following commmand in your terminal and simply go through the generation process.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --full-generate-key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you&#39;d like to submit your key on a keyserver or share it yourself. You&#39;ll need to paste generated files content onto your keyservers website.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --export --armor [your e-mail address] &amp;gt; [filename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Someone can then import it from the keyserver, like we did above, or from the file:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --import --armor &amp;lt; [filename]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can delete keys with&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --delete-keys [searchterm]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and your private keys with&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --delete-secret-keys [searchterm]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where the [searchterm] is either e-mail address, key ID, or really anything that identifies your key.&lt;/p&gt;
&lt;p&gt;You can list keys with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --list-keys&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great, but if you now receive an e-mail signed with a valid signature (which you&#39;ve imported) you&#39;ll get a warning &quot;cannot verify sender&quot;. To fix this, change the level of trust and sign the foreign key.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --edit-key [searchterm]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpg&amp;gt; trust //Here I suggest 3 or 4. Use 5 only for your own keys.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpg&amp;gt; sign&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpg&amp;gt; save&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;ll work now.&lt;/p&gt;
&lt;p&gt;You can move your private keys across different computers. Don&#39;t lose your private keys or else you won&#39;t be able to decrypt your e-mails. If needed (lost, stolen, stale), keys can be revoked.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SSH keys</title>
        <published>2018-03-20T00:00:00+00:00</published>
        <updated>2018-03-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/ssh-keys/"/>
        <id>https://www.wykwit.pl/blog/ssh-keys/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/ssh-keys/">&lt;p&gt;To generate a key-pair issue:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ssh-keygen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will produce two (2) files of a name provided on the prompt: [name] and [name].pub&lt;/p&gt;
&lt;p&gt;[name].pub is what goes on the server, more on that below. File [name] is your secret key, which you&#39;ll use instead of password for authentication. Transfer files between machines either with scp or sftp, whichever you like.&lt;/p&gt;
&lt;p&gt;To use a key on ssh:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ssh -i path/to/your/key [username]@[host]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will be asked for the password. Not the user password, but the (optional, though highly recommended) password which you&#39;ve inputed during the key-creation.&lt;/p&gt;
&lt;p&gt;&quot;[username]@&quot; part can be skipped when $(whoami) == [username]&lt;/p&gt;
&lt;p&gt;In case you don&#39;t know yet - Putty keys ain&#39;t compatible with OpenSSH, but you can convert those keys both ways.&lt;/p&gt;
&lt;p&gt;As for the server settings (&lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;), you need:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~ PubkeyAuthentication yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~ AuthorizedKeysFile .ssh/authorized_keys&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And I suggest:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~ PasswordAuthentication no&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Defaults for the rest are fine.&lt;/p&gt;
&lt;p&gt;Now you need to place your [name].pub (public key) file on the server under: &lt;code&gt;.ssh/authorized_keys&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That&#39;s the most common mistake - IT IS A FILE and the filename must match with your sshd_config.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cat [name].pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will only append to the file. Adding a new key.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ mv [name].pub ~/.ssh/authorized_keys&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will overwrite what you&#39;ve had saved in the file, making old keys unusable (which is good).&lt;/p&gt;
&lt;p&gt;Multiple keys can be used for one account and one key can be used for multiple accounts.
Keys are stored in a separate directory for each user.
You could use direct path to specify one authorized_keys file for the whole system.
For more information RTFM &amp;amp; STFW.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Static IP</title>
        <published>2018-03-13T00:00:00+00:00</published>
        <updated>2018-03-13T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/static-ip/"/>
        <id>https://www.wykwit.pl/blog/static-ip/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/static-ip/">&lt;p&gt;Network configuration - static IP.
Useful for installations and repairs, when dhcp does not work as intended.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/index.php/Network_configuration#Static_IP_address&quot;&gt;https://wiki.archlinux.org/index.php/Network_configuration#Static_IP_address&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I use it way too much.&lt;/p&gt;
&lt;p&gt;Display all the info with a following command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bring the interface up:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip link set eth0 up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Set the IP:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip addr add 192.168.1.13 broadcast 192.168.1.255 dev eth0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip route add 192.168.1.1 dev eth0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip route add default via 192.168.1.1 dev eth0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may try that, instead of these two last commands above:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip route add default via 192.168.1.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Delete all address settings for a given interface:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip addr flush dev eth0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A newer way to set the IP:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip address add 192.168.1.13/24 broadcast + dev eth0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course replace &#39;eth0&#39; with whatever your interface is called (for example: enp1s0) and properly adjust all the IPs.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>cstdio</title>
        <published>2018-03-06T00:00:00+00:00</published>
        <updated>2018-03-06T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/cstdio/"/>
        <id>https://www.wykwit.pl/blog/cstdio/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/cstdio/">&lt;p&gt;Using printf() &amp;amp; scanf() in C/C++ code is not only faster than using cin &amp;amp; cout, but it&#39;s also way simpler and cleaner.&lt;/p&gt;
&lt;p&gt;To use scanf/printf include &#39;stdio.h&#39;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or &#39;cstdio&#39; in C++:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#include &amp;lt;cstdio&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For cin &amp;amp; cout it&#39;s &#39;iostream&#39;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;cin inputs whatever the fuck you want into a variable. There&#39;s no difference in syntax, whether your input is a string or a single integer. That means at the first glance you won&#39;t know what to expect from the input.
Syntax:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cin &amp;gt;&amp;gt; [variable] &amp;gt;&amp;gt; [another variable] &amp;gt;&amp;gt; [etc.];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That way you can get the input into 3 (or more) variables. For instance, this might input 3 different numbers into 3 different vars, but might as well get you a number, a string, and a char.&lt;/p&gt;
&lt;p&gt;cout works similarly, it spits out your variables to the output. To input more variables (of different types?), you need to add even more &quot;&amp;lt;&amp;lt;&quot;. AFAIK that is necesarry. So, if you want to output a few numbers, each separated with a few characters, you need to add &quot;&amp;lt;&amp;lt;&quot; in between every single part of your call. Syntax:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cout &amp;lt;&amp;lt; [vars] &amp;lt;&amp;lt; &amp;quot;or text\n &amp;quot; &amp;lt;&amp;lt; [more vars] &amp;lt;&amp;lt; [etc.];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice, that the first variable won&#39;t be spaced out from the string that comes after it. On the output you might get for example &quot;1321or text&quot;...&lt;/p&gt;
&lt;p&gt;To clear out: &#39;\n&#39; means newline. Escaped characters work both with couts and printfs. Some others are &#39;\t&#39; for tab and &#39;\a&#39; for a beep sound.&lt;/p&gt;
&lt;p&gt;Now to the printf(), as it&#39;s simpler to output, than to input.&lt;/p&gt;
&lt;p&gt;printf() takes a string(char table in C) and parses it, replacing special character sequences with variables, which you pass to the function as later arguments. This might seem confusing for you C++ monkeys, but it&#39;s really not. Syntax looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;printf(&amp;quot;yo %[type code], simple, ain&amp;#39;t it? %[same] %[etc.]\n&amp;quot;, [var1], [var2], [etc.]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The string has to be there, or else you&#39;ll get a compilation error. By the [type code] I mean one of these sweeties below:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%d - int (same as %i)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%ld - long int (%li)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%lld - long long&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%f - float&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%lf - double&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%c - char&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%s - string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%x - hexadecimal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you&#39;ve probably already figured out, you need to supply which type you want to output on which place. This %something is a placeholder for the value of our variable. Such approach has a number of benefits. First of all, you know what type you&#39;re outputting/inputing on the first glance. Secondably - it&#39;s much simpler to space out variables with whatever you like. Mixing and formatting output is just way easier with printf.&lt;/p&gt;
&lt;p&gt;scanf() works similarly, but there&#39;s a small difference. You shouldn&#39;t supply your variables straight to the function, that won&#39;t tell it anything. You pass the space where you want your variable to be saved, so an address of a variable, a POINTER. Simple as that. If you don&#39;t know ANYTHING about pointers and memory addresses, just remember that with every type, except for tables (particularly char tables/strings), you need to preceed your variable name with a single &#39;&amp;amp;&#39; character. This will pass the address instead of the value further to the function. The syntax is as folows:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;scanf(&amp;quot; %s %[?] %[?]&amp;quot;, [stringname], &amp;amp;[var1], &amp;amp;[var2]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;passed string typically consists just of spaceholders and spaces. By a space, scanf means every white character. In this case, it&#39;ll ignore every &#39;\n&#39; and &#39; &#39; preceeding our string.&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;// input with a format string (to a string)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;scanf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%s&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; stringname&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;// input with a format string (for other types)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;scanf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%?&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;varname&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;// output with a format string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;printf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%?&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; varname&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s basically it. An example:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	int&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;	scanf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%d&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	int&lt;/span&gt;&lt;span&gt; tab&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;		scanf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%d&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span&gt;tab&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;		printf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%d, &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; tab&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;			printf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;	printf&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;%d.&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;\n\t&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;And that&amp;#39;s it.&lt;/span&gt;&lt;span style=&quot;color: #F5C2E7;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;/span&gt;&lt;span&gt; tab&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;BONUS:
to get higher i/o speed with cin/cout use following lines in your c++ main function:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;std::ios_base::sync_with_stdio(0);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;std::cin.tie(0);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;std::cout.tie(0);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>RTFM</title>
        <published>2018-01-21T00:00:00+00:00</published>
        <updated>2018-01-21T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/rtfm/"/>
        <id>https://www.wykwit.pl/blog/rtfm/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/rtfm/">&lt;p&gt;RTFM = Read The Fucking Manual&lt;/p&gt;
&lt;p&gt;How to know which parameters to use with a command?&lt;/p&gt;
&lt;p&gt;In GNU/Linux you can usually issue a command with &#39;--help&#39; parameter, which will display a help page for you. If not, try &#39;-h&#39;, &#39;-H&#39;, &#39;-?&#39; or none parameters.&lt;/p&gt;
&lt;p&gt;You can read man(ual) pages with:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ man &amp;lt;command or keyword&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re not sure what you&#39;re looking for, try:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ apropos &amp;lt;search term&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don&#39;t know what a command does, there is:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ whatis &amp;lt;command&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and on Arch Linux (for packages):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pacman -Qi &amp;lt;packagename&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;on Debian-based distros that would be:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ apt show &amp;lt;packagename&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For online man pages check &#39;info&#39; command, it seems to work just like &#39;man&#39;.&lt;/p&gt;
&lt;p&gt;If you don&#39;t know where a certain program is, you can use:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ whereis &amp;lt;name&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re still clueless STFW.&lt;/p&gt;
&lt;p&gt;STFW = Search the &lt;em&gt;Friendly&lt;/em&gt; Web&lt;/p&gt;
&lt;p&gt;Try to avoid proprietary search engines like Google or Bing if you can.&lt;/p&gt;
&lt;p&gt;I suggest using: &lt;a rel=&quot;external&quot; href=&quot;https://searx.me/&quot;&gt;https://searx.me/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a rel=&quot;external&quot; href=&quot;https://stackoverflow.com/&quot;&gt;https://stackoverflow.com/&lt;/a&gt; is your friend.&lt;/p&gt;
&lt;p&gt;Here are some more references:
&lt;a rel=&quot;external&quot; href=&quot;http://www.catb.org/~esr/faqs/smart-questions.html&quot;&gt;http://www.catb.org/~esr/faqs/smart-questions.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Read before you post.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Underclocking</title>
        <published>2018-01-20T00:00:00+00:00</published>
        <updated>2018-01-20T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.wykwit.pl/blog/underclocking/"/>
        <id>https://www.wykwit.pl/blog/underclocking/</id>
        
        <content type="html" xml:base="https://www.wykwit.pl/blog/underclocking/">&lt;p&gt;Program you&#39;re gonna need: cpupower.
It&#39;s in the official repository.&lt;/p&gt;
&lt;p&gt;More info: &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/index.php/CPU_frequency_scaling#cpupower&quot;&gt;CPU frequency scaling on the Arch wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can probably figure out the rest on your own...&lt;/p&gt;
&lt;p&gt;Have a look at: &lt;code&gt;/etc/default/cpupower&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cpupower frequency-info&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cpupower frequency-set -g powersave&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cpupower frequency-set -u 3.1GHz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cpupower frequency-set -u 2.8GHz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
</feed>
