# Snips

*September 28, 2024*
 — by Flaviu Vlaicu

> snips.sh is a free, anonymous, open source, snippet service.


# SSH-powered pastebin alternative with a human-friendly TUI and web UI

## snips.sh is a free, anonymous, open source, snippet service.

After @clneagu  showed me this project on GitHub, I deployed it using Docker to give it a try. My initial impression is that the service is incredibly user-friendly. For anyone who spends a lot of time in the terminal and frequently needs to save notes or share them, this tool can significantly boost productivity by eliminating the need to switch between different apps.

Features:

-   ⚡️  Zero-install: use from any machine with SSH client installed

-   🌐  Web UI: syntax-highlighted code with short links and Markdown rendering

-   🖥️  TUI: never leave your terminal for snippet management/viewing

-   🔑  No passwords: all you need is an SSH key

-   👤  Anonymous: no sign ups, no logins, no email required

-   🕗  URLs with TTL: time-limited access for sensitive sharing

-   🐳  Self-hostable: containerized and light on resources

-   🧠  ML language detection: intelligently identify source code

### Upload from any machine, no install necessary.

![Snips cat command](/images/2024-09/snips-cat.jpg)

### Download files and pipe into your favorite $PAGER.

![Snipes PAGER](/images/2024-09/snips-pager-1.jpg)

![Snips PAGER](/images/2024-09/snips-pager-2.jpg)

### Something secret to share? Create a temporary, time-bound URL for restricted access.

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
echo 'my secred message' | ssh go.vlaicu.io -- -private
```

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
ssh f:NcgEXjJCsB@go.vlaicu.io -- sign -ttl 5m
```

![Snips echo command](/images/2024-09/snips-echo.jpg)

![Snips ssh](/images/2024-09/snips-url.jpg)

## Self Hosting:

I use Cloudify.ro
 for all the projects I deploy or test. I appreciate its minimalist and intuitive interface for managing virtual machines, along with the ease of quickly adding extra IP addresses and taking snapshots.

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
git clone https://github.com/robherley/snips.sh.git
```

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
docker build -t snips.sh .
```

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
docker run -p 22:2222 -p 8080:8080 -v $PWD/data:/data ghcr.io/robherley/snips.sh
```

```dockerfile {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
FROM --platform=${BUILDPLATFORM} golang:1.23 AS build

ARG TARGETARCH BUILDPLATFORM

WORKDIR /build

COPY go.mod ./
COPY go.sum ./
RUN go mod download
RUN go mod verify

COPY . .

RUN dpkg --add-architecture arm64 && \
        apt-get update && \
        apt-get install -y \
                gcc-aarch64-linux-gnu \
                libsqlite3-dev:arm64 && \
        mkdir /tmp/extra-lib

RUN if [ "${TARGETARCH}" = "amd64" ]; then \
  script/install-libtensorflow; \
  cp /usr/local/lib/libtensorflow.so.2 /tmp/extra-lib/; \
  cp /usr/local/lib/libtensorflow_framework.so.2 /tmp/extra-lib/; \
  go build -a -o 'snips.sh'; \
else \
  CC=aarch64-linux-gnu-gcc GOARCH=${TARGETARCH} CGO_ENABLED=1 go build -ldflags "-linkmode external -extldflags -static" -a -o 'snips.sh'; \
fi

FROM --platform=${BUILDPLATFORM} ubuntu:22.04

COPY --from=build /tmp/extra-lib/* /usr/local/lib/
COPY --from=build /build/snips.sh /usr/bin/snips.sh

RUN ldconfig

ENV SNIPS_HTTP_INTERNAL=http://0.0.0.0:8080
ENV SNIPS_SSH_INTERNAL=ssh://0.0.0.0:2222
ENV SNIPS_HTTP_EXTERNAL=https://snips.vlaicu.io
ENV SNIPS_SSH_EXTERNAL=ssh://go.vlaicu.io:22

EXPOSE 8080 22

ENTRYPOINT [ "/usr/bin/snips.sh" ]
```
The reason why I have two subdomains is that Cloudflare does not proxy route port 22, so in order to have a SSL certificate on the web UI, I used a different subdomain from the one used for ssh and TUI *Terminal User Interface. Each of the two domains go.vlaicu.io
 and snips.vlaicu.io
 point to different IP addresses in Cloudflare, the web UI is proxied and the TUI is DNS only.

## Backups:

Since SQLite is a single file on disk, the danger of  corrupting/losing a database is quite high. Luckily, it’s extremely  simple to set up LiteStream
.
Wherever your SQLite file is running, all you need is to set up a LiteStream
 on your host and point it to an S3-compatible object storage. It takes minutes to set up
, and then you’re good to go 👍
Here’s an example of a docker-compose.yml:

```dockerfile {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
version: "3"
services:
  litestream:
    command: replicate
    image: 'litestream/litestream'
    restart: unless-stopped
    volumes:
      - /home/snips/data:/data
      - ./litestream.yml:/etc/litestream.yml
```
And the litestream.yml configuration:

```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
access-key-id: <secret>
secret-access-key: <secret>

dbs:
  - path: /data/snips.db
    replicas:
      - url: s3://<url>/backups
```
If you have any questions about self-hosting the service, feel free to reach out.
More on how to setup database replication using Litestream and Amazon S3 in this article ↴
https://x.com/flaviuvlaicu/article/1839345407828402468


---
*Source: [https://vlaicu.io/posts/snips/](https://vlaicu.io/posts/snips/)*
