idk
This commit is contained in:
1 parent
1c70d34cf3
commit
6c10631a6a
14 files changed
+704
No files matched your search
@@ -34,6 +34,9 @@ plan
|
||||
.terraform.lock.hcl
|
||||
generated.yml
|
||||
|
||||
# Secrets generated/persisted by ansible lookups (e.g. omnivore.yml)
|
||||
ansible/plays/machine_setup/credentials/
|
||||
|
||||
# terraform.tfvars should contain no secrets
|
||||
!terraform.tfvars
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
- name: Set up domain-watchdog
|
||||
hosts: domain-watchdog
|
||||
become: yes
|
||||
tasks:
|
||||
- name: default_packages
|
||||
ansible.builtin.include_tasks: ../../templates/default_packages.yml
|
||||
|
||||
- name: create_user
|
||||
ansible.builtin.include_tasks: ../../templates/create_user.yml
|
||||
vars:
|
||||
username: nick
|
||||
github_user: Chewbaccalakis
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.include_tasks: ../../templates/install_docker.yml
|
||||
|
||||
- name: Add nick to docker group
|
||||
ansible.builtin.user:
|
||||
name: nick
|
||||
groups:
|
||||
- docker
|
||||
append: true
|
||||
|
||||
- name: Deploy Domain Watchdog
|
||||
vars:
|
||||
domain_watchdog_dir: /opt/domain-watchdog
|
||||
block:
|
||||
- name: Clone domain-watchdog repo
|
||||
ansible.builtin.git:
|
||||
repo: https://github.com/maelgangloff/domain-watchdog.git
|
||||
dest: "{{ domain_watchdog_dir }}"
|
||||
version: master
|
||||
update: yes
|
||||
|
||||
- name: Create public/content directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ domain_watchdog_dir }}/public/content"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
# Pulled from Infisical, not generated/persisted to disk. Run this
|
||||
# playbook as `infisical run -- ansible-playbook -i inventory ...`
|
||||
# with DOMAIN_WATCHDOG_POSTGRES_PASSWORD, DOMAIN_WATCHDOG_APP_SECRET,
|
||||
# and DOMAIN_WATCHDOG_JWT_PASSPHRASE secrets set in the workspace.
|
||||
- name: Read secrets from environment (populated by `infisical run`)
|
||||
ansible.builtin.set_fact:
|
||||
domain_watchdog_postgres_password: "{{ lookup('ansible.builtin.env', 'DOMAIN_WATCHDOG_POSTGRES_PASSWORD') }}"
|
||||
domain_watchdog_app_secret: "{{ lookup('ansible.builtin.env', 'DOMAIN_WATCHDOG_APP_SECRET') }}"
|
||||
domain_watchdog_jwt_passphrase: "{{ lookup('ansible.builtin.env', 'DOMAIN_WATCHDOG_JWT_PASSPHRASE') }}"
|
||||
no_log: true
|
||||
|
||||
- name: Verify required secrets were provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- domain_watchdog_postgres_password | length > 0
|
||||
- domain_watchdog_app_secret | length > 0
|
||||
- domain_watchdog_jwt_passphrase | length > 0
|
||||
fail_msg: >-
|
||||
DOMAIN_WATCHDOG_POSTGRES_PASSWORD, DOMAIN_WATCHDOG_APP_SECRET, and
|
||||
DOMAIN_WATCHDOG_JWT_PASSPHRASE must be set. Run this playbook via
|
||||
`infisical run -- ansible-playbook -i inventory ...` with those
|
||||
secrets defined in the workspace.
|
||||
|
||||
- name: Deploy .env file (docker compose variable substitution)
|
||||
ansible.builtin.template:
|
||||
src: templates/domain-watchdog.env.j2
|
||||
dest: "{{ domain_watchdog_dir }}/.env"
|
||||
mode: "0600"
|
||||
|
||||
- name: Deploy .env.local file (app secrets)
|
||||
ansible.builtin.template:
|
||||
src: templates/domain-watchdog.env.local.j2
|
||||
dest: "{{ domain_watchdog_dir }}/.env.local"
|
||||
mode: "0600"
|
||||
|
||||
- name: Pull prebuilt Domain Watchdog images
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
chdir: "{{ domain_watchdog_dir }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Start Domain Watchdog via docker compose
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ domain_watchdog_dir }}"
|
||||
register: domain_watchdog_compose_up
|
||||
changed_when: "'Started' in domain_watchdog_compose_up.stderr or 'Created' in domain_watchdog_compose_up.stderr"
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
- name: Set up Grist
|
||||
hosts: grist
|
||||
become: yes
|
||||
tasks:
|
||||
- name: default_packages
|
||||
ansible.builtin.include_tasks: ../../templates/default_packages.yml
|
||||
|
||||
- name: create_user
|
||||
ansible.builtin.include_tasks: ../../templates/create_user.yml
|
||||
vars:
|
||||
username: nick
|
||||
github_user: Chewbaccalakis
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.include_tasks: ../../templates/install_docker.yml
|
||||
|
||||
- name: Add nick to docker group
|
||||
ansible.builtin.user:
|
||||
name: nick
|
||||
groups:
|
||||
- docker
|
||||
append: true
|
||||
|
||||
- name: Deploy Grist
|
||||
vars:
|
||||
grist_dir: /opt/grist
|
||||
grist_hostname: grist.atlashorizon.net
|
||||
grist_oidc_issuer_host: auth.atlashorizon.net
|
||||
block:
|
||||
- name: Create persist directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ grist_dir }}/persist"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Deploy docker-compose.yml
|
||||
ansible.builtin.copy:
|
||||
src: templates/grist-docker-compose.yml
|
||||
dest: "{{ grist_dir }}/docker-compose.yml"
|
||||
mode: "0644"
|
||||
|
||||
# Pulled from Infisical, not generated/persisted to disk. Run this
|
||||
# playbook as `infisical run -- ansible-playbook -i inventory ...`
|
||||
# with GRIST_SESSION_SECRET, GRIST_OIDC_IDP_CLIENT_ID, and
|
||||
# GRIST_OIDC_IDP_CLIENT_SECRET secrets set in the workspace.
|
||||
#
|
||||
# The OIDC client must be registered in Authelia with redirect URI
|
||||
# https://grist.atlashorizon.net/oauth2/callback.
|
||||
- name: Read secrets from environment (populated by `infisical run`)
|
||||
ansible.builtin.set_fact:
|
||||
grist_session_secret: "{{ lookup('ansible.builtin.env', 'GRIST_SESSION_SECRET') }}"
|
||||
grist_oidc_client_id: "{{ lookup('ansible.builtin.env', 'GRIST_OIDC_IDP_CLIENT_ID') }}"
|
||||
grist_oidc_client_secret: "{{ lookup('ansible.builtin.env', 'GRIST_OIDC_IDP_CLIENT_SECRET') }}"
|
||||
no_log: true
|
||||
|
||||
- name: Verify required secrets were provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- grist_session_secret | length >= 32
|
||||
- grist_oidc_client_id | length > 0
|
||||
- grist_oidc_client_secret | length > 0
|
||||
fail_msg: >-
|
||||
GRIST_SESSION_SECRET (>=32 chars), GRIST_OIDC_IDP_CLIENT_ID, and
|
||||
GRIST_OIDC_IDP_CLIENT_SECRET must be set. Run this playbook via
|
||||
`infisical run -- ansible-playbook -i inventory ...` with those
|
||||
secrets defined in the workspace.
|
||||
|
||||
- name: Deploy .env file (docker compose variable substitution)
|
||||
ansible.builtin.template:
|
||||
src: templates/grist.env.j2
|
||||
dest: "{{ grist_dir }}/.env"
|
||||
mode: "0600"
|
||||
|
||||
- name: Pull prebuilt Grist image
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
chdir: "{{ grist_dir }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Start Grist via docker compose
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ grist_dir }}"
|
||||
register: grist_compose_up
|
||||
changed_when: "'Started' in grist_compose_up.stderr or 'Created' in grist_compose_up.stderr"
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
- name: Set up nametag
|
||||
hosts: nametag
|
||||
become: yes
|
||||
tasks:
|
||||
- name: default_packages
|
||||
ansible.builtin.include_tasks: ../../templates/default_packages.yml
|
||||
|
||||
- name: create_user
|
||||
ansible.builtin.include_tasks: ../../templates/create_user.yml
|
||||
vars:
|
||||
username: nick
|
||||
github_user: Chewbaccalakis
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.include_tasks: ../../templates/install_docker.yml
|
||||
|
||||
- name: Add nick to docker group
|
||||
ansible.builtin.user:
|
||||
name: nick
|
||||
groups:
|
||||
- docker
|
||||
append: true
|
||||
|
||||
- name: Deploy Nametag
|
||||
vars:
|
||||
nametag_dir: /opt/nametag
|
||||
block:
|
||||
- name: Clone nametag repo
|
||||
ansible.builtin.git:
|
||||
repo: https://github.com/mattogodoy/nametag.git
|
||||
dest: "{{ nametag_dir }}"
|
||||
version: master
|
||||
update: yes
|
||||
|
||||
- name: Create backups directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ nametag_dir }}/backups"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
# Pulled from Infisical, not generated/persisted to disk. Run this
|
||||
# playbook as `infisical run -- ansible-playbook -i inventory ...`
|
||||
# with NAMETAG_DB_PASSWORD, NAMETAG_NEXTAUTH_SECRET,
|
||||
# NAMETAG_CRON_SECRET, and NAMETAG_REDIS_PASSWORD secrets set in
|
||||
# the workspace.
|
||||
- name: Read secrets from environment (populated by `infisical run`)
|
||||
ansible.builtin.set_fact:
|
||||
nametag_db_password: "{{ lookup('ansible.builtin.env', 'NAMETAG_DB_PASSWORD') }}"
|
||||
nametag_nextauth_secret: "{{ lookup('ansible.builtin.env', 'NAMETAG_NEXTAUTH_SECRET') }}"
|
||||
nametag_cron_secret: "{{ lookup('ansible.builtin.env', 'NAMETAG_CRON_SECRET') }}"
|
||||
nametag_redis_password: "{{ lookup('ansible.builtin.env', 'NAMETAG_REDIS_PASSWORD') }}"
|
||||
no_log: true
|
||||
|
||||
- name: Verify required secrets were provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- nametag_db_password | length > 0
|
||||
- nametag_nextauth_secret | length >= 32
|
||||
- nametag_cron_secret | length >= 16
|
||||
- nametag_redis_password | length > 0
|
||||
fail_msg: >-
|
||||
NAMETAG_DB_PASSWORD, NAMETAG_NEXTAUTH_SECRET (>=32 chars),
|
||||
NAMETAG_CRON_SECRET (>=16 chars), and NAMETAG_REDIS_PASSWORD
|
||||
must be set. Run this playbook via `infisical run --
|
||||
ansible-playbook -i inventory ...` with those secrets defined
|
||||
in the workspace.
|
||||
|
||||
- name: Deploy .env file
|
||||
ansible.builtin.template:
|
||||
src: templates/nametag.env.j2
|
||||
dest: "{{ nametag_dir }}/.env"
|
||||
mode: "0600"
|
||||
|
||||
# docker-compose.yml declares nametag-network and proxy as external
|
||||
# networks, so docker compose up fails unless they already exist.
|
||||
- name: Create external Docker networks required by docker-compose.yml
|
||||
ansible.builtin.command:
|
||||
cmd: "docker network create {{ item }}"
|
||||
loop:
|
||||
- nametag-network
|
||||
- proxy
|
||||
register: nametag_network_create
|
||||
changed_when: "'Error' not in nametag_network_create.stderr"
|
||||
failed_when: nametag_network_create.rc != 0 and 'already exists' not in nametag_network_create.stderr
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
|
||||
- name: Pull prebuilt Nametag images
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
chdir: "{{ nametag_dir }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Start Nametag via docker compose
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ nametag_dir }}"
|
||||
register: nametag_compose_up
|
||||
changed_when: "'Started' in nametag_compose_up.stderr or 'Created' in nametag_compose_up.stderr"
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
- name: Set up Supernote Private Cloud
|
||||
hosts: supernote
|
||||
become: yes
|
||||
tasks:
|
||||
- name: default_packages
|
||||
ansible.builtin.include_tasks: ../../templates/default_packages.yml
|
||||
|
||||
- name: create_user
|
||||
ansible.builtin.include_tasks: ../../templates/create_user.yml
|
||||
vars:
|
||||
username: nick
|
||||
github_user: Chewbaccalakis
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.include_tasks: ../../templates/install_docker.yml
|
||||
|
||||
- name: Add nick to docker group
|
||||
ansible.builtin.user:
|
||||
name: nick
|
||||
groups:
|
||||
- docker
|
||||
append: true
|
||||
|
||||
- name: Deploy Supernote Private Cloud
|
||||
vars:
|
||||
supernote_dir: /opt/supernote
|
||||
block:
|
||||
- name: Create data persistence directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ supernote_dir }}/{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop:
|
||||
- sndata/db_data
|
||||
- sndata/config/mysql/conf.d
|
||||
- sndata/redis_data
|
||||
- sndata/recycle
|
||||
- sndata/logs/cloud
|
||||
- sndata/logs/app
|
||||
- sndata/logs/web
|
||||
- sndata/convert
|
||||
- supernote_data
|
||||
|
||||
# Downloaded fresh each run so upstream schema changes apply on
|
||||
# reruns, per Supernote's own upgrade instructions. docker-compose.yml
|
||||
# is vendored instead (see templates/supernote-docker-compose.yml) -
|
||||
# the upstream file is missing the initdb mounts this playbook needs.
|
||||
- name: Download Supernote database init script
|
||||
ansible.builtin.get_url:
|
||||
url: https://supernote-private-cloud.supernote.com/cloud/supernotedb.sql
|
||||
dest: "{{ supernote_dir }}/supernotedb.sql"
|
||||
mode: "0644"
|
||||
force: yes
|
||||
|
||||
- name: Deploy docker-compose.yml
|
||||
ansible.builtin.copy:
|
||||
src: templates/supernote-docker-compose.yml
|
||||
dest: "{{ supernote_dir }}/docker-compose.yml"
|
||||
mode: "0644"
|
||||
|
||||
# Pulled from Infisical, not generated/persisted to disk. Run this
|
||||
# playbook as `infisical run -- ansible-playbook -i inventory ...`
|
||||
# with SUPERNOTE_MYSQL_ROOT_PASSWORD, SUPERNOTE_MYSQL_PASSWORD,
|
||||
# SUPERNOTE_REDIS_PASSWORD, SUPERNOTE_SMTP_SERVER, SUPERNOTE_SMTP_USER,
|
||||
# and SUPERNOTE_SMTP_PASSWORD secrets set in the workspace.
|
||||
# SUPERNOTE_SMTP_PORT (default 465) and SUPERNOTE_SMTP_ENCRYPTION
|
||||
# (default ssl) are optional.
|
||||
- name: Read secrets from environment (populated by `infisical run`)
|
||||
ansible.builtin.set_fact:
|
||||
supernote_mysql_root_password: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_MYSQL_ROOT_PASSWORD') }}"
|
||||
supernote_mysql_password: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_MYSQL_PASSWORD') }}"
|
||||
supernote_redis_password: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_REDIS_PASSWORD') }}"
|
||||
supernote_smtp_server: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_SMTP_SERVER') }}"
|
||||
supernote_smtp_port: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_SMTP_PORT') }}"
|
||||
supernote_smtp_user: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_SMTP_USER') }}"
|
||||
supernote_smtp_password: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_SMTP_PASSWORD') }}"
|
||||
supernote_smtp_encryption: "{{ lookup('ansible.builtin.env', 'SUPERNOTE_SMTP_ENCRYPTION') }}"
|
||||
no_log: true
|
||||
|
||||
- name: Verify required secrets were provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- supernote_mysql_root_password | length > 0
|
||||
- supernote_mysql_password | length > 0
|
||||
- supernote_redis_password | length > 0
|
||||
- supernote_smtp_server | length > 0
|
||||
- supernote_smtp_user | length > 0
|
||||
- supernote_smtp_password | length > 0
|
||||
fail_msg: >-
|
||||
SUPERNOTE_MYSQL_ROOT_PASSWORD, SUPERNOTE_MYSQL_PASSWORD,
|
||||
SUPERNOTE_REDIS_PASSWORD, SUPERNOTE_SMTP_SERVER,
|
||||
SUPERNOTE_SMTP_USER, and SUPERNOTE_SMTP_PASSWORD must be set.
|
||||
Run this playbook via `infisical run -- ansible-playbook -i
|
||||
inventory ...` with those secrets defined in the workspace.
|
||||
|
||||
- name: Deploy .env file (docker compose variable substitution)
|
||||
ansible.builtin.template:
|
||||
src: templates/supernote.env.j2
|
||||
dest: "{{ supernote_dir }}/.env"
|
||||
mode: "0600"
|
||||
|
||||
- name: Deploy SMTP config init script
|
||||
ansible.builtin.template:
|
||||
src: templates/supernote-email-init.sql.j2
|
||||
dest: "{{ supernote_dir }}/supernote-email-init.sql"
|
||||
mode: "0600"
|
||||
|
||||
- name: Pull prebuilt Supernote images
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
chdir: "{{ supernote_dir }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Start Supernote Private Cloud via docker compose
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ supernote_dir }}"
|
||||
register: supernote_compose_up
|
||||
changed_when: "'Started' in supernote_compose_up.stderr or 'Created' in supernote_compose_up.stderr"
|
||||
|
||||
# docker-entrypoint-initdb.d scripts only run once, against an empty
|
||||
# database, so reruns wouldn't otherwise pick up SMTP changes made in
|
||||
# Infisical. Re-applying here keeps Infisical the source of truth.
|
||||
- name: Apply SMTP configuration to the database
|
||||
ansible.builtin.shell:
|
||||
cmd: >-
|
||||
docker compose exec -T -e MYSQL_PWD="{{ supernote_mysql_root_password }}"
|
||||
mariadb mysql -u root supernotedb < {{ supernote_dir }}/supernote-email-init.sql
|
||||
chdir: "{{ supernote_dir }}"
|
||||
changed_when: false
|
||||
no_log: true
|
||||
@@ -0,0 +1,11 @@
|
||||
# Managed by Ansible (domain-watchdog.yml) - secrets sourced from Infisical
|
||||
# via `infisical run -- ansible-playbook ...`.
|
||||
#
|
||||
# Consumed by docker compose for variable substitution in docker-compose.yml.
|
||||
|
||||
POSTGRES_VERSION=16
|
||||
POSTGRES_DB=app
|
||||
POSTGRES_USER=app
|
||||
POSTGRES_PASSWORD={{ domain_watchdog_postgres_password }}
|
||||
|
||||
SERVER_NAME=:80
|
||||
@@ -0,0 +1,16 @@
|
||||
# Managed by Ansible (domain-watchdog.yml) - secrets sourced from Infisical
|
||||
# via `infisical run -- ansible-playbook ...`.
|
||||
#
|
||||
# Loaded into the app/worker containers via docker-compose.yml's env_file.
|
||||
|
||||
APP_SECRET={{ domain_watchdog_app_secret }}
|
||||
JWT_PASSPHRASE={{ domain_watchdog_jwt_passphrase }}
|
||||
|
||||
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
||||
|
||||
MAILER_DSN=null://null
|
||||
MAILER_SENDER_NAME="Domain Watchdog"
|
||||
MAILER_SENDER_EMAIL=[email protected]
|
||||
|
||||
REGISTRATION_ENABLED=true
|
||||
REGISTRATION_VERIFY_EMAIL=false
|
||||
@@ -0,0 +1,12 @@
|
||||
# Managed by Ansible (grist.yml). Vendored here since grist-core has no
|
||||
# docker-compose.yml at its repo root (see docker-compose-examples/ upstream).
|
||||
services:
|
||||
grist:
|
||||
image: gristlabs/grist:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8484:8484"
|
||||
volumes:
|
||||
- ./persist:/persist
|
||||
env_file:
|
||||
- .env
|
||||
@@ -0,0 +1,19 @@
|
||||
# Managed by Ansible (grist.yml) - secrets sourced from Infisical via
|
||||
# `infisical run -- ansible-playbook ...`.
|
||||
#
|
||||
# Consumed by docker compose for variable substitution in docker-compose.yml,
|
||||
# and loaded directly into the Grist container via env_file.
|
||||
|
||||
APP_HOME_URL=https://{{ grist_hostname }}
|
||||
GRIST_IN_SERVICE=true
|
||||
GRIST_SESSION_SECRET={{ grist_session_secret }}
|
||||
|
||||
# OIDC via Authelia - client must be registered there with redirect URI
|
||||
# https://{{ grist_hostname }}/oauth2/callback
|
||||
GRIST_OIDC_IDP_ISSUER=https://{{ grist_oidc_issuer_host }}
|
||||
GRIST_OIDC_IDP_CLIENT_ID={{ grist_oidc_client_id }}
|
||||
GRIST_OIDC_IDP_CLIENT_SECRET={{ grist_oidc_client_secret }}
|
||||
|
||||
# Authelia's OIDC discovery doc doesn't advertise end_session_endpoint, so
|
||||
# Grist must be told not to call it on logout.
|
||||
GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=true
|
||||
@@ -0,0 +1,24 @@
|
||||
# Managed by Ansible (nametag.yml) - secrets sourced from Infisical via
|
||||
# `infisical run -- ansible-playbook ...`.
|
||||
#
|
||||
# This file is loaded twice: docker compose reads it from the project
|
||||
# directory for ${VAR} substitution in docker-compose.yml, and the app
|
||||
# container also loads it directly via env_file.
|
||||
|
||||
# Database
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_NAME=nametag_db
|
||||
DB_USER=nametag
|
||||
DB_PASSWORD={{ nametag_db_password }}
|
||||
|
||||
# Redis (rate limiting & caching)
|
||||
REDIS_PASSWORD={{ nametag_redis_password }}
|
||||
REDIS_URL=redis://:{{ nametag_redis_password }}@redis:6379
|
||||
|
||||
# Application URL
|
||||
NEXTAUTH_URL=http://{{ ansible_host }}:3000
|
||||
NEXTAUTH_SECRET={{ nametag_nextauth_secret }}
|
||||
|
||||
# Cron
|
||||
CRON_SECRET={{ nametag_cron_secret }}
|
||||
@@ -0,0 +1,72 @@
|
||||
# Managed by Ansible (omnivore.yml) - generated secrets persist in
|
||||
# ansible/plays/machine_setup/credentials/omnivore/ on the control node.
|
||||
|
||||
# Postgres & Migrate
|
||||
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD={{ omnivore_postgres_password }}
|
||||
POSTGRES_DB=omnivore
|
||||
PGPASSWORD={{ omnivore_postgres_password }}
|
||||
PG_REPLICATION=false
|
||||
|
||||
PG_HOST=postgres
|
||||
PG_PASSWORD={{ omnivore_pg_password }}
|
||||
PG_DB=omnivore
|
||||
PG_USER=app_user
|
||||
PG_PORT=5432
|
||||
PG_POOL_MAX=20
|
||||
|
||||
# API
|
||||
|
||||
API_ENV=local
|
||||
IMAGE_PROXY_SECRET={{ omnivore_image_proxy_secret }}
|
||||
JWT_SECRET={{ omnivore_jwt_secret }}
|
||||
SSO_JWT_SECRET={{ omnivore_sso_jwt_secret }}
|
||||
GATEWAY_URL=http://api:8080/api
|
||||
CONTENT_FETCH_URL=http://content-fetch:8080/?token={{ omnivore_verification_token }}
|
||||
GCS_USE_LOCAL_HOST=true
|
||||
GCS_UPLOAD_BUCKET=omnivore
|
||||
AUTO_VERIFY=true
|
||||
# Minio credentials are hardcoded in docker-compose.yml for the minio and
|
||||
# createbuckets services, so these must match those literal values.
|
||||
AWS_ACCESS_KEY_ID=minio
|
||||
AWS_SECRET_ACCESS_KEY=miniominio
|
||||
AWS_REGION=us-east-1
|
||||
CONTENT_FETCH_QUEUE_ENABLED=true
|
||||
|
||||
IMAGE_PROXY_URL=http://{{ ansible_host }}:7070
|
||||
CLIENT_URL=http://{{ ansible_host }}:3000
|
||||
LOCAL_MINIO_URL=http://{{ ansible_host }}:1010
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
|
||||
# Mail
|
||||
WATCHER_API_KEY={{ omnivore_mail_watcher_key }}
|
||||
LOCAL_EMAIL_DOMAIN=domain.tld
|
||||
# SNS_ARN=arn_of_sns #for if you use SES and SNS for Email.
|
||||
|
||||
# Web
|
||||
APP_ENV=prod
|
||||
BASE_URL=http://{{ ansible_host }}:3000
|
||||
SERVER_BASE_URL=http://{{ ansible_host }}:4000
|
||||
HIGHLIGHTS_BASE_URL=http://{{ ansible_host }}:3000
|
||||
# USE_DISCOVER_AI=true
|
||||
# OPENAI_API_KEY=<OPENAI_API_KEY>
|
||||
|
||||
# Content Fetch
|
||||
VERIFICATION_TOKEN={{ omnivore_verification_token }}
|
||||
REST_BACKEND_ENDPOINT=http://api:8080/api
|
||||
SKIP_UPLOAD_ORIGINAL=true
|
||||
|
||||
# Minio
|
||||
MINIO_ACCESS_KEY=minio
|
||||
MINIO_SECRET_KEY=miniominio
|
||||
AWS_S3_ENDPOINT_URL=http://minio:9000
|
||||
|
||||
# Export
|
||||
EXPORT_QUEUE_NAME=omnivore-backend-queue
|
||||
|
||||
# Youtube
|
||||
YOUTUBE_TRANSCRIPT_PROMPT=Reformat the supplied transcript data adding formatting, puncuation, and paragraphs, but do not summarize or change the content. Format the output as markdown.
|
||||
YOUTUBE_MAXIMUM_VIDEO_DURATION_TRANSCRIPT=1801
|
||||
@@ -0,0 +1,101 @@
|
||||
# Vendored from https://supernote-private-cloud.supernote.com/cloud/docker-compose.yml,
|
||||
# with two fixes applied:
|
||||
# - the mariadb service is missing docker-entrypoint-initdb.d mounts in the
|
||||
# upstream file, so supernotedb.sql would never actually load into a
|
||||
# fresh database; added below.
|
||||
# - a second init script (supernote-email-init.sql, rendered by Ansible
|
||||
# from Infisical-sourced secrets) pre-seeds SMTP settings into
|
||||
# u_email_config so registration/password-reset emails work without a
|
||||
# manual trip through the web UI's "Email Settings" dialog.
|
||||
# supernote-service's DB_HOSTNAME/MYSQL_*/REDIS_* env vars are also inlined
|
||||
# directly here instead of upstream's separate .dbenv/env_file, since they're
|
||||
# just ${VAR} substitutions from the same .env used by mariadb/redis.
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.6.24
|
||||
container_name: mariadb
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
MYSQL_DATABASE: supernotedb
|
||||
MYSQL_USER: ${MYSQL_USER}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||
TZ: ${TZ:-UTC}
|
||||
command: --skip-name-resolve --bind-address=0.0.0.0
|
||||
volumes:
|
||||
- ./sndata/db_data:/var/lib/mysql
|
||||
- ./sndata/config/mysql/conf.d:/etc/mysql/conf.d:ro
|
||||
- ./supernotedb.sql:/docker-entrypoint-initdb.d/00-supernotedb.sql:ro
|
||||
- ./supernote-email-init.sql:/docker-entrypoint-initdb.d/01-supernote-email-init.sql:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p$$MYSQL_ROOT_PASSWORD || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7.4.7
|
||||
container_name: redis
|
||||
environment:
|
||||
TZ: ${TZ:-UTC}
|
||||
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
|
||||
volumes:
|
||||
- ./sndata/redis_data:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
|
||||
notelib:
|
||||
image: docker.io/supernote/notelib:6.9.3
|
||||
container_name: notelib
|
||||
environment:
|
||||
TZ: ${TZ:-UTC}
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
restart: unless-stopped
|
||||
|
||||
supernote-service:
|
||||
image: docker.io/supernote/supernote-service:26.06.04
|
||||
container_name: supernote-service
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "19071:19071"
|
||||
- "18072:18072"
|
||||
- "${FRONTEND_PORT:-19072}:8080"
|
||||
- "${DOMAIN_PORT:-8199}:8080"
|
||||
environment:
|
||||
EXTERNAL_PORT_BACKEND: "19071"
|
||||
EXTERNAL_PORT_FRONTEND: ${FRONTEND_PORT:-19072}
|
||||
EXTERNAL_PORT_DOMAIN: ${DOMAIN_PORT:-8199}
|
||||
TZ: ${TZ:-UTC}
|
||||
DB_HOSTNAME: mariadb
|
||||
MYSQL_DATABASE: supernotedb
|
||||
MYSQL_USER: ${MYSQL_USER}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
volumes:
|
||||
- ./sndata/recycle:/home/supernote/recycle
|
||||
- ./supernote_data:/home/supernote/data
|
||||
- ./sndata/logs/cloud:/home/supernote/cloud/logs
|
||||
- ./sndata/logs/app:/home/supernote/logs
|
||||
- ./sndata/logs/web:/var/log/nginx
|
||||
- ./sndata/convert:/home/supernote/convert
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
@@ -0,0 +1,30 @@
|
||||
-- Managed by Ansible (supernote.yml) - SMTP secrets sourced from Infisical
|
||||
-- via `infisical run -- ansible-playbook ...`.
|
||||
--
|
||||
-- Mounted into the mariadb container's docker-entrypoint-initdb.d/ so it
|
||||
-- seeds u_email_config on first boot, and re-applied by the playbook via
|
||||
-- `docker compose exec` on every run so Infisical stays the source of truth.
|
||||
--
|
||||
-- u_email_config's schema/upsert key come from a third-party reverse
|
||||
-- engineering of Supernote's supernotedb.sql (not officially documented) -
|
||||
-- see https://github.com/liketheduck/supernote-private-cloud-docker. Verify
|
||||
-- against Email Settings in the web UI if Supernote changes this schema.
|
||||
|
||||
USE supernotedb;
|
||||
|
||||
INSERT INTO u_email_config (smtp_server, port, user_name, password, encryption, flag)
|
||||
VALUES (
|
||||
'{{ supernote_smtp_server }}',
|
||||
'{{ supernote_smtp_port | default(465) }}',
|
||||
'{{ supernote_smtp_user }}',
|
||||
'{{ supernote_smtp_password }}',
|
||||
'{{ supernote_smtp_encryption | default("ssl") }}',
|
||||
'Y'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
smtp_server='{{ supernote_smtp_server }}',
|
||||
port='{{ supernote_smtp_port | default(465) }}',
|
||||
user_name='{{ supernote_smtp_user }}',
|
||||
password='{{ supernote_smtp_password }}',
|
||||
encryption='{{ supernote_smtp_encryption | default("ssl") }}',
|
||||
flag='Y';
|
||||
@@ -0,0 +1,10 @@
|
||||
# Managed by Ansible (supernote.yml) - secrets sourced from Infisical via
|
||||
# `infisical run -- ansible-playbook ...`.
|
||||
#
|
||||
# Consumed by docker compose for ${VAR} substitution in docker-compose.yml.
|
||||
|
||||
MYSQL_ROOT_PASSWORD={{ supernote_mysql_root_password }}
|
||||
MYSQL_USER=supernote
|
||||
MYSQL_PASSWORD={{ supernote_mysql_password }}
|
||||
|
||||
REDIS_PASSWORD={{ supernote_redis_password }}
|
||||
Reference in new issue
Block a user