đŸ§‘â€đŸ’» Host din egen tshare backend

@mikkelrask · April 14, 2025 · 10 min read

Hvis ikke du allerede kender tshare, er det mÄske fordi det er en bash script baseret terminal-output-deler som jeg umiddelbart vil sige at jeg vibede mig til ... sÄdan i gÄr-agtigt.

not me vibing with Claude

SÄ det er fair nok, hvis ikke du gÞr - sÄ fÞr vi gÄr i gang med hvordan du rent faktisk fÄr din bagende op og kÞre, skal vi nok lige gennemgÄ hvad tshare er, hvad det fikser, og hvorfor man skulle have lyst til at hoste selv - klik her hvis du bare vil skip dialogue og gÄ til dit main objective...

📜 tshare: origins

Egentlig ville jeg oprindeligt bare brainstorme lidt med min buddy Claude Sonnét III, efter at have set en artikel/blog omkring termbin. En online service til at dele terminal output via sin browser.. Noget der kan vÊre mange forskellige grunde til at ville.. Men jeg var knapt sÄ imporneret over hvordan man skulle bruge det

SÄ uden at det pÄ nogen mÄde skal blive til bashing af termbin eller noget som helst minder om, sÄ kunne jeg ikke lide at deres service (vigtigt at notere at deres (100% gratis!) produkt er selve den online service, og ikke ligesom mit lille projekt her en blanding af en cli applikation og en service) afhang af at man brugte NetCat (`nc`) og for at skulle dele sit output skulle pipe sin kommando ind i nc med terminbin.com 9999 som serveren.

Eksempel pÄ et termbin kald:

uv run main.py | nc termbin.com 9999

Min tanke var, at mange der eks. sÞger hjÊlp online til troubleshooting eller pÄ anden vis bare har brug for at dele noget output, sikkert ikke har netcat installeret og mÄske synes at syntaksen som termbin benytter sig af virker "overvÊldende", med brug af bÄde specialtegn, tal og hvad har vi.

I know, I know - jeg hĂžrer dig allerede pointere at de samme personer selvfĂžlgelig heller ikke har tshare installeret, men hey - mĂ„ske installerer du det đŸ€·

Men anyway var det som nĂŠvnt fx for at finde ud af, om det bare var folkene bag termbin der havde nogle personlige netcat-kinks, eller om der rent faktisk var en eller anden mega Ă„benlys ting der gjorde det til den logiske rute at gĂ„ for sĂ„dan et projekt, som jeg bare ikke kendte til đŸ€”

Man ved ikke hvor meget man ikke ved...

Hvad ved jeg, det kunne vÊre at det var en kÊmpe fordel ved kommandoer med ekseptionelt langt output, long-running processes eller hvad ved jeg, at nc virkeligt ville shine - jeg har meget begrÊnset first hand erfaring med den 30 pr gamle teknologi, sÄ det var de her spÞrgsmÄl jeg forsÞgte at finde svaret pÄ..

đŸ—Łïž Plain vanilla...

Min anden gripe med termbin var noget mere overfladisk, og samtidigt nok ikke noget jeg egentlig havde brug for at brainstorme med Clauey om - siden man ser sit output pÄ pÄ termbin.com var det jeg kalder apache http styling: hvid baggrund med en default sort monospaced font.

Ingen syntax hightlighting fancyness eller nothing - SÄ ja - jeg var nok som sagt mere imponeret over deres idé, end deres faktisk udfÞrsel.

OgsĂ„ selvom jeg udmĂŠrket ved at pastebinit eksisterer og nemt kan installeres pĂ„ alle mulige forskellige systemer og distros, og gĂžre akurat det samme som tshare men med pastebin.com som "backend", er jeg ligesĂ„ bevidst om hvor nemt det faktisk er bare at pipe outputtet af en kommando ind i eks. wl-copy, xclip eller macos' indbyggede pbcopy - med andre ord - proppe outputtet in din udklipsholder. (eks: uv run main.py | wl-copy - boom đŸ€·đŸ€Ż).

