diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..760659f
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -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 }}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..3f5ecf9
--- /dev/null
+++ b/Dockerfile
@@ -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
\ No newline at end of file
diff --git a/README.md b/README.md
index 4e4e091..c569fad 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
📋 paste
-**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!
@@ -10,8 +10,8 @@ The user-interface is quite simple; it supports syntax highlighting, automatic i
-
## 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!
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.
### Host your own
+
If you want to host your own paste, first you need to compile it:
```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.
+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
+
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.
-To set the language of a paste, use the `Content-Type` header with value `text/` (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/` (e.g. `Content-Type: text/yaml` for a _.yml_ file).
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..b153ba5
--- /dev/null
+++ b/docker-compose.yml
@@ -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: {}
diff --git a/docker/nginx.conf b/docker/nginx.conf
new file mode 100644
index 0000000..0afd2a7
--- /dev/null
+++ b/docker/nginx.conf
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/docker/reverseproxy-nginx.conf b/docker/reverseproxy-nginx.conf
new file mode 100644
index 0000000..017ba9c
--- /dev/null
+++ b/docker/reverseproxy-nginx.conf
@@ -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/;
+ }
+}
\ No newline at end of file
diff --git a/src/App.js b/src/App.js
index f366d50..2b041bb 100644
--- a/src/App.js
+++ b/src/App.js
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import Editor from './components/Editor';
import parseContentType from 'content-type-parser';
import { languageIds } from './util/highlighting';
+import { bytebinUrl } from './util/constants';
function getPasteIdFromUrl() {
const path = window.location.pathname;
@@ -14,7 +15,7 @@ function getPasteIdFromUrl() {
async function loadFromBytebin(id) {
try {
- const resp = await fetch('https://bytebin.lucko.me/' + id);
+ const resp = await fetch(bytebinUrl + id);
if (resp.ok) {
const content = await resp.text();
const type = parseLanguageFromContentType(
diff --git a/src/components/EditorControls.js b/src/components/EditorControls.js
index d92a0cc..9cda168 100644
--- a/src/components/EditorControls.js
+++ b/src/components/EditorControls.js
@@ -7,6 +7,7 @@ import copy from 'copy-to-clipboard';
import { MenuButton, Button } from './Menu';
import { languageIds } from '../util/highlighting';
import themes from '../style/themes';
+import { postUrl } from '../util/constants';
export default function EditorControls({
code,
@@ -142,7 +143,7 @@ async function saveToBytebin(code, language) {
const compressed = gzip(code);
const contentType = langaugeToContentType(language);
- const resp = await fetch('https://bytebin.lucko.me/post', {
+ const resp = await fetch(postUrl, {
method: 'POST',
headers: {
'Content-Type': contentType,
diff --git a/src/util/constants.js b/src/util/constants.js
new file mode 100644
index 0000000..87dfa5b
--- /dev/null
+++ b/src/util/constants.js
@@ -0,0 +1,4 @@
+export const bytebinUrl =
+ process.env.REACT_APP_BYTEBIN_URL || 'https://bytebin.lucko.me/';
+
+export const postUrl = bytebinUrl + 'post';