<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:webfeeds="http://webfeeds.org/rss/1.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:link href="https://her.st/feed.xml" rel="self" type="application/rss+xml" />
    <title>her.st - Do you see it yet?</title>
    <link href="https://her.stfeed.xml" rel="self" />
    <link href="https://her.st/" />
    <updated>2025-01-24T19:14:18+00:00</updated>
    <id>https://her.st/</id>
    <author>
        <name>trbl</name>
    </author>

    
    <entry>
        <title>symbolism, meditation, prayer, psychedelics</title>
        <id>https://her.st/usr/bin/symbolism-rituals-part-one.html</id>
        <link href="https://her.st/usr/bin/symbolism-rituals-part-one.html" />
        <webfeeds:cover image="/assets/images/enlit_thumb.webp" />
        <webfeeds:icon>/assets/images/enlit_thumb.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/enlit.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2024-04-05T00:00:00+00:00</updated>
        <content type="html">
            &lt;h2 id=&quot;jungs-mist&quot;&gt;Jung’s Mist&lt;/h2&gt;

&lt;p&gt;There’s a time in your life - if you can think back far enough - where you did not know that you were separate from everything else. When you did not discriminate between you and an ant crawling through the dirt. Everyhting is One and One is All. Carl Jung called the moment of realization the ‘stepping out of the mist’.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“[..] That was in my eleventh year. There I suddenly was on my way to school I stepped out of a mist. It was just as if I had been in a mist, walking in a mist, and I stepped out of it and I knew, “I am.” “I am what I am.” And then I thought, “But what have I been before?” And then I found that I had been in a mist, not knowing how to differentiate my self from things. I was just one thing among other things.” – C. G. Jung&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you ‘step out of the mist’, you become like god. And you - like him - are alone.&lt;/p&gt;

&lt;h2 id=&quot;adam-and-the-apple&quot;&gt;Adam and the Apple&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;The word fruit appears in Hebrew as פֶּ֫רִי (pərî). As to which fruit may have been the forbidden fruit of the Garden of Eden, possibilities include apple, grape, pomegranate, fig, carob, etrog or citron, pear, quince, and &lt;em&gt;mushrooms&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Adam was not conscious before eating the forbidden fruit. He had awareness but He was not conscious.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“And the serpent said unto the woman, Ye shall not surely die: For God doth know that in the day ye eat thereof, then your eyes shall be opened, and ye shall be as gods, knowing good and evil.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;center&gt;
    &lt;img src=&quot;/assets/images/good-evil-pov.png&quot; alt=&quot;good is a point of view&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;Good and evil have no objective existance, you can only be taught what good and evil are.
Without betraying god, loyalty to god was meaningless. Eating the forbidden fruit gave him the experience of evil and provided the contrast to good.&lt;/p&gt;

&lt;h3 id=&quot;yin-yang&quot;&gt;Yin Yang&lt;/h3&gt;

&lt;center&gt;
    &lt;img src=&quot;/assets/images/yinyang.webp&quot; alt=&quot;yin yang symbol&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;This is usually oversimplified as “the bad contains a bit of good” and “the good contains some bad”. This hides the truth. If you deny one side, you never experience the other side to its fullest. You lack the contrast. This is conveniently left out from the movies.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“One quickly learns that the Jedi Code does not give all the answers. If you are to truly understand, then you will need the contrast, not adherence to a single ideal.” – Kreia&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;There is no virtue in a harmless persion for not harming.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Are you a nice person who could never hurt anyone? Are you unable to fight? Are you… harmless?  Harmless people are not good. If you can’t harmm there is no virtue in not harming.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“[..] fear and cowardice, dressed up as morality.” – Nietzsche&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are not capable of cruelty, you are the victim to someone who is. You have to be capable of it and then learn to control it. How else are you supposed to respect yourself and demand to be respected?&lt;/p&gt;

&lt;center&gt; &lt;img src=&quot;/assets/images/weakness-offends-me-meme.webp&quot; alt=&quot;your weakness offends me meme&quot; /&gt; &lt;/center&gt;

&lt;p&gt;Weak people are dangerous because they deny their potential for it.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“if you are going to be a figher, you have to want to win and you have to want to hurt people. But not for the sake of hurting them, thats what makes you different than an evil person. But you have to have that capacity. You have to develop that. And you know, thats a step to the way of enlightenment, weirdly enough, because that isn’t what people think.” – J. B. Peterson&lt;/p&gt;
&lt;/blockquote&gt;

&lt;center&gt;
    &lt;img src=&quot;/assets/images/jfc.webp&quot; alt=&quot;yin yang symbol&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;In Kung Fu Training you will learn how to break the arm, ribcage and nose of an attacker in a single fluid motion on your first day of training and practice it on your peers and your peers on you. Injuries during training are common. You might just get a bit too carried away or not have paid sufficient attention and injure or get injured. You learn quickly how much harm you are capable of inflicting unintentionally, and it will dawn on you how much more you could do intentionally.&lt;/p&gt;

&lt;p&gt;With time you become very dangerous, but at the same time, you learn discipline and mental strength. You learn how to be focused, and confident. When somoene tries to provoke a fight, you can respond with confidence to make the aggressor rethink his choice - and if he doesn’t, he will regret it.&lt;/p&gt;

&lt;p&gt;In the end, learning to fight is the best way not to get into fights in the future. Strong people know how dangerous they are and learn how control it.&lt;/p&gt;

&lt;h3 id=&quot;the-shadow&quot;&gt;The Shadow&lt;/h3&gt;

&lt;p&gt;You have to understand that you are no saint, in fact you are much closer to being satan himself. Jung said your shadow reaches right down into the depths of hell.
Given the right circumstances, you’d be exactly like Hitler, Stalin, Mao, … And if you don’t know that, you know nothing about people or yourself.&lt;/p&gt;

&lt;p&gt;Learning that about yourself is not fun. That’s why you didn’t do it. You have to be willing to descend into hell to learn things like that.
If you want to find wisdom, the answer is behind the door you do not want to go through at all. That’s where you kept it all this time.&lt;/p&gt;

&lt;p&gt;Integrating the shadow means to step out of the moral framework you have built around you. All the things you denied yourself to feel or experience. Whatever you supress has to be brought into your life and integrated into it.&lt;/p&gt;

&lt;p&gt;By denying those things, you also deny feeling the opposites to their full extent.&lt;/p&gt;

&lt;h2 id=&quot;spiritual-disciplines&quot;&gt;Spiritual Disciplines&lt;/h2&gt;

&lt;p&gt;They work. But not how they are practiced today. They also don’t require supernatural beings or explanations. They work even if you do not believe in them. I’ll tell you how.&lt;/p&gt;

&lt;h3 id=&quot;prayers&quot;&gt;Prayers&lt;/h3&gt;

&lt;p&gt;Especially in the western/christian world, prayer has been bastardized into begging “God” for handouts. People think praying for strength will magically make them stronger. The Clergy will tel you that if you pray for strenght, god will put you into situations that will give you a chance to practice strength.&lt;/p&gt;

&lt;p&gt;Cute, but doesnt work like that.&lt;/p&gt;

&lt;p&gt;Prayer was taken alot more serious in the past. Why do you think prayer is still a thing today? Do you think the people who started your religion were praying like you and had the same answer-ratio that you got? No. Their prayer worked 9 times out of 10. Even though there is no god.&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;/assets/images/trigger-me-jesus.webp&quot; alt=&quot;triggered jesus meme&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;You see, 10min of prayer is not enough. You want to pray for a prolongued amount of time. You will know when you are doing it long enough and right. Repeat the prayer over and over and over…&lt;/p&gt;

&lt;h3 id=&quot;mantra&quot;&gt;Mantra&lt;/h3&gt;

&lt;p&gt;Mantras are phrases or sounds you repeat at a certain rythm, almost like a song, over extended periods of time. The human brain is quite bad at multitasking, so, by repeating words or sounds, your brains language region is occupied and can’t function in autopilot. That basically means, you deny your brain to create and think thoughts for extended periods of time. Your brain does not like that. It will try its best to make you stop. First you will get bored, then you will slur the words or sounds and break the rythm. Those little errors will kick your mind back into autopilot and you will have chatter in your skull. If you persist, eventually you will start to hallucinate as your brains visual region takes over the task of thinking thoughts.&lt;/p&gt;

&lt;h3 id=&quot;meditation&quot;&gt;Meditation&lt;/h3&gt;

&lt;p&gt;People do it completely backwards.
Meditation is not about saying “Om” and focusing your attention on your breath or heartbeat. Its not about controlling your mind. You are not supposed to stop thinking.
What you want to do is to let the thoughts flow freely and stop passing judgement on them. The goal is observe them come and go and to practice mindfulness. You should be able to be consciously aware of thoughts before they are completely ‘prepared’ and your inner voice starts to speak them to you. You should observe and take mental notes on what sensations you feel in your body when you experience certain thoughts. You do this until you dissociate from your ego and watch your thoughts like an external observer.&lt;/p&gt;

&lt;h3 id=&quot;fasting&quot;&gt;Fasting&lt;/h3&gt;

&lt;p&gt;Once again, fasting has been washed down and turned on easy-mode for todays population. Intermittend fasting as is now being practiced does bring some health benefits, but it will not get you closer to “god” or “enlightenment”. You want to starve yourself for a week or two. Some monks sat in a temple and meditated without food until they died sitting. Some were even turned into statues and preserved forever. Don’t you think they’d have gotten up if nothing happened to them in their mind as they were approaching death? The closer you get to death, the more you will learn. Clearly one of the worst ways to affect your mind. Not very healthy. But there’s always a time and place for everything.&lt;/p&gt;

&lt;h3 id=&quot;sacrifice&quot;&gt;Sacrifice&lt;/h3&gt;

&lt;p&gt;Imagine standing in front of an altar in a dark, candle lit underground room. Surrounded by other people in robes, chanting prayers.
On the altar, there is a young woman, naked, blindfolded, breathing slowly and deeply. The ritual master slowly raising a dagger above his head as the people chant louder and louder, until he brings the dagger down with force, stabbing the woman in the chest and her screams hall through the dungeon as she fights a losing battle for her life.&lt;/p&gt;

&lt;p&gt;Just readng this should have made you feel something. Imagine experiencing something like that for real. Do you understand? Traumatic experiences alter your state of concsiousness. I think I’d rather do a few weeks of fasting.&lt;/p&gt;

&lt;h3 id=&quot;psychedelics&quot;&gt;Psychedelics&lt;/h3&gt;

&lt;p&gt;The fastest way. Most religions originally had their special potion. Clearly, a psychedelic potion. If I were to start a religon, I’d ‘prove’ it right by giving my acolytes a potion laced with psilocybe mushrooms and set up an appointment with god or satan for them.&lt;/p&gt;

&lt;p&gt;Ego Death is is the key. Given a high enough dose of psilocybin for example, you will be convinced that you are dying. No matter how rational you think you are, even if you remind yourself that you are just on psychedelics and everything is fine, you will still believe that you have done it this time and taken too much. For all you know, you are literally dying. But your body survives.&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;/assets/images/ifyoudiebeforeyoudie.webp&quot; alt=&quot;Inscription over a door at St. Paul&apos;s Monastery on Mt. Athos&quot; /&gt;
&lt;/center&gt;
&lt;blockquote&gt;
  &lt;p&gt;“If you die before you die, then you won’t die when you die.” – Inscription over a door at St. Paul’s Monastery on Mt. Athos&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The most astounding property of psilocybin and possibly other psychedelic agents - however, I only know this about psilocybin for a fact - is the ability to re-mount your subconscious from readonly to read/write.&lt;/p&gt;

&lt;p&gt;You can put a spotlight on any automatic behavior, any impulse response, and then just “will” it into a new behavior. It’s as easy as saying “this behavior no longer serves me, i will not do this anymore” and the next day you wake up a changed man.&lt;/p&gt;

&lt;p&gt;For reference: I’ve spent ~9 years in PTSD therapy, stationary for &lt;em&gt;significant&lt;/em&gt; amounts of time, been on all kinds of drugs which get prescribed randomly and switched for others in the same random manner, countless hours of therapy sessions and talking about everything. This yielded zero improvements. One heavy dose of psilocybin with the conscious goal of improving my life and 8 hours later, I was virtually symptom free and started functioning. But not only that. I did a career speedrun the likes of which nobody would believe.&lt;/p&gt;

&lt;p&gt;You will never be able to talk me out of advocating psychedelics. They are a great tool and they have saved my life.&lt;/p&gt;

&lt;h3 id=&quot;zen-and-desire&quot;&gt;Zen and Desire&lt;/h3&gt;

&lt;p&gt;The root teaching of Buddhism is the following: &lt;strong&gt;You suffer because you desire&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As soon as you start practicing zen, your spiritual teacher will use mindgames on you to break through your mental conditioning. He will guide you towards enlightenment like a prankster. First he will make you give up all your possessions - often by donating it to him. Then he will start giving you more and more chores and excercises until you are completely overwhlemed and have a mental breakdown. Here’s an example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Student&lt;/em&gt;: I am suffering.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Master&lt;/strong&gt;: You suffer because you desire.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Student&lt;/em&gt;: What shall I do?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Master&lt;/strong&gt;: Try not to desire.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Student&lt;/em&gt;: I have tried not to desire for many months now, I still find myself to desire&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Master&lt;/strong&gt;: Try not to desire less than you can.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[often never or after a long time]&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Student&lt;/em&gt;: I now desire &lt;strong&gt;not to desire&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more you desire enlightenment, the longer it will take you to accept your inevitable and unavoidable defeat. You will be trapped in a loop, a catch-22 - like the Oroburos eating its own tail. Eventually you &lt;strong&gt;will&lt;/strong&gt; have a breakdown and accept your inability to do what is asked from you, and during this painful emotional resignation, you may truly understand:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you seek it, you can not find it.&lt;/li&gt;
  &lt;li&gt;If you dont want it, you have it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Buddha himself sat in the mountains under a tree for weeks trying to achieve enlightenment, and only at the last moment when he accepted defeat and got up, it suddenly happened to him.&lt;/p&gt;

&lt;h2 id=&quot;englightenment&quot;&gt;Englightenment&lt;/h2&gt;

&lt;p&gt;The experience of enlightenment is indescribable and incomprehensible until you get a taste first hand.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You experience three ‘people’ inside you.
    &lt;ul&gt;
      &lt;li&gt;one that is your identity, the ego&lt;/li&gt;
      &lt;li&gt;one that creates thought, the thinker&lt;/li&gt;
      &lt;li&gt;one that processes thought, the prover&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The thinker finally shuts up
    &lt;ul&gt;
      &lt;li&gt;no more chatter in the skull, no compulsive thinking&lt;/li&gt;
      &lt;li&gt;silence in your mind is the new normal mode&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;A feeling of peace at an unimaginable magnitude
    &lt;ul&gt;
      &lt;li&gt;calmness, serenity, hearing birds chirp and truly appreciating it&lt;/li&gt;
      &lt;li&gt;no more anger, more patience&lt;/li&gt;
      &lt;li&gt;seeing through peope playing out the act that is their ego&lt;/li&gt;
      &lt;li&gt;no worries, no anxiety, just acceptance&lt;/li&gt;
      &lt;li&gt;understanding why things are the way they are&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;A boost of Confidence, you no longer identify with your identity
    &lt;ul&gt;
      &lt;li&gt;your identity is put in the background&lt;/li&gt;
      &lt;li&gt;you stop caring about status, fame or power&lt;/li&gt;
      &lt;li&gt;you start to see whats really important&lt;/li&gt;
      &lt;li&gt;public speaking is suddenly easy&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;A feeling of connectedness with everything
    &lt;ul&gt;
      &lt;li&gt;feeling reborn&lt;/li&gt;
      &lt;li&gt;no longer fear death&lt;/li&gt;
      &lt;li&gt;highly enhanced sense of empathy&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those effects last forever as far as I can tell and are the new default.&lt;/p&gt;

&lt;p&gt;You will still get sad, worried, angry, start obsessively thinking thoughts and get worked up by all of it - but as soon as you notice, you can just stop.&lt;/p&gt;

&lt;p&gt;You will find a kind of enjoyment in negative emotions. YOu can face your fears, like the fear of heights by sitting at the edge of a cliff in absolute terror, then take a step back - in your mind - and observe your thoughts, all the sensations you feel in your body and take mental notes as if you were an observer. This works for everything.&lt;/p&gt;