Man kunne nemt argumentere at det ville vÊre mindst ligesÄ nemt, som at bruge tshare hvor man sÄ afhÊnger af én eller anden random dudes vibede API og hvad ved jeg - men jeg mener stadig at hvor nemt outputtet er at dele, herfra stadig afhÊnger af hvor man skal dele det, hvor man pÄ nogle sider skal wrappe kodeelementer i tripple backticks `````````, andre med <pre></pre> og nogle [code][/code] og hvad vi ellers har af variationer for at beholde formatteringen af vores output.

⚡ "Det gĂ„r nemlig' hurtigt..."

lo and behold - Claude fucker ikke rundt og var ikke klar pÄ at brainstorme, eller spilde tid pÄ at uddybe netcat selling points..!

10x audhd developer Som en Êgte 10x audhd udvikler pÄ dobbelt dosis ritalin, crack og koffein, sendte "han" mig blot fÞlgende filer som sit svar:

├──server.js
├──package.json
├──tshare
├──public/
│   ├── index.html
│   ├── view.html

De fem filer der indeholdte alt hvad der var brug for, for at replikere funktionaliteten fra termbin og pastebinit - men med en pénere terminal syntax (synes jeg) og selvfþlgeligt - ricing af dit output! 😎

Efter lidt Göstas pingen-pongen med Claude fik jeg det som jeg ville have det - og i sidste ende var stÞrstedelen af vores frem-og-tilbage ift selve landing page designet og wording pÄ siden, mere end den faktiske funktionalitet..

đŸ€· SĂ„ hvordan foregĂ„r det

Lad os se pÄ kommanden fra termbin eksemplet overfor, men med tshare in da mix i stedet:

# termbin syntax
uv run main.py | nc termbin.com 9999 
# tshare syntax
tshare uv run main.py

Ingen piping, port numre eller domÊner - man prefixer vitterligt bare kommandoen man vil kÞre med tshare, og nÄr kommandoen er fÊrdig med at kÞre, populater den automatisk et delbart link i din udklipsholderen, klar til at dele pÄ dit support forum, slack/teams eller hvad din use case nu er.
Der er et par flags man kan appende ogsÄ - se dem her eller ved at kÞre tshare uden yderligere argumenter.

đŸ€” Hvad sender tshare

Den sender dit output, sammen med lidt metadata til en simpel API, der returnerer det delbare link.

Af det metadata der sendes til api'et er der:

  • Kommandoen som outputtet stammer fra, inklussiv alle argumenter (i.e `uv run main.py`)
  • Hvor pĂ„ systemet kommandoen er kaldt (Current working directory)
  • Maskinens hostname
  • Specificeret syntax (Valgfri hvis du invoker med -s lang / --syntax lang i.e tshare -s python uv run main.py )

😬 Jamen... Hvorfor sender du dog dĂ©t?! #bigbrother

Om det skal gemme dit hostname er jeg stadig lidt i tvivl om, da det ingen umiddelbart troubleshooting formÄl har, som jeg kan se - jeg tog det med, med tanken om at lidt replikere en terminal, pÄ linket hvor outputtet bliver vist. SÄ det blev sÄdan lidt du ved... user@hostname ~/bin $> neofetch hackerman-agtig ..

Men jeg fx valgte at ikke tage brugernavnet med, af privatlivshensyn, men igen.. in the end sĂ„ er det her lavet til mig og ja.. Det kan sagtens ske at jeg ogsĂ„ fjerner hostname som default - det kan ogsĂ„ sagtens vĂŠre at jeg reintroducerer at dĂ©t at uploade brugernavnet... Hvem ved, det kan vĂŠre man kan styre det via en conf eller via flag, det kan vĂŠre jeg aldrig rĂžr ved det her igen đŸ€·

Download i dag, fÞr tshare ogsÄ bliver enshitified!

Anyways, det var the lore omkring tshare, hvordan det blev til, og hvad det prĂžver at lĂžse - nu som lovet; hvordan man hoster sin egen backend! // Best wishes and good luck - Story Lord out!

đŸ’„ TL;DR

Her gÄr vi igennem hvordan du kÞrer backenden lokalt med docker, og specificerer din server URL til tshare

1. Download tshare fra Github

Hent serveren og dens nĂždvendige filer i Github repoet, og cd ind i mappen

git clone git@github.com:mikkelrask/terminal-share.git tshare
cd tshare

2. Udspecificer dit Docker image

Opret en Dockerfile i mappen - bare brug din yndlings-editor, i.e med code Dockerfile og udfyld filen med fĂžlgende indhold:

FROM node:20-alpine

WORKDIR /app

COPY package.json package-lock.json* ./

RUN npm ci --only=production

COPY server.js ./
COPY public/ ./public
COPY tshare ./public/tshare
COPY pastes ./pastes

EXPOSE 3000

CMD ["node", "server.js"]

Det bruger node:current-alpine som base image, kopierer package.json, server.js og public/ mappen der indeholder html siderne der viser outputtet, og eksponerer port 3000 i den endelige container, hvor kommandoen node server.js kÞres nÄr man up'er sin container.

3. Byg og kĂžr dit Docker image

NÄr du har din Dockerfile klar kan du bygge dit custom image med:

docker build tshare .

og starte selve servicen med:

docker run -p 3000:3000 tshare

Du kan Êndre den fÞrste af de to 3000, hvis du har noget andet kÞrende pÄ localhost:3000, hvor det er vigtigt at den anden 3000 af de to forbliver 3000..

docker run -p 3010:3000 thsare 

Du kan nu bekrĂŠfte at servicen kĂžrer ved at besĂžge http://localhost:3000 in din browser, som nu gerne skulle vise tshare s landingpage eller hvis du vil blive i terminalen docker ps hvor tshare-app gerne skulle kĂžre og PORTS kolonnen gerne skulle vise 3000/tcp.

3. Alternativt kan du bruge docker compose

Som alternativ til trin 3, kan du efter at have specificeret din Dockerfile oprette compose.yml hvis du af en eller anden Ärsag foretrÊkker et docker compose setup - i know I do!

Som fĂžr kĂžrer du bare code compose.yml og udfylder fĂžlgende:

services:
  tshare:
    build:
      context: .
      dockerfile: Dockerfile
    image: tshare:latest
    container_name: tshare-app
    restart: unless-stopped
    ports:
      - "3000:3000"  
    volumes:
      - ./pastes:/app/pastes  
    environment:
      - NODE_ENV=production      

En af fordelene ved denne approach er at json filerne der oprettes nÄr du bruger tshare er mapped til din lokale pastes/ mappe i projekt-mappen, sÄledes at nÊste gang du evt. rebuilder dit docker image, at dine tidligere pastes fortsat er tilgÊngelige.

4. Fix tshare API endpoint

Nu hvor du har servicen kĂžrende lokalt skal vi faktisk bare sĂžrge for at tshare sender dataen til den korrekte backend, frem for den default.

Den nemmeste mÄde ville vÊre at tilfÞje -u http://localhost:3000 til din kommando

tshare -u "http://localhost:3000" uv run main.py

Evt. via et shell alias (`alias tshare="tshare -u "http://localhost:3000"\`) in din .bashrc, .zshrc eller hvilken shell du nu engang bruger.

