Eric Bower
·
23 Sep 24
marketing.page.tmpl
1{{template "base" .}}
2
3{{define "title"}}pubsub using ssh{{end}}
4
5{{define "meta"}}
6<meta name="description" content="pubsub using ssh" />
7
8<meta property="og:type" content="website">
9<meta property="og:site_name" content="{{.Site.Domain}}">
10<meta property="og:url" content="https://{{.Site.Domain}}">
11<meta property="og:title" content="{{.Site.Domain}}">
12<meta property="og:description" content="pubsub using ssh">
13{{end}}
14
15{{define "attrs"}}class="container-sm"{{end}}
16
17{{define "body"}}
18<header class="flex flex-col items-center gap">
19 <img src="https://pico.sh/logo.svg" alt="pico logo" width="50" height="50" />
20 <h1 class="text-2xl font-bold text-center">Authenticated <code>*nix</code> pipes over <code>ssh</code></h1>
21</header>
22
23<hr />
24
25<article class="flex flex-col gap-2">
26 <div>
27 <p>
28 The simplest authenticated pubsub system. Send messages through
29 user-defined channels. By default, channels are private to the authenticated
30 ssh user. The default pubsub model is multicast with bidirectional
31 blocking, meaning a publisher (<code>pub</code>) will send its message to all
32 subscribers (<code>sub</code>) on a channel. Further, both <code>pub</code> and
33 <code>sub</code> will wait for at least one event to be sent or received on the channel.
34 </p>
35
36 <blockquote>This service is undergoing active development, expect bugs, feature dev, and server restarts</blockquote>
37 </div>
38
39 <div>
40 <h2 class="text-xl">A basic API</h2>
41 <pre>ssh {{.Site.Domain}} sub mykey</pre>
42 <pre>echo "hello world!" | ssh {{.Site.Domain}} pub mykey</pre>
43
44 <details>
45 <summary>Demo</summary>
46 <script
47 src="https://asciinema.org/a/52qRVi77CTjfAoZj9IaGMygDr.js"
48 id="asciicast-52qRVi77CTjfAoZj9IaGMygDr"
49 async="true"
50 data-theme="dracula"
51 data-loop="true"
52 data-speed="1.5"
53 data-idle-time-limit="2"
54 ></script>
55 </details>
56 </div>
57
58 <div>
59 <h2 class="text-xl">Simple desktop notifications</h2>
60 <pre>ssh {{.Site.Domain}} sub notify; notify-send "job done!"</pre>
61 <pre>./longjob.sh; ssh {{.Site.Domain}} pub notify -e</pre>
62 </div>
63
64 <div>
65 <h2 class="text-xl">File sharing</h2>
66 <pre>cat doc.md | ssh {{.Site.Domain}} pub thedoc</pre>
67 <pre>ssh {{.Site.Domain}} sub thedoc > ./important.md</pre>
68
69 <details>
70 <summary>Demo</summary>
71 <script
72 src="https://asciinema.org/a/TW0chshVssDj35hvr9NKNC2CK.js"
73 id="asciicast-TW0chshVssDj35hvr9NKNC2CK"
74 async="true"
75 data-theme="dracula"
76 data-loop="true"
77 data-speed="1.5"
78 data-idle-time-limit="2"
79 ></script>
80 </details>
81 </div>
82
83 <div>
84 <h2 class="text-xl">Pipe command output</h2>
85 <p>Send command output through our <code>pipe</code> command.</p>
86
87 <details>
88 <summary>Demo</summary>
89 <script
90 src="https://asciinema.org/a/7e3SVyxKa31D0iZ4X5PJm8b6E.js"
91 id="asciicast-7e3SVyxKa31D0iZ4X5PJm8b6E"
92 async="true"
93 data-theme="dracula"
94 data-loop="true"
95 data-speed="1.5"
96 data-idle-time-limit="2"
97 ></script>
98 </details>
99 </div>
100
101 <div>
102 <h2 class="text-xl">Chat</h2>
103 <p>Use our <code>pipe</code> command to have a chat with someone.</p>
104 <pre>ssh {{.Site.Domain}} pipe mychan -p</pre>
105 <p>Now anyone with a <code>pico</code> account can subscribe to this channel using the same command.</p>
106
107 <details>
108 <summary>Demo</summary>
109 <script
110 src="https://asciinema.org/a/fLBHAcPQqqawkrdpRdgEVFNrm.js"
111 id="asciicast-fLBHAcPQqqawkrdpRdgEVFNrm"
112 async="true"
113 data-theme="dracula"
114 data-loop="true"
115 data-speed="1.5"
116 data-idle-time-limit="2"
117 ></script>
118 </details>
119 </div>
120
121 <div>
122 <h2 class="text-xl">Pipe reverse shell</h2>
123 <p>If you squint hard enough you can give users interactive access to your shell.</p>
124
125 <details>
126 <summary>Demo</summary>
127 <script
128 src="https://asciinema.org/a/S3LSLOi9mHQOPZHoK0xlkiKLM.js"
129 id="asciicast-S3LSLOi9mHQOPZHoK0xlkiKLM"
130 async="true"
131 data-theme="dracula"
132 data-loop="true"
133 data-speed="1.5"
134 data-idle-time-limit="2"
135 ></script>
136 </details>
137 </div>
138
139 <div>
140 <h2 class="text-xl">Simple CI/CD</h2>
141 <pre>ssh {{.Site.Domain}} sub myimg; docker pull myimg && docker up -d dev</pre>
142 <pre>docker buildx build --push -t myimg .; ssh {{.Site.Domain}} pub myimg -e</pre>
143 </div>
144
145 <div>
146 <h2 class="text-xl">Pubsub interactions</h2>
147
148 <h3 class="text-lg">Multiple subs</h3>
149 <details>
150 <summary>Demo</summary>
151 <script
152 src="https://asciinema.org/a/Ccee82V83EUyaZzFYbTn36BLF.js"
153 id="asciicast-Ccee82V83EUyaZzFYbTn36BLF"
154 async="true"
155 data-theme="dracula"
156 data-loop="true"
157 data-speed="1.5"
158 data-idle-time-limit="2"
159 ></script>
160 </details>
161
162 <h3 class="text-lg">Multiple pubs</h3>
163 <details>
164 <summary>Demo</summary>
165 <script
166 src="https://asciinema.org/a/ONe1OphgsKUt9MMPVRBiSbwd0.js"
167 id="asciicast-ONe1OphgsKUt9MMPVRBiSbwd0"
168 async="true"
169 data-theme="dracula"
170 data-loop="true"
171 data-speed="1.5"
172 data-idle-time-limit="2"
173 ></script>
174 </details>
175
176 <h3 class="text-lg">Multiple pubs and subs</h3>
177 <details>
178 <summary>Demo</summary>
179 <script
180 src="https://asciinema.org/a/HAlhNCLFLvuGjiqnEEUvWVi1h.js"
181 id="asciicast-HAlhNCLFLvuGjiqnEEUvWVi1h"
182 async="true"
183 data-theme="dracula"
184 data-loop="true"
185 data-speed="1.5"
186 data-idle-time-limit="2"
187 ></script>
188 </details>
189 </div>
190
191 <div>
192 <h2 class="text-xl">Send a public message</h2>
193 <pre>echo "hello world!" | ssh {{.Site.Domain}} pub mychan -p</pre>
194 <p>Now anyone with a <code>pico</code> account can subscribe to this channel:</p>
195 <pre>ssh {{.Site.Domain}} sub mychan -p</pre>
196 </div>
197
198 <div>
199 <h2 class="text-xl">Caveats</h2>
200 <p>
201 You must always pipe something into <code>pub</code> or else it will block
202 indefinitely until the process is killed. However, you can provide a
203 flag to send an empty message: <code>pub xyz -e</code>.
204 </p>
205 </div>
206
207 <div>
208 <h2 class="text-xl">Inspiration</h2>
209 <p>
210 A special thanks to <a href="https://patchbay.pub">patchbay.pub</a> for our inspiration.
211 </p>
212 </div>
213
214 <div class="text-center mb-2">
215 <p>built on our <a href="https://github.com/picosh/pubsub">go pkg</a>.</p>
216 <a href="https://pico.sh/getting-started" class="btn-link inline-block">GET STARTED</a>
217 </div>
218</article>
219
220{{template "marketing-footer" .}}
221{{end}}