&lt;p&gt;You can speak your mind without fear of being ridiculed, you no longer worry about what people think about you. That’s why you do not lie. You don’t work for money, you just work for knowledge. You get a minimalist life and home without much stuff because you don’t need many things and dont desire things you dont need.&lt;/p&gt;

&lt;p&gt;You go to bed and your mind is no longer reminding you of all the fuck-ups you have (or surely will) commit in the future. You’re fine with fucking up every now and then. Nightmares disappear.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Edit: After the death of my Dog and weeks of grief and sadness on a level I’ve not experienced before, not even for a human, I am still standing by what I’ve said above.
I was able to embrace the grief and sadness but also put it aside when I had to.&lt;/p&gt;

&lt;p&gt;R.I.P Inu.&lt;/p&gt;

&lt;p&gt;– Nov 28th 2020 - Oct 21st 2024&lt;/p&gt;

&lt;h4 id=&quot;footnotes&quot;&gt;footnotes&lt;/h4&gt;

&lt;center&gt;
    &lt;video controls=&quot;&quot; style=&quot;width: 854px; height: auto&quot;&gt;
        &lt;source src=&quot;/assets/images/masterpiece.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
&lt;/center&gt;

&lt;blockquote&gt;
  &lt;p&gt;‘the thinker’ &amp;amp; ‘the prover’ borrowed from “Prometheus Rising” by Robert Anton Wilson&lt;/p&gt;
&lt;/blockquote&gt;

        </content>
    </entry>
    
    <entry>
        <title>freedom</title>
        <id>https://her.st/usr/bin/freedom.html</id>
        <link href="https://her.st/usr/bin/freedom.html" />
        <webfeeds:cover image="/assets/images/freedom.webp" />
        <webfeeds:icon>/assets/images/freedom.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/freedom_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2024-04-05T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;rule-of-thumb&quot;&gt;rule of thumb&lt;/h1&gt;

&lt;center&gt; &lt;img src=&quot;/assets/images/iq.webp&quot; alt=&quot;iq distribution midwit meme&quot; /&gt; &lt;/center&gt;

&lt;p&gt;The majority is not very intelligent -&amp;gt; The majoriy does certain things -&amp;gt; Doing those things is not very intelligent.&lt;/p&gt;

&lt;h2 id=&quot;obvious-examples&quot;&gt;obvious examples&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Stupid Majority&lt;/th&gt;
      &lt;th&gt;Intelligent Minority&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;they want more money&lt;/td&gt;
      &lt;td&gt;they want to need less of it&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they go into debt for liabilities&lt;/td&gt;
      &lt;td&gt;they go into debt for assets&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they need full time jobs&lt;/td&gt;
      &lt;td&gt;they work for fun&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they have university degrees&lt;/td&gt;
      &lt;td&gt;they have real skills&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they believe others&lt;/td&gt;
      &lt;td&gt;they question themselves&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they do what authority commands&lt;/td&gt;
      &lt;td&gt;they do, given reason to&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they are on social media&lt;/td&gt;
      &lt;td&gt;they are not&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they watch mainstream media&lt;/td&gt;
      &lt;td&gt;they do not&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they parrot what they are being told&lt;/td&gt;
      &lt;td&gt;they have original thoughts&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;they vote&lt;/td&gt;
      &lt;td&gt;they abstain&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The majority of people will even stop at a red pedestrian light and not cross an empty road until the light turns green. They are barely autonomous, and just like sheep, as soon as you walk across the red light, they will follow behind you.&lt;/p&gt;

&lt;h2 id=&quot;why-not-to-vote&quot;&gt;why not to vote&lt;/h2&gt;

&lt;p&gt;Elections no longer matter (if they ever did is another subject entirely) but all over europe right wing parties win 2024 and are &lt;strong&gt;not allowed to rule&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-to-be-free&quot;&gt;how to be free&lt;/h2&gt;

&lt;p&gt;First of all you need to understand how and why you were programmed.&lt;/p&gt;

&lt;p&gt;You were programmed to want money. Everyone has a natural tendency to be greedy. Whatever you have will become boring and you will want more.  You want that new iPhone every year because its better, or a new computer or a bigger house, a better fucking fridge, whatever you have, eventually something better will catch your eye and you will want it. For &lt;em&gt;-some-&lt;/em&gt; reason. That’s how humanity made it this far. Survivial is enough for animals and natural selection, but not for us. We want to perpetually improve things and make them better. Capitalism is an ingenius system to encourage that behavior and steers whole societies into that direction by exploiting this innate desire.&lt;/p&gt;

&lt;p&gt;Obviously, businesses exploit that in ways more insidious than just making better products. They use all kinds of dirty tricks to keep you consooming. From psyops to planned obsolencence. They will get you to consume one way or the other. After all, they are in the business of making money. And you are working 40h/week to spend it with them.&lt;/p&gt;

&lt;h2 id=&quot;pressure&quot;&gt;pressure&lt;/h2&gt;

&lt;p&gt;Everyone wants you to “get a job” and not be “lazy” or a “freeloader”. Usually those people are the most vocal supporters of politicians who do no useful work whatsoever.&lt;/p&gt;

&lt;p&gt;Being a politician and being on welfare is almost exactly the same thing: both are paid by the tax payer, but only one of them lies to us on TV. Get what job exactly? During the Covid19 Pandemic most people lost their jobs because they were deemed non-essential &lt;em&gt;and rightfully so&lt;/em&gt;. Most jobs are not required to be done, they just exist to keep the system going.&lt;/p&gt;

&lt;p&gt;Small businesses are obsolete, the megacorps have taken over. You can get everything delivered from amazon, your groceries get delivered by the big supermarket chains, you can order everything that’s essential from some big company. It doesn’t matter what your opinion on those big corporations is, they provide convenience no small business can provide and the majority of people want that convenience.&lt;/p&gt;

&lt;p&gt;They won. And the sooner people accept that, the sooner they can stop wasting their time and energy doing useless jobs that are reminiscent of occupational therapy, just keeping people busy so they don’t think about how fucked up the state of affairs is.&lt;/p&gt;

&lt;p&gt;Now, you could get a non-essential job, like software development. What are you going to build? Most likely something a marketing agency convinced enough people they need and not something useful. If you’re fine wasting your life on something like that be my guest.&lt;/p&gt;

&lt;p&gt;You see, at some point you realize that there’s no real demand for any low-tech entrepreneurship anymore. The companies that do those things nowdays have been founded 100 years ago and live off of government contracts, own or still rent their stores and workshops at pre-war prices. If they had to rent or pay off a mortgage nowdays, they’d simply not be able to stay open.&lt;/p&gt;

&lt;p&gt;And if you’re not in the top ~5% of the IQ distribution, you have no chance of competing in any high-tech field. So you’re stuck with the low-tech stuff, and there’s no demand for that.&lt;/p&gt;

&lt;h2 id=&quot;breaking-the-loop&quot;&gt;breaking the loop&lt;/h2&gt;

&lt;h3 id=&quot;step-1-cut-all-your-costs&quot;&gt;Step 1: Cut all your costs&lt;/h3&gt;

&lt;p&gt;Buy food in bulk. Buy everything you can 2nd-hand. Do not rely on any services like plumbers or hairdressers, instead learn how to do that stuff yourself. Pick up a new hobby like soldering or woodworking, get a toolbox. Become a man that will just solve the task at hand without relying on a better man.&lt;/p&gt;

&lt;p&gt;If you want to invest in something and you take a loan or credit, you are not investing, you are making the bank invest and the bank will make you work for decades to pay it back. If you currently have debt, pay it off as soon as possible. You can not be free if you are in debt. You are a slave to the bank. Do not go into debt before you &lt;em&gt;actually&lt;/em&gt; know the difference between an &lt;em&gt;asset&lt;/em&gt; and a &lt;em&gt;liability&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you think a house you live in is an asset you do not understand the difference.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cancel all subscriptions. Cancel all contracts. Get a cheaper phone plan, get a cheaper internet plan. You don’t need cable or Netflix. Do not pay for anything you can get for free. Learn how to get things for free. Before you make any purchase that isn’t necessary to survive, wait 14 days. After 14 days you will realize that you don’t need it. If you still want it, buy it. From my experience, you won’t buy most things because you forget you wanted them.&lt;/p&gt;

&lt;h3 id=&quot;step-2-move-to-a-cheap-place&quot;&gt;Step 2: move to a cheap place&lt;/h3&gt;

&lt;p&gt;Get a cheaper apartment. Embrace complete minimalism. Get a Bed, Chair, Table and rice cooker. That’s all you need to survive, you’d be surprised how versatile a rice cooker is. You don’t even need a fridge. Turns out half of the year its cold enough outside to just put stuff outside your windowbed to refrigerate it. Don’t bring all of your old stuff, sell it all. You don’t need it.&lt;/p&gt;

&lt;h3 id=&quot;steo-3-quit-wage-slavery&quot;&gt;Steo 3: quit wage slavery&lt;/h3&gt;

&lt;p&gt;At this point your cost of living should be so low, even government welfare is enough to sustain you. You can now quit your job and live off of welfare. You can now do whatever you want. You can work on your own projects and learn new skills. You are almost free. Take small jobs on demand, whatever you are qualified for, get full time jobs, quit them after a month or two, once you made enough money to do what you want to do and spend the rest of the time on learning and practicing new skills.&lt;/p&gt;

&lt;p&gt;Avoid working for money. Work for experience or for the joy of doing, learning, creating or helping others. You never have to worry about if the job pays enough now. You can do whatever job you want to do. The money you do get, you invest into assets and/or new skills that will save you money in the long run.&lt;/p&gt;

&lt;h3 id=&quot;step-4-freedom&quot;&gt;Step 4: freedom&lt;/h3&gt;

&lt;p&gt;Once you’ve learned enough skills to make money on your own, or get any job you want, you can basically pack your shit whenever you want and leave. That’s freedom. You can go anywhere you want, you can do whatever you want. The job you accepted turns out to be shit? Just quit. You don’t &lt;em&gt;need&lt;/em&gt; the money anyway. You just took the job to learn something or to get money for an investment. Just get a different job.&lt;/p&gt;

&lt;h4 id=&quot;book&quot;&gt;Book&lt;/h4&gt;

&lt;p&gt;And if you want to learn more about how the system works, I recommend reading “DIE SHEEPLE DIE” by The Honorable DJ Hives. It’s a free ebook and I’ve attached it below. It’s written in a way the stupid majority can not read. It is &lt;strong&gt;FNORD&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Every appearance of the [misspelled] word subconsciously generates a feeling of uneasiness and confusion, and prevents rational consideration of the subject. This results in a perpetual low-grade state of fear in the populace. This in turn perpetuates the need for Government, because without fear, people don’t need Government.” – The Illuminatus Trilogy (Novel, 1974).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;/assets/DIE-SHEEPLE-DIE.pdf&quot;&gt;DIE SHEEPLE DIE! by The Benevolent DJ Hives&lt;/a&gt;&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>LLMs solved the search problem</title>
        <id>https://her.st/usr/bin/rip-google.html</id>
        <link href="https://her.st/usr/bin/rip-google.html" />
        <webfeeds:cover image="/assets/images/baibaigoogle.webp" />
        <webfeeds:icon>/assets/images/baibaigoogle.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/baibaigoogle_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2023-03-23T00:00:00+00:00</updated>
        <content type="html">
            &lt;h3 id=&quot;google-is-dead&quot;&gt;Google is dead&lt;/h3&gt;

&lt;p&gt;Google has emerged as the predominant source of information, offering answers to a wide range of queries, from trivial to scholarly. Its vast resources, including billions of web pages, articles, books, images, and videos, have replaced libraries as the go-to places for knowledge and culture. Google’s success can be attributed to its convenience, enabling users to access information 24/7 from anywhere in the world. Google’s personalization features, which tailor results to users’ preferences, behavior, and relevant factors, have also played a crucial role in its widespread adoption.&lt;/p&gt;

&lt;p&gt;Google’s commercial nature means that it collects and analyzes users’ data to improve its algorithms and provide relevant results, making users the product, not the customer. While other companies also collect data, Google’s dominance and value lie in its data collection. Nonetheless, Google’s algorithms are not neutral or objective, and they can be influenced by censorship laws or political agendas. The quality of Google’s results can be inconsistent, depending on the sources it indexes and ranks.&lt;/p&gt;

&lt;p&gt;Google’s dominance may be coming to an end as it has not released any new products in years, and its acquisition of other companies has not resulted in significant innovation. Its size is now limiting its ability to move quickly in a fast-changing landscape, and it risks being left behind.&lt;/p&gt;

&lt;h3 id=&quot;the-search-problem&quot;&gt;The Search Problem&lt;/h3&gt;

&lt;p&gt;The search problem refers to the challenge of efficiently and accurately retrieving relevant information from vast amounts of data. This problem is particularly relevant in the context of search engines like Google and Bing, which index and search through billions of web pages.&lt;/p&gt;

&lt;p&gt;In order to solve the search problem, search engines like Google and Bing use complex algorithms to analyze the content of web pages and determine their relevance to specific search queries. These algorithms take into account a wide range of factors, such as the frequency and location of keywords on a web page, the popularity of the page, and the credibility of the source.&lt;/p&gt;

&lt;p&gt;Google and Bing systematically download and analyze web pages and index the content of those pages into a searchable database. Ranking involves determining the relevance and importance of each page in relation to specific search queries.&lt;/p&gt;

&lt;h3 id=&quot;the-solution-llms&quot;&gt;The Solution: LLMs&lt;/h3&gt;

&lt;p&gt;Storing massive amounts of text in a searchable format requires an index, similar to Google’s. However, even small-scale, self-hosted Full-Text-Search solutions like ElasticSearch require &lt;em&gt;insane&lt;/em&gt; amounts of RAM, often in the hundreds of gigabytes, for comparatively benign datasets. Google, on the other hand, requires entire data centers to store everything.&lt;/p&gt;

&lt;p&gt;Literally tens of thousands of servers spread across multiple data centers. To give you an idea of the scale, according to a report from Statista, as of 2021, Google’s search index contained over 130 trillion web pages, and the company processes over 3.5 billion searches per day. This level of scale requires an enormous amount of hardware resources to maintain and operate.&lt;/p&gt;

&lt;p&gt;In contrast, Large Language Models (LLMs) like LLaMA’s 65 billion parameter model, trained on over 1 trillion tokens, require only about 10GB of disk/ram and can be queried easily with 100 tokens per second on a consumer GPU. This is an incredible level of compression and performance for searching vast amounts of information.&lt;/p&gt;

&lt;p&gt;GPT4 by OpenAI, a model trained on over 100 times more tokens than LLaMA, yet with only marginally more parameters and hence disk/ram requirements pretty much knows everything and fits into a single server.&lt;/p&gt;

&lt;p&gt;With LLaMA, parameter count can be trimmed without losing much accuracy. You can shave off half the size and still have the same quality for a given language, like English. Furthermore, LLMs are currently unoptimized for space/resource usage, and techniques such as trimming and quantization are improving every month. Quantization algorithms can currently quantize a 16-bit model down to 4 bits, saving three-quarters of the RAM/DISK requirements while still delivering almost identical results when queried. The potential for further optimization in this area is truly mind-blowing.&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>nginx mirroring</title>
        <id>https://her.st/usr/bin/nginx-mirroring.html</id>
        <link href="https://her.st/usr/bin/nginx-mirroring.html" />
        <webfeeds:cover image="/assets/images/nginxmirror.webp" />
        <webfeeds:icon>/assets/images/nginxmirror.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/nginxmirror_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-12-10T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;nginx-mirroring&quot;&gt;nginx mirroring&lt;/h1&gt;

&lt;p&gt;So you might want to implement some basic realtime functionality on your website. Think of the Hit Counter for example, or maybe you want to do some realtime logging. What if you wanted to do something with requests but you don’t want to use Javascript? What if you on’t want to rewrite your site with some kind of dynamic backend? You can use Nginx to do that!&lt;/p&gt;

&lt;p&gt;When I deployed OpenFaaS (Functions as a Service), something identical to AWS’s Lambda, I wanted to write a small function that would log the requests to my site. The easiest way would be to have a small &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of my site, but I didn’t want to do that. I like the idea of being free of Javascript, and I don’t want to have to rewrite my site to use a dynamic backend.&lt;/p&gt;

