Sign in

dothash

@dothash.win
2.5K followers 1.8K following 998 posts

CTO in the Media Industry in Norway • x.com/iamdothash Omarchy Core Team member

PostsRepliesMedia
dothash @dothash.win · 03/08/2025
VPN bans incoming for the UK. Time to pivot. Set up a VPN-like tunnel using any servers with an SSH connection $ sshuttle --dns -r <username>@<ip> 0.0.0.0/0 ::/0
$ sshuttle \
  # Forward DNS queries to prevent leaks.
  --dns \
  # Connect as 'root' to the remote server.
  -r root@65.108.151.237 \
  # Forward all IPv4 traffic.
  0.0.0.0/0 \
  # Forward all IPv6 traffic.
  ::/0

$ curl -4 icanhazip.com
65.108.151.237

$ curl -6 icanhazip.com
2a01:4f9:c011:8e77::1
8505
dothash @dothash.win · 31/07/2025
I've created two Omarchy themes, part of the extra themes. Ash Snow manuals.omamix.org/2/the-omarch...
150
dothash @dothash.win · 14/04/2025
100% AI A pomodoro app written in @golang.org. I call it gomodoro. Took me around 1 hour.
130
dothash @dothash.win · 12/03/2025
Different ways to fry an egg
040
dothash @dothash.win · 22/02/2025
The main reason I got the Zend Certified Engineer certification back in 2012
The php elephant
3180
dothash @dothash.win · 19/02/2025
GIT Gud
Cursor f*ck up my 4 months of works


Question
Disclamer, I'm a moron who worked on the same project without thinking about the risk that Cursor could break
everything. Yesterday, Cursor (even though 1 only asked it to feed a view on my U) destroyed months of
development.
My question: How do you back up your projects/versions to ensure that the next action on cursor is reversible?
Ops!


Also, I know that while I'm the concern, cursor isn't the only culprit, it's also Claude (while good overall) still has
some flaws
290
dothash @dothash.win · 18/02/2025
Migrations
A man tired of life
181
dothash @dothash.win · 14/02/2025
After a decade with git, I learned about git clean -f! It removes untracked files from your working directory, which is useful for cleaning up after builds or when you've accidentally created files you don't want to commit.
4141
dothash @dothash.win · 07/02/2025
Is the Cloudflare analytics even correct? 👀
This is a snapshot of the Cloudflare dashboard for hemmelig.app, showing website traffic and performance data for the past 30 days (January 8th to February 7th). Here's a summary:
Key Metrics:
 * Unique Visitors: 13,850
 * Total Requests: 135,450
 * Percent Cached: 60.83%
 * Total Data Served: 2 GB
 * Data Cached: 1 GB
100
dothash @dothash.win · 19/01/2025
The perfect twins. @coolify.io & @neovim.io
Two coffee mugs. Coolify and neovim logo.
2110
dothash @dothash.win · 14/01/2025
don't take this seriously
const dedupe = new Map();

dedupe.set(1, 1337)
dedupe.set(1, 1337)
dedupe.set(1, 1337)
dedupe.set(1, 1337)
dedupe.set(2, 1337)
Map(2) {1 => 1337, 2 => 1337}
120
dothash @dothash.win · 29/12/2024
Yeah, I have not earned 4179 stars as far as I know
Stats from my git-wrapped.com
250
dothash @dothash.win · 17/12/2024
We're closing in to the Christmas holidays. Did you know phising is one of the top risks during these times? Stay alert 👀
020
dothash @dothash.win · 11/12/2024
May the force be with you
git push --no-verify --force origin main
4270
dothash @dothash.win · 05/12/2024
I just had an afternoon nap
It appears to be a meme featuring a photo of Samuel Melton Fisher, an American actor who played the role of 'Grizzly Adams' in the NBC television series 'The Life and Times of Grizzly Adams'. The meme's text humorously suggests that people who take naps are courageous for waking up twice in one day.


But with my face on it
290
dothash @dothash.win · 04/12/2024
It was a rough time being at the computer lab during secondary school
An image of Sub7, or SubSeven or Sub7Server, is a Trojan horse - more specifically a Remote Trojan Horse - program originally released in February 1999
5190
dothash @dothash.win · 03/12/2024
Did you know you can connect to a remote host using the docker context? → It feels like your local machine → You can add multiple contexts → You can easily switch back to your local docker environment Note to self: RTFM, and you will learn.
# Create a new context named iamgroot 
# This context is set to an remote host using SSH
docker context create iamgroot --docker host=ssh://dothash@iamgroot

# Use the next context
docker context use iamgroot

