Ryan Thomas

  • Home
  • About
  • GitHub
  • Archive
  • Installing Urbit on Ubuntu 20.04 LTS with AWS Lightsail

    July 8, 2022

    The official guide for installing Urbit on a Linux server is accurate enough and up to date. At the same time, it’s easy for documentation on Urbit at this stage in its development to get deprecated substantially, and running any project like this will involve variation by some combination of preference and environmental necessity.

    I recommend following the official guide, to which I defaulted throughout the process, from which I deviated slightly as follows. This is not intended as a replacement for or even supplement to the official guide so much as a place of refuge in case someone runs into trouble.

    Identity

    Your unique identity within the Urbit namespace is basically a phonetic IP address and is called a planet (with stars and galaxies up the network hierarchy). If you don’t have any connections in the Urbit community, you can start by booting up a comet and then asking around for a planet, or you can just buy one. I’ve skimmed at least a dozen websites that sell them either in USD or ETH, and after recent cost reductions in the way these are generated it’s not uncommon to see them sold for $10 – $30. This is a great way to support someone you like – or you can pay (currently) much less by buying a planet on Azimuth for 0.002 ETH which for me 5 days ago amounted to less than $3 with gas fees.

    Server Basics

    I’ve had good luck with another VPS provider over the years, but for this project I opted for a vanilla Ubuntu 20.04 LTS server through AWS Lightsail for $5/month – mainly because the first 3 months are free.

    Urbit these days is accessed both as a command-line shell called dojo and broadcast through a web interface called landscape. The official documentation by default advises you to run sudo setcap ‘cap_net_bind_service=+ep’ ~/urbit/urbit so that Urbit is prioritized access to the HTTP port 80 as the default web server though I ended up electing to reverse this via sudo setcap -r ~/urbit/urbit so that it runs on 8080 instead. I then ran the former command to the path of my nginx binary instead, and configured Nginx as a proxy server.

    Note that Urbit guides which point you in this direction tend to be older, and it’s likely that future versions of the urbit binary will likely require flags like –http-port for such configurations to work consistently.

    I’m a hacker, and I learn things my own way; despite the fact that I’ve run various headless web servers, I’ve never really had to think about port access before and I got a better understanding of the basics while trying to diagnose what I initially suspected were improperly configured SSL certificates.

    I eventually discovered AWS has their own proprietary network firewall, accessed through the web console and independent of the firewalls running inside the actual Linux system like ufw/iptables. HTTPS (port 443) is disabled by default.

    I suppose this might not have been the case had I opted for a VM that had a webserver pre-installed, but the choice was between installing things myself on Ubuntu or loading the RHEL-based “Amazon Linux,” about which I had at least a couple reservations.

    For setting up HTTPS with LetsEncrypt, Amazon recommends you use the snap version on their servers rather than python3-certbot-nginx, that you do it while the web server’s systemd service is stopped, and that you then go in and incorporate the public keys into your server configuration manually. Note that Amazon’s exact instructions vary depending on which type of distribution package you have.

    I don’t think this is necessary, but in my case I used their method to validate my certificates and copied over pieces from a configuration I had generated with python3-certbot-nginx previously.

    Media Management

    To facilitate uploading media, Landscape is designed to integrate with a file service Amazon created called S3. The official guide walks you through the process of setting up a S3 “bucket” wherein they recommend purchasing a package from DigitalOcean. Amazon of course offers the service as well, but their documentation suggests their API no longer validates V2 Signatures, which Urbit requires.

    Fortunately, the Urbit team accurately outlines how to install and configure MinIO for a self-hosted solution. One thing they don’t spell out for you (unless I missed it) is that you’re creating a docker container for MinIO that is saved and can be run after future reboots via docker start minio-urbit

    I deviated from their instructions only in that I used Nginx instead of using Caddy. I had made this decision only while misdiagnosing the problems I mentioned above, so I do not think it should be necessary.

    Nginx Configuration

    This site was very helpful in translating the recommended setup for Caddy into an identically functional Nginx configuration. The MinIO configuration involves the creation of two proxy servers, into which I integrated a third for Landscape.

    One advantage to doing this with Caddy is that it would have automated the validation and installation of the SSL certificates. In the case of other web servers, you just have to set everything up for HTTP and use a version of Certbot that will update the config for you. In the configuration template below, Urbit runs on 8080 (HTTP), MinIO runs on 9000 and 9001, and Nginx receives all three and sends them out on 80 (HTTP) and 443 (HTTPS).

    /etc/nginx/sites-enabled/main

    server {
            server_name urbit.yourdomain.org;
            location / {
                    proxy_set_header Host $host;
                    proxy_set_header Connection '';
                    proxy_http_version 1.1;
                    proxy_pass http://127.0.0.1:8080;
                    chunked_transfer_encoding off;
                    proxy_buffering off;
                    proxy_cache off;
                    proxy_redirect default;
                    proxy_set_header Forwarded for=$remote_addr;
            }
    
        listen 80; # managed by Certbot
    
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/yourpath/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/yourpath/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
    
        # Redirect non-https traffic to https
        if ($scheme != "https") {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
    }

    /etc/nginx/sites-enabled/bucket

    server {
        # MinIO console
        server_name console.s3.yourdomain.org;
        ignore_invalid_headers off;
        client_max_body_size 0;
        proxy_buffering off;
    
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_connect_timeout 300;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;
            proxy_pass http://localhost:9001;
       }
    
        listen 80; 
    
        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/yourpath/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/yourpath/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
    
    }
    
    server {
        # MinIO server
        server_name s3.yourdomain.org;
        ignore_invalid_headers off;
        client_max_body_size 0;
        proxy_buffering off;
    
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_connect_timeout 300;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;
            proxy_pass http://localhost:9000;
       }
    
        listen 80; 
    
        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/yourpath/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/yourpath/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
    
    }
    
    server {
        # MinIO server
        server_name media.s3.yourdomain.org;
        ignore_invalid_headers off;
        client_max_body_size 0;
        proxy_buffering off;
    
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_connect_timeout 300;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;
            proxy_pass http://localhost:9000;
       }
    
        listen 80; 
    
        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/yourpath/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/yourpath/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
    
    }
    

    Shell Scripts

    In order to run Urbit as a background process but also be able to access its shell in the foreground as needed, I downloaded and compiled abduco which is very easy and should have no awkward dependencies. This serves the same purpose as tmux or screen as Urbit recommends except that these latter two are terminal multiplexers and abduco is only a session manager.

    I then incorporated abduco into 3 shell scripts in my user’s ~/bin directory (I can’t recall if this is part of $PATH by default) and in which its function should be clarified below. In the words of Dr. Emmett L. Brown, “please excuse the crudity of this model, I didn’t have time to build it to scale.”

    ~/bin/urbit-boot

    #!/bin/sh
    # If urbit isn’t running, launch an abduco session named “urbit,” in which the command urbit
    # is run, and for which Ctrl+Q is bound to hide the session. 
    
    pidof urbit && {
    
    printf '\n%s\n\n' "An instance of urbit is already running."; exit 1;
    
    }
    
    printf '\n%s\n%s\n\n' \
    "Launching new detachable Urbit instance via abduco."  \
    "Press Ctrl+Q to return to shell. Restore with urbit-restore." 
    
    abduco -e ^q -c urbit $HOME/urbit/urbit -p 34543 $HOME/urbit/sampel-palnet

    ~/bin/urbit-restore

    #!/bin/sh
    # Find the abduco process with the session name urbit and
    # re-attach it to the current command-line. If urbit isn’t running, return an error.
    
    printf '\n%s\n%s\n\n'  \
    "Restoring existing Urbit instance via abduco."   \
    "Press Ctrl+Q to return to shell. Restore  \
    with urbit-restore."
    
    abduco -e ^q -a urbit || {
    
    pidof urbit && { printf '\n%s\n\n' "Urbit is already running without an attachable session." ; exit 0; }
    #must return successful exit code, 0; error means urbit needs to be run!
    
    printf '\n%s\n\n' "Urbit is not running."
    
    exit 1
    
    }

    Finally, this third script really could just be a function:

    ~/bin/urbit

    #!/bin/sh
    # If urbit-restore returns an error, make sure urbit really isn’t
    # running, and then run urbit-boot.
    urbit-restore || pidof urbit || urbit-boot 

    Creating a Systemd Service

    Finally, a stable web server should be able to survive reboots without manual intervention. In other words we need to automate the launching of the MinIO docker container as well as the urbit server. There are different ways of doing this, but here’s what I did.

    /opt/root-launches-users-urbit

    #!/bin/sh
    # Root automatically logs user in, runs usual start script as the
    # user, then starts docker
    
    #launch urbit for user as reattachable abduco session
    runuser -l  myuser -c "/home/myuser/bin/urbit-boot"  >/dev/null 2>&1 &
    
    #launch minio for connected media bucket
    docker start minio-urbit

    /etc/systemd/system/urbit-daemon.service

    [Unit]
    Description=root starts urbit and media bucket for user at system boot
    
    [Service]
    ExecStart=/opt/root-launches-users-urbit
    
    [Install]
    WantedBy=multi-user.target
  • Copy awesomewm notifications to the clipboard

    January 28, 2022
    function copy_naughty()
    -- Copy naughty notification(s) to clipboard in v4.3; API changes in
    -- later versions should simplify. Multiple notifications are outputed
    -- to a table, then concatenated as one string sent to xclip.
    
      local cs -- "combined string"
      local output = {}
      for s in pairs(naughty.notifications) do
        for p in pairs(naughty.notifications[s]) do
          local ntfs = naughty.notifications[s][p]
          for i, notify in pairs(ntfs) do
               table.insert(output, notify.textbox.text)
          end
        end
      end
    
      if output[1] == nil then return nil end
      local lb = "\n" ; for i = 1, #output do
          if cs == nil then cs = output[i] else
              cs = cs .. lb .. output[i]
          end
      end
    
      io.popen('xclip -selection clipboard','w'):write(cs):close()
      naughty.notify({ position = "bottom_middle", timeout = 1, text = "Copied" })
    
    end

  • Consortium News: High Court Allows Assange to Appeal to Supreme Court

    January 25, 2022

    Read More: https://consortiumne … upreme-court-appeal/

  • Control the awesomewm system tray using only the keyboard

    January 24, 2022

    We are surprised at the time of this writing that the system tray remains such an obvious bottleneck in the nevertheless ubiquitous fight against mouse-dependency among neckbeards the world over.

    I present accordingly, systray_hints.

  • The AwesomeWM signal they don’t want you to know about!

    January 16, 2022
    -- Replace registration popup in Sublime Text with less obtrusive reminder
    -- Tested in Build 4126
    client.connect_signal("manage", function(c)
        if c.class == "Sublime_text" and c.name == nil and c.floating then
            c.hidden = true
            local prop = "WM_TRANSIENT_FOR" -- Trial popups lack this property
            local id = c.window
            local cmd = "xprop -id " .. id .. " | grep " .. prop
            awful.spawn.easy_async_with_shell(cmd, function(o, e, r, exitcode)
                if exitcode == 1 then
                    c:kill() -- TO DO: Add a less annoying trial reminder here
                else
                    c.hidden = false; c:jump_to() -- Unhide other dialog boxes
                end
            end)
        end
    end)
  • John Pilger Speaks Outside Old Bailey Court on the Trial of Julian Assange

    September 8, 2020

  • An Open Letter to Russell Brand

    August 27, 2020

    Dear Brother Russell,

    As you are already no doubt aware, the Trump Administration last year bribed Ecuador $4.2 Billion to have Julian Assange stripped of his citizenship and thrown in Belmarsh prison specifically for exercising his journalistic duties in publishing the war crimes of the Bush Administration exposed by Chelsea Manning.

    Julian’s rendition hearing resumes in less than two weeks. The state of our corporate media apparatus is so infernal that no one will speak up for Julian because they are afraid that in doing so they might be construed as being a supporter of the man whose administration is most singularly responsible for his imprisonment without formal arrest, his torture and his immanent death.

    To date, Julian’s highest profile celebrity supporter is M.I.A., who is – from the point of view of general pop culture, missing in action. You have demonstrated on so many occasions your ability to speak truth to power truthfully, in a world where speaking truth to power halfheartedly is a state-sanctioned fashion trend.

    You have a unique and important voice.

    I remember vividly that summer of 2012 that Julian took refuge in the Ecuadorian embassy. I was learning about Advaita Vedanta and beginning my metaphysical practices under the tutelage of a noble and erudite Sufi lineage. I spent every night in prayer and meditation and every day alternating between coverage of Julian’s story and watching episodes of Brand X. I don’t know how I stumbled across it. I had only known you then from some movies you were in which I didn’t love. Brand X blew me away.

    I saw you were a fellow seeker, that your humor was uniquely capable of evoking the most lofty metaphysical insights into the lowest gutter and therefore bringing them to absolutely everyone. You and Julian were part of the same emancipatory moment, that explosive and magical unity that came out of Occupy Wall Street that meant everything and went No Where. I write this letter because I know my sense of kinship with each of you is no accident.

    Please consider raising your voice to raise immediate awareness and help direct public attention to the grave injustice of Julian’s situation.

    Written interview from earlier this year with UN Special Rapporteur on Torture, Nils Melzer, a valuable read when the discussing the matter today: “A murderous system is being created before our very eyes” – Republik

    Please see also Action 4 Assange, an impressive group of independent journalists featuring a brilliant man I think you would like named Steve Poikonen, providing some of the best regular coverage and analysis of Julian’s situation. They continue to be serious about stopping Julian’s extradition by instigating public pressure. They regularly interview very brilliant and sometimes high-profile people like former CIA analyst Ray McGovern, and anyone else whose voice can add substance to the present conversation.

    I implore from the bottom of my heart, please take a stand for Julian Assange. Without the immediate normalization of public pressure today, there will be no real anti-war journalism left in the world tomorrow.

    https://dontextraditeassange.com

    Yours sincerely,

    Ryan Thomas

  • 2020 UFO Prediction

    July 29, 2020

    After the aliens land on Earth and announce their existence through verified accounts on social media, vast corners of the world are united by widespread acceptance of their new place in the universe.

    Shaykh Yusuf al-Qaradawi and Pope Francis, almost immediately, issue official edicts formally recognizing belief in the existence of extraterrestrial life. But roughly 33% of the population – across existing ideological divides – remains skeptical of the validity of the news.

    The first human the aliens meet is Donald Trump – with whom they make the Deal of the Millennium™, but the meeting goes unreported and takes place entirely in secret.

    The aliens then host a conference with dozens of world leaders in Paris. The people of the earth are ecstatic to hear the announcement of mass distribution of COVID vaccines from outer space – this in exchange merely for humanity’s indentured servitude.

    Throughout the first 48 hours of Disclosure, the subject of Trump is barely mentioned in the news cycle at all, but it then begins to dominate again. Reportedly angry that he was not “invited” to the conference, Trump tweets that our new alien overlords are losers. He tweets again that they’re not even real aliens.

    Corporate media and Silicon Valley – on direct orders, curiously enough, from the Trump Administration – subsequently circulate and advance the meme that only Trump supporters don’t believe in the alien thing. Within 24 hours of hearing this, all liberals suddenly believe in the alien thing. And more Trump supporters agree it’s a hoax.

    Food and grocery delivery services are halted. Americans succumb to mass cannibalism. We never find out if the aliens were real.

  • System Update with Glenn Greenwald – How Congress Maintains Endless War

    July 9, 2020

  • Schrödinger’s President

    May 26, 2020

    Authored by Caitlin Johnstone.

    Right-wing pundit Ann Coulter went on a surprisingly vitriolic anti-Trump rant the other day, calling the president a “complete blithering idiot”, an “actual retard”, and “the most disloyal human God ever created” for his treatment of Jeff Sessions and his failure to build the border wall per his campaign promise.

    “Coulter is right,” comedian Tim Dillon tweeted in response. “Trump doesn’t really care about immigration or the wall, it was just the way to win. He likes winning. You don’t live your entire life being a Hollywood star who hangs with the Clintons and Jeffrey Epstein and then decide you actually like people from Ohio.”

    Which is true. Trump and his handlers understood that rising anti-immigration sentiment in America was a key to winning the presidency, but he never cared about immigration and never had any intention of going out of his way to do anything about it (which is why even his deportation numbers are still below Obama’s). Just one of the many ways where the popular narrative about Trump–the story everyone’s telling about him–differs wildly from the reality.

    It is normal to have multiple contradictory mainstream narratives running about a president at the same time, and for none of those narratives to be accurate. Obama was simultaneously a progressive champion of sanity and a socialist Muslim from Kenya hell bent on America’s destruction, none of which was true but both of which were believed with equal fervor by either side of the illusory partisan divide.

    What’s unusual about Trump is that there are multiple contradictory narratives running about him at the same time, within the same political factions. His own base is able to hold the belief that Trump is a brilliant strategic mastermind who is commanding a covert counter-coup to overthrow the Deep State, for example, while simultaneously excusing all the many, many establishment capitulations that he makes as being beyond his control. Much like Schrödinger’s proverbial pet Trump exists for them in two mutually contradictory states at once: a skillful hero who is taking down the Deep State, and a hapless victim who can’t control what happens in his own administration because it’s all being controlled by the Deep State.

    On the other side of the imaginary partisan divide, Democrats spent years advancing the mutually contradictory narratives that Trump is at once (A) idiotic, (B) mentally ill, and (C) running a covert operation to sabotage America in the interests of Russia–but cleverly evading detection under intense scrutiny. They also hold him as simultaneously presenting an unprecedented threat to American democracy and also perfectly safe to keep voting in support of continuing and expanding his military and surveillance powers.

    None of these narratives have anything to do with reality, yet they consume an immense amount of oxygen in US political discourse while Trump continues and expands the many depraved agendas of his predecessors (Consortium News: Biden Can’t Return US to Normal, Because Trump is a Normal President).

    Trump is not a populist champion of the little guy, nor a closet Nazi working to establish a white ethnostate, nor a Kremlin asset, but is in fact nothing other than a miserable rich man from a miserable rich family who did what it takes to get elected to the presidency of a racist, corrupt, bloodthirsty empire and remain there for a full term. Everything else is narrative which is wholly divorced from reality.

    The reason we can have wildly popular narratives dominating mainstream political discourse for years on end without their containing a shred of actual reality is because human experience is dictated by mental stories far more than most people realize. Establishment power structures, who have their hands in both parties of America’s two-handed political sock puppet show, stand everything to gain and nothing to lose by using narrative control to keep the public debating fake nonsense instead of the actual horrible things this administration is doing like imprisoning Julian Assange for journalism, vetoing attempts to save Yemen, inflicting starvation sanctions on Iran and Venezuela, and initiating cold war escalations against two nuclear-armed nations.

    If people truly understood the extent to which mental narrative dominates their experience of life, propaganda, advertising and all other forms of psychological manipulation would be regarded by our society similarly to physical assault or property theft. For anyone who is interested in the pernicious ways narrative manipulation is used to keep people confused and conflicted while powerful people roll out toxic agendas, Trump is a very interesting case study indeed.

    If humanity is to survive, people are going to have to evolve beyond the sticky relationship with mental narrative which enables establishment spinmeisters to keep an entire nation transfixed by fake stories about a very conventionally evil president instead of pushing for the real changes we’ll need to make if we’re to overcome the existential hurdles looming on our horizon. Learning to distinguish reality from narrative will send the whole prison crashing down.


    Shared with permission from author Caitlin Johnstone. https://caitlinjohnstone.com/2020/05/26/schrodingers-president/

←Previous Page
1 2 3
Next Page→

Copyright © 1989-2031 Ryan Thomas. Verbatim copying and redistribution of this page in part or entirety is permitted provided this notice is preserved. Buy me a coffee