&lt;p&gt;The basic idea is to multicast the http requests to a function so the flow looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ascii&quot;&gt;                                            ┌──────────┐
                                       ┌───►│ Function │
                                       |    └──────────┘
    ┌────────┐    ┌───────┐   ┌────────┤
    │ Client ├────| Nginx ├───| MIRROR │ 
    └────────┘    └───────┘   └────────┤
                                       │    ┌─────────┐
                                       └───►│ Content │
                                            └─────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which can be implemented like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ssl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;her&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# .. cert stuff omitted
&lt;/span&gt;    
    &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mirror&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# mirror requests to /log_function
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;mirror_request_body&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# if you want to mirror the payload change this to &apos;on&apos;
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;her&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# your content root
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log_function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                 &lt;span class=&quot;c1&quot;&gt;# don&apos;t allow public access
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;her&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# your function
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to write a function that will log the requests. I wrote a simple function in C# that will log the requests to a Redis database.&lt;/p&gt;

&lt;h2 id=&quot;the-function&quot;&gt;The Function&lt;/h2&gt;

&lt;p&gt;First we have to create a new openfaas function. I’m using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csharp-httprequest&lt;/code&gt; template&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;faas-cli template store pull csharp-httprequest
faas-cli new nginxlog &lt;span class=&quot;nt&quot;&gt;--lang&lt;/span&gt; csharp-httprequest &lt;span class=&quot;nt&quot;&gt;--gateway&lt;/span&gt; https://f.her.st
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;this will create a new folder called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log_function&lt;/code&gt; with the following files:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ascii&quot;&gt;├── log_function
│   ├── log_function.csproj
│   └── log_function.cs
└── log_function.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;For more information about the function template, see the &lt;a href=&quot;https://docs.openfaas.com/cli/templates/&quot;&gt;openfaas docs&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside log_function.cs you’ll see something like&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Microsoft.AspNetCore.Http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Function&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FunctionHandler&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StreamReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadToEndAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;Hello! Your input was &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to add StackExchange.Redis to the project.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dotnet add package StackExchange.Redis
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can add the code to log the requests to Redis.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Microsoft.AspNetCore.Http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;StackExchange.Redis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Function&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FunctionHandler&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RedisHost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10.1.0.105:6379&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConnectionMultiplexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ConnectAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RedisHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;funcInput&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FunctionInput&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Headers&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JsonSerializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;funcInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redis&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connectTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDatabase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FunctionId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incrTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StringIncrementAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;requests:count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetAddAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;requests&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WhenAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incrTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FunctionInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IHeaderDictionary&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can build the function and deploy it to our OpenFaaS instance&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;faas-cli build &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; log_function.yml
faas-cli push &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; log_function.yml
faas-cli deploy &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; log_function.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-result&quot;&gt;The Result&lt;/h2&gt;

&lt;p&gt;Let’s send a request to our function and see what happens.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl https://f.her.st/nginxlog | jq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Headers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;*/*&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Accept-Encoding&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gzip&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;10.62.0.37:8080&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;curl/7.86.0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Call-Id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2fea566b-2684-46d7-9af3-98d3b57b158d&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Forwarded-For&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;42.0.69.69&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Forwarded-Host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;f.her.st&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Forwarded-Proto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Forwarded-Scheme&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Real-Ip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;42.0.69.69&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;X-Start-Time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1670663513325430714&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;now let’s send a request to the blog&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl https://her.st/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s check the Redis database to see if the request was logged.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;redis-cli &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1 GET requests:count
&lt;span class=&quot;s2&quot;&gt;&quot;2&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Works like a charm!&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>coding is dead</title>
        <id>https://her.st/usr/bin/coding-is-dead.html</id>
        <link href="https://her.st/usr/bin/coding-is-dead.html" />
        <webfeeds:cover image="/assets/images/jobs.webp" />
        <webfeeds:icon>/assets/images/jobs.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/jobs_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-12-01T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;ai-is-better-than-you&quot;&gt;AI is better than you&lt;/h1&gt;

&lt;p&gt;AIs like Github Copilot will replace the need for general purpose software developers very soon. Already Copilot is alot more useful to me than a junior. It writes entire methods from a tiny comment and usually writes decent code at that. As soon as you figure out how to talk to it, it will tell you pretty much anything you want to know. This is just the beginning. Copilot is the first AI to write code. Other AIs already create Art that wins competitions, we have Video generation AI, we have speech synthesis, even AIs that write entire blog posts on major news sites. The rate of improvement is ridiculous. All of those AIs created utter shit two years ago and today they are almost on the level of a human.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In the future, people will just descibe what software they want and the AI will write it for them. For free, in a few seconds. We won’t be able to compete with that. That future is maybe - optimistically - 5 years away.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;frontend-development&quot;&gt;frontend development&lt;/h2&gt;
&lt;p&gt;Webdevs will be the first to fall victim to it I predict. No matter how highly you think about yourself as a webdev, especially the frontend, its doesnt take more than a few weeks to learn the basics and more than room-temperature IQ. Already most companies outsource frontend stuff to 1$/hr indians. There’s already some AIs that can create entire websites from a few screenshots and prompts. They existed before Copilot and they will be better than you in a few years.&lt;/p&gt;

&lt;h2 id=&quot;mobile-apps&quot;&gt;mobile apps&lt;/h2&gt;
&lt;p&gt;Next in line will be mobile app developers who are not much more than glorified webdevs. They will be replaced by AIs that can write apps for all platforms at the same time in a few seconds.&lt;/p&gt;

&lt;h2 id=&quot;backend-developers&quot;&gt;backend developers&lt;/h2&gt;
&lt;p&gt;REST APIs are very trivial too, especially if you use microservices or something else with a very strict architecture and flow. AI will write better SQL queries than you, too.&lt;/p&gt;

&lt;h2 id=&quot;general-purpose-software-developers&quot;&gt;general purpose software developers&lt;/h2&gt;
&lt;p&gt;Unit Testing will be done by AIs too. They will write the tests for you and run them. You will just have to tell them what to test.
UIs will be generated by AIs too. You will just have to tell them what to show and how to show it. They will even write the code for you.
Utilities, Scripts, DevOps, everything will be done by AIs. Those things are trivial and usually passed to juniors anyway.&lt;/p&gt;

&lt;h2 id=&quot;specialized-software-developers&quot;&gt;specialized software developers&lt;/h2&gt;

&lt;p&gt;If you’re working on something that is very specific and non trivial, like low level networking code, optimization, … you’re safe for a couple more years. But even then, AIs will be able to write code that is better than you in a few years.&lt;/p&gt;

&lt;h2 id=&quot;copilot--others&quot;&gt;copilot &amp;amp; others&lt;/h2&gt;

&lt;p&gt;They do not sleep. They are not limited by typing speed, they dont take breaks and they are extremely cheap to run. Yes, you might need a 100$/m subscription for some serious stuff, or run it on a server that costs you a few 1000$ a  month, but that’s still orders of magnitude cheaper than a team of developers.&lt;/p&gt;

&lt;p&gt;Hardware acceleration of AI just started a few years ago. Initially we had GPUs do the heavy lifting, but now we have FPGAs, ASICs, TPUs, … that are orders of magnitude faster than GPUs. They are also orders of magnitude cheaper and more power efficient. Supercomputer clusters have been built with AI accelerators for years now and they train AIs 24/7/365. They are already better than humans at many things. You are training AIs everytime you solve captchas, play games, use google, … and you are training them to be better than you. Well, you are classifying training data for them, but you get the point.&lt;/p&gt;

&lt;h2 id=&quot;computer-linguists&quot;&gt;computer-linguists&lt;/h2&gt;

&lt;p&gt;Eventually I think people will get really good at describing things to AIs and get hired just for that. You won’t hire a programmer but an computer-linguist to “develop” your software. A person that is intrinsically good at describing things to AIs, with a good understanding of the domain, the problem, and maybe a bit above Junior level programming skills to be able to write the glue code if needed.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;conclusion&lt;/h3&gt;

&lt;p&gt;We took our jobs.&lt;/p&gt;

&lt;h4 id=&quot;update-7th-dec-2022&quot;&gt;update 7th Dec 2022&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/vnzAY1SUFSA&quot;&gt;https://youtu.be/vnzAY1SUFSA&lt;/a&gt;&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>education</title>
        <id>https://her.st/usr/bin/education.html</id>
        <link href="https://her.st/usr/bin/education.html" />
        <webfeeds:cover image="/assets/images/carlin.webp" />
        <webfeeds:icon>/assets/images/carlin.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/carlin_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-11-08T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;&lt;em&gt;I’m going to write from the perspective of a high iq autodidactic individual who values self determination and autonomy above anything else.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;public-schools&quot;&gt;public schools&lt;/h1&gt;

&lt;p&gt;Designed to break your autonomy and resistance to authority, from the first day you’re forced to sit still for hours and do &lt;em&gt;as&lt;/em&gt; you are told, &lt;em&gt;when&lt;/em&gt; you are told and &lt;em&gt;how&lt;/em&gt; you are told. If you resist, you get sanctioned. Either you will be told to do more stuff (eg. repeatedly write a sentence  or copy a paragraph) or you will be punished (eg. detention, suspension, expulsion). The goal is to break your autonomy and make you a good worker. A good worker is someone who waits for instruction and does as he is told without question.&lt;/p&gt;

&lt;p&gt;Education boils down to obedience training - as you would train a dog. A dog works for treats and his training is basically just conditioning his behavior to get treats by following instruction. Children do not get treats, they get grades. Grades are a form of social currency. They are a way to measure your worth in society, your obedience to authority, your ability to follow instruction. The child’s parents believe in this reward because they were taught to and their parents believed in it for the same reason. If you follow this back a few generations, you arrive at a point in time when education actually did result in better lives, but that has been out of date for at least 3 generations at the time of writing. If you go back to the 1950s it still does not work. The world has changed and the system has not.&lt;/p&gt;

&lt;h2 id=&quot;university&quot;&gt;university&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;You pay twice for your education: once with money and once with time. – AI generated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A waste of time and money for most professions. If there is no danger to human life you can learn everything you need on your own. I might not want a surgeon to trial and error his skills on life human beings, but if you’re in a theoretical field there’s no reason not to. Most practical fields are of no danger to anyone but yourself either. Additionally, every degree is bundled together with subjects that have no relevance to what you want to do. Even if university access is free in your country, it is still too expensive to attend.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;University standardizes the knowledge of different fields. It is a way to make sure that everyone has the same knowledge. – AI generated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s take computer science as an example here, as I had to interview my fair share of graduates.&lt;/p&gt;

&lt;p&gt;I’m a senior now and throughout the years I’ve had to hold the hands of alot of juniors and get them started. On average, compsci graduates have all the same skills. You have 50 graduates who have learned the identical stuff applying for the job, interview one of them and you know all of them. They are useless. You have to spell out every step of the way for them to know what they are supposed to do and then hold their hand till the end. If you get a CV without a portfolio of projects they did on their own time that resume goes into the trash. It takes way less time to teach a self-taught programmer the obscure but useful things compsci graduates understand than teaching those graduates how to be a competent programmer.&lt;/p&gt;

&lt;p&gt;This is not my opinion, this is first-hand real-world experience.&lt;/p&gt;

&lt;p&gt;Nowdays you’re lucky if you can dump a folder of creds and profiles on a new hire and say “there you go, that has your wiregurad profile, your company password manager and your creds for internal services, please setup your laptop and clone this repo”. Most won’t be able to figure it out on their own, which is quite an achievement if you consider they have a compsci degree.&lt;/p&gt;

&lt;h2 id=&quot;testing&quot;&gt;testing&lt;/h2&gt;

&lt;p&gt;Testing measures your short-term memory first and foremost. That’s why testing has been dumbed down over the years, lowering the passing scores, simplifying the language of the questions. As soon as there’s complex syntax used and variables hidden in the query, the conditioned child will no longer be able to process the information and draw conclusions. Children have been conditioned to follow clear instruction, with every step of the way being verbosely defined. Nothing is left to the imagination. The child was not allowed to think for himself, be creative or autonomous. And now it can’t be.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The purpose of exams is not to measure your knowledge, it is to measure your obedience to authority. – AI generated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;jobs&quot;&gt;jobs&lt;/h2&gt;

&lt;p&gt;Now you’re prepared to join the workforce. You will be doing as you are told for the next 50 years until retirement. For a fraction of the money you could have made if you had been self-employed. Well, at least that’s what I’d have said 5 years ago, now post-covid, all the small businesses went bankrupt and the big guys bought all of it up. So now you’re stuck in the workforce.&lt;/p&gt;

&lt;h2 id=&quot;retirement--beyond&quot;&gt;retirement &amp;amp; beyond&lt;/h2&gt;

&lt;p&gt;Your body is tired now and will cease to function shortly after. This is the time when you won’t have regrets like “Oh I wish i studied harder, worked harder, spent more time in the office”. You will be in denial. You will be happy that you can finally rest and live your life, not allowing thoughts like “I could have done that from the beginning”, “I’ve wasted my life playing a game that wasnt worth playing”. You will have health issues from age and exhaustion and won’t be able to really live your life now.&lt;/p&gt;

&lt;p&gt;The energy you once had will have faded and as the darkness approaches, you will finally have the courage to admit to yourself and your children that you’ve wasted your life.  That you should have spent more time with your family and doing things you wanted to do. You will tell your children to take it easy and follow their dreams, to not worry about what everyone else thinks about you. Like your grandparents told you, but you didn’t believe. But it’s too late for your children now. They’re adults and in the middle of the same game you’ve lost, and they will lose too, because like yourself, they were conditioned to follow instruction and do as they are told, just not your last instruction, but the instruction of the system.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;conclusion&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;The educational system works as intended but not for the benefit of the students. It is a system that is designed to produce workers for the economy. The system is not designed to produce critical thinkers, innovators, or entrepreneurs but to produce good consumers who will buy the products and services of the economy, citizens who will pay taxes and obey the laws, soldiers who will fight for the country, drones who will do as they are told and not question authority. Slaves.&lt;/p&gt;
&lt;/blockquote&gt;

        </content>
    </entry>
    
    <entry>
        <title>introducing: atlas - my gemini server</title>
        <id>https://her.st/usr/bin/atlas-gemini-server.html</id>
        <link href="https://her.st/usr/bin/atlas-gemini-server.html" />
        <webfeeds:cover image="/assets/images/atlas.webp" />
        <webfeeds:icon>/assets/images/atlas.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/atlas_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-08-26T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;Atlas is a gemini server without any dependencies. It works on x86, x64 and ARM64. Linux is supported and Windows/MacOS should work fine too - but I don’t know since I don’t use either. The name refers to the launch rocket used to launch the gemini capsules into space.&lt;/p&gt;

&lt;h3 id=&quot;features&quot;&gt;Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;C#/net7&lt;/li&gt;
  &lt;li&gt;gemini://&lt;/li&gt;
  &lt;li&gt;titan://&lt;/li&gt;
  &lt;li&gt;spartan://&lt;/li&gt;
  &lt;li&gt;CGI&lt;/li&gt;
  &lt;li&gt;VHOST&lt;/li&gt;
  &lt;li&gt;Simple configuration&lt;/li&gt;
  &lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;gemini&quot;&gt;gemini://&lt;/h2&gt;

&lt;p&gt;After a week of trial and error with the occasional look at the documentation, I’ve finished the first version of atlas. The gemini protocol is super easy to understand and implement but the other features I wanted were not :D&lt;/p&gt;

&lt;p&gt;There’s no way to upload anything using gemini. The best you can do is to use the INPUT request to pass query strings to the server.&lt;/p&gt;

&lt;h2 id=&quot;titan&quot;&gt;titan://&lt;/h2&gt;

&lt;p&gt;So there’s a companion protocol called Titan which allows you to upload files. The Titan protocol uses the same status codes as gemini and works just fine in-band.&lt;/p&gt;

&lt;p&gt;gemini:// and titan:// are pretty much the same, titan just adds a filename and size parameter inside the META section of the request. Very easy to parse.&lt;/p&gt;

&lt;h3 id=&quot;spartan&quot;&gt;spartan://&lt;/h3&gt;

