From 43f9a55f48d2adbe38d6e921a43af282b69b58d9 Mon Sep 17 00:00:00 2001 From: Joshua Kirkcaldy Date: Fri, 22 Nov 2024 09:58:43 +0000 Subject: [PATCH] new pages --- content/_index.md | 17 +-- content/docs/Installation/_index.md | 12 ++ content/docs/Installation/database.md | 145 +++++++++++++++++++ content/docs/Installation/install_glympse.md | 97 +++++++++++++ content/docs/Installation/services.md | 26 ++++ content/docs/Setup/_index.md | 7 + content/docs/Setup/admin_settings.md | 4 + content/docs/_index.md | 21 +-- content/docs/first-page.md | 9 -- content/docs/folder/_index.md | 10 -- content/docs/folder/leaf.md | 7 - content/user_docs/_index.md | 18 +++ hugo.yaml | 29 ++-- i18n/en.yaml | 2 + static/images/logo.png | Bin 0 -> 16025 bytes 15 files changed, 339 insertions(+), 65 deletions(-) create mode 100644 content/docs/Installation/_index.md create mode 100644 content/docs/Installation/database.md create mode 100644 content/docs/Installation/install_glympse.md create mode 100644 content/docs/Installation/services.md create mode 100644 content/docs/Setup/_index.md create mode 100644 content/docs/Setup/admin_settings.md delete mode 100644 content/docs/first-page.md delete mode 100644 content/docs/folder/_index.md delete mode 100644 content/docs/folder/leaf.md create mode 100644 content/user_docs/_index.md create mode 100644 i18n/en.yaml create mode 100644 static/images/logo.png diff --git a/content/_index.md b/content/_index.md index 72f68d8..50b692c 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,17 +1,14 @@ --- -title: My Site +title: Glympse toc: false --- -This is the landing page. - -## Explore - -{{< cards >}} - {{< card link="docs" title="Docs" icon="book-open" >}} - {{< card link="about" title="About" icon="user" >}} -{{< /cards >}} +Glympse is a your solution to a hybrid production. Access your rushes from across the globe and view in a web browser. Allow your teams to work where they want when they need to. ## Documentation -For more information, visit [Hextra](https://imfing.github.io/hextra). +{{< cards >}} + {{< card link="docs" title="Server Admin" icon="book-open" >}} + {{< card link="user_docs" title="User Documentation" icon="user" >}} +{{< /cards >}} + diff --git a/content/docs/Installation/_index.md b/content/docs/Installation/_index.md new file mode 100644 index 0000000..827264d --- /dev/null +++ b/content/docs/Installation/_index.md @@ -0,0 +1,12 @@ +--- +title: Installation +next: /docs/Installation/database +weight: 1 +--- +To install Glympse, you will need a database, a redis cache and a rabbitmq queue all of which must be accessible by all of the Glympse containers you deploy. For that reason it is recommended to keep this as a separate compose file. + +{{< cards >}} + {{< card link="/docs/installation/database/" title="Database Install" icon="database" >}} + {{< card link="/docs/installation/services" title="Services" icon="selector" >}} + {{< card link="/docs/installation/install_glympse" title="Glympse Install" icon="server" >}} +{{< /cards >}} \ No newline at end of file diff --git a/content/docs/Installation/database.md b/content/docs/Installation/database.md new file mode 100644 index 0000000..d3d1658 --- /dev/null +++ b/content/docs/Installation/database.md @@ -0,0 +1,145 @@ +--- +title: Database Installation +type: docs +prev: /_index +next: docs/install +--- + + + +To install you will first need the database and queue manager running. Every instance of Glympse you run will need to connect to these containers. + +First create your docker network. `docker network create glympse_net` + +Then create a a directory and compose file: +``` +mkdir /opt/glympse_database + +cd /opt/glympse_database + +nano /opt/glympse_database/compose.yml +``` + +Paste the following, be sure to change the passwords and any other personal details before saving. + +```yaml {filename="compose.yml"} +services: + redis: + image: redis:alpine + container_name: redis + restart: always + ports: + - 6379:6379 + volumes: + - /opt/glympse_database/redis_data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 30s + timeout: 10s + retries: 3 + networks: + glympse_net: null + rabbitmq: + image: rabbitmq:3.13.4-management + container_name: rabbitmq + volumes: + - type: bind + source: /opt/glympse_database/rabbitmq.conf + target: /etc/rabbitmq/conf.d/10-defaults.conf + ports: + - 15672:15672 + - 5672:5672 + networks: + glympse_net: null + mysql: + image: mysql:8.0 + container_name: mysql + environment: + MYSQL_ROOT_PASSWORD: + MYSQL_DATABASE: glympse + MYSQL_USER: glympse + MYSQL_PASSWORD: + volumes: + - /opt/glympse/mysql:/var/lib/mysql + - type: bind + source: /opt/glympse_database/my.cnf + target: /etc/my.cnf + ports: + - 6033:6033 + - 3306:3306 + networks: + glympse_net: null +networks: + default: + external: true + name: glympse_net +``` +There are two more files that you need to create and save before running the compose file. + +First is the mysql config file. + +Create a file called my.cnf in the glympse_database directory: `nano my.cnf` and paste the following: + +```conf {filename="my.cnf"} +# For advice on how to change settings please see +# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html + +[mysqld] +# +# Remove leading # and set to the amount of RAM for the most important data +# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. +# innodb_buffer_pool_size = 128M +# +# Remove leading # to turn on a very important data integrity option: logging +# changes to the binary log between backups. +# log_bin +# +# Remove leading # to set options mainly useful for reporting servers. +# The server defaults are faster for transactions and fast SELECTs. +# Adjust sizes as needed, experiment to find the optimal values. +# join_buffer_size = 128M +# sort_buffer_size = 2M +# read_rnd_buffer_size = 2M + +# Remove leading # to revert to previous value for default_authentication_plugin, +# this will increase compatibility with older clients. For background, see: +# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin +# default-authentication-plugin=mysql_native_password +skip-host-cache +skip-name-resolve +datadir=/var/lib/mysql +socket=/var/run/mysqld/mysqld.sock +secure-file-priv=/var/lib/mysql-files +user=mysql +connect_timeout = 600 +net_read_timeout = 30 +wait_timeout = 28800 +interactive_timeout = 28800 + +pid-file=/var/run/mysqld/mysqld.pid +[client] +socket=/var/run/mysqld/mysqld.sock + +!includedir /etc/mysql/conf.d/ + +``` + +Finally create a config file for rabbitmq: `nano rabbitmq.conf` and paste the following: + +be sure to change the password for something secure and keep note of it as you will need it for your compose env files. + +```conf {filename="rabbitmq.conf"} +default_vhost = glympse +default_user = glympse +default_pass = +default_permissions.configure = .* +default_permissions.read = .* +default_permissions.write = .* +default_user_tags.administrator = true +default_user_tags.management = true +default_user_tags.glympse = true +consumer_timeout = 31622400000 +``` \ No newline at end of file diff --git a/content/docs/Installation/install_glympse.md b/content/docs/Installation/install_glympse.md new file mode 100644 index 0000000..345c1f6 --- /dev/null +++ b/content/docs/Installation/install_glympse.md @@ -0,0 +1,97 @@ +--- +title: Install Glympse +type: docs +prev: docs/services +next: docs/ +--- +To install glympse we first need to create a docker compose file and then an env file. These two files will allow you to configure most out of the box settings. Once you're set these up, you will be able to change more setting from the webui. + +Services default to enabled, to disable a service, change yes to no in the environment section of the compose file. To enable a service, either change the environment variable to yes or delete/comment the line. + +UWSGI and NGINX are required for the webui service + +The following compose file will enable all services in a single container. This will work but it is possible that the transcoding and transcribing tasks can slow down the webui if you're running on a slower machine. + +```yaml {filename="compose.yml"} +services: + Glympse: + image: git.themainframe.co.uk/josh/glympse + container_name: Glympse + restart: unless-stopped + ports: + - 80:80 + environment: + TZ: Europe/London + ENABLE_UWSGI: yes + ENABLE_NGINX: yes + ENABLE_CELERY_BEAT: yes + ENABLE_PROCESSING: yes + ENABLE_MIGRATIONS: yes + ENABLE_TRANSCRIBER: yes + ENABLE_TRANSCODER: yes + volumes: + - /opt/glympse/logs:/Glympse/logs + - /opt/glympse/.env:/Glympse/config/.env + - :/media + - :/rushes:ro + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: + - 00000000:01:00.0 + capabilities: + - gpu + memcached: + image: memcached:latest + container_name: memcached + entrypoint: memcached -m 256 + restart: unless-stopped +networks: + default: + external: true + name: glympse_net +``` + + +The following env file is required. You will need to change some of the options to what you specified in the database section of the install. + +Every line must be in the env file for every container you run regardless of what services are enabled. + +```env {filename=".env"} +DJANGO_SETTINGS_MODULE="Glympse.settings.production" +SECRET_KEY="" +SECRET_ADMIN_URL= +CSRF_TRUSTED_ORIGINS=https://"" +ALLOWED_HOSTS="" +ADMINS='' +DOMAIN='' +MAX_FIELDS=5000 +SQL_ENGINE="django.db.backends.mysql" +SQL_DATABASE="glympse" +SQL_USER="glympse" +SQL_PASSWORD="" +SQL_HOST="mysql" +SQL_PORT="3306" +EMAIL_HOST="" +EMAIL_PORT="" +EMAIL_USE_TLS="" +EMAIL_HOST_USER="" +EMAIL_HOST_PASSWORD="" +DEFAULT_FROM_EMAIL="Glympse" +ALLOWED_EMAIL_DOMAINS="" +REDIS_HOST="redis://redis:6379" +RABBITMQ_URL="amqp://glympse:@rabbitmq:5672/glympse" +ADMIN_USERNAME="" +ADMIN_EMAIL="" +ADMIN_PASSWORD="" +LOG_LEVEL="INFO" +TIMEZONE="Europe/London" +MICROSOFT_AUTH_CLIENT_ID='' +MICROSOFT_AUTH_CLIENT_SECRET='' +MICROSOFT_AUTH_TENANT_ID='' +MEMCACHED='memcached:11211' +CUDA_DEVICE='cuda:0' +DEBUG=False +``` \ No newline at end of file diff --git a/content/docs/Installation/services.md b/content/docs/Installation/services.md new file mode 100644 index 0000000..2d1f985 --- /dev/null +++ b/content/docs/Installation/services.md @@ -0,0 +1,26 @@ +--- +title: Glympse Services +type: docs +prev: / +next: docs/install_glympse +--- + +Glympse is split into multiple services so you can split the workload between multiple machines. + +The available services are as follows: +* WebUI\ + This is the webui front end. The reverse proxy needs to point to the machine that is running this service. It is possible to run more than one frontend for load balancing purposes. + +* Processing\ + This service is responsible for scanning the rushes drives and inserting the rushes into the Glympse database. It is also responsible for other background tasks such as sending emails etc. This worker will run 16 simultaneous tasks. + +* Transcoding - **Prefers Nvidia GPU**\ +This is the transcoding engine. It takes the raw rushes and transcodes them to lower resolution proxy files that can be streamed. The transcoder will try use cuda hardware acceleration but will fall back to software if it is unavailable. This worker will run 4 simultaneous tasks. + +* Long Transcoding\ +This was set up to create the thumbnail preview for the video player when you hover over the video play bar to allow for scrubbing. This worker will run 16 simultaneous tasks. + +* Transcribing - **Requires Nvidia GPU**\ + This is responsible for transcribing clips. A modern Nvidia GPU is required for this to work. It is possible to select a different model that may better suit the available hardware. A GPU with more VRAM can support a larger model. This worker will run a single task at a time. + +It is possible to run one or more services in a single docker container. the running services are managed through the environment settings in the compose file. \ No newline at end of file diff --git a/content/docs/Setup/_index.md b/content/docs/Setup/_index.md new file mode 100644 index 0000000..02229b5 --- /dev/null +++ b/content/docs/Setup/_index.md @@ -0,0 +1,7 @@ +--- +title: System Setup +next: /docs/setup/admin_settings +weight: 2 +--- + +There are two main ways to change settings for Glympse. The first is the env file, the second is to change some settings from within the application. This can be done whilst the server is up and running from a central point, whereas changes to the env file will need to be replicated on each docker container. \ No newline at end of file diff --git a/content/docs/Setup/admin_settings.md b/content/docs/Setup/admin_settings.md new file mode 100644 index 0000000..03268a7 --- /dev/null +++ b/content/docs/Setup/admin_settings.md @@ -0,0 +1,4 @@ +--- +title: Admin Settings +#next: /docs/Installation/database +--- \ No newline at end of file diff --git a/content/docs/_index.md b/content/docs/_index.md index 73dfb20..0006510 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -1,18 +1,13 @@ --- -title: Documentation -next: first-page +title: Server Admin +next: /docs/Installation/database --- -This is a demo of the theme's documentation layout. +This is the documentation for the admin of a Glympse server. -## Hello, World! +Glympse is supplied as a docker container exclusively. -```go {filename="main.go"} -package main - -import "fmt" - -func main() { - fmt.Println("Hello, World!") -} -``` +#### Prerequisites: +* docker +* docker compose +* Nvidia GPU for transcribing (preferred for transcoding tasks) diff --git a/content/docs/first-page.md b/content/docs/first-page.md deleted file mode 100644 index 4af40a1..0000000 --- a/content/docs/first-page.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Demo Page -type: docs -prev: / -next: docs/folder/ ---- - -A simple demo page. - diff --git a/content/docs/folder/_index.md b/content/docs/folder/_index.md deleted file mode 100644 index 5050ade..0000000 --- a/content/docs/folder/_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Folder -type: docs -prev: docs/first-page -next: docs/folder/leaf -sidebar: - open: true ---- - -Pages can be organized into folders. diff --git a/content/docs/folder/leaf.md b/content/docs/folder/leaf.md deleted file mode 100644 index 7c9ee2a..0000000 --- a/content/docs/folder/leaf.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Leaf Page -type: docs -prev: docs/folder/ ---- - -This page is under a folder. diff --git a/content/user_docs/_index.md b/content/user_docs/_index.md new file mode 100644 index 0000000..98898c6 --- /dev/null +++ b/content/user_docs/_index.md @@ -0,0 +1,18 @@ +--- +title: User Documentation +next: first-page +--- + +This is a demo of the theme's documentation layout. + +## Hello, World! + +```go {filename="main.go"} +package main + +import "fmt" + +func main() { + fmt.Println("Hello, World!") +} +``` \ No newline at end of file diff --git a/hugo.yaml b/hugo.yaml index 30f9991..a78ab8c 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -1,5 +1,5 @@ # Hugo configuration file -title: My Site +title: Glympse # import hextra as module module: @@ -19,13 +19,10 @@ markup: menu: main: - name: Docs - pageRef: /docs + pageRef: / weight: 1 - - name: About - pageRef: /about - weight: 2 - name: Contact ↗ - url: "https://github.com/imfing" + url: "https://git.themainframe.co.uk/josh" weight: 3 - name: Search weight: 4 @@ -33,24 +30,24 @@ menu: type: search - name: GitHub weight: 5 - url: "https://github.com/imfing/hextra-starter-template" + url: "https://git.themainframe.co.uk/josh/glympse_docs" params: icon: github - - name: Twitter - weight: 6 - url: "https://twitter.com/" - params: - icon: x-twitter params: navbar: displayTitle: true - displayLogo: false + displayLogo: true + logo: + path: images/logo.png + link: / + width: 40 + height: 40 footer: - displayCopyright: false - displayPoweredBy: true + displayCopyright: true + displayPoweredBy: false editURL: enable: true - base: "https://github.com/imfing/hextra-starter-template/edit/main/content" + base: "https://git.themainframe.co.uk/josh/Glympse_Docs/src/branch/main/content" diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 0000000..41e5b5e --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,2 @@ +copyright: "© 2024 Joshua Kirkcaldy" +editThisPage: "Edit this page on TheMainframe →" diff --git a/static/images/logo.png b/static/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cde00ae5a0ab408b1e9736486b0b8848578330b3 GIT binary patch literal 16025 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 literal 0 HcmV?d00001