I set up snoot.club so i could have a place to throw up quick ideas, and also to
provide my friends with places to host their ideas. The goal was that I’d be
able to run a script and very quickly have a new domain with a folder i could
put things in that would show on that domain.
The DNS records are set up
with a wildcard A and a wildcard AAAA record pointing *.snoot.club
to the
snoot.club linode. This way the moment a process
starts listening on a given name (like chee.party
), it is available on the
net.
I’ve got a wildcard letsencrypt
certificate
set up on the site, so any subdomain of snoot.club is covered by the same
certificate. Those are a bit of a nightmare to maintain because you have to do
deploy two more DNS records every three months, but it’s worth it for the
convenience during the other parts of the months.
I’ve thought about automating the 30 minutes it takes me every 3 months, using
dig(1)
and the linode
api
but that only ever seems like a great idea during those 30 minutes.
The idea was that a person (let’s call them jimmy
) would ask me for an
account, i’d run a script (create_snoot jimmy
) and that would set up a base
configuration for them that would give them a place to put files they wanted to
be on their site jimmy.snoot.club
.
Once I had the SSL certs and DNS sorted out, I wrote a collection of scrappy
bash scripts to try out the idea.
The script generates them a user account on the snoot.club linux server, and
puts them into a group called undercommon
. It makes a directory for them that
contains only their ssh public key (which will let them log in), and a
folder called “website”.
There’s a section in snoot.club’s
sshdconfig file that checks if
people are in that group and then disallows them from using any program other
than FTP software, and
doesn’t let them view any files outside of their directory.
Match Group undercommon
ChrootDirectory /snoots
PermitTTY no
ForceCommand internal-sftp
trust issues
I wanted people with more advanced needs to be able to do more advanced things,
but I didn’t want them to have access the whole system.
After creating the unix account, and the ftp entry point for the snoot, the
script also creates a docker
container for them. That’s a
kind of tiny machine of their own, that lives inside the snoot.club machine. The
docker container forwards two ports: ssh
and web (80). The http server
configuration that is built when jimmy
is created points jimmy.snoot.club
at
the whatever the docker container has running on port 80 (the web port).
I provide jimmy with a port for them to use when they are sshing in, (so they’d
do like ssh root@snoot.club -p 33532
) and then they ssh not into snoot.club
but into the docker container that is jimmy.snoot.club
. this way they get to
do anything they want without having to have full access to the snoot.club
machine!
the default app in the docker contain is a static server pointing at the
“website” directory, the same one the user can see when they ftp in.
fun doesn’t scale
this system works fine until there are more than like 30-40 people. that’s
fine. if it ever got popular it could be rewritten. it’s so easy to lose
momentum of your ideas if you’re trying to plan for what if it ever gets
bigger. most of them won’t, and it doesn’t actually matter! build things you
want to for you and your friends, and if you ever need to make it better then
you can do it then!
while i’m on that subject: we don’t need to all pretend to be brands, we should
be doing silly things like having a completely different style sheet on every
page and the web is mostly people, not companies. and the companies are also
made of people. be people.
the rewrite
over the christmas and new year period i was in a barn at the bottom of a some
rich folks garden in putney, and i rewrote the shell scripts in
javascript. the bed there
was very cosy and i also made a christmas dinner (but i didn’t cook the chicken
right and it got scary).
this one works pretty good! the things it does are the same. it offers to
download a new snoot’s authorized keys from github (thanks
jake for this idea), and it prints out coloured
messages and has emoji and feels pretty good.
i created a special image for the docker container that contained perl6 rakudo,
and started the script with pm2
on boot and would
restart the server if there were any changes.
time
so this worked really well for 6 months! kj built the
facepainting and rowan did a
throwback and abe built a
shop and chee built some
stuff. but then I started wanting it to be simpler. some
problems had started to occur. here’s some things that we’d run into:
- it was difficult to work together
- docker containers take up so much space and memory??
- it’s so complex
- there were lots of ports, two per user, it didn’t feel right
- i actually ran out of available docker network nodes or something? i dno
I started to look into other options. I created another chroot-based system that
worked similar to how the ftp
thing works but allowed more control. That still
felt too heavy.
socks
Reading the node.js documentation i noticed this in the http module
docs: server.listen()
Starts the HTTP server listening for connections. This method is identical to
server.listen()
from net.Server
.
and in the net.server docs
one of the signatures listed is a Unix Domain
Socket. now, i love unix
domain sockets. i built a window manager in
javascript that used a
unix domain socket as its main form of management. it was cool. everything was a
command. i used it irl as my main window manager for 6 months. the use of
sockets was inspired by my favourite window manager
wmii which was in turn inspired by
the plan9 operating
system created at bell
labs. the same place that invented
unix, lasers and wifi (also transistors and nearly everything else). (though
both wmii and plan9 use the 9P protocol, not Unix Domain Sockets).
trust
Anyway, so, this is the solution. I’ve rebuilt snoot.club again and i’ve decided
just to trust everyone. All the snoots have access to the main machine, they
have read permissions on eachother’s website files (by default). And instead of
ports the contract is that every snoot’s server listens on a file called sock
.
subs(1)
in order to get this to work i needed to run a command simultaneously in every
subdirectory of the /snoots
folder and restart only jimmy
’s server if only
jimmy
changed. For this i built a new tool called
subs
. it’s built in
rust and it’s on
crates.io. you can install it with cargo install subs
.
Usage: subs [options] PROGRAM [root_dir]
Options:
-t, --type TYPE set the management type [choices: watch, socket, none]
-s, --socket NAME set the socket path. sending the socket a message like
"restart xxx" will restart the process running in the directory
"xxx". [default: ./subsocket]
-i, --watch-ignore PATTERN pattern to ignore when watching (matches whole path)
-h, --help get help PROGRAM will be run in parallel in every subdirectory
(SUB), as SUB's owner. A placeholder "{}" is available to PROGRAM, it will be
replaced with SUB.
[default: none]
git
In a kind-of unrelated move I’ve been trying to pull back from using Google,
Facebook, and Microsoft products.
Facebook I’m free from, the last thing was WhatsApp which i just straight up
deleted and that’s been fine. email me
Google is off my phone and out of my search bar, but I still use their office
suite at work.
Microsoft I had been fairly free of, but then they bought GitHub and I got
unfree. So I’ve gone back to emacs from
Atom (i’m enjoying it) and I’ve deleted or archived all the code that was on
github.com and set up a cgit server and put them
all there.
If you’re a snoot you can add your own things to
git.snoot.club by making a bare git repo in
~/git/whatever.git
and pushing to it.
more
the next thing i need to work on is some kind of documentation site for talking
new snoots through how to log in, set up git repos, run their page locally,
deploy etc. after all recent changes, the helpful getting started guide that was
provided to all snoots is wrong and bad.
also a doc page for explaining that installing dependencies and building assets
is their responsibility, but the start script will be run by the server.
also so many other things.
— chee (hi@chee.party) 2019-08-17