diff --git a/README.md b/README.md index e943b33..1c2a3df 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,42 @@ # Opengist +Opengist + +Opengist is a **self-hosted** pastebin **powered by Git**. All snippets are stored in a Git repository and can be +read and/or modified using standard Git commands, or with the web interface. +It is similiar to [GitHub Gist](https://gist.github.com/), but open-source and could be self-hosted. + +[Documentation](/docs) • [Demo](https://opengist.thomice.li) + + ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/thomiceli/opengist?sort=semver) ![License](https://img.shields.io/github/license/thomiceli/opengist?color=blue) -![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/thomiceli/opengist/go.yml) +[![Go CI](https://github.com/thomiceli/opengist/actions/workflows/go.yml/badge.svg)](https://github.com/thomiceli/opengist/actions/workflows/go.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/thomiceli/opengist)](https://goreportcard.com/report/github.com/thomiceli/opengist) -A self-hosted pastebin **powered by Git**. [Try it here](https://opengist.thomice.li). - -* [Features](#features) -* [Install](#install) - * [With Docker](#with-docker) - * [From source](#from-source) -* [Configuration](#configuration) - * [Via YAML file](#configuration-via-yaml-file) - * [Via Environment Variables](#configuration-via-environment-variables) -* [Administration](#administration) - * [Use Nginx as a reverse proxy](#use-nginx-as-a-reverse-proxy) - * [Use Fail2ban](#use-fail2ban) -* [Configure OAuth](#configure-oauth) -* [License](#license) ## Features * Create public, unlisted or private snippets -* Clone / Pull / Push snippets **via Git** over HTTP or SSH +* [Init](/docs/usage/init-via-git.md) / Clone / Pull / Push snippets **via Git** over HTTP or SSH * Revisions history * Syntax highlighting ; markdown & CSV support * Like / Fork snippets * Search for snippets ; browse users snippets, likes and forks -* Editor with indentation mode & size ; drag and drop files * Download raw files or as a ZIP archive * OAuth2 login with GitHub, Gitea, and OpenID Connect -* Avatars via Gravatar or OAuth2 providers -* Light/Dark mode -* Responsive UI -* Enable or disable signups * Restrict or unrestrict snippets visibility to anonymous users -* Admin panel : delete users/gists; clean database/filesystem by syncing gists -* SQLite database -* Logging * Docker support +* [More...](/docs/index.md#features) -#### Todo - -- [ ] Translation -- [ ] Code/text search -- [ ] Embed snippets -- [ ] Tests -- [ ] Filesystem/Redis support for user sessions -- [ ] Have a cool logo - -## Install +## Quick start ### With Docker Docker [images](https://github.com/thomiceli/opengist/pkgs/container/opengist) are available for each release : ```shell -docker pull ghcr.io/thomiceli/opengist:1.4 +docker pull ghcr.io/thomiceli/opengist:1 ``` It can be used in a `docker-compose.yml` file : @@ -105,167 +84,12 @@ make Opengist is now running on port 6157, you can browse http://localhost:6157 -## Configuration -Opengist provides flexible configuration options through either a YAML file and/or environment variables. -You would only need to specify the configuration options you want to change — for any config option left untouched, Opengist will simply apply the default values. +## Documentation -
-Configuration option list +The documentation is available in [/docs](/docs) directory. -| YAML Config Key | Environment Variable | Default value | Description | -| --------------------- | ------------------------ | -------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -| log-level | OG_LOG_LEVEL | `warn` | Set the log level to one of the following: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, `panic`. | -| external-url | OG_EXTERNAL_URL | none | Public URL for the Git HTTP/SSH connection. If not set, uses the URL from the request. | -| opengist-home | OG_OPENGIST_HOME | home directory | Path to the directory where Opengist stores its data. | -| db-filename | OG_DB_FILENAME | `opengist.db` | Name of the SQLite database file. | -| sqlite.journal-mode | OG_SQLITE_JOURNAL_MODE | `WAL` | Set the journal mode for SQLite. More info [here](https://www.sqlite.org/pragma.html#pragma_journal_mode) | -| http.host | OG_HTTP_HOST | `0.0.0.0` | The host on which the HTTP server should bind. | -| http.port | OG_HTTP_PORT | `6157` | The port on which the HTTP server should listen. | -| http.git-enabled | OG_HTTP_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via HTTP. (`true` or `false`) | -| ssh.git-enabled | OG_SSH_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via SSH. (`true` or `false`) | -| ssh.host | OG_SSH_HOST | `0.0.0.0` | The host on which the SSH server should bind. | -| ssh.port | OG_SSH_PORT | `2222` | The port on which the SSH server should listen. | -| ssh.external-domain | OG_SSH_EXTERNAL_DOMAIN | none | Public domain for the Git SSH connection, if it has to be different from the HTTP one. If not set, uses the URL from the request. | -| ssh.keygen-executable | OG_SSH_KEYGEN_EXECUTABLE | `ssh-keygen` | Path to the SSH key generation executable. | -| github.client-key | OG_GITHUB_CLIENT_KEY | none | The client key for the GitHub OAuth application. | -| github.secret | OG_GITHUB_SECRET | none | The secret for the GitHub OAuth application. | -| gitea.client-key | OG_GITEA_CLIENT_KEY | none | The client key for the Gitea OAuth application. | -| gitea.secret | OG_GITEA_SECRET | none | The secret for the Gitea OAuth application. | -| gitea.url | OG_GITEA_URL | `https://gitea.com/` | The URL of the Gitea instance. | -| oidc.client-key | OG_OIDC_CLIENT_KEY | none | The client key for the OpenID application. | -| oidc.secret | OG_OIDC_SECRET | none | The secret for the OpenID application. | -| oidc.discovery-url | OG_OIDC_DISCOVERY_URL | none | Discovery endpoint of the OpenID provider. | - -
- -### Configuration via YAML file - -The configuration file must be specified when launching the application, using the `--config` flag followed by the path to your YAML file. - -```shell -./opengist --config /path/to/config.yml -``` - -You can start by copying and/or modifying the provided [config.yml](config.yml) file. - -### Configuration via Environment Variables - -Usage with Docker Compose : - -```yml -services: - opengist: - # ... - environment: - OG_LOG_LEVEL: "info" - # etc. -``` -Usage via command line : - -```shell -OG_LOG_LEVEL=info ./opengist -``` - -## Administration - -### Use Nginx as a reverse proxy - -Configure Nginx to proxy requests to Opengist. Here is an example configuration file : -``` -server { - listen 80; - server_name opengist.example.com; - - location / { - proxy_pass http://127.0.0.1:6157; - 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-Proto $scheme; - } -} -``` - -Then run : -```shell -service nginx restart -``` - -### Use Fail2ban - -Fail2ban can be used to ban IPs that try to bruteforce the login page. -Log level must be set at least to `warn`. - -Add this filter in `etc/fail2ban/filter.d/opengist.conf` : -```ini -[Definition] -failregex = Invalid .* authentication attempt from -ignoreregex = -``` - -Add this jail in `etc/fail2ban/jail.d/opengist.conf` : -```ini -[opengist] -enabled = true -filter = opengist -logpath = /home/*/.opengist/log/opengist.log -maxretry = 10 -findtime = 3600 -bantime = 600 -banaction = iptables-allports -port = anyport -``` - -Then run -```shell -service fail2ban restart -``` - -## Configure OAuth - -Opengist can be configured to use OAuth to authenticate users, with GitHub, Gitea, or OpenID Connect. - -
-Integrate Github - -* Add a new OAuth app in your [Github account settings](https://github.com/settings/applications/new) -* Set 'Authorization callback URL' to `http://opengist.domain/oauth/github/callback` -* Copy the 'Client ID' and 'Client Secret' and add them to the configuration : - ```yaml - github.client-key: - github.secret: - ``` -
- -
-Integrate Gitea - -* Add a new OAuth app in Application settings from the [Gitea instance](https://gitea.com/user/settings/applications) -* Set 'Redirect URI' to `http://opengist.domain/oauth/gitea/callback` -* Copy the 'Client ID' and 'Client Secret' and add them to the configuration : - ```yaml - gitea.client-key: - gitea.secret: - # URL of the Gitea instance. Default: https://gitea.com/ - gitea.url: http://localhost:3000 - ``` -
- -
-Integrate OpenID - -* Add a new OAuth app in Application settings of your OIDC provider -* Set 'Redirect URI' to `http://opengist.domain/oauth/openid-connect/callback` -* Copy the 'Client ID', 'Client Secret', and the discovery endpoint, and add them to the configuration : - ```yaml - oidc.client-key: - oidc.secret: - # Discovery endpoint of the OpenID provider. Generally something like http://auth.example.com/.well-known/openid-configuration - oidc.discovery-url: http://auth.example.com/.well-known/openid-configuration - ``` -
## License -Opengist is licensed under the [AGPL-3.0 license](LICENSE). +Opengist is licensed under the [AGPL-3.0 license](/LICENSE). diff --git a/docs/administration/fail2ban-setup.md b/docs/administration/fail2ban-setup.md new file mode 100644 index 0000000..cb76ec3 --- /dev/null +++ b/docs/administration/fail2ban-setup.md @@ -0,0 +1,29 @@ +# Fail2ban setup + +Fail2ban can be used to ban IPs that try to bruteforce the login page. +Log level must be set at least to `warn`. + +Add this filter in `etc/fail2ban/filter.d/opengist.conf` : +```ini +[Definition] +failregex = Invalid .* authentication attempt from +ignoreregex = +``` + +Add this jail in `etc/fail2ban/jail.d/opengist.conf` : +```ini +[opengist] +enabled = true +filter = opengist +logpath = /home/*/.opengist/log/opengist.log +maxretry = 10 +findtime = 3600 +bantime = 600 +banaction = iptables-allports +port = anyport +``` + +Then run +```shell +service fail2ban restart +``` diff --git a/docs/administration/nginx-reverse-proxy.md b/docs/administration/nginx-reverse-proxy.md new file mode 100644 index 0000000..9accdb6 --- /dev/null +++ b/docs/administration/nginx-reverse-proxy.md @@ -0,0 +1,22 @@ +# Use Nginx as a reverse proxy + +Configure Nginx to proxy requests to Opengist. Here is an example configuration file : +``` +server { + listen 80; + server_name opengist.example.com; + + location / { + proxy_pass http://127.0.0.1:6157; + 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-Proto $scheme; + } +} +``` + +Then run : +```shell +service nginx restart +``` diff --git a/docs/administration/oauth-providers.md b/docs/administration/oauth-providers.md new file mode 100644 index 0000000..9b1e73e --- /dev/null +++ b/docs/administration/oauth-providers.md @@ -0,0 +1,39 @@ +# Use OAuth providers + +Opengist can be configured to use OAuth to authenticate users, with GitHub, Gitea, or OpenID Connect. + +## Github + +* Add a new OAuth app in your [Github account settings](https://github.com/settings/applications/new) +* Set 'Authorization callback URL' to `http://opengist.domain/oauth/github/callback` +* Copy the 'Client ID' and 'Client Secret' and add them to the [configuration](/docs/configuration/cheat-sheet.md) : + ```yaml + github.client-key: + github.secret: + ``` + + +## Gitea + +* Add a new OAuth app in Application settings from the [Gitea instance](https://gitea.com/user/settings/applications) +* Set 'Redirect URI' to `http://opengist.domain/oauth/gitea/callback` +* Copy the 'Client ID' and 'Client Secret' and add them to the [configuration](/docs/configuration/cheat-sheet.md) : + ```yaml + gitea.client-key: + gitea.secret: + # URL of the Gitea instance. Default: https://gitea.com/ + gitea.url: http://localhost:3000 + ``` + + +## OpenID Connect + +* Add a new OAuth app in Application settings of your OIDC provider +* Set 'Redirect URI' to `http://opengist.domain/oauth/openid-connect/callback` +* Copy the 'Client ID', 'Client Secret', and the discovery endpoint, and add them to the [configuration](/docs/configuration/cheat-sheet.md) : + ```yaml + oidc.client-key: + oidc.secret: + # Discovery endpoint of the OpenID provider. Generally something like http://auth.example.com/.well-known/openid-configuration + oidc.discovery-url: http://auth.example.com/.well-known/openid-configuration + ``` diff --git a/docs/configuration/cheat-sheet.md b/docs/configuration/cheat-sheet.md new file mode 100644 index 0000000..5400570 --- /dev/null +++ b/docs/configuration/cheat-sheet.md @@ -0,0 +1,25 @@ +# Configuration Cheat Sheet + +| YAML Config Key | Environment Variable | Default value | Description | +|-----------------------|--------------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| log-level | OG_LOG_LEVEL | `warn` | Set the log level to one of the following: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, `panic`. | +| external-url | OG_EXTERNAL_URL | none | Public URL for the Git HTTP/SSH connection. If not set, uses the URL from the request. | +| opengist-home | OG_OPENGIST_HOME | home directory | Path to the directory where Opengist stores its data. | +| db-filename | OG_DB_FILENAME | `opengist.db` | Name of the SQLite database file. | +| sqlite.journal-mode | OG_SQLITE_JOURNAL_MODE | `WAL` | Set the journal mode for SQLite. More info [here](https://www.sqlite.org/pragma.html#pragma_journal_mode) | +| http.host | OG_HTTP_HOST | `0.0.0.0` | The host on which the HTTP server should bind. | +| http.port | OG_HTTP_PORT | `6157` | The port on which the HTTP server should listen. | +| http.git-enabled | OG_HTTP_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via HTTP. (`true` or `false`) | +| ssh.git-enabled | OG_SSH_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via SSH. (`true` or `false`) | +| ssh.host | OG_SSH_HOST | `0.0.0.0` | The host on which the SSH server should bind. | +| ssh.port | OG_SSH_PORT | `2222` | The port on which the SSH server should listen. | +| ssh.external-domain | OG_SSH_EXTERNAL_DOMAIN | none | Public domain for the Git SSH connection, if it has to be different from the HTTP one. If not set, uses the URL from the request. | +| ssh.keygen-executable | OG_SSH_KEYGEN_EXECUTABLE | `ssh-keygen` | Path to the SSH key generation executable. | +| github.client-key | OG_GITHUB_CLIENT_KEY | none | The client key for the GitHub OAuth application. | +| github.secret | OG_GITHUB_SECRET | none | The secret for the GitHub OAuth application. | +| gitea.client-key | OG_GITEA_CLIENT_KEY | none | The client key for the Gitea OAuth application. | +| gitea.secret | OG_GITEA_SECRET | none | The secret for the Gitea OAuth application. | +| gitea.url | OG_GITEA_URL | `https://gitea.com/` | The URL of the Gitea instance. | +| oidc.client-key | OG_OIDC_CLIENT_KEY | none | The client key for the OpenID application. | +| oidc.secret | OG_OIDC_SECRET | none | The secret for the OpenID application. | +| oidc.discovery-url | OG_OIDC_DISCOVERY_URL | none | Discovery endpoint of the OpenID provider. | diff --git a/docs/configuration/index.md b/docs/configuration/index.md new file mode 100644 index 0000000..1327aa4 --- /dev/null +++ b/docs/configuration/index.md @@ -0,0 +1,38 @@ +# Configuration + +Opengist provides flexible configuration options through either a YAML file and/or environment variables. +You would only need to specify the configuration options you want to change — for any config option left untouched, +Opengist will simply apply the default values. + +The [configuration cheat sheet](cheat-sheet.md) lists all available configuration options. + + +## Configuration via YAML file + +The configuration file must be specified when launching the application, using the `--config` flag followed by the path +to your YAML file. + +```shell +./opengist --config /path/to/config.yml +``` + +You can start by copying and/or modifying the provided [config.yml](/config.yml) file. + + +## Configuration via Environment Variables + +Usage with Docker Compose : + +```yml +services: + opengist: + # ... + environment: + OG_LOG_LEVEL: "info" + # etc. +``` +Usage via command line : + +```shell +OG_LOG_LEVEL=info ./opengist +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..09a0c88 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,52 @@ +# Opengist + +Opengist is a **self-hosted** pastebin **powered by Git**. All snippets are stored in a Git repository and can be +read and/or modified using standard Git commands, or with the web interface. +It is similiar to [GitHub Gist](https://gist.github.com/), but open-source and could be self-hosted. + +Written in [Go](https://go.dev), Opengist aims to be fast and easy to deploy. + + +## Features + +* Create public, unlisted or private snippets +* [Init](/docs/usage/init-via-git.md) / Clone / Pull / Push snippets **via Git** over HTTP or SSH +* Revisions history +* Syntax highlighting ; markdown & CSV support +* Like / Fork snippets +* Search for snippets ; browse users snippets, likes and forks +* Editor with indentation mode & size ; drag and drop files +* Download raw files or as a ZIP archive +* OAuth2 login with GitHub, Gitea, and OpenID Connect +* Avatars via Gravatar or OAuth2 providers +* Light/Dark mode +* Responsive UI +* Enable or disable signups +* Restrict or unrestrict snippets visibility to anonymous users +* Admin panel : + * delete users/gists; + * clean database/filesystem by syncing gists + * run `git gc` for all repositories +* SQLite database +* Logging +* Docker support + + +## System requirements + +[Git](https://git-scm.com/download) is obviously required to run Opengist, as it's the main feature of the app. +Version **2.20** or later is recommended as the app has not been tested with older Git versions. + +[OpenSSH](https://www.openssh.com/) suite if you wish to use Git over SSH + + +## Components + +* Backend Web Framework: [Echo](https://echo.labstack.com/) +* ORM: [GORM](https://gorm.io/) +* Frontend libraries: + * [Tailwind CSS](https://tailwindcss.com/) + * [CodeMirror](https://codemirror.net/) + * [Day.js](https://day.js.org/) + * [highlight.js](https://highlightjs.org/) + * and [others](/package.json) diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..3def026 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,59 @@ +# Installation + +## With Docker + +Docker [images](https://github.com/thomiceli/opengist/pkgs/container/opengist) are available for each release : + +```shell +docker pull ghcr.io/thomiceli/opengist:1 +``` + +It can be used in a `docker-compose.yml` file : + +1. Create a `docker-compose.yml` file with the following content +2. Run `docker compose up -d` +3. Opengist is now running on port 6157, you can browse http://localhost:6157 + +```yml +version: "3" + +services: + opengist: + image: ghcr.io/thomiceli/opengist:1 + container_name: opengist + restart: unless-stopped + ports: + - "6157:6157" # HTTP port + - "2222:2222" # SSH port, can be removed if you don't use SSH + volumes: + - "$HOME/.opengist:/opengist" +``` + +You can define which user/group should run the container and own the files by setting the `UID` and `GID` environment +variables : + +```yml +services: + opengist: + # ... + environment: + UID: 1001 + GID: 1001 +``` + + +## From source + +Requirements : +* [Git](https://git-scm.com/downloads) (2.20+) +* [Go](https://go.dev/doc/install) (1.20+) +* [Node.js](https://nodejs.org/en/download/) (16+) + +```shell +git clone https://github.com/thomiceli/opengist +cd opengist +make +./opengist +``` + +Opengist is now running on port 6157, you can browse http://localhost:6157 diff --git a/docs/usage/init-via-git.md b/docs/usage/init-via-git.md new file mode 100644 index 0000000..231e698 --- /dev/null +++ b/docs/usage/init-via-git.md @@ -0,0 +1,42 @@ +# Init Gists via Git + +Opengist allows you to create new snippets via Git over HTTP. + +Simply init a new Git repository where your file(s) is/are located: + +```shell +git init +git add . +git commit -m "My cool snippet" +``` + +Then add this Opengist special remote URL and push your changes: + +```shell +git remote add origin http://localhost:6157/init + +git push -u origin master +``` + +Log in with your Opengist account credentials, and your snippet will be created at the specified URL: + +```shell +Username for 'http://localhost:6157': thomas +Password for 'http://thomas@localhost:6157': +Enumerating objects: 3, done. +Counting objects: 100% (3/3), done. +Delta compression using up to 8 threads +Compressing objects: 100% (2/2), done. +Writing objects: 100% (3/3), 416 bytes | 416.00 KiB/s, done. +Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 +remote: +remote: Your new repository has been created here: http://localhost:6157/thomas/6051e930f140429f9a2f3bb1fa101066 +remote: +remote: If you want to keep working with your gist, you could set the remote URL via: +remote: git remote set-url origin http://localhost:6157/thomas/6051e930f140429f9a2f3bb1fa101066 +remote: +To http://localhost:6157/init + * [new branch] master -> master +``` + +https://github.com/thomiceli/opengist/assets/27960254/3fe1a0ba-b638-4928-83a1-f38e46fea066 diff --git a/templates/pages/admin_config.html b/templates/pages/admin_config.html index 0c98a87..5ea3af6 100644 --- a/templates/pages/admin_config.html +++ b/templates/pages/admin_config.html @@ -3,7 +3,7 @@
-

{{ .locale.Tr "admin.config-link" (join "" (toStr (.locale.Tr "admin.config-link-overriden")) "") }}

+

{{ .locale.Tr "admin.config-link" (join "" (toStr (.locale.Tr "admin.config-link-overriden")) "") }}