4.1. Mere permanent lĂžsning

Ønsker du en mere permanent lÞsning, der ikke afhÊnger af den lÊngere syntax eller hvilken shell du lige tilfÊldigvis er i, kan du - da tshare blot er et bash script - bare Êndre selve server URL'en i scriptet.

Har du allerede installeret tshare klienten i din $PATH, Äbner du nemt filen i din texteditor med eks:

code $(which tshare)

Har du ikke installeret tshare in din path endnu, kan vi lige fÄ gÞre dét ogsÄ, fÞr vi Äbner filen:

cp ./tshare ~/.local/bin
chmod +x ~/.local/bin/tshare
code ~/.local/bin/tshare

I scriptet skal vi blot Êndre vÊrdien vÊrdien for SERVER_URL variablen der er somewhat Þverst i scriptet, til adressen dit image er hosted pÄ - som i vores eksempel var http://localhost:3000

#SERVER_URL="https://tshare.porgy-ruler.ts.net" 
SERVER_URL="http://localhost:3000"

Bid her mĂŠrke i at der lokalt i 99.999% af alle tilfĂŠlde er tale om http:// og ikke https:// protokollen!
Gem dine Êndringer som du plejer med CTRL+S og sÄ er du faktisk i mÄl.

NÊste gang du invoker en kommando med tshare vil du se at linket du fÄr retur nu er til http://localhost:3000/random-hex frem for den default https://tshare.porgy-ruler.ts.net adresse som jeg hoster.

Og ja- det var dĂ©t đŸ€· Nu kan du dele dit output med alle der er pĂ„ dit lokale netvĂŠrk, eller blot have en lokal samling af outputs - du kan selvfĂžlgelig ogsĂ„ kĂžre det pĂ„ din homelab server, cloud VPS eller hvad ved jeg, og gĂžre tilgĂŠngelig via et faktisk domĂŠne. Men det er her, at jeg tĂŠnker at hvis det er noget du Ăžnsker, at jeg ogsĂ„ tĂŠnker at du selv kan trinnene til at komme i mĂ„l herfra!

Note:
Jeg har blot taget udgangspunkt i at man har vscode eller cursor installeret og kan kaldes med code- har du ikke det, kan du udskifte code med enhver anden text editor - nano er den mest udbredte editor, der samtidig er nem at komme ud af igen (CTRL+X) og prompter dig om du Ăžnsker at gemme dine ĂŠndringer.

Links og dokumentation

Som altid har du ogsÄ her links til github repoet, og de ting jeg ellers referer til i indlÊgget. Har du spÞrgsmÄl, problemer eller forslag, er du mere end velkommen pÄ repoets issues eller discussions, ligesom eventuelle PRs ogsÄ er velkomne.

Links:

@mikkelrask
ComputernĂžrden. Hobby futurist, linux entusiast, hardware hacker, tinkerer og generelt kreativt legebarn. Bosat i KĂžbenhavns Nordvest kvarter med min hund Homie. Jeg har arbejdet med computere hele mit liv, og ser en deres kunnen som en naturlig udvidelse af min egen.
© mr@github:~$ █, Built with Gatsby and hosted on Github.