# List the running containers on the remote server
# Feels like running docker locally
docker ps
1192
dothash @dothash.win · 03/12/2024
Hetzner launched their s3-compatible object storage. It would be a shame if all providers made such an easy to understand UI for pricing. www.hetzner.com/storage/obje...
Pricing of the s3 storage.

100TB storage and 100TB traffic cost 598 euro excluding VAT
181
dothash @dothash.win · 03/12/2024
Good morning, nerds. I add milk to my coffee.
A neovim coffee mug
4170
dothash @dothash.win · 01/12/2024
Image of the GUI
000
dothash @dothash.win · 01/12/2024
It's not going to be a thing, but in 5 minutes, using AI, I created a GUI in Fyne and Golang. Neat. The zoom is annoying. Too lazy to create a new vid.
140
dothash @dothash.win · 01/12/2024
Are you late for standup? I got you. git standup will list your latest commits → github.com/kamranahmeds...
$ git standup -d 2
/Users/ob907/Code/pipe
843fe1a - docs: set the correct url (31 hours ago) <bjarneo>
fb5ff1f - docs: add quick install (31 hours ago) <bjarneo>
7b028e8 - docs: add quick install (31 hours ago) <bjarneo>
295690d - fix: try a new way of injecting the version (31 hours ago) <bjarneo>
b424ba0 - docs: add the cleanup to the flow (31 hours ago) <bjarneo>
118b38a - feat: keep only the latest 5 releases (31 hours ago) <bjarneo>
3102
dothash @dothash.win · 01/12/2024
Today's mood going into 1th of December wondering what is the next technical topic to deep dive into.
170
dothash @dothash.win · 01/12/2024
My first programming book after some years wiggling. Examples from WinXP and IE. Svend Andreas Horgen, if you see this, 🥂
SQL injection example where the images are from WinXP and using IEThe book webprogrammering i PHP
360
dothash @dothash.win · 30/11/2024
Today's mood: the Witcher
This image shows a peaceful winter scene in Scandinavia. Two traditional wooden houses with snow-covered roofs stand in a snowy landscape. The aged wood and recent snowfall create a sense of history and tranquility.
0110
dothash @dothash.win · 30/11/2024
@v0.dev is fun. I can spend hours just creating things..just because. kx6nxba9z7rfu8kzxjmq6p9gozi9zjfr.vercel.app
A preview image of the URL linked in the post.

It shows an image of a book page with the chapter, title, and text.
Subtle brown background, with a font used in books.
180
dothash @dothash.win · 30/11/2024
And this do not include taxes to get it into the country 😅
Image of the shipping price

Mug $199.99
Shipping $321.45
Total $521.44
200
dothash @dothash.win · 29/11/2024
I am man. I need mug. 10kg / 22lbs
Image of the Heavy* Mug | The World's Heaviest Mug
3100
dothash @dothash.win · 29/11/2024
Wørd
The text in the image is a humorous observation about aging. It reads: "Once you hit a certain age, life is just a delicate balance of trying to stay awake and trying to fall asleep. While slowly getting worse at both."
The text is written in a sans-serif font, likely Arial or Helvetica, and is center-aligned on a plain background. The simplicity of the presentation emphasizes the relatable nature of the message.
The image is a text-based meme, likely intended to be shared on social media platforms. It is a commentary on the common experience of aging and the challenges it brings with regards to sleep patterns.
140
dothash @dothash.win · 29/11/2024
Indeed.
"What worries you, masters you."  -- John Locke

A worried man, old portrait, but with my face on it
161
dothash @dothash.win · 28/11/2024
I had to test midjourney. I don't event 😅
A hat with the character P
two eyes
moustache
a pipe that looks like a penis
110
dothash @dothash.win · 28/11/2024
A short video of how this pipe executable works.
040
dothash @dothash.win · 28/11/2024
Reintroducing Pipe v1.0 (copepod), the newly renamed tool that effortlessly pipes your images directly to your instances via SSH. 🚀 Thanks for the suggestions. 🙇 → github.com/bjarneo/pipe #devops #docker
Usage:
  pipe [options]

Options:
  --host            Remote host to deploy to
  --user            SSH user for remote host
  --image           Docker image name (default: app)
  --dockerfile      Path to the dockerfile (default: Dockerfile)
  --tag             Docker image tag (default: latest)
  --platform        Docker platform (default: linux/amd64)
  --ssh-key         Path to SSH key (default: "")
  --container-name  Name for the container (default: app)
  --container-port  Container port (default: 3000)
  --host-port       Host port (default: 3000)
  --env-file        Environment file (default: "")
  --build-arg       Build arguments (can be specified multiple times, format: KEY=VALUE)
  --network         Docker network to connect to
  --volume          Volume mount (can be specified multiple times, format: host:container)
  --cpus            Number of CPUs (e.g., '0.5' or '2')
  --memory          Memory limit (e.g., '512m' or '2g')
  --rollback        Rollback to the previous version
  --version         Show version information
  --help            Show this help message

