---
title: "Pasty: Selfhosted pastebin сервис"
date: 2022-09-15T11:01:12+03:00
draft: true
tags: [tutorial]
---

## Введение

pasty - это Pastebin сервис.

> Pastebin или nopaste — веб-приложение, которое позволяет загружать отрывки текста,
> обычно фрагменты исходного кода, для возможности просмотра окружающими.

(c) [Wikipedia](https://ru.wikipedia.org/wiki/Pastebin)

Адрес сервиса: [pasty.lus.pm](https://pasty.lus.pm/).

Преимущества этого проекта (как и почти всех остальных) это открытый исходный код,
что позволяет развернуть сервис на своём сервере.

## Selfhosting

### Сборка

Исходный код досупен на [GitHub](https://github.com/lus/pasty),
а также на моём [зеркале](https://git.a2s.su/mirror/pasty) Gitea.

В первую очередь `pasty` необходимо собрать из исходного кода,
потому что автор не размещает бинарные сборки.

Проекты на [Go](https://go.dev/) собираются без каких-либо проблем.

```sh
git clone https://github.com/lus/pasty
cd pasty/
go build -o pasty ./cmd/pasty/main.go
```

После завершения операции, в текущей директории появится файл исполняемый `pasty`.

### Настройка

Pasty конфигурируется через файл `.env`, размещённый в тойже директории,
где расположен исполняемый файл.

Pasty поддерживает несколько типов хранения данных, который определяется параметром `PASTY_STORAGE_TYPE`.

**Список поддерживаемых типов хранения данных:**

* [file](https://github.com/lus/pasty#file-file)
* [postgres](https://github.com/lus/pasty#postgresql-postgres)
* [mongodb](https://github.com/lus/pasty#mongodb-mongodb)
* [s3](https://github.com/lus/pasty#s3-s3)

Для каждого из типа хранения присутсуют свои особеннные настройки,
которые можно посмотреть перейдя по ссылке из списка типов выше.

Я буду использовать тип `file`,
для чего мне необходимо добавить второй параметр в настройки
`PASTY_STORAGE_FILE_PATH`.

Значение по умолчанию `./data`.

**Если ты запускаешь исполняемый файл из сторонней директории,
необходимо ещё скопировать каталог `web` из исходников.**

Я допустим создал отдельную директорию `$HOME/Sites/Pasty/`,
настроил в `.env` запуск по адресу **localhost:3004** (`PASTY_WEB_ADDRESS=localhost:3004`),
а в [Nginx]() настроил `location` с `proxy_pass`.

```nginx
location /pastebin/ {
    proxy_pass http://localhost:3004;
}
```

### Глубокая настройка

... заключается в изменении всех остальных параметров,
список которых можно посмотреть в файле README.md
или на странице проекта на GitHub
[pasty#general-environment-variables](https://github.com/lus/pasty#general-environment-variables).

## Использование pasty не на отдельном домене

Если захочется использовать pasty не на отдельном домене/поддомене, например **pastebin.example.com**,
а например как я, по пути **iiiypuk.me/pastebin/**, ничего работать не будет.

Получим ошибку

```text
Failed loading API information:
404 Not Found
```

В первую очередь, необходимо исправить константу `API_BASE_URL`
в файле `/web/assets/js/modules/api.js`.

Это первая строка.

```javascript
const API_BASE_URL = location.protocol + "//" + location.host + "/api/v2";
```

```javascript
const API_BASE_URL = location.protocol + "//" + location.host + "/pastebin" + "/api/v2";
```

Однако опять ничего не заработает, будет ошибка

```text
Could not load paste: paste not found
```

А всё потому, что часть `/pastebin/` в адресе сервис распознаёт, как ID.

```text
api.js:8 
GET https://iiiypuk.me/pastebin/api/v2/pastes/pastebin 404 (Not Found)
```

Вот код, в котором якобы происходит ошибка.

```javascript
export async function getPaste(pasteID) {
    return fetch(API_BASE_URL + "/pastes/" + pasteID);
}
```

Следующий файл, который необходимо исправить `/web/assets/js/modules/state.js`.

В этом куске кода изменяем первую строку:

```javascript
if (location.pathname !== "/") {
        // Extract the paste data (ID and language)
        const split = location.pathname.replace("/", "").split(".");
        const pasteID = split[0];
        const language = split[1];
```

На это:

```javascript
if (location.pathname !== "/pastebin/") {
```

Всё, теперь с главной страницы не редиректит.

Но при сохранении, в редирект не подставляется `/pastebin/`.

Эта часть кода овечает, за редирект на главную, если pasteID отсутсвует в базе. 

```javascript
 // Try to retrieve the paste data from the API
const response = await API.getPaste(pasteID);
if (!response.ok) {
    Notifications.error("Could not load paste: <b>" + await response.text() + "</b>");
    setTimeout(() => location.replace(location.protocol + "//" + location.host), 3000);
    return;
}
```

Исправляем пятую строку на:
```javascript
setTimeout(() => location.replace(location.protocol + "//" + location.host + "/pastebin/"), 3000);
```

По сути во все куски кода с `location.protocol + "//" + location.host` необходимо добавить `/pastebin/`.

```javascript
// Redirect the user to his newly created paste
            location.replace(location.protocol + "//" + location.host + "/" + data.id + (key ? "#" + key : ""));
```

```javascript
// Redirect the user to his newly created paste
            location.replace(location.protocol + "//" + location.host + "/pastebin/" + data.id + (key ? "#" + key : ""));
```

## Мой инстанс

Мой pasty доступен по адресу `TODO: add links`