&lt;p&gt;Spartan was a bit more involved, as it’s not compatible with gemini. It uses a different default port and no encryption. Also the status codes are not identical to those of gemini. I’ve had to open another socket for spartan and write custom handlers for all the different requests. Although the protocol itself is very similar to gemini - simpler really - it is different enough to require a second codepath for parsing requests and sending responses.&lt;/p&gt;

&lt;h3 id=&quot;vhosts&quot;&gt;vhosts&lt;/h3&gt;

&lt;p&gt;Gemini Virtual-Hosts can be easily implemented by looking at the SNI parameter in the TLS handshake, spartan doesn’t use TLS, so they put the hostname into the request header - no problems there.&lt;/p&gt;

&lt;h3 id=&quot;cgi-bin&quot;&gt;cgi-bin&lt;/h3&gt;

&lt;p&gt;CGI scripting was super easy too, just a bunch of different environment variables that get passed to the script and its output redirected to the user’s browser. Authorisation and authentication can be done using the client certificate when the request comes from gemini. If the request comes from spartan however, the script has to do the heavy lifting. Maybe there shouldn’t be any authorization or authentication with spartan since its a plaintext protocol and passwords or tokens would be suseptible to MITM attacks.&lt;/p&gt;

&lt;h3 id=&quot;directory-index&quot;&gt;directory index&lt;/h3&gt;

&lt;p&gt;Directory Listing was implemented directly in the server and creates a nicely spaced list of files. I’ve not done directory navigation yet though. That shouldn’t be too hard though.&lt;/p&gt;

&lt;h3 id=&quot;config&quot;&gt;config&lt;/h3&gt;