Environment Variables:
  HOST                       Remote host to deploy to
  HOST_USER                  SSH user for remote host
  HOST_PORT                  Host port
  HOST_PLATFORM              Docker platform
  SSH_KEY_PATH               Path to SSH key
  DOCKER_IMAGE_NAME          Docker image name
  DOCKER_IMAGE_TAG           Docker image tag
  DOCKER_CONTAINER_NAME      Name for the container
  DOCKER_CONTAINER_PORT      Container port
  DOCKER_BUILD_ARGS          Build arguments (comma-separated KEY=VALUE pairs)
  DOCKER_CONTAINER_ENV_FILE  Environment file
  DOCKER_NETWORK             Docker network to connect to
  DOCKER_CPUS                Number of CPUs
  DOCKER_MEMORY              Memory limit

Examples:
  pipe --host example.com --user deploy
  pipe --env-file .env.production --build-arg GIT_HASH=$(git rev-parse HEAD)
  pipe --host example.com --user deploy --memory "512m"
040
dothash @dothash.win · 28/11/2024
bonus, curl the weather: $ curl v2.wttr.in/oslo
curl wttr.in/Moon
                 .-
             .-
          .-
       .-'
      /@@
    ./
   /@@
  /@@@
  |@@
 /@@@	 Last Quarter +
 | @@	 5 18:42:46
 |@ @	 New Moon -
 |   	 2 10:09:37
 \  .
  |
  \
   \  o
    `\
      \
       `-.
          `-
             `-
                 `-
100
dothash @dothash.win · 28/11/2024
"What was the 1st album you bought with your own money?" In my defense, I was 10.
The backstreet boys, backstreets back album 
https://en.wikipedia.org/wiki/Backstreet%27s_Back
330
dothash @dothash.win · 28/11/2024
I am doing too many things at once. I started the scheduler app a couple of weeks ago, but never launched it. Should I?
Visuals of a bluesky post scheduler app. Input field for text. Image upload. Image alt text. Recurrence. List of scheduled posts.Visuals of a bluesky post scheduler app. Input field for text. Image upload. Image alt text. Recurrence. List of scheduled posts.
140
dothash @dothash.win · 28/11/2024
I use my small terminal ai executable every single day for tasks like this. Here is the source code if you are curious: github.com/bjarneo/tai
tai force kill slack macos
```
pkill -f Slack
```

Explanation: Forcefully kill the Slack application on macOS by searching for processes that match the name "Slack" and terminating them.

> Execute the command? (N/e/y): y
2140
dothash @dothash.win · 26/11/2024
Hurl: Simplify Your API Testing → Test any HTTP API with plain text files. → Perfect for local dev & CI/CD. → Powered by cURL as a Rust wrapper. → Pure terminal Visit hurl.dev for more in-depth information
# The hurl.dothash.win endpoint is available
# for you to test these commands

# Define .hurl files these examples

# Basic GET request
# basic.hurl
GET https://hurl.dothash.win
HTTP 200

# JSON assertion
# json_assertion.hurl
GET https://hurl.dothash.win/users
HTTP 200
[Asserts]
jsonpath "$.[0].name" == "John Doe" 

# Chained request
# chained_request.hurl
GET https://hurl.dothash.win/token
HTTP 200
[Captures]
token: jsonpath "$.token"

GET https://hurl.dothash.win/data
Authorization: Bearer {{token}}
HTTP 200

# Create a new user with a JSON body
# post_json.hurl
POST https://hurl.dothash.win/users
{
  "id": 3,
  "name": "Dothash Smith",
  "email": "dothash@example.com"
}
3112
dothash @dothash.win · 25/11/2024
I will never pay for a browser
Norman Rockwell "Freedom of Speech 1943"

But with my face on it
1171
dothash @dothash.win · 25/11/2024
yq the YAML engineer's best friend If you love the power of `jq` for JSON, meet its YAML counterpart: `yq`. This command-line tool brings the same elegant syntax and flexible processing to YAML files. → github.com/mikefarah/yq
## person.yaml
# name: John Doe
# age: 25
# city: Anytown
# items:
# - name: Shirt
#   price: 15
# - name: Shoes
#   price: 50
# - name: Hat
#   price: 8
    
# Print the yaml
yq . person.yaml

# Extract Values
yq '.name' person.yaml
John Doe

# Update Values
yq '.age = 30' person.yaml
# ... rest of the yaml
# age: 30

# Filter data
yq '.items[] | select(.price < 10)' data.yaml
# name: Hat
# price: 8
0160
dothash @dothash.win · 25/11/2024
Tired of wrestling with JSON data on the command line? Meet `jnv`, an interactive JSON viewer and `jq` filter editor that makes exploring and manipulating JSON easy. → github.com/ynqa/jnv
3163
dothash @dothash.win · 25/11/2024
Taming JSON Data with jq Dealing with JSON data on the command line? `jq` might be your new best friend! This lightweight and flexible tool is like the `sed`, `awk`, and `grep` of the JSON world. → github.com/jqlang/jq Here's a quick taste of what `jq` can do:
# Pretty print JSON
http https://api.openbrewerydb.org/v1/breweries?by_country=England&per_page=3 | jq .

# Extract a specific field
jq ".[1].name" breweries.json
"81 Artisan"

# Filter an array
jq ".[] | select(.phone == \"1825722375\")" breweries.json
{
  "id": "63969ec8-b557-4c71-b993-ad00c99ab70e",
  "name": "360 Degree Brewing Company",
  "phone": "1825722375",
  # ... more fields
}

# Transform data
jq '.[] | select(.phone == "1825722375") | { "new_field": "Hello Bsky", "original_data": . }' breweries.json
{
  "new_field": "Hello Bsky",
  "original_data": {
    "id": "63969ec8-b557-4c71-b993-ad00c99ab70e",
    "name": "360 Degree Brewing Company",
    "phone": "1825722375",
    # ... more fields
  }
}
041
dothash @dothash.win · 25/11/2024
Digging into DNS dig is your go-to command-line tool for exploring the Domain Name System (DNS). Think of it as a detective that helps you uncover the hidden connections between domain names and IP addresses. → More information manned.org/dig Here's how to use it to investigate google.com:
# Find Google's IP addresses
dig +short google.com

# Get the full DNS report for Google
dig +noall +answer google.com

# Check different record types (A, MX, TXT, CNAME, NS)
dig +short google.com A 
dig +short google.com MX
dig +short google.com TXT
dig +short google.com CNAME
dig +short google.com NS

# See all of Google's DNS records
dig google.com ANY

# Use a specific DNS server (like Google's public DNS)
dig @8.8.8.8 google.com

# Trace the path to resolve google.com
dig +trace google.com

# Find the authoritative name servers for google.com
dig +nssearch google.com
1133
dothash @dothash.win · 23/11/2024
A video of the apply and deployment
020
dothash @dothash.win · 23/11/2024
Perfect. Well done! The next step you can try for yourself is to -> Use Cloudflare and point your domain with SSL to the server IP -> Profit You can destroy the entire server with one command to clean up after the testing.
tofu destroy

hcloud_server.docker: Destroying... [id=56559157]
hcloud_server.docker: Destruction complete after 0s
hcloud_ssh_key.sudo: Destroying... [id=24835347]
hcloud_firewall.ssh: Destroying... [id=1756098]
hcloud_firewall.http: Destroying... [id=1756096]
hcloud_firewall.https: Destroying... [id=1756097]
hcloud_ssh_key.sudo: Destruction complete after 1s
hcloud_firewall.https: Destruction complete after 1s
hcloud_firewall.http: Destruction complete after 2s
hcloud_firewall.ssh: Destruction complete after 2s

Destroy complete! Resources: 5 destroyed.
110
dothash @dothash.win · 23/11/2024
Verify the app is running as expected
http -h 65.108.80.226

HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: keep-alive
Content-Length: 327
Content-Type: text/html
Date: Sat, 23 Nov 2024 13:43:27 GMT
ETag: "6734bbf1-147"
Last-Modified: Wed, 13 Nov 2024 14:47:13 GMT
Server: nginx/1.27.2
110
dothash @dothash.win · 23/11/2024
Since we have the docker instance up and running, and a Dockerfile ready. Install copepod and run this command to deploy the docker image to the docker instance -> github.com/bjarneo/cope...
copepod --host=65.108.80.226 \
		--user=root \
		--image=hello-world \
		--tag=v1.0.0 \
		--container-name=hello-world \
		--host-port=80 \
		--container-port=80

# ... more logs
[2024-11-23T13:29:23Z] INFO: Verifying container status...
[2024-11-23T13:29:23Z] INFO: Executing: ssh root@65.108.80.226 "docker ps --filter name=hello-world --format '{{.Status}}'"
[2024-11-23T13:29:24Z] INFO: Deployment completed successfully! 🚀
110
dothash @dothash.win · 23/11/2024
Here is an example Dockerfile where we can deploy an nginx instance that will be exposed on port 80.
# Use the official nginx image as base
FROM nginx:alpine

# Create index.html directly in the container
RUN echo '<!DOCTYPE html>\
<html>\
<head>\
    <title>Hello, World</title>\
</head>\
<body>\
    <div class="container">\
        <h1>Welcome to my app!</h1>\
        <p>If you see this page, the nginx web server is successfully installed and working.</p>\
        <p>This page was created from within the Dockerfile.</p>\
    </div>\
</body>\
</html>' > /usr/share/nginx/html/index.html

# Expose port 80
EXPOSE 80

# Start nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]
110
dothash @dothash.win · 23/11/2024
Install the tofu provider, and apply the infrastructure to Hetzner.
# Install the tofu providers
tofu init

# Dry run with a plan
# this will not apply it, only view the output 
# planned to be run
tofu plan

# Apply it to Hetzner
# Ideally you should not have this env var within the 
# shell history
TF_VAR_hcloud_token=1337 tofu apply

hcloud_ssh_key.sudo: Creating...
hcloud_firewall.ssh: Creating...
hcloud_firewall.https: Creating...
hcloud_firewall.http: Creating...
hcloud_ssh_key.sudo: Creation complete after 1s [id=24835347]
hcloud_firewall.http: Creation complete after 1s [id=1756096]
hcloud_firewall.https: Creation complete after 2s [id=1756097]
hcloud_firewall.ssh: Creation complete after 2s [id=1756098]
hcloud_server.docker: Creating...
hcloud_server.docker: Still creating... [10s elapsed]
hcloud_server.docker: Still creating... [20s elapsed]
hcloud_server.docker: Still creating... [30s elapsed]
hcloud_server.docker: Still creating... [40s elapsed]
hcloud_server.docker: Creation complete after 46s [id=56559157]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Outputs:

server_ips = "65.108.80.226"
110
dothash @dothash.win · 23/11/2024
The content of the main.tf and provider.tf file.
# provider.tf
# Define the hetzner cloud provider
terraform {
  required_providers {
    hcloud = {
      source  = "opentofu/hcloud"
      version = "1.26.1"
    }
  }
}

# main.tf
# Set the variable value in *.tfvars file
# or using the -var="hcloud_token=..." CLI option
# or use env vars like TF_VAR_hcloud_token=
variable "hcloud_token" {
  type    = string
  default = ""
}

variable "ssh_key" {
  type = string

  # Set the default to your key or override
  default = "~/.ssh/id_ed25519.pub"
}

# Configure the Hetzner Cloud Provider
provider "hcloud" {
  token = var.hcloud_token
}

# Create a new SSH key
resource "hcloud_ssh_key" "sudo" {
  name       = "ssh key"
  public_key = file(var.ssh_key)
}

# Set up firewalls 
## Port 80 for unencrypted http
resource "hcloud_firewall" "http" {
  name = "allow_http"
  rule {
    direction = "in"
    protocol  = "tcp"
    port      = 80
    source_ips = [
      "0.0.0.0/0",
      "::/0"
    ]
  }
}

## Allow SSL (https)
resource "hcloud_firewall" "https" {
  name = "allow_https"
  rule {
    direction = "in"
    protocol  = "tcp"
    port      = 443
    source_ips = [
      "0.0.0.0/0",
      "::/0"
    ]
  }
}

## Set the SSH access
resource "hcloud_firewall" "ssh" {
  name = "allow_ssh"
  rule {
    direction = "in"
    protocol  = "tcp"
    port      = 22
    # Limit this to your IP
    # 0.0.0.0/0 means open for all IPs
    source_ips = ["0.0.0.0/0"]
  }
}
# end firewall setup

# Create the docker server
resource "hcloud_server" "docker" {
  name = "docker"
  # Using the predefined docker image from Hetzner
  image        = "docker"
  server_type  = "cpx11"
  location     = "hel1"
  firewall_ids = [hcloud_firewall.http.id, hcloud_firewall.https.id, hcloud_firewall.ssh.id]
  ssh_keys     = [hcloud_ssh_key.sudo.id]

  labels = {
    "purpose" = "Docker installation"
  }
}

# Output the IP addresses of the created servers
output "server_ips" {
  value = hcloud_server.docker.ipv4_address
}
110