This commit is contained in:
Luck
2021-10-27 23:37:42 +01:00
parent f2c46495b0
commit c6824094c3
9 changed files with 163 additions and 6 deletions

49
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Build Docker Image
on:
push:
branches:
- 'master'
tags:
- 'v*'
pull_request:
branches:
- 'master'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=${{ github.ref == 'refs/heads/master' }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
# Build stage
FROM node:lts as build
ARG BYTEBIN_URL="data/"
ENV REACT_APP_BYTEBIN_URL="${BYTEBIN_URL}"
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn
COPY . ./
RUN yarn build
# Run stage
FROM nginx:alpine
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/build /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80/tcp

View File

@@ -1,8 +1,8 @@
<h1 align="center">📋 paste</h1> <h1 align="center">📋 paste</h1>
**paste is a simple web app for writing & sharing code.** It's my own take on conventional pastebin sites like *pastebin.com* or *hastebin*. **paste is a simple web app for writing & sharing code.** It's my own take on conventional pastebin sites like _pastebin.com_ or _hastebin_.
The frontend *(this repository)* is written using the React framework. The backend data storage is handled by a separate web service called [bytebin](https://github.com/lucko/bytebin). The frontend _(this repository)_ is written using the React framework. The backend data storage is handled by a separate web service called [bytebin](https://github.com/lucko/bytebin).
The user-interface is quite simple; it supports syntax highlighting, automatic indentation, many supported languages, themes, zooming in/out, linking to specific lines or sections, and more! The user-interface is quite simple; it supports syntax highlighting, automatic indentation, many supported languages, themes, zooming in/out, linking to specific lines or sections, and more!
@@ -10,8 +10,8 @@ The user-interface is quite simple; it supports syntax highlighting, automatic i
<img src="https://i.imgur.com/03rBijj.gif"> <img src="https://i.imgur.com/03rBijj.gif">
</p> </p>
## Usage ## Usage
I host a public instance of paste at [paste.lucko.me](https://paste.lucko.me). Please feel free to use it to share code/configs/whatever! I host a public instance of paste at [paste.lucko.me](https://paste.lucko.me). Please feel free to use it to share code/configs/whatever!
However please note that the (very-non-legally worded) [terms of service](https://github.com/lucko/bytebin#public-instances) for my public bytebin instance apply here too. If you come across any content which is illegal or infringes on copyright, please [get in touch](https://lucko.me/contact) and let me know so I can remove it. However please note that the (very-non-legally worded) [terms of service](https://github.com/lucko/bytebin#public-instances) for my public bytebin instance apply here too. If you come across any content which is illegal or infringes on copyright, please [get in touch](https://lucko.me/contact) and let me know so I can remove it.
@@ -19,6 +19,7 @@ However please note that the (very-non-legally worded) [terms of service](https:
Uploaded content is retained for 30 days then deleted. Uploaded content is retained for 30 days then deleted.
### Host your own ### Host your own
If you want to host your own paste, first you need to compile it: If you want to host your own paste, first you need to compile it:
```bash ```bash
@@ -32,9 +33,19 @@ yarn start
You can then follow the [create-react-app deployment documentation](https://create-react-app.dev/docs/deployment/) for how to host the build output. I personally recommend deploying to the cloud using a service like Netlify instead of hosting on your own webserver. You can then follow the [create-react-app deployment documentation](https://create-react-app.dev/docs/deployment/) for how to host the build output. I personally recommend deploying to the cloud using a service like Netlify instead of hosting on your own webserver.
If you really want to self-host (including the bytebin data storage part), I suggest using Docker:
```bash
git clone https://github.com/lucko/paste
docker compose up -d
```
You should then (hopefully!) be able to access the application at `http://localhost:8080/`.
## API ## API
paste uses [bytebin](https://github.com/lucko/bytebin) for data storage. paste uses [bytebin](https://github.com/lucko/bytebin) for data storage.
As a result, you can use the [bytebin API](https://github.com/lucko/bytebin#api-usage) to submit/read content programatically. As a result, you can use the [bytebin API](https://github.com/lucko/bytebin#api-usage) to submit/read content programatically.
To set the language of a paste, use the `Content-Type` header with value `text/<language>` (e.g. `Content-Type: text/yaml` for a *.yml* file). To set the language of a paste, use the `Content-Type` header with value `text/<language>` (e.g. `Content-Type: text/yaml` for a _.yml_ file).

26
docker-compose.yml Normal file
View File

@@ -0,0 +1,26 @@
version: '3.8'
services:
paste:
image: paste
bytebin:
image: ghcr.io/lucko/bytebin
volumes:
- data:/opt/bytebin/content
environment:
BYTEBIN_MISC_KEYLENGTH: 5
nginx:
image: nginx:alpine
command: ['nginx', '-g', 'daemon off;']
depends_on:
- paste
- bytebin
ports:
- 8080:80
volumes:
- ./docker/reverseproxy-nginx.conf:/etc/nginx/conf.d/default.conf:ro
volumes:
data: {}

18
docker/nginx.conf Normal file
View File

@@ -0,0 +1,18 @@
# nginx config file for a SPA (single page app)
server {
listen 80 default_server;
gzip on;
gzip_min_length 1000;
gzip_types text/plain text/xml application/javascript text/css;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/index.html /index.html;
}
location ~ \.(?!html) {
try_files $uri =404;
}
}

View File

@@ -0,0 +1,29 @@
# nginx reverse proxy configuration for paste+bytebin
server {
listen 80 default_server;
# paste app
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://paste;
}
# disable bytebin frontend
location = /data/ {
return 404;
}
# proxy /data endpoint to bytebin
location /data/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://bytebin:8080/;
}
}

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import Editor from './components/Editor'; import Editor from './components/Editor';
import parseContentType from 'content-type-parser'; import parseContentType from 'content-type-parser';
import { languageIds } from './util/highlighting'; import { languageIds } from './util/highlighting';
import { bytebinUrl } from './util/constants';
function getPasteIdFromUrl() { function getPasteIdFromUrl() {
const path = window.location.pathname; const path = window.location.pathname;
@@ -14,7 +15,7 @@ function getPasteIdFromUrl() {
async function loadFromBytebin(id) { async function loadFromBytebin(id) {
try { try {
const resp = await fetch('https://bytebin.lucko.me/' + id); const resp = await fetch(bytebinUrl + id);
if (resp.ok) { if (resp.ok) {
const content = await resp.text(); const content = await resp.text();
const type = parseLanguageFromContentType( const type = parseLanguageFromContentType(

View File

@@ -7,6 +7,7 @@ import copy from 'copy-to-clipboard';
import { MenuButton, Button } from './Menu'; import { MenuButton, Button } from './Menu';
import { languageIds } from '../util/highlighting'; import { languageIds } from '../util/highlighting';
import themes from '../style/themes'; import themes from '../style/themes';
import { postUrl } from '../util/constants';
export default function EditorControls({ export default function EditorControls({
code, code,
@@ -142,7 +143,7 @@ async function saveToBytebin(code, language) {
const compressed = gzip(code); const compressed = gzip(code);
const contentType = langaugeToContentType(language); const contentType = langaugeToContentType(language);
const resp = await fetch('https://bytebin.lucko.me/post', { const resp = await fetch(postUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': contentType, 'Content-Type': contentType,

4
src/util/constants.js Normal file
View File

@@ -0,0 +1,4 @@
export const bytebinUrl =
process.env.REACT_APP_BYTEBIN_URL || 'https://bytebin.lucko.me/';
export const postUrl = bytebinUrl + 'post';