mirror of
https://github.com/thomiceli/opengist.git
synced 2025-01-03 16:22:40 +00:00
Better config (#50)
This commit is contained in:
parent
c517c2d9c9
commit
24e3de8fc1
9 changed files with 294 additions and 137 deletions
72
README.md
72
README.md
|
@ -12,6 +12,8 @@ A self-hosted pastebin **powered by Git**. [Try it here](https://opengist.thomic
|
||||||
* [With Docker](#with-docker)
|
* [With Docker](#with-docker)
|
||||||
* [From source](#from-source)
|
* [From source](#from-source)
|
||||||
* [Configuration](#configuration)
|
* [Configuration](#configuration)
|
||||||
|
* [Via YAML file](#configuration-via-yaml-file)
|
||||||
|
* [Via Environment Variables](#configuration-via-environment-variables)
|
||||||
* [Administration](#administration)
|
* [Administration](#administration)
|
||||||
* [Use Nginx as a reverse proxy](#use-nginx-as-a-reverse-proxy)
|
* [Use Nginx as a reverse proxy](#use-nginx-as-a-reverse-proxy)
|
||||||
* [Use Fail2ban](#use-fail2ban)
|
* [Use Fail2ban](#use-fail2ban)
|
||||||
|
@ -53,7 +55,7 @@ A self-hosted pastebin **powered by Git**. [Try it here](https://opengist.thomic
|
||||||
|
|
||||||
A Docker [image](https://github.com/users/thomiceli/packages/container/package/opengist), available for each release, can be pulled
|
A Docker [image](https://github.com/users/thomiceli/packages/container/package/opengist), available for each release, can be pulled
|
||||||
|
|
||||||
```
|
```shell
|
||||||
docker pull ghcr.io/thomiceli/opengist:1
|
docker pull ghcr.io/thomiceli/opengist:1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -76,9 +78,6 @@ services:
|
||||||
- "2222:2222" # SSH port, can be removed if you don't use SSH
|
- "2222:2222" # SSH port, can be removed if you don't use SSH
|
||||||
volumes:
|
volumes:
|
||||||
- "$HOME/.opengist:/root/.opengist"
|
- "$HOME/.opengist:/root/.opengist"
|
||||||
environment:
|
|
||||||
CONFIG: |
|
|
||||||
log-level: info
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### From source
|
### From source
|
||||||
|
@ -96,29 +95,64 @@ Opengist is now running on port 6157, you can browse http://localhost:6157
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Opengist can be configured using YAML. The full configuration file is [config.yml](config.yml), each default key/value
|
Opengist provides flexible configuration options through either a YAML file and/or environment variables.
|
||||||
pair can be overridden.
|
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.
|
||||||
|
|
||||||
### With docker
|
<details>
|
||||||
|
<summary>Configuration option list</summary>
|
||||||
|
|
||||||
Add a `CONFIG` environment variable in the `docker-compose.yml` file to the `opengist` service :
|
| 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. |
|
||||||
|
| 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`) |
|
||||||
|
| http.tls-enabled | OG_HTTP_TLS_ENABLED | `false` | Enable or disable TLS for the HTTP server. (`true` or `false`) |
|
||||||
|
| http.cert-file | OG_HTTP_CERT_FILE | none | Path to the TLS certificate file if TLS is enabled. |
|
||||||
|
| http.key-file | OG_HTTP_KEY_FILE | none | Path to the TLS key file if TLS is enabled. |
|
||||||
|
| 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. |
|
||||||
|
|
||||||
```diff
|
</details>
|
||||||
environment:
|
|
||||||
CONFIG: |
|
|
||||||
log-level: info
|
|
||||||
ssh.git-enabled: false
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### With binary
|
### Configuration via YAML file
|
||||||
|
|
||||||
Create a `config.yml` file (you can reuse this [one](config.yml)) and run Opengist binary with the `--config` flag :
|
The configuration file must be specified when launching the application, using the `--config` flag followed by the path to your YAML file.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./opengist --config /path/to/config.yml
|
./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
|
## Administration
|
||||||
|
|
||||||
|
@ -142,7 +176,7 @@ server {
|
||||||
|
|
||||||
Then run :
|
Then run :
|
||||||
```shell
|
```shell
|
||||||
service nginx restart
|
service nginx restart
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use Fail2ban
|
### Use Fail2ban
|
||||||
|
@ -172,7 +206,7 @@ port = anyport
|
||||||
|
|
||||||
Then run
|
Then run
|
||||||
```shell
|
```shell
|
||||||
service fail2ban restart
|
service fail2ban restart
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configure OAuth
|
## Configure OAuth
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -18,30 +19,30 @@ var C *config
|
||||||
// Not using nested structs because the library
|
// Not using nested structs because the library
|
||||||
// doesn't support dot notation in this case sadly
|
// doesn't support dot notation in this case sadly
|
||||||
type config struct {
|
type config struct {
|
||||||
LogLevel string `yaml:"log-level"`
|
LogLevel string `yaml:"log-level" env:"OG_LOG_LEVEL"`
|
||||||
ExternalUrl string `yaml:"external-url"`
|
ExternalUrl string `yaml:"external-url" env:"OG_EXTERNAL_URL"`
|
||||||
OpengistHome string `yaml:"opengist-home"`
|
OpengistHome string `yaml:"opengist-home" env:"OG_OPENGIST_HOME"`
|
||||||
DBFilename string `yaml:"db-filename"`
|
DBFilename string `yaml:"db-filename" env:"OG_DB_FILENAME"`
|
||||||
|
|
||||||
HttpHost string `yaml:"http.host"`
|
HttpHost string `yaml:"http.host" env:"OG_HTTP_HOST"`
|
||||||
HttpPort string `yaml:"http.port"`
|
HttpPort string `yaml:"http.port" env:"OG_HTTP_PORT"`
|
||||||
HttpGit bool `yaml:"http.git-enabled"`
|
HttpGit bool `yaml:"http.git-enabled" env:"OG_HTTP_GIT_ENABLED"`
|
||||||
HttpTLSEnabled bool `yaml:"http.tls-enabled"`
|
HttpTLSEnabled bool `yaml:"http.tls-enabled" env:"OG_HTTP_TLS_ENABLED"`
|
||||||
HttpCertFile string `yaml:"http.cert-file"`
|
HttpCertFile string `yaml:"http.cert-file" env:"OG_HTTP_CERT_FILE"`
|
||||||
HttpKeyFile string `yaml:"http.key-file"`
|
HttpKeyFile string `yaml:"http.key-file" env:"OG_HTTP_KEY_FILE"`
|
||||||
|
|
||||||
SshGit bool `yaml:"ssh.git-enabled"`
|
SshGit bool `yaml:"ssh.git-enabled" env:"OG_SSH_GIT_ENABLED"`
|
||||||
SshHost string `yaml:"ssh.host"`
|
SshHost string `yaml:"ssh.host" env:"OG_SSH_HOST"`
|
||||||
SshPort string `yaml:"ssh.port"`
|
SshPort string `yaml:"ssh.port" env:"OG_SSH_PORT"`
|
||||||
SshExternalDomain string `yaml:"ssh.external-domain"`
|
SshExternalDomain string `yaml:"ssh.external-domain" env:"OG_SSH_EXTERNAL_DOMAIN"`
|
||||||
SshKeygen string `yaml:"ssh.keygen-executable"`
|
SshKeygen string `yaml:"ssh.keygen-executable" env:"OG_SSH_KEYGEN_EXECUTABLE"`
|
||||||
|
|
||||||
GithubClientKey string `yaml:"github.client-key"`
|
GithubClientKey string `yaml:"github.client-key" env:"OG_GITHUB_CLIENT_KEY"`
|
||||||
GithubSecret string `yaml:"github.secret"`
|
GithubSecret string `yaml:"github.secret" env:"OG_GITHUB_SECRET"`
|
||||||
|
|
||||||
GiteaClientKey string `yaml:"gitea.client-key"`
|
GiteaClientKey string `yaml:"gitea.client-key" env:"OG_GITEA_CLIENT_KEY"`
|
||||||
GiteaSecret string `yaml:"gitea.secret"`
|
GiteaSecret string `yaml:"gitea.secret" env:"OG_GITEA_SECRET"`
|
||||||
GiteaUrl string `yaml:"gitea.url"`
|
GiteaUrl string `yaml:"gitea.url" env:"OG_GITEA_URL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func configWithDefaults() (*config, error) {
|
func configWithDefaults() (*config, error) {
|
||||||
|
@ -77,37 +78,12 @@ func InitConfig(configPath string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if configPath != "" {
|
if err = loadConfigFromYaml(c, configPath); err != nil {
|
||||||
absolutePath, _ := filepath.Abs(configPath)
|
return err
|
||||||
absolutePath = filepath.Clean(absolutePath)
|
|
||||||
file, err := os.Open(absolutePath)
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("No YML config file found at " + absolutePath)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Using config file: " + absolutePath)
|
|
||||||
|
|
||||||
// Override default values with values from config.yml
|
|
||||||
d := yaml.NewDecoder(file)
|
|
||||||
if err = d.Decode(&c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("No config file specified. Using default values.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override default values with environment variables (as yaml)
|
if err = loadConfigFromEnv(c); err != nil {
|
||||||
configEnv := os.Getenv("CONFIG")
|
return err
|
||||||
if configEnv != "" {
|
|
||||||
fmt.Println("Using config from environment variable: CONFIG")
|
|
||||||
d := yaml.NewDecoder(strings.NewReader(configEnv))
|
|
||||||
if err = d.Decode(&c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
C = c
|
C = c
|
||||||
|
@ -159,3 +135,79 @@ func GetHomeDir() string {
|
||||||
absolutePath, _ := filepath.Abs(C.OpengistHome)
|
absolutePath, _ := filepath.Abs(C.OpengistHome)
|
||||||
return filepath.Clean(absolutePath)
|
return filepath.Clean(absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadConfigFromYaml(c *config, configPath string) error {
|
||||||
|
if configPath != "" {
|
||||||
|
absolutePath, _ := filepath.Abs(configPath)
|
||||||
|
absolutePath = filepath.Clean(absolutePath)
|
||||||
|
file, err := os.Open(absolutePath)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("No YAML config file found at " + absolutePath)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Using YAML config file: " + absolutePath)
|
||||||
|
|
||||||
|
// Override default values with values from config.yml
|
||||||
|
d := yaml.NewDecoder(file)
|
||||||
|
if err = d.Decode(&c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("No YAML config file specified.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override default values with environment variables (as yaml)
|
||||||
|
configEnv := os.Getenv("CONFIG")
|
||||||
|
if configEnv != "" {
|
||||||
|
fmt.Println("Using config from environment variable: CONFIG")
|
||||||
|
d := yaml.NewDecoder(strings.NewReader(configEnv))
|
||||||
|
if err := d.Decode(&c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConfigFromEnv(c *config) error {
|
||||||
|
v := reflect.ValueOf(c).Elem()
|
||||||
|
var envVars []string
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
tag := v.Type().Field(i).Tag.Get("env")
|
||||||
|
|
||||||
|
if tag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
envValue := os.Getenv(strings.ToUpper(tag))
|
||||||
|
if envValue == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Field(i).Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
v.Field(i).SetString(envValue)
|
||||||
|
case reflect.Bool:
|
||||||
|
boolVal, err := strconv.ParseBool(envValue)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Field(i).SetBool(boolVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
envVars = append(envVars, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(envVars) > 0 {
|
||||||
|
fmt.Println("Using environment variables config: " + strings.Join(envVars, ", "))
|
||||||
|
} else {
|
||||||
|
fmt.Println("No environment variables config specified.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -185,15 +185,16 @@ func adminSyncReposFromDB(ctx echo.Context) error {
|
||||||
return redirect(ctx, "/admin-panel")
|
return redirect(ctx, "/admin-panel")
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminSettings(ctx echo.Context) error {
|
func adminConfig(ctx echo.Context) error {
|
||||||
setData(ctx, "title", "Admin Settings")
|
setData(ctx, "title", "Configuration")
|
||||||
setData(ctx, "htmlTitle", "Admin Settings - Admin panel")
|
setData(ctx, "htmlTitle", "Configuration - Admin panel")
|
||||||
setData(ctx, "adminHeaderPage", "settings")
|
setData(ctx, "adminHeaderPage", "config")
|
||||||
|
setData(ctx, "c", config.C)
|
||||||
|
|
||||||
return html(ctx, "admin_settings.html")
|
return html(ctx, "admin_config.html")
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminSetSetting(ctx echo.Context) error {
|
func adminSetConfig(ctx echo.Context) error {
|
||||||
key := ctx.FormValue("key")
|
key := ctx.FormValue("key")
|
||||||
value := ctx.FormValue("value")
|
value := ctx.FormValue("value")
|
||||||
|
|
||||||
|
|
|
@ -193,8 +193,8 @@ func Start() {
|
||||||
g2.POST("/gists/:gist/delete", adminGistDelete)
|
g2.POST("/gists/:gist/delete", adminGistDelete)
|
||||||
g2.POST("/sync-fs", adminSyncReposFromFS)
|
g2.POST("/sync-fs", adminSyncReposFromFS)
|
||||||
g2.POST("/sync-db", adminSyncReposFromDB)
|
g2.POST("/sync-db", adminSyncReposFromDB)
|
||||||
g2.GET("/settings", adminSettings)
|
g2.GET("/configuration", adminConfig)
|
||||||
g2.PUT("/set-setting", adminSetSetting)
|
g2.PUT("/set-config", adminSetConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
g1.GET("/all", allGists, checkRequireLogin)
|
g1.GET("/all", allGists, checkRequireLogin)
|
||||||
|
|
|
@ -12,7 +12,7 @@ const setSetting = (key: string, value: string) => {
|
||||||
data.append('key', key);
|
data.append('key', key);
|
||||||
data.append('value', value);
|
data.append('value', value);
|
||||||
data.append('_csrf', ((document.getElementsByName('_csrf')[0] as HTMLInputElement).value));
|
data.append('_csrf', ((document.getElementsByName('_csrf')[0] as HTMLInputElement).value));
|
||||||
return fetch('/admin-panel/set-setting', {
|
return fetch('/admin-panel/set-config', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
body: data,
|
body: data,
|
||||||
|
|
12
public/style.css
vendored
12
public/style.css
vendored
|
@ -140,3 +140,15 @@ table.csv-table thead tr th {
|
||||||
table.csv-table tbody td {
|
table.csv-table tbody td {
|
||||||
@apply border py-1.5 px-1 border-slate-200 dark:border-slate-800;
|
@apply border py-1.5 px-1 border-slate-200 dark:border-slate-800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl.dl-config {
|
||||||
|
@apply grid grid-cols-3 text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.dl-config dt {
|
||||||
|
@apply col-span-1 text-gray-700 dark:text-slate-300 font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.dl-config dd {
|
||||||
|
@apply ml-1 col-span-2 break-words;
|
||||||
|
}
|
||||||
|
|
4
templates/base/admin_header.html
vendored
4
templates/base/admin_header.html
vendored
|
@ -15,8 +15,8 @@
|
||||||
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Users</a>
|
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Users</a>
|
||||||
<a href="/admin-panel/gists" class="{{ if eq .adminHeaderPage "gists" }}bg-gray-100 dark:bg-gray-700 text-slate-700 dark:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
|
<a href="/admin-panel/gists" class="{{ if eq .adminHeaderPage "gists" }}bg-gray-100 dark:bg-gray-700 text-slate-700 dark:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
|
||||||
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Gists</a>
|
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Gists</a>
|
||||||
<a href="/admin-panel/settings" class="{{ if eq .adminHeaderPage "settings" }}bg-gray-100 dark:bg-gray-700 text-slate-700 dark:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
|
<a href="/admin-panel/configuration" class="{{ if eq .adminHeaderPage "config" }}bg-gray-100 dark:bg-gray-700 text-slate-700 dark:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
|
||||||
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Admin settings</a>
|
{{ else }} text-gray-600 dark:text-gray-400 hover:text-gray-400 dark:hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Configuration</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
116
templates/pages/admin_config.html
vendored
Normal file
116
templates/pages/admin_config.html
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
{{ template "header" .}}
|
||||||
|
{{ template "admin_header" .}}
|
||||||
|
|
||||||
|
<div class="grid gap-4 grid-cols-1 md:grid-cols-2">
|
||||||
|
<div class="p-6 bg-gray-50 dark:bg-gray-800 rounded-md border border-gray-200 dark:border-gray-700">
|
||||||
|
<p class="italic text-xs text-gray-400 dark:text-gray-400 mb-4">This configuration can be <a target="_blank" href="https://github.com/thomiceli/opengist#configuration">overridden</a> by a YAML config file and/or environment variables.</p>
|
||||||
|
<dl class="dl-config">
|
||||||
|
<div class="relative col-span-3">
|
||||||
|
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
||||||
|
<div class="w-full border-t border-gray-300"></div>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex justify-center">
|
||||||
|
<span class="bg-gray-50 dark:bg-gray-800 px-2 text-sm text-slate-700 dark:text-slate-300 font-bold">General</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<dt>Log level</dt><dd>{{ .c.LogLevel }}</dd>
|
||||||
|
<dt>External URL</dt><dd>{{ .c.ExternalUrl }}</dd>
|
||||||
|
<dt>Opengist home</dt><dd>{{ .c.OpengistHome }}</dd>
|
||||||
|
<dt>DB filename</dt><dd>{{ .c.DBFilename }}</dd>
|
||||||
|
<div class="relative col-span-3 mt-4">
|
||||||
|
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
||||||
|
<div class="w-full border-t border-gray-300"></div>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex justify-center">
|
||||||
|
<span class="bg-gray-50 dark:bg-gray-800 px-2 text-sm text-slate-700 dark:text-slate-300 font-bold">HTTP</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<dt>HTTP host</dt><dd>{{ .c.HttpHost }}</dd>
|
||||||
|
<dt>HTTP port</dt><dd>{{ .c.HttpPort }}</dd>
|
||||||
|
<dt>HTTP Git enabled</dt><dd>{{ .c.HttpGit }}</dd>
|
||||||
|
<dt>HTTP TLS enabled</dt><dd>{{ .c.HttpTLSEnabled }}</dd>
|
||||||
|
<dt>HTTP Cert file</dt><dd>{{ .c.HttpCertFile }}</dd>
|
||||||
|
<dt>HTTP Key file</dt><dd>{{ .c.HttpKeyFile }}</dd>
|
||||||
|
<div class="relative col-span-3 mt-4">
|
||||||
|
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
||||||
|
<div class="w-full border-t border-gray-300"></div>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex justify-center">
|
||||||
|
<span class="bg-gray-50 dark:bg-gray-800 px-2 text-sm text-slate-700 dark:text-slate-300 font-bold">SSH</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<dt>SSH Git enabled</dt><dd>{{ .c.SshGit }}</dd>
|
||||||
|
<dt>SSH host</dt><dd>{{ .c.SshHost }}</dd>
|
||||||
|
<dt>SSH port</dt><dd>{{ .c.SshPort }}</dd>
|
||||||
|
<dt>SSH external domain</dt><dd>{{ .c.SshExternalDomain }}</dd>
|
||||||
|
<dt>SSH Keygen</dt><dd>{{ .c.SshKeygen }}</dd>
|
||||||
|
<div class="relative col-span-3 mt-4">
|
||||||
|
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
||||||
|
<div class="w-full border-t border-gray-300"></div>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex justify-center">
|
||||||
|
<span class="bg-gray-50 dark:bg-gray-800 px-2 text-sm text-slate-700 dark:text-slate-300 font-bold">OAuth</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<dt>Github Client key</dt><dd>{{ .c.GithubClientKey }}</dd>
|
||||||
|
<dt>Github Secret</dt><dd>{{ .c.GithubSecret }}</dd>
|
||||||
|
<dt>Gitea client Key</dt><dd>{{ .c.GiteaClientKey }}</dd>
|
||||||
|
<dt>Gitea Secret</dt><dd>{{ .c.GiteaSecret }}</dd>
|
||||||
|
<dt>Gitea URL</dt><dd>{{ .c.GiteaUrl }}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ul role="list" class="divide-y divide-slate-300 dark:divide-gray-200 px-4 py-2 sm:px-6 bg-gray-50 dark:bg-gray-800 rounded-md border border-gray-200 dark:border-gray-700">
|
||||||
|
<li class="list-none gap-x-4 py-5">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="flex flex-grow flex-col">
|
||||||
|
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable signup</span>
|
||||||
|
<span class="text-sm text-gray-400 dark:text-gray-400">Forbid the creation of new accounts.</span>
|
||||||
|
</span>
|
||||||
|
<button type="button" id="disable-signup" data-bool="{{ .DisableSignup }}" class="toggle-button {{ if .DisableSignup }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
||||||
|
<span aria-hidden="true" class="{{ if .DisableSignup }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="list-none gap-x-4 py-5">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="flex flex-grow flex-col">
|
||||||
|
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Require login</span>
|
||||||
|
<span class="text-sm text-gray-400 dark:text-gray-400">Enforce users to be logged in to see gists.</span>
|
||||||
|
</span>
|
||||||
|
<button type="button" id="require-login" data-bool="{{ .RequireLogin }}" class="toggle-button {{ if .RequireLogin }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
||||||
|
<span aria-hidden="true" class="{{ if .RequireLogin }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="list-none gap-x-4 py-5">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="flex flex-grow flex-col">
|
||||||
|
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable login form</span>
|
||||||
|
<span class="text-sm text-gray-400 dark:text-gray-400">Forbid logging in via the login form to force using OAuth providers instead.</span>
|
||||||
|
</span>
|
||||||
|
<button type="button" id="disable-login-form" data-bool="{{ .DisableLoginForm }}" class="toggle-button {{ if .DisableLoginForm }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
||||||
|
<span aria-hidden="true" class="{{ if .DisableLoginForm }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="list-none gap-x-4 py-5">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="flex flex-grow flex-col">
|
||||||
|
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable Gravatar</span>
|
||||||
|
<span class="text-sm text-gray-400 dark:text-gray-400">Disable the usage of Gravatar as an avatar provider.</span>
|
||||||
|
</span>
|
||||||
|
<button type="button" id="disable-gravatar" data-bool="{{ .DisableGravatar }}" class="toggle-button {{ if .DisableGravatar }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
||||||
|
<span aria-hidden="true" class="{{ if .DisableGravatar }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{{ .csrfHtml }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module" src="{{ asset "admin.ts" }}"></script>
|
||||||
|
|
||||||
|
{{ template "admin_footer" .}}
|
||||||
|
{{ template "footer" .}}
|
58
templates/pages/admin_settings.html
vendored
58
templates/pages/admin_settings.html
vendored
|
@ -1,58 +0,0 @@
|
||||||
{{ template "header" .}}
|
|
||||||
{{ template "admin_header" .}}
|
|
||||||
|
|
||||||
<div class="mx-auto max-w-lg px-4 py-2 sm:px-6 bg-gray-50 dark:bg-gray-800 rounded-md border border-gray-200 dark:border-gray-700">
|
|
||||||
|
|
||||||
<ul role="list" class="divide-y divide-slate-300 dark:divide-gray-200">
|
|
||||||
<li class="list-none gap-x-4 py-5">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="flex flex-grow flex-col">
|
|
||||||
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable signup</span>
|
|
||||||
<span class="text-sm text-gray-400 dark:text-gray-400">Forbid the creation of new accounts.</span>
|
|
||||||
</span>
|
|
||||||
<button type="button" id="disable-signup" data-bool="{{ .DisableSignup }}" class="toggle-button {{ if .DisableSignup }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
|
||||||
<span aria-hidden="true" class="{{ if .DisableSignup }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="list-none gap-x-4 py-5">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="flex flex-grow flex-col">
|
|
||||||
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Require login</span>
|
|
||||||
<span class="text-sm text-gray-400 dark:text-gray-400">Enforce users to be logged in to see gists.</span>
|
|
||||||
</span>
|
|
||||||
<button type="button" id="require-login" data-bool="{{ .RequireLogin }}" class="toggle-button {{ if .RequireLogin }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
|
||||||
<span aria-hidden="true" class="{{ if .RequireLogin }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="list-none gap-x-4 py-5">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="flex flex-grow flex-col">
|
|
||||||
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable login form</span>
|
|
||||||
<span class="text-sm text-gray-400 dark:text-gray-400">Forbid logging in via the login form to force using OAuth providers instead.</span>
|
|
||||||
</span>
|
|
||||||
<button type="button" id="disable-login-form" data-bool="{{ .DisableLoginForm }}" class="toggle-button {{ if .DisableLoginForm }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
|
||||||
<span aria-hidden="true" class="{{ if .DisableLoginForm }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="list-none gap-x-4 py-5">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="flex flex-grow flex-col">
|
|
||||||
<span class="text-sm font-medium leading-6 text-slate-700 dark:text-slate-300">Disable Gravatar</span>
|
|
||||||
<span class="text-sm text-gray-400 dark:text-gray-400">Disable the usage of Gravatar as an avatar provider.</span>
|
|
||||||
</span>
|
|
||||||
<button type="button" id="disable-gravatar" data-bool="{{ .DisableGravatar }}" class="toggle-button {{ if .DisableGravatar }}bg-primary-600{{else}}bg-gray-300 dark:bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
|
|
||||||
<span aria-hidden="true" class="{{ if .DisableGravatar }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{{ .csrfHtml }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="module" src="{{ asset "admin.ts" }}"></script>
|
|
||||||
|
|
||||||
{{ template "admin_footer" .}}
|
|
||||||
{{ template "footer" .}}
|
|
Loading…
Reference in a new issue