&lt;p&gt;For configuring atlas, i’ve settled on a simple JSON file.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1965&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Capsules&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sallsave.net&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/sallsave.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteTlsCertPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/sallsave.net/sallsave.net.pfx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;FQDN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sallsave.net&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.gmi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Locations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/sallsave.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.gmi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;evilcorp.net&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/evilcorp.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteTlsCertPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/evilcorp.net/evilcorp.net.pfx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;FQDN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;evilcorp.net&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.gmi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;MaxUploadSize&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4194304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Locations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/evilcorp.net/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.gmi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/evilcorp.net/cgi/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;script.csx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;CGI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;RequireClientCert&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AbsoluteRootPath&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/srv/gemini/evilcorp.net/files/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.gmi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;DirectoryListing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AllowFileUploads&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AllowedMimeTypes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text/*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;MaxSizeBytes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1048576&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;image/*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;audio/mpeg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;audio/ogg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;audio/wave&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I took some inspiration from nginx there and since gemini, spartan and titan rely heavily on mimetypes, I’ve added a TSV file of mimetypes that can be easily edited by hand.&lt;/p&gt;

&lt;h3 id=&quot;docker&quot;&gt;docker&lt;/h3&gt;

&lt;p&gt;To make deployment easy, I’ve added docker support.
you can pull it from dockerhub&lt;/p&gt;

&lt;p&gt;&lt;em&gt;docker pull herstfortress/atlas:latest&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;make sure you mount two volumes, one for /srv and one for /etc
the config belongs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/atlas/config.json&lt;/code&gt; and the capsules in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/srv/gemini/my.capsule.com/&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;code&quot;&gt;code&lt;/h3&gt;

&lt;p&gt;The code can be found on &lt;a href=&quot;https://github.com/Alumniminium/atlas&quot;&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s basically it for now.&lt;/p&gt;

&lt;p&gt;You can check out a demo at:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://ec.her.st/&quot;&gt;gemini://ec.her.st/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;spartan://ec.her.st/&quot;&gt;spartan://ec.her.st/&lt;/a&gt;&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>the http web is a lost cause</title>
        <id>https://her.st/usr/bin/http-a-lost-cause.html</id>
        <link href="https://her.st/usr/bin/http-a-lost-cause.html" />
        <webfeeds:cover image="/assets/images/gemini.webp" />
        <webfeeds:icon>/assets/images/gemini.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/gemini_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-08-20T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;&lt;em&gt;I’m going to refer to the HTTP/S-BASED internet as ‘web’ from here on out&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back in the 80s, the web was a new medium for communication, used by real people to communicate with each other. You’d find a website of someone who wrote about something he was interested in and nothing more. No ads, no tracking, no “call to action” buttons, no JavaScript. There were no newsletters or sign-up forms - just a simple website with a couple of pages that linked to other websites with interesting content. That was the time of truly original content. People would make their “WebRings” and have a page dedicated to linking to other people’s websites.&lt;/p&gt;

&lt;p&gt;That’s how you found ‘content’ on the web before search engines like Google ruined it all by incentivizing people to embedd ads, tracking code and keywords into every single page and do shit like “Search Engine Optimization” to get more traffic. In the 90s, more and more people started to get on it and businesses started to get really interested too. It was all about email, and how to use it to market your business and get more people to buy your stuff.&lt;/p&gt;

&lt;p&gt;Today, it’s a big mess. The web is mostly used by businesses. People don’t create websites anymore, they sign up at a couple ‘Social-Media’ platforms and use it to post pictures of food and to repeat what media outlets say to virtue-signal and get a lot of ‘likes’ and ‘shares’ on their posts. It’s used to crowdsource ‘clout’ and dopamine kicks. They know what they are doing. Everyone on the right side of the bell-curve knows what they are doing.&lt;/p&gt;

&lt;p&gt;There are no real people anymore, just a bunch of algorithms that have an Instagram account. I came to the conclusion that the web is not an actual medium that allows you to reach an audience or to share your ideas with the world. It’s an illusion. It’s a bunch of websites that people create for the sole purpose of making money from advertisers. The people running them spend more time on SEO and automation than they do on the actual content.&lt;/p&gt;

&lt;h2 id=&quot;all-browsers-are-spywaremalware-by-google&quot;&gt;all browsers are spyware/malware by Google&lt;/h2&gt;

&lt;p&gt;I’m going to keep this section short, you can &lt;a href=&quot;/usr/bin/which-browser-for-privacy.html&quot;&gt;read my browser post&lt;/a&gt; and &lt;a href=&quot;https://digdeeper.club/articles/browsers.xhtml&quot;&gt;dig deeper&lt;/a&gt; yourself.&lt;/p&gt;

&lt;p&gt;Mozilla gets the majority of its budget from Google and Firefox just exists as a legal shield for Google against an anticompetitive/monopoly lawsuit.
Firefox will die as soon as Google pulls the funding from Mozilla.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT WHAT ABOUT [[PRIVACY BROWSER NAME]]???!?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They are based on firefox or chromium. They exist at the mercy of Google.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT [[BROWSER NAME]] HAS ITS OWN ENGINE!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes and that browser can’t display half of the websites correctly.&lt;/p&gt;

&lt;center&gt;
&lt;i&gt;burn it all down and rebuild it from the ashes&lt;/i&gt;
&lt;br /&gt;
&lt;img src=&quot;/assets/images/gemini.webp&quot; alt=&quot;best viewed on gemini&quot; /&gt;
&lt;/center&gt;

&lt;h1 id=&quot;gemini&quot;&gt;gemini&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;You may think of Gemini as “the web, stripped right back to its essence” or as “Gopher, souped up and modernised just a little”, depending upon your perspective (the latter view is probably more accurate) – Project Gemini FAQ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gemini is a new protocol (june 2019) that explicitly states that it opposes the use of the web for anything other than displaying content. No ads, no tracking, no “call to action” buttons, no JavaScript. Just a lightweight browser that can display .gmi files.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;as of early 2021 there were about 200,000 known Gemini URLs, spread across about 750 “capsules” (the Gemini community’s term for “sites”), 500 domains and 600 IP addresses. – Project Gemini FAQ&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Protocol is so simple that it’s possible to implement it and create a basic browser  in a single weekend. I’m going to attempt this myself - stay tuned for that - it’s a fun project. Also there seems to be a lot of interest in the project.&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;gemini://gemini.bortzmeyer.org/&quot;&gt;the statistics (gemini uri)&lt;/a&gt; there’s 2622 of them, totaling about half a million of URIs.&lt;/p&gt;

&lt;p&gt;There’s quite a bit of content on gemini!&lt;/p&gt;

&lt;h2 id=&quot;no-server-side-styling&quot;&gt;no server-side styling&lt;/h2&gt;

&lt;p&gt;There’s no css support. There’s no styling support what-so-ever on the server. The rationale is, the CLIENT is the one who decides how to display the content. Finally we can have unified styling across all sites! No need for ‘dark mode’ extensions that make the content look like shit.&lt;/p&gt;

&lt;h2 id=&quot;the-protocol-will-never-change&quot;&gt;the protocol will never change&lt;/h2&gt;

&lt;p&gt;If you write your own client for fun, you can use the protocol today, tomorrow and in 10 years, without having to update your code.&lt;/p&gt;

&lt;h2 id=&quot;the-markup-language-will-never-change&quot;&gt;the markup language will never change&lt;/h2&gt;

&lt;p&gt;The markup language is Gemtext. It’s a simple markup language that will not change.
Unlike Markup (and Markdown…) which has different flavours, Gemini Markup is consistent.&lt;/p&gt;

&lt;h2 id=&quot;gemini-markup&quot;&gt;gemini markup&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Long lines get wrapped by the client to fit the screen&lt;/li&gt;
  &lt;li&gt;Short lines &lt;em&gt;don’t&lt;/em&gt; get joined together unlike Markdown&lt;/li&gt;
  &lt;li&gt;Write paragraphs as single long lines&lt;/li&gt;
  &lt;li&gt;Blank lines are rendered as blank lines&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;language-gemtext&quot;&gt;Headings
# Heading
## Sub-heading
### Sub-Sub-heading

List
* Mercury
* Gemini
* Apollo

Quote
&amp;gt; I contend that text-based websites should not exceed in size the major works of Russian literature.

Code
    ```
        echo &quot;Hello World&quot;
    ```

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that’s it. Easy to learn, easy to style locally, easy to parse and render. There’s no special syntax.&lt;/p&gt;

&lt;h2 id=&quot;quickstart&quot;&gt;quickstart&lt;/h2&gt;

&lt;p&gt;I’m currently using &lt;a href=&quot;https://gmi.skyjake.fi/lagrange/&quot;&gt;lagrange, a gui client&lt;/a&gt; until my own one is done. The website looks exactly like how the client renders gemini sites out of the box. &lt;a href=&quot;https://geminiquickst.art/&quot;&gt;geminiquickst.art&lt;/a&gt; is a great place to start exploring.&lt;/p&gt;

&lt;h2 id=&quot;gemini-sites-capsules&quot;&gt;gemini sites (capsules)&lt;/h2&gt;
&lt;!-- [gem.her.st - my gemini site](gemini://gem.her.st/) --&gt;

&lt;p&gt;&lt;a href=&quot;gemini://gemini.bortzmeyer.org/&quot;&gt;gemini.bortzmeyer.org - Crawler, Statistics about Capsules, Gemini Software&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://heavysquare.com/&quot;&gt;heavysquare.com - A personal blog about tech, coding and random thoughts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://astrobotany.mozz.us/&quot;&gt;astrobotany.mozz.us - Virtual Garden Game&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://mozz.us/&quot;&gt;mozz.us - cool collection of projects like geminichat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://tilde.pink/&quot;&gt;tilde.pink -  tilde.pink is an open tilde server, providing shell, email, and gopher/gemini accounts.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://konpeito.media/&quot;&gt;konpeito.media - Low-Fi Music&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;gemini://rawtext.club/&quot;&gt;rawtext.club - Resist the dazzling spectacle of mainstream social and news media.&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;have-fun&quot;&gt;have fun&lt;/h3&gt;

&lt;p&gt;I’ll be writing my own gemini server called &lt;a href=&quot;https://en.wikipedia.org/wiki/Atlas-Agena&quot;&gt;Atlas&lt;/a&gt; and my own client called &lt;a href=&quot;https://en.wikipedia.org/wiki/Extravehicular_activity&quot;&gt;EVA&lt;/a&gt; now - following the gemini naming convention.&lt;/p&gt;

&lt;p&gt;Peace!&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>the RG351MP</title>
        <id>https://her.st/usr/bin/the-rg351mp.html</id>
        <link href="https://her.st/usr/bin/the-rg351mp.html" />
        <webfeeds:cover image="/assets/images/rg351mp.webp" />
        <webfeeds:icon>/assets/images/rg351mp.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/351ELEC-PF_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2022-03-13T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;the-software&quot;&gt;the software&lt;/h1&gt;

&lt;p&gt;I have no idea what the factory shipped, I was afraid of anbernic-poisoning so I immediately went to flash ArkOS … 3 times… unsuccessfully and then settled for 351elec @ &lt;a href=&quot;https://351elec.de/&quot;&gt;https://351elec.de/&lt;/a&gt;.
&lt;img src=&quot;/assets/images/351ELEC-PF.webp&quot; alt=&quot;351elec logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;elec was a new experience for me. Linux, yes, but everything runs as root, there are no users, no homes, not even a package manager. Getting dotnet and monogame up and running was quite the adventure.&lt;/p&gt;

&lt;!-- *I&apos;ve written a wiki page on how to make c#/monogame work over at 351elec.de by the time you read this* --&gt;

&lt;p&gt;Now, what can this thing do? Let’s look at the hardware so we can get a rough idea about its capabilities.&lt;/p&gt;

&lt;h3 id=&quot;cpu-rk3326&quot;&gt;CPU: RK3326&lt;/h3&gt;

&lt;p&gt;The official Anbernic Store says its a 1.5ghz CPU, that however is a &lt;em&gt;lie&lt;/em&gt;. It runs at 1.3ghz. I’ll be taking a look at overclocking later, maybe I can make it true.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Quad-core ARM Cortex-A35 CPU&lt;/li&gt;
  &lt;li&gt;ARM Neon Advanced SIMD&lt;/li&gt;
  &lt;li&gt;ARMv8 Cryptography Extensions&lt;/li&gt;
  &lt;li&gt;256KB unified system L2 cache&lt;/li&gt;
  &lt;li&gt;VFPv3 single and double-precision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alright, so we’re dealing with an Ultra-Low-Power CPU from long-long-ago. The L2 cache is hilariously small, there’s no L3 cache at all.
1GB of DDR3L RAM is not fast either and the GPU will share it with the CPU, making it even slower. Small cache, slow RAM, I’m predicting a memory bandwidth bottleneck. At least it can do SIMD, so we can vectorize our code. Now let’s look at the GPU.&lt;/p&gt;

&lt;h3 id=&quot;gpu-mali-g31-mp2&quot;&gt;GPU: Mali G31 MP2&lt;/h3&gt;

&lt;p&gt;Further research shows it’s running at 650 MHz, has two cores and can push 1,3 GPix/s, 980 MT/s or 21.4 GFLOPs.
Interestingly, ARM claims 4x MSAA has almost no performance overhead - we’ll see about that!
Also surprisingly, it supports Vulkan!&lt;/p&gt;

&lt;h5 id=&quot;apis&quot;&gt;APIs&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;OpenGL ES 3.2&lt;/li&gt;
  &lt;li&gt;Vulkan 1.1&lt;/li&gt;
  &lt;li&gt;OpenCL 2.0&lt;/li&gt;
  &lt;li&gt;h264,h265,VP9 - Decode &amp;amp; Encode&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;handheld-xbox&quot;&gt;handheld xbox&lt;/h3&gt;

&lt;p&gt;So we’re basically working with an original xbox in terms of performance - with some extra CPU cores and newer feature-sets. Sweet.&lt;/p&gt;

&lt;p&gt;Anbernic was smart enough to use a low resolution screen, namely a 3.5”, 640x480 @ 60hz IPS screen.&lt;br /&gt;
Most manufacturers would have slapped a 720p or 1080p screen on it just for marketing and cripple the rest of the hardware, but at 640x480, there aren’t many pixels to push.&lt;/p&gt;

&lt;p&gt;I want to add that the screen is super crisp. The resolution is more than enough for the size.&lt;/p&gt;

&lt;h4 id=&quot;getting-distracted&quot;&gt;getting distracted&lt;/h4&gt;

&lt;p&gt;Suikoden, Pokemon, Earthbound, Batsugun, Alien Soldier, Advance Wars 2, Tekken 3…. I’ve already wasted a couple of hours writing this post, even at this moment, it’s next to me playing some demo videos of random games as screensaver (which you can jump into by pressing start, launching the game that’s currently playing, super cool!) begging me to pick it up or at least look at it.&lt;/p&gt;

&lt;p&gt;Can’t wait to play some more Destruction Derby later, but the dog will want out before I’m done writing. Ugh.&lt;/p&gt;

&lt;h1 id=&quot;game-development&quot;&gt;game development&lt;/h1&gt;

&lt;p&gt;The primary reason for me to even buy this device has been to give me some additional motivation for creating games. I want to target the RG351 directly and make it my primary platform. I figured becoming a console game developer would be cool as it would impose a lot of hard limitations on me - not only in terms of performance, but also input methods and screen size.&lt;/p&gt;

&lt;p&gt;elec is a readonly OS. Every reboot - it resets. Persistent storage is only possible in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/storage&lt;/code&gt;. Which is the 2nd uSD card in the RG351MP. That’s fine by me.&lt;/p&gt;

&lt;p&gt;Since elec has no real shell, ships almost no libraries and has no terminal, we need to setup a couple of things like a script to launch our game and find/ship all the files required for the game to function. On MonoGame you need to ship &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libGL.so.1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libEGL.so.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;351elec is a 64bit OS and the RK3326 is an ARM CPU, that makes our dotnet command&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotnet publish -c release -r linux-arm64&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;but first we have to enable single file output.&lt;/p&gt;

&lt;p&gt;csproj&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class=&quot;nt&quot;&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;net6&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;MonoGamePlatform&amp;gt;&lt;/span&gt;DesktopGL&lt;span class=&quot;nt&quot;&gt;&amp;lt;/MonoGamePlatform&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TieredCompilation&amp;gt;&lt;/span&gt;false&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TieredCompilation&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;PublishSingleFile&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/PublishSingleFile&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;SelfContained&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/SelfContained&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;now we scp the contents of the publish folder and create our little launcher script&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;gamedir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/storage/roms/ports/test/&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/opt/system/Tools/PortMaster/&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controlfolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/system/Tools/PortMaster&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/opt/tools/PortMaster/&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controlfolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/tools/PortMaster&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/roms/ports&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controlfolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/roms/ports/PortMaster&quot;&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/roms2/ports&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controlfolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/roms2/ports/PortMaster&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controlfolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/storage/roms/ports/PortMaster&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Starting Pixel Engine (.net6, C#10, ECS) by https://her.st/&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/tty0
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$controlfolder&lt;/span&gt;/control.txt
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$controlfolder&lt;/span&gt;/tasksetter.sh

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LIBGL_ES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;31
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LIBGL_FB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SDL_VIDEO_GL_DRIVER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$gamedir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/libs/libGL.so.1&quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$gamedir&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$GPTOKEYB&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Pixel&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./test.gptk&quot;&lt;/span&gt; &amp;amp;
&lt;span class=&quot;nv&quot;&gt;$TASKSET&lt;/span&gt; ./Pixel &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/tty0
&lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-9&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;pidof gptokeyb&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;33c&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /dev/tty0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;map.gptk:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;back = esc
start = enter
a = enter
b = up
x = \&quot;
y = \&quot;
l1 = mouse_right
l2 = mouse_right
r1 = mouse_left
r2 = mouse_left
up = w
down = s
left = a
right = d
left_analog_up = up
left_analog_down = down
left_analog_left = left
left_analog_right = right
right_analog_up = mouse_movement_up
right_analog_down = mouse_movement_down
right_analog_left = mouse_movement_left
right_analog_right = mouse_movement_right
deadzone_triggers = 3000
mouse_scale = 8192
mouse_delay = 16
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The “game” will now show up in 351elec and you’ll be able to launch it.&lt;/p&gt;

&lt;p&gt;That’s as far as I got in a day. Documentation didn’t exist so I had to reverse engineer other ports to figure out how to port &amp;gt;.&amp;gt;
I got my PixelGlue engine running, tomorrow I’ll get inputs working properly…&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;conclusion&lt;/h2&gt;

&lt;p&gt;For game development on the RG351MP, the architectural choice seems obvious -&amp;gt; ECS&lt;/p&gt;

&lt;p&gt;We need to hit the cache or we cripple the GPU with increased memory bandwidth requirements from the CPU side. It will be essential to use all four cores as they’re rather weak.&lt;/p&gt;

&lt;p&gt;Vulkan goes without saying, however that’s out of reach for me at this point. I lack the required skills.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s smaller yet heavier than expected (i didn’t check the measurements)&lt;/li&gt;
  &lt;li&gt;The D-PAD lacks a center pin, it can press all directions at once - and often does so&lt;/li&gt;
  &lt;li&gt;The screen isn’t very vibrant and quite dim - no usage outdoors if sun&lt;/li&gt;
  &lt;li&gt;The sound is meh. NO bass, muddy mids, exaggerated highs.&lt;/li&gt;
  &lt;li&gt;The battery life seems to be 5 hours, not 8&lt;/li&gt;
  &lt;li&gt;You can’t really use both analog sticks at once due to ergonomics&lt;/li&gt;
  &lt;li&gt;Too slow for N64, Dreamcast, PSP.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;stay-tuned-for-part-2&quot;&gt;stay tuned for part 2&lt;/h1&gt;

        </content>
    </entry>
    
    <entry>
        <title>how VPNs are not helping you</title>
        <id>https://her.st/usr/bin/how-vpns-are-not-helping-you.html</id>
        <link href="https://her.st/usr/bin/how-vpns-are-not-helping-you.html" />
        <webfeeds:cover image="/assets/images/vpns-big.webp" />
        <webfeeds:icon>/assets/images/vpns-big.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/vpns-big_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2021-08-10T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;First of all, a VPN will only hide information from your ISP as you are encrypting everything on your computer and then send it to the VPN provider which then decrypts it and passes it on to the open internet. This means the VPN provider itself has the ability to see exactly what you’re doing and keep records of every packet you send through it.&lt;/p&gt;

&lt;h2 id=&quot;what-if-vpns-are-illegal-in-your-country&quot;&gt;what if vpns are illegal in your country&lt;/h2&gt;

&lt;p&gt;Then you’re fucked as soon as you connect.&lt;/p&gt;

&lt;center&gt;&lt;img src=&quot;/assets/images/vpn1.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;
&lt;center&gt;&lt;img src=&quot;/assets/images/vpn2.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

&lt;p&gt;The popular VPN protocols like OpenVPN and WireGuard are easily detected on the network. Even if your government doesn’t know what sites you access, they see that you are using a VPN and the IP of the VPN server you’re connected to. Now they can call your ISP, get your address and come arrest you. They don’t even have to go to the VPN provider in that situation.&lt;/p&gt;

&lt;p&gt;SSH is usually not monitored though, and supports tunneling. If you happen to own a vps somewhere that isn’t directly connected to you, you might create a socks5 tunnel quite easily&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh &lt;span class=&quot;nt&quot;&gt;-ND&lt;/span&gt; 8080 user@ho.st &lt;span class=&quot;c&quot;&gt;# Creates the socks5 proxy&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; socks5h://localhost:8080 https://wtfismyip.com/text &lt;span class=&quot;c&quot;&gt;# uses the proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;center&gt;&lt;img src=&quot;/assets/images/vpn3.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

&lt;p&gt;but make no mistake, ssh tunnels have a considerable impact on your net speed, especially ping times.&lt;/p&gt;

&lt;center&gt;&lt;img src=&quot;/assets/images/speed1.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

&lt;p&gt;compared to without the tunnel&lt;/p&gt;

&lt;center&gt;&lt;img src=&quot;/assets/images/speed2.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

&lt;p&gt;That’s just a socks proxy though, not a VPN. DNS for example will still bypass the tunnel.&lt;/p&gt;

&lt;h2 id=&quot;vpns-are-legal-and-my-vpn-provider-doesnt-keep-logs&quot;&gt;vpn’s are legal and my vpn provider doesn’t keep logs&lt;/h2&gt;

&lt;p&gt;Let’s give them the benefit of doubt and say they really don’t. Who’s to say the Datacenter they reside in doesn’t? After all, packets from protocols like OpenVPN are easily identified on their infrastructure - as I’ve made evident above.&lt;/p&gt;

&lt;p&gt;Additionally, if the VPN you’re using is in any of the following countries&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Australia&lt;/li&gt;
  &lt;li&gt;British Overseas territories (e.g. British virgin islands)&lt;/li&gt;
  &lt;li&gt;Canada&lt;/li&gt;
  &lt;li&gt;Israel&lt;/li&gt;
  &lt;li&gt;Japan&lt;/li&gt;
  &lt;li&gt;New Zealand&lt;/li&gt;
  &lt;li&gt;United Kingdom&lt;/li&gt;
  &lt;li&gt;United States&lt;/li&gt;
  &lt;li&gt;Denmark&lt;/li&gt;
  &lt;li&gt;Netherlands&lt;/li&gt;
  &lt;li&gt;France&lt;/li&gt;
  &lt;li&gt;Norway&lt;/li&gt;
  &lt;li&gt;Germany&lt;/li&gt;
  &lt;li&gt;Belgium&lt;/li&gt;
  &lt;li&gt;Spain&lt;/li&gt;
  &lt;li&gt;South Korea&lt;/li&gt;
  &lt;li&gt;Singapore&lt;/li&gt;
  &lt;li&gt;Sweden&lt;/li&gt;
  &lt;li&gt;Italy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are required &lt;em&gt;by law&lt;/em&gt; to have logs and share them with the authorities.
Even if they &lt;em&gt;claim&lt;/em&gt; not to keep logs. If you live in one of them, your government can spy on you by proxy - simply report you to a member-state and request the data from them.&lt;/p&gt;

&lt;p&gt;Additionally, in order to pay the VPN provider, you have to give them your payment details which are directly linked to you. The only VPN provider on the clear-net that allows cash payments and no sharing of personal details - as far as I know - is &lt;a href=&quot;https://mullvad.net/&quot;&gt;mullvad&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you think your VPN provider will defend you when they get pressured/threatened by a government to surrender the data they have about you? Risking their business? Their money? Don’t be naive.&lt;/p&gt;

&lt;center&gt;&lt;img src=&quot;/assets/images/capitalism2.gif&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

        </content>
    </entry>
    
    <entry>
        <title>which browser for privacy</title>
        <id>https://her.st/usr/bin/which-browser-for-privacy.html</id>
        <link href="https://her.st/usr/bin/which-browser-for-privacy.html" />
        <webfeeds:cover image="/assets/images/privacybrowser.webp" />
        <webfeeds:icon>/assets/images/privacybrowser.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/privacybrowser_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2021-08-03T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;A common misconception is that cookies are used for tracking and cleaning cookies or pre-emptively blocking some or even all 3rd party cookies will make you untraceable.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That might have been the case 10 years ago.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today they are tracking you by identifying your browser’s and by extension your system’s unique characteristics. That’s what people mean when they talk about ‘fingerprinting’ and - contrary to what some cybersecurity ‘experts’ tell you in their YouTube videos or blogs - there’s &lt;em&gt;nothing&lt;/em&gt; you can do against it.&lt;/p&gt;

&lt;h2 id=&quot;but-some-browsers-prevent-fingerprinting&quot;&gt;but some browsers prevent fingerprinting&lt;/h2&gt;

&lt;p&gt;Yeah so they claim but they don’t &lt;em&gt;really&lt;/em&gt; prevent it. Let’s take Brave Browser for example. They have a unique set of measures they take against fingerprinting you, like for example blocking canvas read access or changing the list of fonts it reports to be installed on the host. You might already noticed the issue: a unique set of measures. Already they can deduce that the browser in use is Brave, can simply fingerprint based on other characteristics and so you become - yet again - traceable.&lt;/p&gt;

&lt;h2 id=&quot;who-are-they-and-what-do-they-use-to-fingerprint-you&quot;&gt;who are ‘they’ and what do they use to fingerprint you&lt;/h2&gt;

&lt;p&gt;Primarily Google and Facebook.&lt;/p&gt;

&lt;p&gt;Google Analytics is on 99.9% of websites that show up on a google search. It doesn’t stop with google analytics though, they also own YouTube and many websites embed YouTube videos.
Facebook has the infamous Like button and embedded content, like Photos, Videos, Comments …
Both also happily let you sign up with their accounts elsewhere - “Register using Google/Facebook” or “Link your Social Account”.&lt;/p&gt;

&lt;p&gt;It gets far more insidious when you consider all the spin-offs they own and you probably use as well, like Facebook Messenger, Google Hangouts, WhatsApp, Gmail,…&lt;/p&gt;

&lt;p&gt;If you use any of that, it now has a name to your fingerprint, a phone number, emails and all their contents which tell them which other websites you have an account on, where you work and which jobs you applied to among a plethora of other more or less sensitive data.&lt;/p&gt;

&lt;p&gt;If you pool all that information together (they do that completely automated) they pretty much know exactly who you are, what you do, where you are and what you like/dislike.&lt;/p&gt;

&lt;h2 id=&quot;so-what-is-the-solution&quot;&gt;so what is the solution&lt;/h2&gt;

&lt;p&gt;There’s only one real solution. Get rid of Facebook and google. Close your accounts, never go back to them. Don’t use google to search the internet (use Searx, Startpage), don’t use YouTube to watch videos (use PeerTube, Odysee/LBRY), don’t use Facebook to stay in touch with your friends and family (meet, chat using XMPP or signal) and instead of GMail, host your own or find yourself an alternative.&lt;/p&gt;

&lt;h2 id=&quot;what-if-i-cant-get-rid-of-it&quot;&gt;what if i can’t get rid of it&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;There’s still a way but it’s tedious and easy to fuck up.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Isolate your browsing habits to different browsers and create new accounts wherever possible.&lt;/li&gt;
  &lt;li&gt;Have one browser for Facebook.&lt;/li&gt;
  &lt;li&gt;Have one browser for Google Services and&lt;/li&gt;
  &lt;li&gt;and another for everything else that’s in no way connected to your Google/Facebook accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;AND PAY ATTENTION&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;you probably created a bunch of accounts in other places with Facebook/Google Social Login &lt;em&gt;OR YOUR GMAIL ADDRESS&lt;/em&gt;. Some accounts might even be connected to both. Logging into any account that’s connected to either outside of the designated browser will set you back to square one. Create new accounts if you ever linked them to your social accounts.&lt;/p&gt;

&lt;h2 id=&quot;browser-recommendations&quot;&gt;browser recommendations&lt;/h2&gt;

&lt;p&gt;While avoiding Google Chrome and Microsoft Edge might be obvious and needs no explanation, I also avoid Firefox and Brave.&lt;/p&gt;

&lt;p&gt;Firefox blogs about &lt;a href=&quot;https://blog.mozilla.org/en/mozilla/we-need-more-than-deplatforming/&quot;&gt;pro-cancel culture stuff&lt;/a&gt; and uses Google Search by default - which is their biggest source of income.&lt;/p&gt;

&lt;p&gt;Brave has a history of &lt;a href=&quot;https://www.theverge.com/2020/6/8/21283769/brave-browser-affiliate-links-crypto-privacy-ceo-apology&quot;&gt;rewriting urls you visit with their affiliate ones&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past I’ve recommended browsers like Dissenter, WaterFox… all of them turned out to be evil. Might as well just abandon hope and give up on the Web.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc1436&quot;&gt;Gopher could be an alternative&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;is-that-enough&quot;&gt;is that enough?&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>imposter-syndrome as competitive edge</title>
        <id>https://her.st/usr/bin/imposter-syndrome-as-competitive-edge.html</id>
        <link href="https://her.st/usr/bin/imposter-syndrome-as-competitive-edge.html" />
        <webfeeds:cover image="/assets/images/morpheus.webp" />
        <webfeeds:icon>/assets/images/morpheus.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/morpheus_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2020-08-27T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;my-aquired-imposter-syndrome&quot;&gt;my aquired imposter-syndrome&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;no, this isn’t clickbait and I’ll make a case for it&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I started getting into programming almost 14 years ago - when I was 14 - i was immersed in a developer community with a handful of very gifted programmers but also hundreds of copy/paste kids from the first minute. I had joined an english-only private server community that wrote MMORPG servers from scratch.. as someone who could barely order a drink in english and didn’t even know how to pronounce ‘C#’. Thankfully, there was a guide on how to download some source code, compile it and how to connect your game client to it, it required zero programming knowledge and was basically unzip and F5 in visual studio. Half an hour later I was writing an advertisement about my new server.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;They tore me apart like fucking vultures.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When reality comes crashing down on you, you have a binary choice: accept it or go into denial. I had no idea what I was doing and people were quick to point that out. My first choice was denial. I defended myself saying most other servers are using the same source code and have the same problems and my Hamachi room was better and my uptime was from after-school hours till the morning before I had to turn off my computer (ahh what i’d give to be 14 again). I felt like i was competing nicely with the majority but people immediately pointed out that ‘just because the majority is a bit more shit it doesn’t meant my shit is good’&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I felt horrible - because they started making sense.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having players play on my shitty server - talking with me, encouraging me, telling me about all the known bugs and exploits,.. - was a source of good feels though, so I couldn’t just quit. I had found something that truly gave me joy in life, i was passionate and driven. I’d just scroll through the code files and read everything trying very hard to understand at least a single line. I’d read the threads on the forum, 200 pages in one go if it was that long, to get some insight into programming; what were people talking about? Is anyone posting code? Is there something I could copy paste?&lt;/p&gt;

&lt;p&gt;There was a lot of discourse, my english was too bad to make sense of most of it but i was persistent! Failure was not an option, I’d prove all those cunts wrong and learn how to fix the problems and create something they couldn’t criticize anymore, force them to see me as an equal! How they saw me instead was a kiddy who couldn’t do anything bot leech off of others and copy paste together some shit others had to write.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Back to feeling terrible I guess.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After some weeks of copy paste I had the skill of a GOD… &lt;em&gt;in copy paste&lt;/em&gt; … still couldn’t write any code myself but at least I somehow figured out how scopes work and where I have to paste stuff and that I sometimes had to rename a variable. Most of the other people leeching code couldn’t figure out where to paste stuff and if there was a typo somewhere they’d complain on the forums about “shit releases” because the “code doesn’t work”. That gave me some joy. Additionally I had picked up a couple terms and keywords, i had a rough idea what an integer and a string was, i knew about semicolons and curly braces and one guide that showed how to add a new NPC to the game was easily deconstructed into the knowledge of how to edit existing NPCs. That opened up a lot of new terrain for me. Now I’d be able to create some basic quests! I’d spend days to build a trivial ‘talk to A then talk to B then get item C’ quests. My players liked what I was doing and the american / british players I had would improve the grammar, spelling and wording and I’d update the code. I felt good again! Posted my first ‘guides’ on how to make those quests on the forums, .. and get torn into pieces by people shitting all over my code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hello darkness my old friend…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Months later, I’d have hardly any issues reading english forum posts, i’d read parts of code and understand them. I finally discovered StackOverflow! Now I could ask my questions there and get answers from professionals! Wrong. I got shamed and banned within a week. There’s been some leaks of new source code with much more features, it wasn’t as easy to setup, required MySQL and Apache, config files and it was unstable as fuck. But I knew i needed to make it work to stay competitive.
I’d spend the first day trying to figure out what MySql was, what apache was, how i’d get the database imported and the server connected to it, how to create a SignUp page in php, ended up paying someone 10$ for a blank page with a username and password box and a submit button. That’s when I created my first paypal account at the age of 15 and spending half my monthly pocket money. &lt;em&gt;Paypal was supposed to be 18+ but in the early days they didn’t do any verification.&lt;/em&gt; Sadly that ruined the end of the month. I had to pay 20$ a month for 1GB of 3G internet and I just spent half of it. So a couple days later internet was gone for the rest of the month. Without any internet all I had was trial and error, changing random stuff and see what happens, do more NPCs and quests, write a list of things to google when I had internet again,.. and fearing that all my players would bail on me for the long downtime.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;and i couldn’t blame anyone but me&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two years later, I’d be comfortable writing code, implement custom features nobody else had ever even thought about. I’d stay in the top 3 for months, have the most popular private servers for a year while the big guys took a break working on their next version. Those big guys still saw me as the same Leecher I had been in the beginning. They’d always talk shit about me, when I posted code they’d still heavily scrutinize it and find 500 things wrong in a 100 character line of code. It got to a point where I thought i was just a complete failure. I felt like I improved A LOT but the people i looked up to and wanted recognition from wouldn’t give it to me, just the polar opposite. Another problem was that I had reached the stage where I could actually understand their criticism and see the truth in it. There was no denial anymore, I knew they were right. I was proud of how good I had become on my own but the people I looked up to would always prove that I hadn’t become good at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I felt like a complete scam.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I took a break from the private server scene and bought a book on C#, read it, did all the practices, it was horribly boring. I stated writing some random utility tools for my personal use, made some tools for friends, dabbled with GUI programming and chat applications. My coding abilities were very much constrained to the MMORPG servers I was working on. I had no idea how to do anything else but I learned quickly after a slow start. Writing my own chat client/server to replace MSN was the first project i got really into since taking a break from the private server development. Eventually I realized that I could probably write my own private server from scratch as its just like a chat server, just with different logic and more packet types - which were already available in the community.&lt;/p&gt;

&lt;p&gt;So I started writing my own. I’d have two, three sometimes four reference projects open in visual studio, initially copying a lot of parts without modifying them in any meaningful way, primarily the cryptographer, the packets, the packet parsers, and the calculations and dice-rolls. After 5 months I had something that was almost playable. You could login, kill monsters, get experience, use skills, talk to NPCs,.. all of the basic stuff worked - more or less. Surely now they couldn’t call me a leech anymore, right?  “Half of the code is leeched and the other half is even worse”&lt;/p&gt;

&lt;center&gt; &lt;img src=&quot;/assets/images/pride.gif&quot; alt=&quot;pride&quot; /&gt; &lt;/center&gt;

&lt;p&gt;I’d never get a job if i didn’t start learning how to write proper code. If I want to turn my passion into my job I have to become as good as them. I started pestering the guys i idolized. Please teach me how I can improve, please show me your code so I can learn. No fuck off! Please! NO! PLEASE SELL ME YOUR CODE, ILL GIVE U 100$! 100$? Hahaha I spent months on this code its worth at least 300$! OK ILL GIVE YOU 300$!&lt;/p&gt;

&lt;p&gt;I probably spent 600$ on private server source codes in total. I bought some off of the guys directly, others I bought from people they trusted, others I manipulated into giving me their for free and even others I’d pester into letting me watch them code on TeamViewer. I’d ask for control to check out files and make sure I got every file from top to bottom for at least a moment. They didn’t know that I ran screen-recording software so I could slow it down later and type it all out. Which I did. It took hours and hours.&lt;/p&gt;

&lt;p&gt;Often times I’d look at their code and find myself dumbstruck by never having seen certain classes or attributes or unsafe code in unconventional places. I’d take parts of that code to StackOverflow or other people i knew and ask for explanation if google didn’t yield anything.&lt;/p&gt;

&lt;p&gt;I got quite good at this point. I was more than comfortable writing code, I even wrote another server from scratch, this time with minimal “inspiration”. And I made sure it used less RAM than any other public server, was more CPU efficient than any other public server, would never crash and would still have features nobody else had. I’d get sooo obsessed about optimizing code because I knew people would just shit on it again if it wasn’t perfect. I’d take courses about low level C# programming with unsafe code, I’d take courses on Threading and read CodeProject articles on “High Performance Sockets” and “Memory Allocations” all of that. Eventually I made my server run on a raspberry Pi - i realized that if I set my target hardware to something as powerful as a retarded potato, I’d have no problems with performance when I actually put it on a VPS for production.&lt;/p&gt;

&lt;p&gt;I’d get great results, everything would be fast enough, use weird memory optimizations like packing things in BitArrays, stackalloc, pointers, threads,.. and my code would look absolutely horrible every time i got half way through to completion… I always felt like a scam again. I mean after all, if I hated my code and could see 100 things that are wrong, im sure they could see 500 things that are wrong with it. I was too afraid to post anything anymore because I couldn’t take the shame.&lt;/p&gt;

&lt;h1 id=&quot;the-revelation&quot;&gt;the revelation&lt;/h1&gt;

&lt;p&gt;One of my idols had sold me his code and even after all my pestering, still talked to me and occasionally even answered some questions (though I’ll never forget his default response to 90% of my questions: “I forget D:”). He was a couple years older than me and had a job as a programmer when I sent him my latest server I had written from scratch. It was the first time he said “its not bad”.&lt;/p&gt;

&lt;center&gt; &lt;img src=&quot;/assets/images/happy.webp&quot; alt=&quot;happy&quot; /&gt; &lt;/center&gt;

&lt;p&gt;I said that one day I’ll become a professional software developer too and get a job in the industry and that I’ll keep learning until I’m useful and try to get into uni for a computer science degree.&lt;/p&gt;

&lt;h2 id=&quot;he-laughed-and-told-me-that-im-clearly-better-than-most-of-his-colleagues&quot;&gt;He laughed and told me that I’m clearly better than most of his colleagues&lt;/h2&gt;

&lt;p&gt;Telling me that some computer science graduates struggle with reversing an array and most juniors need someone to hold their hand just to write code that works - let alone efficiently or beautifully.&lt;/p&gt;

&lt;p&gt;He said that almost all code is shit code, that his code is shit code in his eyes, that it keeps him on his toes, pushing the limits, getting better, that if you are your own critic and take your criticism to heart and work with it, success is inevitable and you’ve earned the the right to call yourself a programmer.&lt;/p&gt;

&lt;p&gt;He said as soon as you become complacent you stagnate and become a fraud.&lt;/p&gt;

&lt;h2 id=&quot;today&quot;&gt;today&lt;/h2&gt;

&lt;p&gt;I’m convinced, Imposter-syndrome is just as bad as pride. Good servants but bad masters. The key is to find balance. Know what you can do, know what you can’t and be honest about both.&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>simplifying our image hosting service</title>
        <id>https://her.st/usr/bin/simplifying-our-image-hosting-service-without-csharp.html</id>
        <link href="https://her.st/usr/bin/simplifying-our-image-hosting-service-without-csharp.html" />
        <webfeeds:cover image="/assets/images/simplifyingimagehostservice.webp" />
        <webfeeds:icon>/assets/images/simplifyingimagehostservice.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/simplifyingimagehostservice_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2020-08-25T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;lets-cut-out-the-middle-man&quot;&gt;Let’s cut out the middle-man&lt;/h1&gt;

&lt;h2 id=&quot;-fuck-ftp&quot;&gt;$ fuck FTP&lt;/h2&gt;

&lt;p&gt;Last time we’ve setup vsftp to handle our image uploads. This foolishness ends now. We’ve already got our SSH Server up and we can easily transfer files through it.
Let’s do that, shall we?&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt remove vsftp &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-fuck-apache&quot;&gt;$ fuck Apache&lt;/h2&gt;

&lt;p&gt;Apache configs suck.
Hello nginx.&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt remove apache2 &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nginx &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-setting-up-nginx&quot;&gt;$ setting up nginx&lt;/h2&gt;

&lt;p&gt;Let’s also change the domain from &lt;em&gt;h.img.alumni.re&lt;/em&gt; to &lt;em&gt;cdn.her.st&lt;/em&gt; as I’m not going to be using my homeserver anymore.&lt;/p&gt;

&lt;p&gt;We’re going to use &lt;em&gt;threaded async IO&lt;/em&gt; and &lt;em&gt;sendfile&lt;/em&gt; for maximum throughput on potentially big files like binary data, audio and video but not for small things like images and assets (which are mostly css and js text files). There’s some added latency involved when using threaded async IO so its only worth paying that overhead if the file tansfer will usually take more than a couple seconds. We really don’t want to add any additional latency to image requests as that would unnecessarily slow down page loading speed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/etc/nginx/sites-enabled/default&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/srv/http/cdn.her.st;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;index.html;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;server_name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;cdn.her.st;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;try_files&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/bin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;sendfile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;on;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;aio&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;threads;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;try_files&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/videos&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;sendfile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;on;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;aio&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;threads;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;try_files&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/audio&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;sendfile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;on;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;aio&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;threads;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;try_files&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/assets&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;sendfile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;on;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;try_files&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s spin up the service and we’re done!&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;nginx &lt;span class=&quot;nt&quot;&gt;--now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-porting-imgup-to-bash&quot;&gt;$ porting ImgUp to bash&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then 
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;scp &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt; trbl@cdn.her.st:/srv/http/cdn.her.st/images/&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/assets/images/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | xclip &lt;span class=&quot;nt&quot;&gt;-sel&lt;/span&gt; clip
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/assets/images/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; (added to clipboard)&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;usage:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;imgup /path/to/image.jpg [Optional remote filename]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much better than the C# clusterfuck with multiple classes.&lt;/p&gt;

&lt;h1 id=&quot;we-did-it-again-d&quot;&gt;we did it again! :D&lt;/h1&gt;

&lt;p&gt;The first iteration brought down complexity and increased performance! Can’t ask for a better outcome considering how little effort this took.&lt;/p&gt;

&lt;h2 id=&quot;whats-left&quot;&gt;whats left&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;imgup argument parsing&lt;/li&gt;
  &lt;li&gt;make universal script that can upload any kind of file&lt;/li&gt;
  &lt;li&gt;create multiple versions of the image (server sided?)&lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;Raw image&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;Resized to Thumbnail Size&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

        </content>
    </entry>
    
    <entry>
        <title>ssh is power</title>
        <id>https://her.st/usr/bin/ssh-is-power.html</id>
        <link href="https://her.st/usr/bin/ssh-is-power.html" />
        <webfeeds:cover image="/assets/images/00976e4a-27cc-4a29-8f1d-5053ac22d054.webp" />
        <webfeeds:icon>/assets/images/00976e4a-27cc-4a29-8f1d-5053ac22d054.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/00976e4a-27cc-4a29-8f1d-5053ac22d054_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2020-02-03T00:00:00+00:00</updated>
        <content type="html">
            &lt;p&gt;let’s just jump right in.&lt;/p&gt;

&lt;h2 id=&quot;port-forwarding&quot;&gt;port forwarding&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Did you know, you can fuckin port forward with fuckin ssh?!&lt;/em&gt;
You might want to host a gameserver so you can play with your friend, or show a client your progress by giving him
access to your local webserver - but you are behind a firewall and don’t want to or simply can’t forward the ports?
SSH can do it. All you need is a cheap server, &lt;a href=&quot;/hosting/&quot;&gt;like the cheapest of my Micro plans&lt;/a&gt; and you can use it to forward ports in a single line.&lt;/p&gt;

&lt;h3 id=&quot;remote-forwarding&quot;&gt;remote forwarding&lt;/h3&gt;

&lt;p&gt;For said scenarios above, where you run a server locally and want to expose it to the internet, like a webserver or gameserver
running on port 8080&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -R 8080:127.0.0.1:8080 user@hostname.her.st
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;now you can give &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hostname.her.st:8080&lt;/code&gt; (or the server IP) to your friend or client, and ssh will tunnel everything to your local machine.&lt;/p&gt;

&lt;h3 id=&quot;local-forwarding&quot;&gt;local forwarding&lt;/h3&gt;

&lt;p&gt;now let’s say you want to access a mysql server that’s running on your server. You can’t connect to it over the internet
MySQL will only listen on 3306 locally, and be firewalled off. Still want to connect your dev environment to it? SSH can do it.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -L 3306:127.0.0.1:3306 user@hostname.her.st
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;if you now connect your mysql client to 127.0.0.1:3306, you will actually connect to hostname.her.st:3306 (and you get encryption for free)&lt;/p&gt;

&lt;h3 id=&quot;appendix&quot;&gt;appendix&lt;/h3&gt;

&lt;p&gt;The format is defined like that:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8080:127.0.0.1:8080&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;RemotePort (on the server):Destination (your computer):LocalPort(on your computer)&lt;/p&gt;

&lt;h2 id=&quot;disconnected---no-problem&quot;&gt;disconnected - no problem&lt;/h2&gt;

&lt;p&gt;if you have access to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt; on the server, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -t user@hostname.her.st screen -RR&lt;/code&gt; and you will create a screen immediately
upon login, or reattach to the last one if it exists. Similar behavior can be achieved with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt;. if your internet connection
goes down or indeed even if you close the terminal, your stuff will keep running.&lt;/p&gt;

&lt;h2 id=&quot;mount-remote-filesystem-locally&quot;&gt;mount remote filesystem locally&lt;/h2&gt;

&lt;p&gt;tired of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt; yet? try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;run-a-speedtest&quot;&gt;run a speedtest&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yes | pv | ssh remote_host &quot;cat &amp;gt;/dev/null&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and it it’s good enough (internet: &amp;gt;= 5mb/s, local: 35mb/s)&lt;/p&gt;

&lt;h3 id=&quot;mount-it&quot;&gt;mount it&lt;/h3&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sshfs &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; reconnect,ServerAliveInterval&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;15,ServerAliveCountMax&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3,idmap&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;user user@hostname.her.st:/ /mnt/server-root
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;now you can just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mv&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt/server-root&lt;/code&gt; to upload files. you can treat it like any folder.&lt;/p&gt;

&lt;h2 id=&quot;oh-and-visual-studio-code&quot;&gt;oh and visual studio code&lt;/h2&gt;

&lt;p&gt;You can literally let vscode ssh into your server, install itself there, copy all your local settings and extensions over and have vsc run on your server instead
so your development environment is always the same, no matter what device you use. All your files will be stored on the server too, so no more forgetting your files either. I’ve been using it for months and love it.
&lt;a href=&quot;https://code.visualstudio.com/docs/remote/ssh&quot;&gt;https://code.visualstudio.com/docs/remote/ssh&lt;/a&gt;&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>unlimited free proxies</title>
        <id>https://her.st/usr/bin/unlimited-free-proxies.html</id>
        <link href="https://her.st/usr/bin/unlimited-free-proxies.html" />
        <webfeeds:cover image="/assets/images/proxy1.webp" />
        <webfeeds:icon>/assets/images/proxy1.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/proxy1_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2019-11-20T00:00:00+00:00</updated>
        <content type="html">
            &lt;h2 id=&quot;c-proxy-checker&quot;&gt;c# proxy checker&lt;/h2&gt;

&lt;p&gt;With the shit that’s going down in Hong Kong, Iran and dozens of other places around the world, VPN’s and Proxies are in high demand. Wouldn’t it be great if we had a free unlimited supply of web proxies? Googling around for some free ones, I mostly found sketchy websites with sketchy paid plans, and a couple Pastebin links with massive lists of IP’s and ports…&lt;/p&gt;

&lt;p&gt;…massive lists with IP’s and ports…&lt;/p&gt;
&lt;center&gt; &lt;img src=&quot;/assets/images/i.webp&quot; alt=&quot;hmm&quot; /&gt; &lt;/center&gt;

&lt;p&gt;But before we even try to automatically search Pastebin for new proxy lists, we have to make sure that we can test proxies in the first place; Thankfully, .net comes with &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/framework/network-programming/how-to-enable-a-webrequest-to-use-a-proxy-to-communicate-with-the-internet&quot;&gt;full proxy support&lt;/a&gt; and you can use it in a single line!&lt;/p&gt;

&lt;p&gt;I’ve made one and put it on github, I call it &lt;a href=&quot;https://github.com/Alumniminium/SockPuppet&quot;&gt;SockPuppet&lt;/a&gt; because it tests SOCKS web proxies.&lt;/p&gt;
&lt;center&gt;&lt;img src=&quot;/assets/images/badum.webp&quot; alt=&quot;badum tss&quot; /&gt;&lt;/center&gt;

&lt;h2 id=&quot;arch&quot;&gt;arch&lt;/h2&gt;

&lt;p&gt;My version is a simple Producer-Consumer setup that only keeps twice as many proxies in memory as it has worker threads, in case the lists get really big after running the scraper for a few weeks or months. I’ve annotated the code and encourage you to quickly read over it.&lt;/p&gt;

&lt;h4 id=&quot;blockingcollection&quot;&gt;BlockingCollection&lt;T&gt;&lt;/T&gt;&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proxies&lt;/code&gt; here is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockingCollection&amp;lt;Proxy&amp;gt;&lt;/code&gt;. If you never heard about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockingCollection&amp;lt;T&amp;gt;&lt;/code&gt;, it’s kinda like a threadsafe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; that behaves like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConcurrentQueue&amp;lt;T&amp;gt;&lt;/code&gt;. You &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreach&lt;/code&gt; it just like a List and every iteration the current item is removed from the collection. That being said, a foreach loop on a BlockingCollection will &lt;em&gt;never return&lt;/em&gt;. The &lt;em&gt;Collection&lt;/em&gt; is going to start &lt;em&gt;Blocking&lt;/em&gt; when it’s  empty - which is perfect for the consumer workloop of our Producer/Consumer setup.&lt;/p&gt;

&lt;p&gt;In addition, it can also be made to block on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add(T item)&lt;/code&gt;! Usually we’d need a lock of some kind to keep the ‘queue’ from growing too big. Simply instantiate it with the overload that accepts an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundCapacity&lt;/code&gt; like so:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blockingColl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BlockingCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bockingColl.Add()&lt;/code&gt; will block as soon as there’s 10 elements in it.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WorkLoop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// threads will be blocked at Proxies.GetConsumingEnumerable()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// as long as everything INSIDE the foreach loop is threadsafe&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// we can throw as many threads on it as our network can handle&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Proxies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetConsumingEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;// connect to proxy, download website&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Alive&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Safe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Safe = Identical response as without proxy&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// write to output file&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// write to stdout, IP starts at position 8&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Alive&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ Up! ]&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[Down!]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Writer&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StreamWriter&lt;/code&gt; and is &lt;em&gt;not&lt;/em&gt; threadsafe, also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Console&lt;/code&gt;’s threadsafety will break if you start changing colors.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StartThreads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threadCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Threads&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;threadCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threadCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WorkLoop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Target the method above&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// IsBackground = true&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// if the main thread exits kill this thread,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// don&apos;t wait for it to exit and keep a zombie process running&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsBackground&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;parsing&quot;&gt;parsing&lt;/h2&gt;

&lt;p&gt;We’re having an easy time again, the parser will be a breeze!&lt;/p&gt;

&lt;p&gt;The go-to format you find on Pastebin is ‘&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP:PORT&lt;/code&gt;’ like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;222.252.25.168:8080
178.200.170.41:80
50.197.38.230:60724
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s write a parser that will only read a sane amount of lines while checking them in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WorkLoop&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; threads, great performance, great resource utilization. We don’t waste RAM or sacrifice startup time by reading everything and instead do things on demand with a healthy buffer.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EndOfStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// while there is shit to read&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//always trim your lines!&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//naive implementation&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// expecting only valid data&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ushort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// (╯°□°）╯︵ ┻━┻ &lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Proxies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// BlockingCollection&amp;lt;Proxy&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;testing&quot;&gt;testing&lt;/h2&gt;

&lt;p&gt;Now, testing the Proxy is super easy. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebProxy&lt;/code&gt; is a built-in class, just like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HttpWebRequest&lt;/code&gt;. Both together and we’re virtually done.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;HttpWebRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpWebRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://her.st&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BypassProxyOnLocal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Proxy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserAgent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ProxyTester Version: 1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Timeout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;WebResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StreamReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;webResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetResponseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadToEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;Alive&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// proxy is working&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Alive&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// proxy is not working&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;sorting&quot;&gt;sorting&lt;/h2&gt;

&lt;p&gt;It would make sense to do multiple rounds of sorting, by latency, by throughput, by country, we will focus on sorting by country first. There’s 100’s of ‘free’ APIs for ‘Geo-IP’ lookups, but there’s always one catch: after a certain amount of queries, they ask for your credit card.&lt;/p&gt;

&lt;p&gt;How do those services do it? I’ve done some googling and as it turns out, there’s free databases available, most notably the &lt;a href=&quot;https://www.ip2location.com/database&quot;&gt;IP2Location Db’s&lt;/a&gt; - we will use LITE-DB5 which has a C# parser by the Taiwanese &lt;a href=&quot;https://github.com/SkyLandTW&quot;&gt;Sky Land Universal Corporation&lt;/a&gt; licensed under the Unlicense. Perfect. Let’s legally steal their code and hook it up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will dive deeper into how this db was created in my next networking article&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Proxy&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Locator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Locate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IPAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OrderedProxies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContainsKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;OrderedProxies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;());&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OrderedProxies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;OrderedProxies?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the code above, I created a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dictionary&amp;lt;string Country, List&amp;lt;Proxy&amp;gt;&amp;gt;&lt;/code&gt; namely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OrderedProxies&lt;/code&gt; which lets me group the proxies by country very easily. In the next part, I hope to have had time to refactor and rename most of the worst variable and class names. I’ve been facepalming too much while writing this article. I am fully aware that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Trace&lt;/code&gt; method makes the entire producer/consumer setup pointless.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;what’s next?&lt;/h2&gt;

&lt;p&gt;There’s still a lot to be added to this little service. Off the top of my head:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ping proxies to find the best latency&lt;/li&gt;
  &lt;li&gt;run speedtest to find the best throughput&lt;/li&gt;
  &lt;li&gt;automate Pastebin harvesting&lt;/li&gt;
  &lt;li&gt;database&lt;/li&gt;
  &lt;li&gt;web api with json responses - REST like.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;see you soon&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>creating an image hosting web service</title>
        <id>https://her.st/usr/bin/creating-image-hosting-web-service-in-csharp.html</id>
        <link href="https://her.st/usr/bin/creating-image-hosting-web-service-in-csharp.html" />
        <webfeeds:cover image="/assets/images/9d17f4a4-16cf-4815-b711-694f67b3e882.webp" />
        <webfeeds:icon>/assets/images/9d17f4a4-16cf-4815-b711-694f67b3e882.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/9d17f4a4-16cf-4815-b711-694f67b3e882_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2019-07-11T00:00:00+00:00</updated>
        <content type="html">
            &lt;h1 id=&quot;weve-got-work-to-do&quot;&gt;We’ve got work to do&lt;/h1&gt;

&lt;h2 id=&quot;-needs&quot;&gt;$ needs&lt;/h2&gt;

&lt;p&gt;Easy to use service that lets us host images and other static data and allows direct linking and embedding.
Any webserver will do.
I have a virtual server with apache2, so I’ll use that.
Considering that box also runs a FTP server, we shall upload our files using FTP.
We also need an app that can take an image path as argument,
upload it to our service and copies the direct link to it straight into the clipboard.&lt;/p&gt;

&lt;p&gt;The app should be a command line tool and do nothing without arguments.&lt;/p&gt;

&lt;h2 id=&quot;-requirements&quot;&gt;$ requirements&lt;/h2&gt;

&lt;p&gt;A tiny private server should be able to host everything we need.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Web Server&lt;/li&gt;
  &lt;li&gt;FTP Server&lt;/li&gt;
  &lt;li&gt;SSL&lt;/li&gt;
  &lt;li&gt;UploaderApp&lt;/li&gt;
  &lt;li&gt;Possibly a Browser / Management app in the future&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;-setting-up-the-webserver&quot;&gt;$ setting up the webserver&lt;/h2&gt;

&lt;p&gt;First we have to install a webserver. Usually I’d use Nginx, but since I have an apache server already up, I’ll go with that.&lt;/p&gt;

&lt;p&gt;I’ll use a custom subdomain for this service.
&lt;a href=&quot;https://cdn.her.st/&quot;&gt;https://cdn.her.st/&lt;/a&gt;
Here’s a visual representation why I chose this domain in case you are wondering:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;   Server   &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;   Type   &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;   Domain   &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;   TLD   &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;h&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;img&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;alumni&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;re&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h&lt;/code&gt; symbolizes my Homeserver.&lt;/p&gt;

&lt;script id=&quot;asciicast-LE8DDiKwULqYMFofPFwALUpe8&quot; src=&quot;https://asciinema.org/a/LE8DDiKwULqYMFofPFwALUpe8.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;

&lt;h4 id=&quot;install-apache&quot;&gt;install apache&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Updating the repos and installing everything we need
&amp;gt; sudo apt update &amp;amp;&amp;amp; sudo apt install apache2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apache is installed and ready, you can verify that by going to &lt;a href=&quot;http://0.0.0.0/&quot;&gt;http://0.0.0.0/&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;setup-vhost&quot;&gt;setup VHOST&lt;/h4&gt;

&lt;p&gt;Now its time to configure the virtual host. To do that, we have to create a text file in&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/sites-enabled/&lt;/code&gt;
called
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdn.her.st.conf&lt;/code&gt; (replace the name with your domain)
and put some text inside of it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/apache2/sites-enabled/cdn.her.st.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*:80&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        # ServerName is supposed to be DOMAIN . TLD
        ServerName alumni.re
        # ServerAlias is supposed to be the entire (sub)domain
        ServerAlias cdn.her.st
        # Document root is where your files will be stored
        DocumentRoot /var/www/cdn.her.st/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And for my final trick, let’s create the directory structure for the webserver.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# We&apos;ve set this path above as DocumentRoot&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /var/www/cdn.her.st
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /var/www/cdn.her.st/html
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /var/www/cdn.her.st/html/img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After setting the DNS records of your subdomain at your provider, your site should be ready, you can verify that by going to it in a browser: &lt;a href=&quot;http://cdn.her.st/&quot;&gt;http://cdn.her.st/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;-setting-up-certbot-for-free-ssl&quot;&gt;$ setting up Certbot for free SSL&lt;/h2&gt;

&lt;p&gt;Pretty important to set up SSL nowdays as every browser will freak the fuck out if your images come from an ‘insecure source’ - basically over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https&lt;/code&gt; … There’s no real benefit in encrypting static files, but if it makes the browsers happy..&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Updating the repos and installing everything we need&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;apache2 certbot python-certbot-apache
&lt;span class=&quot;c&quot;&gt;# let it do it&apos;s magic&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot &lt;span class=&quot;nt&quot;&gt;--apache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you’re asked how you want to enable SSL, chose “redirect”, wait for certbot to finish writing new configs and pulling the certs, then run&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot renew &lt;span class=&quot;nt&quot;&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If that command fails, check &lt;a href=&quot;https://certbot.eff.org/help/&quot;&gt;Certbot Help&lt;/a&gt; otherwise, let’s automate the renewal process by adding&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 1 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /usr/bin/certbot renew &amp;amp; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to your crontab (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt; crontab -e&lt;/code&gt;) - and dont forget the new line at the end or it will complain..&lt;/p&gt;

&lt;h2 id=&quot;-setup-ftp&quot;&gt;$ setup FTP&lt;/h2&gt;

&lt;p&gt;I regret using FTP for this already, but let’s get it installed and setup. In theory, you could skip this step and use http uploads, but I rather have something isolated from the webserver, as I plan on writing my own webserver for static content later, and I probably won’t implement anything but GET. Enough rambling, let’s punch in some commands to install it and enable it on boot.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;vsftpd &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;vsftpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s add our FTP user&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#ftp boi gonna live in the webroot (and get jailed into it)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; useradd ftp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /var/www/cdn.her.st/html
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;passwd ftp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we have to make sure our server is setup properly. We will need to configure write permissions, ports, directories and authentication. I’ve attached my configuration file which should work for you too.&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;/etc/vsftpd.conf&lt;/span&gt; 
&lt;span class=&quot;py&quot;&gt;listen_ipv6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;anonymous_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NO&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;anon_upload_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NO&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;local_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;write_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;dirmessage_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use_localtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;xferlog_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;connect_from_port_20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NO&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;secure_chroot_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/var/run/vsftpd/empty&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pam_service_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ftp&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;rsa_cert_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/etc/letsencrypt/live/cdn.her.st/cert.pem&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;rsa_private_key_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/etc/letsencrypt/live/cdn.her.st/privkey.pem&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;ssl_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;require_ssl_reuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NO&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pasv_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pasv_min_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1024&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pasv_max_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1025&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;allow_writeable_chroot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;chroot_local_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;chroot_list_enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YES&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;chroot_list_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/etc/vsftpd.chroot_list&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;file_open_mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0777&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;local_umask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;022&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/vsftpd.chroot_list&lt;/code&gt; is an empty file. Just run&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo touch&lt;/span&gt; /etc/vsftpd.chroot_list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to create it, also notice I’m re-using our SSL cert we got for our webserver earlier. I’ve taken the default path here, so when certbot renews it, vsftpd will always use the newest one.&lt;/p&gt;

&lt;p&gt;Now let’s start the ftp server.&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start vsftpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;bonus-step-disallow-ssh-for-ftp-user&quot;&gt;bonus step: disallow ssh for ftp user&lt;/h3&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add/edit the following line&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;DenyUsers ftp &lt;span class=&quot;c&quot;&gt;# ftp is my user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart vsftpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-bringing-it-all-together-with-our-c-netcore-app&quot;&gt;$ bringing it all together with our c# netcore app&lt;/h2&gt;

&lt;h4 id=&quot;review&quot;&gt;review&lt;/h4&gt;

&lt;p&gt;Let’s quickly review what we got setup so far so we can start thinking about how we are going to implement that in code..&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Webserver w/ ssl &amp;amp; domain&lt;/li&gt;
  &lt;li&gt;FTP Server w/ ssl &amp;amp; domain&lt;/li&gt;
  &lt;li&gt;FTP User w/ r+w access to domain’s root folder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and here’s what we still need&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;App that let’s me upload images quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;c&quot;&gt;c&lt;/h2&gt;

&lt;p&gt;Let’s start with the FTP Upload first. That should be the most difficult part here. Thankfully, the .net framework already has pre-made classes to deal with FTP, namely  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FtpWebRequest&lt;/code&gt;. So let’s design our first class, the one responsible for uploading images…&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Uploader&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// First we will set our root address for the following requests&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FTP_IMG_ROOT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ftp://cdn.her.st/images/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Next we set our Id file&apos;s public HTTP url, we will download this and parse it to set the current Id.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HTTP_IMG_ID_FILE&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/assets/images/Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// We use the curId as something like a counter, so we don&apos;t overwrite old files. I decided to do this on the client since *I&apos;m* the only client.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Don&apos;t be an idiot.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Since this is a static class and its initialized only if arguments are passed, its ok to block in the constructor.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Don&apos;t do this is bigger applications. &lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Uploader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// as stated above, here we download and parse the Id file so we know what the last Id on the server is&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// (it gets worse)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DownloadFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTP_IMG_ID_FILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TryParse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadAllText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;nextId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// Saves a couple of lines of code :D&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FtpWebRequest&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateUploadRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FtpWebRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FTP_IMG_ROOT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Credentials&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NetworkCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ftp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EnableSsl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// this is the reason we can&apos;t use WebClient. It won&apos;t work with ssl.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WebRequestMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ftp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UploadFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// not sure why i ended up using tasks... i bet they just slow everything down tbh..&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// you test that and email me the results. blog@her.st ;D&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UploadAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// further attemt at creating a more unique path but still giving it some readability.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// this would turn File.txt into File_3948.txt&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// I don&apos;t even check if a file with the same name exists and just assume so.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Asking the server for a file list, looking for it and THEN starting to upload&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// takse too much time. This is single user anyways, I won&apos;t run 20 instances of this shit.&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateUploadRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFileNameWithoutExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;_&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileStream&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OpenRead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// doing streams like a good boi in case file is biiig&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftpStream&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetRequestStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CopyToAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ftpStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// but in the end I take the lazy route.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UpdateId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Told you it&apos;d get worse.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RequestUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AbsoluteUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ftp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// did you think the server would keep track of the counter? &lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UpdateId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Interlocked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Increment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// atomicly incrementing our counters because by now i have no idea where our methods execute&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Interlocked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Increment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// doing this seems to calm me down, no idea if its snakeoil&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteAllTextAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// we write it so we can read it ...&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateUploadRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// another request&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileStream&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OpenRead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Id.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// this is a file with a fucking number in it. Number might get big, lets use a stream XDDDDDDD&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftpStream&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetRequestStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CopyToAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ftpStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// another lazy way out&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Couple of lines of code, nothing too fancy, kept it simple for the most part. I wish I went with HTTP uploads instead, having to deal with the FtpWebRequest directly made this class way bigger than it needed to be. Let’s make our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Main()&lt;/code&gt; smaller :D&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// no args? no bueno.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// seppuku&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// upload image, get direct link bacl&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Uploader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UploadAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// if this is the last file, don&apos;t add a new line at the end.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// add to url list&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AppendLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// add line to url list&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// optional&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// set clipboard to the url list &lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Clipboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// another kind of seppuku&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not much to say about that.. I’m using a command line utility called xclip to set the clipboard on linux because I’m too lazy to figure out how to properly do that. Anyways, it works so I’m happy.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Clipboard&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// gotta write it into a temp file for xclip :D fuck you xclip :D&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmpFilePath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetTempFileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteAllText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpFilePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;// now we cat it and pipe it into xclip..&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;-c \&quot;cat &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpFilePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; | xclip -i -selection clipboard\&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Process&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;StartInfo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProcessStartInfo&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;FileName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;UseShellExecute&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// y u no exit u shit? setting the clipboard won&apos;t take 5sec on the slowest potato. &lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Kill after 5 sec, sumting wong.&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WaitForExit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpFilePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// its not you, its me&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;f5&quot;&gt;F5&lt;/h1&gt;

&lt;p&gt;We did it. The minimal viable product is complete. We will iterate over the code and expand its functionality soon -
There’s a couple of things we can put on our todo list now, as we have a working prototype.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;refactor and clean up the code&lt;/li&gt;
  &lt;li&gt;Convert to WebP&lt;/li&gt;
  &lt;li&gt;create multiple versions of the image&lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;Raw image&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;Resized to Thumbnail Size&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Copy all the links into the clipboard with formatting for easy copy/paste into new Article.md&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First things first though, here’s how I’ll use this application:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Print + &lt;span class=&quot;nb&quot;&gt;shift
        &lt;/span&gt;maim &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; ~/upload.png&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; cwebp ~/upload.png &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ~/upload.webp&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; imgup ~/upload.webp &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; play ~/.config/.ding.wav &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; trash ~/upload.webp &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ~/upload.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maim&lt;/code&gt; is a screenshot utility and gives you a selection rectangle you can place with your mouse, then save it to my home directory as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upload.png&lt;/code&gt;, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cwebp&lt;/code&gt; a command line webp converter, saving it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upload.webp&lt;/code&gt; next to the source file, invoking our app, I’ve called it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ImgUp&lt;/code&gt;  passing it the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upload.webp&lt;/code&gt; path, then after it finishes uploading, I play a ding sound and delete the files from my home directory.&lt;/p&gt;

&lt;p&gt;The URL to the image is now in my clipboard and I can CTRL+V it here
&lt;img src=&quot;/assets/images/upload_12.webp&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

        </content>
    </entry>
    
    <entry>
        <title>the birth of a programmer</title>
        <id>https://her.st/usr/bin/birth-of-a-programmer.html</id>
        <link href="https://her.st/usr/bin/birth-of-a-programmer.html" />
        <webfeeds:cover image="/assets/images/de3f063d-962f-4426-bb85-5aa6c48497cf.webp" />
        <webfeeds:icon>/assets/images/de3f063d-962f-4426-bb85-5aa6c48497cf.webp</webfeeds:icon>
        <webfeeds:logo>/assets/images/de3f063d-962f-4426-bb85-5aa6c48497cf_thumb.webp</webfeeds:logo>
        <webfeeds:accentColor>FD2186</webfeeds:accentColor>
        <webfeeds:related layout="card" target="browser"/>
        <updated>2019-07-10T00:00:00+00:00</updated>
        <content type="html">
            &lt;center&gt;&lt;img src=&quot;/assets/images/upload_13.webp&quot; height=&quot;50%&quot; alt=&quot;birth&quot; /&gt;&lt;/center&gt;

&lt;p&gt;A bit over a decade ago a series of coincidences made me embark on the quest of becoming a programmer. The event that started everything must have been when thirteen year old me with his old &lt;a href=&quot;http://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%202400+%20-%20AXDA2400DKV3C.html&quot;&gt;Athlon XP 2400&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/DDR_SDRAM&quot;&gt;256 MB DDR RAM&lt;/a&gt;, &lt;a href=&quot;https://www.anandtech.com/show/1005&quot;&gt;nforce2 board&lt;/a&gt;,  an (infamous) &lt;a href=&quot;https://en.wikipedia.org/wiki/GeForce_4_series&quot;&gt;Geforce4 MX 440&lt;/a&gt; Windows XP Computer, was trying to play &lt;a href=&quot;https://store.steampowered.com/app/32370/STAR_WARS__Knights_of_the_Old_Republic/&quot;&gt;Star Wars Knights of the Old Republic&lt;/a&gt; in the early 2000’s.
it was a very &lt;em&gt;cinematic&lt;/em&gt; experience in the menu, and a glorified PowerPoint presentation inside the &lt;a href=&quot;https://swtor.fandom.com/wiki/Endar_Spire&quot;&gt;Endar Spire&lt;/a&gt;. What I’m talking about? Horrible performance. Single digit framerates.&lt;/p&gt;

&lt;p&gt;I was determined to get to the bottom of this. Why would my computer betray me at a time like this?&lt;/p&gt;

&lt;h2 id=&quot;down-the-rabbithole&quot;&gt;Down the Rabbithole&lt;/h2&gt;

&lt;p&gt;Of course, I immediately tracked down the only Computerstore in town and went there. It was a tiny shop with three or four employees, boss was still working the register and the entire store had a family vibe to it. Not to mention the shelves stacked to the roof with the newest graphics cards, motherboards, CPU’s, networking gear, printers, pre-built Systems, CRTs and a couple of early LCD’s - with the good old 4:3 aspect ratio.&lt;/p&gt;

&lt;p&gt;Now, this PC I had gotten when my family upgraded to a Pentium 4 with Hyperthreading and a Geforce 6600 was already obsolete and the store guy told me that there’s not much to be done, but told me to get another 256MB RAM module now and a better graphics card in the future. I don’t know how much I spent on that module but I vividly remember it was a lot for me back then as a 13-year-old.&lt;/p&gt;

&lt;p&gt;Turns out that guy knew what he was talking about, doubling up on RAM made a big difference! I’d now have ~20 FPS and could actually play the game I was so excited about.&lt;/p&gt;

&lt;p&gt;A month later I found a 35$ (and also infamous) &lt;a href=&quot;https://www.techpowerup.com/gpu-specs/geforce-fx-5500.c926&quot;&gt;Geforce FX 5500&lt;/a&gt; at an electronics store and bought it immediately. It had twice the VRAM and it was bigger! Naively thinking that I had struck a bargain and would go home, put it in, turn up all the graphical settings on all my games and just go&lt;/p&gt;

&lt;center&gt; &lt;img src=&quot;/assets/images/upload_12.webp&quot; height=&quot;75%&quot; alt=&quot;PC Master race&quot; /&gt; &lt;/center&gt;

&lt;p&gt;Yea. It didn’t happen. Still had too little RAM, my CPU was a slow singlecore and I just upgraded to my second mistake.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;was&lt;/em&gt; an improvement from the Geforce4 MX but not a whole lot more. Turns out the worst cards Nvidia ever released up to that point were the Geforce 4 series and the FX 5000 series :)
A year later Oblivion came out and the FX 5500 didn’t cut it, went back to the computer shop and got a &lt;a href=&quot;https://www.techpowerup.com/gpu-specs/radeon-hd-2600-pro.c212&quot;&gt;AMD Radeon HD 2600 PRO&lt;/a&gt; because it still worked with the AGP bus. Yes, I wasn’t even using PCIe yet…&lt;/p&gt;

&lt;p&gt;Tinkering with my computer taught me a lot though, I’d open it up, tear it apart and reassemble it, try to run it without all the components, see what happens, change out parts with stuff I sourced from the dumpsters, breaking Windows XP once a month and reinstalling it, buying books about computers or going to the local community center for internet access as I didn’t have any access to the internet at home until next year, try to squeeze out every single bit of performance from this little shitty slow computer was also highly rewarding. I’d obsess over a point increase in benchmark scores, I’d &lt;a href=&quot;https://web.archive.org/web/20060428113026/http://www.motherboards.org/articlesd/how-to-guides/41_1.html&quot;&gt;overvolt and overclock my CPU with a pencil&lt;/a&gt; - nowadays people increase a multiplayer in the bios and think they’re overclockers - disgusting XD - and disable windows services, deleting protected system files to free up some space on my 80GB IDE HDD that sounded like a peppermill being thrown down the stairs when it was doing something .. anything..&lt;/p&gt;

&lt;p&gt;There was no turning back now.&lt;/p&gt;

&lt;h2 id=&quot;modding&quot;&gt;Modding&lt;/h2&gt;

&lt;p&gt;&lt;img style=&quot;float: left; margin-right: 30px;&quot; src=&quot;/assets/images/upload_9.webp&quot; alt=&quot;nwedit&quot; width=&quot;25%&quot; /&gt;
If you didn’t have internet or money, you had to spend a lot of your time with the same things. When I got bored, I couldn’t watch a YouTube video - YouTube didn’t exist - so what do you do? Well, for me it was either going out, walking to friends houses and asking them if they wanted to come outside and do something because - you guessed it - we didn’t have phones either. Also most of the time, you’d go from friend to friend to friend to friend, often walking for hours, through the entire city till you find someone who has time and can be fucking bothered to come out. I’d always try to plan my routes before embarking and it never felt like I had taken the best route. I hadn’t heard of &lt;a href=&quot;https://en.wikipedia.org/wiki/Travelling_salesman_problem&quot;&gt;the traveling salesman problem&lt;/a&gt; yet. The alternative would have been playing old games or making my own maps, items, NPCs, and Quests in the original &lt;a href=&quot;https://www.gog.com/game/neverwinter_nights_enhanced_edition_pack&quot;&gt;Neverwinter Nights&lt;/a&gt;, the only game I owned that shipped with modding tools.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I thought I could negotiate more computer time with the lifegivers by showing them productivity. A futile endeavour&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I spent countless hours with the NWEditor, I still remember vividly, sitting in my room, building my first city, populating it with NPC’s, setting waypoints for each of them, making them have a daily routine, loads of dialog and quests …. with rewards that broke the entire game cause I got to set the stats of the items too… That was the first time power corrupted me and turned me into a maniac. - all while listening to
‘Ridin dirty’ by Chamillionaire :D&lt;/p&gt;

&lt;p&gt;Later I’d buy &lt;a href=&quot;https://www.yoyogames.com/gamemaker&quot;&gt;GameMaker&lt;/a&gt; and &lt;a href=&quot;https://github.com/LeeBamberTGC/FPS-Creator-Classic&quot;&gt;FPS Maker (which is now Open Source!)&lt;/a&gt; trying to make something cool I could show off, but that never happened, GameMaker was too complicated and FPS Maker was the most hideous thing i’ve ever seen and felt terrible. I remember building a D-Day map with hordes of enemies that’d never stop, and you’d have to protect your bunkers for as long as you could. It would work for two waves and then nothing would spawn. Never figured out what was wrong.&lt;/p&gt;

&lt;p&gt;Turns out making games is hard and a thirteen-year-old without any programming experience can’t do it.&lt;/p&gt;

&lt;h2 id=&quot;the-internet&quot;&gt;The Internet&lt;/h2&gt;

&lt;p&gt;Prepaid 3G Internet launched. No contract, no need to be an adult, just walk to the store, get a starter kit with USB Modem and SIM card, plug it in, install the software, dial in and surf. It was amazing. Finally I could play multiplayer games over the internet, finally I could look at websites and see what’s on the internet, download free software, free games, discover piracy, download more &lt;em&gt;cough&lt;/em&gt; free stuff,…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun fact: my 3G internet was a breathtaking 1mbits download (110kb/s) and I paid 25$ per Gigabyte - exactly how much money I got from my granny a month&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Eventually I’ve started playing a random Chinese MMORPG called &lt;a href=&quot;https://co.99.com/&quot;&gt;Conquer Online&lt;/a&gt;, my first MMORPG experience. I spent so much time on this grindy &lt;em&gt;free to play &amp;amp; pay to win&lt;/em&gt; game.
Conquer reminded me of Diablo and Sacred even a tiny bit about Neverwinter, so I was immediately in love with it and ignored all the pay to win stuff.
Then one day another one of life’s coincidences: Googling around for Conquer leveling bots and hacks, I came around a game-hacking forum and on it I’d find something that’d change my life forever.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This game actually had a pretty new private server community and there were private server source codes available for download.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;to-be-continued&quot;&gt;&lt;em&gt;to be continued&lt;/em&gt;&lt;/h3&gt;

        </content>
    </entry>
    

</feed>