add tailscale
This commit is contained in:
parent
8ef71691e0
commit
f1695d1d8d
@ -1,13 +0,0 @@
|
||||
---
|
||||
- name: Mount vfs
|
||||
ansible.posix.mount:
|
||||
src: "{{ vfs_mount_tag }}"
|
||||
path: /mnt/vfs
|
||||
fstype: virtiofs
|
||||
state: mounted
|
||||
|
||||
- name: Restart bright
|
||||
community.docker.docker_container:
|
||||
name: bright
|
||||
state: started
|
||||
restart: true
|
@ -1,85 +0,0 @@
|
||||
---
|
||||
|
||||
# Terraform Vultr provider doesn't have a VFS resource/datasource yet.
|
||||
# This is a workaround for that missing feature.
|
||||
#
|
||||
# @see https://github.com/vultr/terraform-provider-vultr/issues/560
|
||||
- name: Get the VFS id
|
||||
ansible.builtin.uri:
|
||||
url: https://api.vultr.com/v2/vfs
|
||||
method: GET
|
||||
status_code: 200
|
||||
headers:
|
||||
Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
register: vfs_list
|
||||
|
||||
- name: Get VFS variables
|
||||
ansible.builtin.set_fact:
|
||||
bright_vfs_id: "{{ vfs_list.json.vfs | selectattr('label', 'equalto', 'bright') | map(attribute='id') | first }}"
|
||||
|
||||
- name: Debug the bright VFS id
|
||||
ansible.builtin.debug:
|
||||
msg: "The VFS ID for 'bright' is {{ bright_vfs_id }}"
|
||||
|
||||
- name: Attach VFS to Vultr instance
|
||||
ansible.builtin.uri:
|
||||
url: https://api.vultr.com/v2/vfs/{{ bright_vfs_id }}/attachments/{{ hostvars[inventory_hostname]['vultr_instance_id'] }}
|
||||
method: PUT
|
||||
status_code:
|
||||
- 200
|
||||
- 201
|
||||
- 409
|
||||
headers:
|
||||
Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
register: vfs_attach
|
||||
changed_when:
|
||||
- vfs_attach.json is defined
|
||||
- "'state' in vfs_attach.json"
|
||||
- vfs_attach.json.state == "ATTACHED"
|
||||
notify:
|
||||
- Mount vfs
|
||||
- Restart bright
|
||||
|
||||
- name: Debug vfs_attach
|
||||
ansible.builtin.debug:
|
||||
var: vfs_attach
|
||||
|
||||
- name: Get the VFS mount_tag
|
||||
ansible.builtin.set_fact:
|
||||
vfs_mount_tag: "{{ vfs_attach.json.mount_tag | default('') }}"
|
||||
|
||||
|
||||
- name: Setup docker container
|
||||
community.docker.docker_container:
|
||||
name: bright
|
||||
image: gitea.futureporn.net/futureporn/bright:latest
|
||||
pull: always
|
||||
state: started
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
- "/mnt/vfs/futureporn:/mnt/vfs/futureporn"
|
||||
env:
|
||||
DB_HOST: "{{ hostvars['fp-db-0']['internal_ip'] }}"
|
||||
DB_USER: "{{ lookup('dotenv', 'DB_USER', file='../.env') }}"
|
||||
DB_NAME: "bright"
|
||||
DB_PORT: "5432"
|
||||
DB_PASS: "{{ lookup('dotenv', 'DB_PASS', file='../.env') }}"
|
||||
MIX_ENV: prod
|
||||
PUBLIC_S3_ENDPOINT: https://futureporn-b2.b-cdn.net
|
||||
PATREON_REDIRECT_URI: https://bright.futureporn.net/auth/patreon/callback
|
||||
SITE_URL: https://bright.futureporn.net
|
||||
PHX_HOST: bright.futureporn.net
|
||||
AWS_BUCKET: futureporn
|
||||
AWS_REGION: us-west-000
|
||||
AWS_HOST: s3.us-west-000.backblazeb2.com
|
||||
SECRET_KEY_BASE: "{{ lookup('dotenv', 'SECRET_KEY_BASE', file='../.env') }}"
|
||||
PATREON_CLIENT_SECRET: "{{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../.env') }}"
|
||||
PATREON_CLIENT_ID: "{{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../.env') }}"
|
||||
AWS_ACCESS_KEY_ID: "{{ lookup('dotenv', 'AWS_ACCESS_KEY_ID', file='../.env') }}"
|
||||
AWS_SECRET_ACCESS_KEY: "{{ lookup('dotenv', 'AWS_SECRET_ACCESS_KEY', file='../.env') }}"
|
||||
TRACKER_HELPER_ACCESSLIST_URL: https://tracker.futureporn.net/accesslist
|
||||
TRACKER_HELPER_USERNAME: "{{ lookup('dotenv', 'TRACKER_HELPER_USERNAME', file='../.env') }}"
|
||||
TRACKER_HELPER_PASSWORD: "{{ lookup('dotenv', 'TRACKER_HELPER_PASSWORD', file='../.env') }}"
|
||||
TRACKER_URL: https://tracker.futureporn.net:6969
|
||||
CACHE_DIR: /mnt/vfs/futureporn # we use Vultr File System to share cache among all Phoenix instances
|
@ -1,3 +0,0 @@
|
||||
---
|
||||
|
||||
coolify_dir: /opt/coolify
|
@ -1,25 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Install Coolify using official installer
|
||||
ansible.builtin.shell: |
|
||||
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash
|
||||
args:
|
||||
creates: /coolify/docker-compose.yml # adjust if needed to prevent reruns
|
||||
|
||||
|
||||
# @note securely connect to coolify webui using SSH tunneling.
|
||||
# ssh -L 8000:localhost:8000 root@our
|
||||
|
||||
|
||||
# @see https://coolify.io/docs/knowledge-base/server/firewall
|
||||
- name: Allow UFW ports
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- 8000 # coolify UI
|
||||
- 6001 # real-time comms
|
||||
- 6002 # terminal
|
||||
- 80
|
||||
- 443
|
@ -1,179 +0,0 @@
|
||||
---
|
||||
|
||||
|
||||
|
||||
- name: Install apt packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- python3-psycopg2
|
||||
update_cache: yes
|
||||
state: present
|
||||
|
||||
|
||||
- name: Ensure required packages are installed
|
||||
apt:
|
||||
name:
|
||||
- curl
|
||||
- ca-certificates
|
||||
- postgresql-common
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Create directory for PostgreSQL apt key
|
||||
file:
|
||||
path: /usr/share/postgresql-common/pgdg
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Download PostgreSQL signing key
|
||||
get_url:
|
||||
url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
|
||||
dest: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
|
||||
mode: '0644'
|
||||
|
||||
- name: Add PostgreSQL APT repository
|
||||
apt_repository:
|
||||
repo: "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt {{ ansible_distribution_release }}-pgdg main"
|
||||
filename: "pgdg"
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install PostgreSQL 16
|
||||
apt:
|
||||
name: postgresql-16
|
||||
state: present
|
||||
|
||||
- name: Start postgres
|
||||
ansible.builtin.systemd_service:
|
||||
name: postgresql@16-main
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Create a new database with name "future_porn"
|
||||
community.postgresql.postgresql_db:
|
||||
name: future_porn
|
||||
become: true
|
||||
become_user: postgres
|
||||
|
||||
- name: Create postgres user and set password
|
||||
community.postgresql.postgresql_user:
|
||||
name: postgres
|
||||
password: "{{ lookup('dotenv', 'DB_PASSWORD', file='../../../.env.production') }}"
|
||||
expires: infinity
|
||||
become: true
|
||||
become_user: postgres
|
||||
|
||||
- name: Grant privs
|
||||
community.postgresql.postgresql_privs:
|
||||
login_db: "{{ lookup('dotenv', 'DB_NAME', file='../../../.env.production') }}"
|
||||
roles: "{{ lookup('dotenv', 'DB_USER', file='../../../.env.production') }}"
|
||||
type: schema
|
||||
objs: public
|
||||
privs: ALL
|
||||
become: true
|
||||
become_user: postgres
|
||||
|
||||
|
||||
- name: Allow access on Vultr VPC subnet
|
||||
community.postgresql.postgresql_pg_hba:
|
||||
dest: /etc/postgresql/16/main/pg_hba.conf
|
||||
contype: host
|
||||
users: all
|
||||
databases: all
|
||||
method: scram-sha-256
|
||||
source: 10.2.112.0/20
|
||||
keep_comments_at_rules: true
|
||||
comment: "Vultr VPC"
|
||||
|
||||
- name: set listen_addresses
|
||||
community.postgresql.postgresql_alter_system:
|
||||
param: listen_addresses
|
||||
value: '*'
|
||||
become: true
|
||||
become_user: postgres
|
||||
|
||||
- name: set port
|
||||
community.postgresql.postgresql_alter_system:
|
||||
param: port
|
||||
value: '5432'
|
||||
become: true
|
||||
become_user: postgres
|
||||
|
||||
|
||||
# - name: Setup volume
|
||||
# community.docker.docker_volume:
|
||||
# name: pg_data
|
||||
|
||||
# - name: Setup docker container
|
||||
# community.docker.docker_container:
|
||||
# name: postgres
|
||||
# image: postgres:16
|
||||
# pull: missing
|
||||
# state: started
|
||||
# ports:
|
||||
# - "0.0.0.0:5432:5432"
|
||||
# env:
|
||||
# POSTGRES_USER: "{{ lookup('dotenv', 'DB_USER', file='../../../../.env.production') }}"
|
||||
# POSTGRES_DB: "{{ lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production') }}"
|
||||
# POSTGRES_PASSWORD: "{{ lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production') }}"
|
||||
# mounts:
|
||||
# - type: volume
|
||||
# target: "/var/lib/postgresql/data"
|
||||
# source: "pg_data"
|
||||
|
||||
- name: Set default UFW policy to deny incoming
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
||||
direction: incoming
|
||||
|
||||
- name: Allow /20 subnet access for VPC
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: '5432'
|
||||
proto: tcp
|
||||
from: 10.2.112.0/20
|
||||
|
||||
|
||||
|
||||
# sudo ufw default deny incoming
|
||||
|
||||
# - name: start pgweb
|
||||
# community.docker.docker_container:
|
||||
# name: pgweb
|
||||
# image: sosedoff/pgweb:latest
|
||||
# pull: missing
|
||||
# state: started
|
||||
# ports:
|
||||
# - "8091:8091"
|
||||
# env:
|
||||
# POSTGRES_USER: "postgres"
|
||||
# POSTGRES_DB: "our"
|
||||
# POSTGRES_PASSWORD: "{{ lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production') }}"
|
||||
# PGWEB_DATABASE_URL: "postgres://{{lookup('dotenv', 'DB_USER', file='../../../../.env.production'):{{lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production')@postgres:}}}}"
|
||||
# mounts:
|
||||
# - type: volume
|
||||
# target: "/var/lib/postgresql/data"
|
||||
# source: "pg_data"
|
||||
|
||||
|
||||
# pgweb:
|
||||
# container_name: out-pgweb
|
||||
# image: sosedoff/pgweb
|
||||
# depends_on:
|
||||
# postgres:
|
||||
# condition: service_healthy
|
||||
# environment:
|
||||
# PGWEB_DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}?sslmode=disable
|
||||
# ports:
|
||||
# - "8091:8081"
|
||||
# healthcheck:
|
||||
# test: ["CMD", "curl", "-f", "http://localhost:8081"]
|
||||
# interval: 10s
|
||||
# retries: 5
|
||||
# start_period: 10s
|
||||
# timeout: 10s
|
@ -1,3 +0,0 @@
|
||||
---
|
||||
infisical_caddy_image: caddy:2
|
||||
infisical_docker_tag: latest-postgres
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Restart caddy
|
||||
community.docker.docker_container:
|
||||
name: infisical-caddy-1
|
||||
image: "{{ infisical_caddy_image }}"
|
||||
state: started
|
||||
restart: true
|
||||
|
||||
- name: Restart infisical
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/infisical
|
||||
state: restarted
|
@ -1,45 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Ensure infisical directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/infisical
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Generate .env file
|
||||
ansible.builtin.template:
|
||||
src: env.j2
|
||||
dest: /opt/infisical/.env
|
||||
mode: "0600"
|
||||
|
||||
- name: Install passlib
|
||||
ansible.builtin.pip:
|
||||
name: passlib # dependency of Ansible's passwordhash
|
||||
state: present
|
||||
|
||||
- name: Template Caddyfile
|
||||
ansible.builtin.template:
|
||||
src: Caddyfile.j2
|
||||
dest: /opt/infisical/Caddyfile
|
||||
mode: "0600"
|
||||
notify:
|
||||
- Restart caddy
|
||||
|
||||
- name: Template Docker Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: /opt/infisical/docker-compose.yml
|
||||
mode: "0644"
|
||||
|
||||
- name: Start up docker-compose.yml
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/infisical
|
||||
state: present
|
||||
|
||||
- name: Configure firewall
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- 443
|
@ -1,13 +0,0 @@
|
||||
|
||||
infisical.futureporn.net {
|
||||
# basic_auth {
|
||||
# {{ lookup('dotenv', 'INFISICAL_BASIC_AUTH_USERNAME', file='../../../../.env')}} {{ lookup('dotenv', 'INFISICAL_BASIC_AUTH_PASSWORD', file='../../../../.env') | password_hash('bcrypt') }}
|
||||
# }
|
||||
|
||||
reverse_proxy infisical-backend:8080 {
|
||||
health_uri /
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
x-logging: &default-logging
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-20m}"
|
||||
max-file: "${LOG_MAX_FILE:-10}"
|
||||
compress: "true"
|
||||
|
||||
services:
|
||||
caddy:
|
||||
image: {{ infisical_caddy_image }}
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
- caddy_data:/data
|
||||
ports:
|
||||
- 443:443
|
||||
environment:
|
||||
- BASE_URL=infisical.futureporn.net
|
||||
logging: *default-logging
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
backend:
|
||||
container_name: infisical-backend
|
||||
image: infisical/infisical:{{ infisical_docker_tag }}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
db-migration:
|
||||
condition: service_completed_successfully
|
||||
pull_policy: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
ports:
|
||||
- 80:8080
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
redis:
|
||||
container_name: infisical-redis
|
||||
image: redis
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
volumes:
|
||||
- ./volumes/redis:/data
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
db:
|
||||
container_name: infisical-db
|
||||
image: postgres:14-alpine
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
volumes:
|
||||
- ./volumes/postgres:/var/lib/postgresql/data
|
||||
networks:
|
||||
- infisical
|
||||
healthcheck:
|
||||
test: "pg_isready --username=${POSTGRES_USER} && psql --username=${POSTGRES_USER} --list"
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
|
||||
db-migration:
|
||||
container_name: infisical-db-migration
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
image: infisical/infisical:{{ infisical_docker_tag }}
|
||||
env_file: .env
|
||||
command: npm run migration:latest
|
||||
pull_policy: always
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
networks:
|
||||
infisical:
|
||||
|
||||
volumes:
|
||||
caddy_data: null
|
@ -1,23 +0,0 @@
|
||||
# Website URL
|
||||
SITE_URL=https://infisical.futureporn.net
|
||||
|
||||
# Keys
|
||||
# Required key for platform encryption/decryption ops
|
||||
# GENERATE YOUR OWN KEY WITH `openssl rand -hex 16`
|
||||
ENCRYPTION_KEY={{ lookup('dotenv', 'INFISICAL_ENCRYPTION_KEY', file='../../../../.env') }}
|
||||
|
||||
# JWT
|
||||
# Required secrets to sign JWT tokens
|
||||
# GENERATE YOUR OWN KEY WITH `openssl rand -base64 32`
|
||||
AUTH_SECRET={{ lookup('dotenv', 'INFISICAL_AUTH_SECRET', file='../../../../.env') }}
|
||||
|
||||
# Postgres
|
||||
POSTGRES_PASSWORD={{ lookup('dotenv', 'INFISICAL_POSTGRES_PASSWORD', file='../../../../.env') }}
|
||||
POSTGRES_USER=infisical
|
||||
POSTGRES_DB=infisical
|
||||
# Do not change the next line
|
||||
DB_CONNECTION_URI=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
|
||||
|
||||
# Redis
|
||||
# Do not change the next line
|
||||
REDIS_URL=redis://redis:6379
|
@ -1,29 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Ensure komodo directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/komodo
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Get docker compose file
|
||||
ansible.builtin.get_url:
|
||||
url: komodo https://raw.githubusercontent.com/moghtech/komodo/main/compose/ferretdb.compose.yaml
|
||||
dest: /opt/komodo
|
||||
mode: "0755"
|
||||
|
||||
- name: Get .env file
|
||||
ansible.builtin.get_url:
|
||||
url: https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env
|
||||
dest: /opt/komodo
|
||||
mode: "0755"
|
||||
|
||||
# we need to use lineinfile to set the following
|
||||
- name: set config
|
||||
ansible.builtin.lineinfile:
|
||||
|
||||
|
||||
|
||||
- name: Run Komodo core
|
||||
|
||||
|
@ -1,119 +0,0 @@
|
||||
|
||||
|
||||
# KOMODO_DISABLE_USER_REGISTRATION=true
|
||||
# KOMODO_ENABLE_NEW_USERS=false
|
||||
# KOMODO_DISABLE_NON_ADMIN_CREATE=true
|
||||
# KOMODO_HOST=https://komodo.future.porn
|
||||
# KOMODO_DB_USERNAME=admin
|
||||
# KOMODO_DB_PASSWORD=admin
|
||||
# KOMODO_PASSKEY=a_random_passkey
|
||||
|
||||
####################################
|
||||
# 🦎 KOMODO COMPOSE - VARIABLES 🦎 #
|
||||
####################################
|
||||
|
||||
## These compose variables can be used with all Komodo deployment options.
|
||||
## Pass these variables to the compose up command using `--env-file komodo/compose.env`.
|
||||
## Additionally, they are passed to both Komodo Core and Komodo Periphery with `env_file: ./compose.env`,
|
||||
## so you can pass any additional environment variables to Core / Periphery directly in this file as well.
|
||||
|
||||
## Stick to a specific version, or use `latest`
|
||||
COMPOSE_KOMODO_IMAGE_TAG=latest
|
||||
|
||||
## DB credentials
|
||||
KOMODO_DB_USERNAME=admin
|
||||
KOMODO_DB_PASSWORD=admin
|
||||
|
||||
## Configure a secure passkey to authenticate between Core / Periphery.
|
||||
KOMODO_PASSKEY=a_random_passkey
|
||||
|
||||
## Set your time zone for schedules
|
||||
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
TZ=Etc/UTC
|
||||
|
||||
#=-------------------------=#
|
||||
#= Komodo Core Environment =#
|
||||
#=-------------------------=#
|
||||
|
||||
## Full variable list + descriptions are available here:
|
||||
## 🦎 https://github.com/moghtech/komodo/blob/main/config/core.config.toml 🦎
|
||||
|
||||
## Note. Secret variables also support `${VARIABLE}_FILE` syntax to pass docker compose secrets.
|
||||
## Docs: https://docs.docker.com/compose/how-tos/use-secrets/#examples
|
||||
|
||||
## Used for Oauth / Webhook url suggestion / Caddy reverse proxy.
|
||||
KOMODO_HOST="{{ komodo_host }}"
|
||||
## Displayed in the browser tab.
|
||||
KOMODO_TITLE=fp Komodo
|
||||
## Create a server matching this address as the "first server".
|
||||
## Use `https://host.docker.internal:8120` when using systemd-managed Periphery.
|
||||
KOMODO_FIRST_SERVER=https://periphery:8120
|
||||
## Make all buttons just double-click, rather than the full confirmation dialog.
|
||||
KOMODO_DISABLE_CONFIRM_DIALOG=false
|
||||
|
||||
## Rate Komodo polls your servers for
|
||||
## status / container status / system stats / alerting.
|
||||
## Options: 1-sec, 5-sec, 15-sec, 1-min, 5-min, 15-min
|
||||
## Default: 15-sec
|
||||
KOMODO_MONITORING_INTERVAL="15-sec"
|
||||
## Interval at which to poll Resources for any updates / automated actions.
|
||||
## Options: 15-min, 1-hr, 2-hr, 6-hr, 12-hr, 1-day
|
||||
## Default: 1-hr
|
||||
KOMODO_RESOURCE_POLL_INTERVAL="1-hr"
|
||||
|
||||
## Used to auth incoming webhooks. Alt: KOMODO_WEBHOOK_SECRET_FILE
|
||||
KOMODO_WEBHOOK_SECRET=a_random_secret
|
||||
## Used to generate jwt. Alt: KOMODO_JWT_SECRET_FILE
|
||||
KOMODO_JWT_SECRET=a_random_jwt_secret
|
||||
## Time to live for jwt tokens.
|
||||
## Options: 1-hr, 12-hr, 1-day, 3-day, 1-wk, 2-wk
|
||||
KOMODO_JWT_TTL="1-day"
|
||||
|
||||
## Enable login with username + password.
|
||||
KOMODO_LOCAL_AUTH=true
|
||||
## Disable new user signups.
|
||||
KOMODO_DISABLE_USER_REGISTRATION=false
|
||||
## All new logins are auto enabled
|
||||
KOMODO_ENABLE_NEW_USERS=false
|
||||
## Disable non-admins from creating new resources.
|
||||
KOMODO_DISABLE_NON_ADMIN_CREATE=false
|
||||
## Allows all users to have Read level access to all resources.
|
||||
KOMODO_TRANSPARENT_MODE=false
|
||||
|
||||
## Prettier logging with empty lines between logs
|
||||
KOMODO_LOGGING_PRETTY=false
|
||||
## More human readable logging of startup config (multi-line)
|
||||
KOMODO_PRETTY_STARTUP_CONFIG=false
|
||||
|
||||
## OIDC Login
|
||||
KOMODO_OIDC_ENABLED=false
|
||||
## Must reachable from Komodo Core container
|
||||
# KOMODO_OIDC_PROVIDER=https://oidc.provider.internal/application/o/komodo
|
||||
## Change the host to one reachable be reachable by users (optional if it is the same as above).
|
||||
## DO NOT include the `path` part of the URL.
|
||||
# KOMODO_OIDC_REDIRECT_HOST=https://oidc.provider.external
|
||||
## Your OIDC client id
|
||||
# KOMODO_OIDC_CLIENT_ID= # Alt: KOMODO_OIDC_CLIENT_ID_FILE
|
||||
## Your OIDC client secret.
|
||||
## If your provider supports PKCE flow, this can be ommitted.
|
||||
# KOMODO_OIDC_CLIENT_SECRET= # Alt: KOMODO_OIDC_CLIENT_SECRET_FILE
|
||||
## Make usernames the full email.
|
||||
## Note. This does not work for all OIDC providers.
|
||||
# KOMODO_OIDC_USE_FULL_EMAIL=true
|
||||
## Add additional trusted audiences for token claims verification.
|
||||
## Supports comma separated list, and passing with _FILE (for compose secrets).
|
||||
# KOMODO_OIDC_ADDITIONAL_AUDIENCES=abc,123 # Alt: KOMODO_OIDC_ADDITIONAL_AUDIENCES_FILE
|
||||
|
||||
## Github Oauth
|
||||
KOMODO_GITHUB_OAUTH_ENABLED=false
|
||||
# KOMODO_GITHUB_OAUTH_ID= # Alt: KOMODO_GITHUB_OAUTH_ID_FILE
|
||||
# KOMODO_GITHUB_OAUTH_SECRET= # Alt: KOMODO_GITHUB_OAUTH_SECRET_FILE
|
||||
|
||||
## Google Oauth
|
||||
KOMODO_GOOGLE_OAUTH_ENABLED=false
|
||||
# KOMODO_GOOGLE_OAUTH_ID= # Alt: KOMODO_GOOGLE_OAUTH_ID_FILE
|
||||
# KOMODO_GOOGLE_OAUTH_SECRET= # Alt: KOMODO_GOOGLE_OAUTH_SECRET_FILE
|
||||
|
||||
## Aws - Used to launch Builder instances.
|
||||
KOMODO_AWS_ACCESS_KEY_ID= # Alt: KOMODO_AWS_ACCESS_KEY_ID_FILE
|
||||
KOMODO_AWS_SECRET_ACCESS_KEY= # Alt: KOMODO_AWS_SECRET_ACCESS_KEY_FILE
|
@ -1,95 +0,0 @@
|
||||
###################################
|
||||
# 🦎 KOMODO COMPOSE - FERRETDB 🦎 #
|
||||
###################################
|
||||
|
||||
## This compose file will deploy:
|
||||
## 1. Postgres + FerretDB Mongo adapter (https://www.ferretdb.com)
|
||||
## 2. Komodo Core
|
||||
## 3. Komodo Periphery
|
||||
|
||||
services:
|
||||
postgres:
|
||||
# Recommended: Pin to a specific version
|
||||
# https://github.com/FerretDB/documentdb/pkgs/container/postgres-documentdb
|
||||
image: ghcr.io/ferretdb/postgres-documentdb
|
||||
labels:
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
restart: unless-stopped
|
||||
# ports:
|
||||
# - 5432:5432
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: ${KOMODO_DB_USERNAME}
|
||||
POSTGRES_PASSWORD: ${KOMODO_DB_PASSWORD}
|
||||
POSTGRES_DB: postgres
|
||||
|
||||
ferretdb:
|
||||
# Recommended: Pin to a specific version
|
||||
# https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb
|
||||
image: ghcr.io/ferretdb/ferretdb
|
||||
labels:
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
# ports:
|
||||
# - 27017:27017
|
||||
volumes:
|
||||
- ferretdb-state:/state
|
||||
environment:
|
||||
FERRETDB_POSTGRESQL_URL: postgres://${KOMODO_DB_USERNAME}:${KOMODO_DB_PASSWORD}@postgres:5432/postgres
|
||||
|
||||
core:
|
||||
image: ghcr.io/moghtech/komodo-core:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
|
||||
labels:
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- ferretdb
|
||||
ports:
|
||||
- 9120:9120
|
||||
env_file: ./compose.env
|
||||
environment:
|
||||
KOMODO_DATABASE_ADDRESS: ferretdb:27017
|
||||
KOMODO_DATABASE_USERNAME: ${KOMODO_DB_USERNAME}
|
||||
KOMODO_DATABASE_PASSWORD: ${KOMODO_DB_PASSWORD}
|
||||
volumes:
|
||||
## Core cache for repos for latest commit hash / contents
|
||||
- repo-cache:/repo-cache
|
||||
## Store sync files on server
|
||||
# - /path/to/syncs:/syncs
|
||||
## Optionally mount a custom core.config.toml
|
||||
# - /path/to/core.config.toml:/config/config.toml
|
||||
## Allows for systemd Periphery connection at
|
||||
## "http://host.docker.internal:8120"
|
||||
# extra_hosts:
|
||||
# - host.docker.internal:host-gateway
|
||||
|
||||
## Deploy Periphery container using this block,
|
||||
## or deploy the Periphery binary with systemd using
|
||||
## https://github.com/moghtech/komodo/tree/main/scripts
|
||||
periphery:
|
||||
image: ghcr.io/moghtech/komodo-periphery:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
|
||||
labels:
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
restart: unless-stopped
|
||||
env_file: ./compose.env
|
||||
volumes:
|
||||
## Mount external docker socket
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
## Allow Periphery to see processes outside of container
|
||||
- /proc:/proc
|
||||
## Specify the Periphery agent root directory.
|
||||
## Must be the same inside and outside the container,
|
||||
## or docker will get confused. See https://github.com/moghtech/komodo/discussions/180.
|
||||
## Default: /etc/komodo.
|
||||
- ${PERIPHERY_ROOT_DIRECTORY:-/etc/komodo}:${PERIPHERY_ROOT_DIRECTORY:-/etc/komodo}
|
||||
|
||||
volumes:
|
||||
# Postgres
|
||||
postgres-data:
|
||||
# FerretDB
|
||||
ferretdb-state:
|
||||
# Core
|
||||
repo-cache:
|
@ -1,3 +0,0 @@
|
||||
---
|
||||
|
||||
our_caddy_image: caddy:2
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Restart app
|
||||
ansible.builtin.systemd_service:
|
||||
name: our-server
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
@ -1,198 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Create futureporn group
|
||||
ansible.builtin.group:
|
||||
name: futureporn
|
||||
state: present
|
||||
|
||||
- name: Create futureporn user
|
||||
ansible.builtin.user:
|
||||
name: futureporn
|
||||
group: futureporn
|
||||
create_home: true
|
||||
home: /home/futureporn
|
||||
system: true
|
||||
|
||||
- name: Ensure futureporn directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/futureporn
|
||||
state: directory
|
||||
mode: "0755"
|
||||
notify:
|
||||
- Restart app
|
||||
|
||||
- name: Ensure config directory exists
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/etc/futureporn/our
|
||||
state: directory
|
||||
mode: "0755"
|
||||
notify:
|
||||
- Restart app
|
||||
|
||||
- name: Generate .env file
|
||||
ansible.builtin.template:
|
||||
src: env.j2
|
||||
dest: "{{ env_file }}"
|
||||
mode: "0600"
|
||||
notify:
|
||||
- Restart app
|
||||
|
||||
- name: Download Futureporn source code
|
||||
ansible.builtin.git:
|
||||
repo: https://gitea.futureporn.net/futureporn/fp
|
||||
dest: /opt/futureporn
|
||||
version: "{{ our_commit }}"
|
||||
update: true
|
||||
tags:
|
||||
- our
|
||||
notify:
|
||||
- Restart app
|
||||
|
||||
- name: Install Our packages based on package.json
|
||||
community.general.npm:
|
||||
path: "{{ app_dir }}"
|
||||
|
||||
|
||||
- name: Install passlib
|
||||
ansible.builtin.pip:
|
||||
name: passlib # dependency of Ansible's passwordhash
|
||||
state: present
|
||||
|
||||
- name: Create our-server service
|
||||
ansible.builtin.template:
|
||||
src: our-server.service.j2
|
||||
dest: /etc/systemd/system/our-server.service
|
||||
mode: "0644"
|
||||
notify:
|
||||
- Restart app
|
||||
|
||||
|
||||
|
||||
# - name: Template Caddyfile
|
||||
# ansible.builtin.template:
|
||||
# src: Caddyfile.j2
|
||||
# dest: /opt/our/Caddyfile
|
||||
# mode: "0600"
|
||||
# notify:
|
||||
# - Restart caddy
|
||||
|
||||
# - name: Template Docker Compose file
|
||||
# ansible.builtin.template:
|
||||
# src: docker-compose.yml.j2
|
||||
# dest: /opt/our/docker-compose.yml
|
||||
# mode: "0644"
|
||||
# notify:
|
||||
# - Restart app
|
||||
|
||||
- name: Set default UFW policy to deny incoming
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
||||
direction: incoming
|
||||
|
||||
- name: Configure firewall
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- 443
|
||||
- 80
|
||||
|
||||
|
||||
|
||||
- name: Allow /20 subnet access
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
from: 10.2.112.0/20
|
||||
loop:
|
||||
- 3000
|
||||
|
||||
# Bright app Reference
|
||||
# ---
|
||||
|
||||
# # Terraform Vultr provider doesn't have a VFS resource/datasource yet.
|
||||
# # This is a workaround for that missing feature.
|
||||
# #
|
||||
# # @see https://github.com/vultr/terraform-provider-vultr/issues/560
|
||||
# - name: Get the VFS id
|
||||
# ansible.builtin.uri:
|
||||
# url: https://api.vultr.com/v2/vfs
|
||||
# method: GET
|
||||
# status_code: 200
|
||||
# headers:
|
||||
# Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
# register: vfs_list
|
||||
|
||||
# - name: Get VFS variables
|
||||
# ansible.builtin.set_fact:
|
||||
# our_vfs_id: "{{ vfs_list.json.vfs | selectattr('label', 'equalto', 'our') | map(attribute='id') | first }}"
|
||||
|
||||
# - name: Debug the our VFS id
|
||||
# ansible.builtin.debug:
|
||||
# msg: "The VFS ID for 'our' is {{ our_vfs_id }}"
|
||||
|
||||
# - name: Attach VFS to Vultr instance
|
||||
# ansible.builtin.uri:
|
||||
# url: https://api.vultr.com/v2/vfs/{{ our_vfs_id }}/attachments/{{ hostvars[inventory_hostname]['vultr_instance_id'] }}
|
||||
# method: PUT
|
||||
# status_code:
|
||||
# - 200
|
||||
# - 201
|
||||
# - 409
|
||||
# headers:
|
||||
# Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
# register: vfs_attach
|
||||
# changed_when:
|
||||
# - vfs_attach.json is defined
|
||||
# - "'state' in vfs_attach.json"
|
||||
# - vfs_attach.json.state == "ATTACHED"
|
||||
# notify:
|
||||
# - Mount vfs
|
||||
# - Restart our
|
||||
|
||||
# - name: Debug vfs_attach
|
||||
# ansible.builtin.debug:
|
||||
# var: vfs_attach
|
||||
|
||||
# - name: Get the VFS mount_tag
|
||||
# ansible.builtin.set_fact:
|
||||
# vfs_mount_tag: "{{ vfs_attach.json.mount_tag | default('') }}"
|
||||
|
||||
|
||||
# - name: Setup docker container
|
||||
# community.docker.docker_container:
|
||||
# name: our
|
||||
# image: gitea.futureporn.net/futureporn/our:latest
|
||||
# pull: always
|
||||
# state: started
|
||||
# ports:
|
||||
# - "4000:4000"
|
||||
# volumes:
|
||||
# - "/mnt/vfs/futureporn:/mnt/vfs/futureporn"
|
||||
# env:
|
||||
# DB_HOST: "{{ hostvars['fp-db-0']['internal_ip'] }}"
|
||||
# DB_USER: "{{ lookup('dotenv', 'DB_USER', file='../.env') }}"
|
||||
# DB_NAME: "our"
|
||||
# DB_PORT: "5432"
|
||||
# DB_PASS: "{{ lookup('dotenv', 'DB_PASS', file='../.env') }}"
|
||||
# MIX_ENV: prod
|
||||
# PUBLIC_S3_ENDPOINT: https://futureporn-b2.b-cdn.net
|
||||
# PATREON_REDIRECT_URI: https://our.futureporn.net/auth/patreon/callback
|
||||
# SITE_URL: https://our.futureporn.net
|
||||
# PHX_HOST: our.futureporn.net
|
||||
# AWS_BUCKET: futureporn
|
||||
# AWS_REGION: us-west-000
|
||||
# AWS_HOST: s3.us-west-000.backblazeb2.com
|
||||
# SECRET_KEY_BASE: "{{ lookup('dotenv', 'SECRET_KEY_BASE', file='../.env') }}"
|
||||
# PATREON_CLIENT_SECRET: "{{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../.env') }}"
|
||||
# PATREON_CLIENT_ID: "{{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../.env') }}"
|
||||
# AWS_ACCESS_KEY_ID: "{{ lookup('dotenv', 'AWS_ACCESS_KEY_ID', file='../.env') }}"
|
||||
# AWS_SECRET_ACCESS_KEY: "{{ lookup('dotenv', 'AWS_SECRET_ACCESS_KEY', file='../.env') }}"
|
||||
# TRACKER_HELPER_ACCESSLIST_URL: https://tracker.futureporn.net/accesslist
|
||||
# TRACKER_HELPER_USERNAME: "{{ lookup('dotenv', 'TRACKER_HELPER_USERNAME', file='../.env') }}"
|
||||
# TRACKER_HELPER_PASSWORD: "{{ lookup('dotenv', 'TRACKER_HELPER_PASSWORD', file='../.env') }}"
|
||||
# TRACKER_URL: https://tracker.futureporn.net:6969
|
||||
# CACHE_DIR: /mnt/vfs/futureporn # we use Vultr File System to share cache among all Phoenix instances
|
@ -1,6 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Setup fastify app
|
||||
ansible.builtin.include_tasks: fastify.yml
|
||||
tags:
|
||||
- fastify
|
@ -1,33 +0,0 @@
|
||||
ORIGIN=https://future.porn
|
||||
|
||||
COOKIE_SECRET={{ lookup('dotenv', 'COOKIE_SECRET', file='../../../../.env.production')}}
|
||||
DB_USER={{ lookup('dotenv', 'DB_USER', file='../../../../.env.production')}}
|
||||
DB_PASSWORD={{ lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production')}}
|
||||
DB_NAME=future_porn
|
||||
|
||||
CDN_ORIGIN=https://fp-usc.b-cdn.net
|
||||
CDN_TOKEN_SECRET={{ lookup('dotenv', 'CDN_TOKEN_SECRET', file='../../../../.env.production')}}
|
||||
NODE_ENV=production
|
||||
|
||||
DATABASE_URL={{ lookup('dotenv', 'DATABASE_URL', file='../../../../.env.production')}}
|
||||
PGADMIN_DEFAULT_EMAIL={{ lookup('dotenv', 'PGADMIN_DEFAULT_EMAIL', file='../../../../.env.production')}}
|
||||
PGADMIN_DEFAULT_PASSWORD={{ lookup('dotenv', 'PGADMIN_DEFAULT_PASSWORD', file='../../../../.env.production')}}
|
||||
|
||||
PATREON_CLIENT_ID={{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../../../../.env.production')}}
|
||||
PATREON_CLIENT_SECRET={{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../../../../.env.production')}}
|
||||
|
||||
PATREON_API_ORIGIN=https://www.patreon.com
|
||||
PATREON_AUTHORIZE_PATH=/oauth2/authorize
|
||||
PATREON_TOKEN_PATH=/api/oauth2/token
|
||||
|
||||
S3_BUCKET=fp-usc
|
||||
S3_REGION=us-west-000
|
||||
S3_KEY_ID={{ lookup('dotenv', 'S3_KEY_ID', file='../../../../.env.production')}}
|
||||
S3_APPLICATION_KEY={{ lookup('dotenv', 'S3_APPLICATION_KEY', file='../../../../.env.production')}}
|
||||
S3_ENDPOINT=https://s3.us-west-000.backblazeb2.com
|
||||
|
||||
|
||||
|
||||
CACHE_ROOT='/mnt/vfs/futureporn/our'
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
[Unit]
|
||||
Description=FuturePorn Our Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory={{ app_dir }}
|
||||
ExecStart=/usr/bin/env /usr/bin/npx tsx src/index.ts
|
||||
#ExecStart=/usr/bin/env /usr/bin/npx dotenvx run -f {{ env_file }} -- npx tsx src/index.ts
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User={{ app_user }}
|
||||
EnvironmentFile={{ env_file }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
[Unit]
|
||||
Description=FuturePorn Our Worker
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory={{ app_dir }}
|
||||
ExecStart=/usr/bin/env NODE_ENV=production /usr/bin/node dist/worker.js
|
||||
Restart=on-failure
|
||||
User={{ app_user }}
|
||||
EnvironmentFile={{ env_file }}
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
app_user: futureporn
|
||||
app_dir: /opt/futureporn/services/our
|
||||
app_entry: dist/main.js
|
||||
env_file: /usr/local/etc/futureporn/our/env
|
||||
nodejs_version: "20.x"
|
||||
our_commit: main
|
@ -1,2 +0,0 @@
|
||||
---
|
||||
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Restart worker
|
||||
ansible.builtin.systemd_service:
|
||||
name: our-worker
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
@ -1,75 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Create futureporn group
|
||||
ansible.builtin.group:
|
||||
name: futureporn
|
||||
state: present
|
||||
|
||||
- name: Create futureporn user
|
||||
ansible.builtin.user:
|
||||
name: futureporn
|
||||
group: futureporn
|
||||
create_home: true
|
||||
home: /home/futureporn
|
||||
system: true
|
||||
|
||||
- name: Ensure futureporn directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/futureporn
|
||||
state: directory
|
||||
mode: "0755"
|
||||
notify:
|
||||
- restart worker
|
||||
|
||||
- name: Ensure config directory exists
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/etc/futureporn/our
|
||||
state: directory
|
||||
mode: "0755"
|
||||
notify:
|
||||
- restart worker
|
||||
|
||||
- name: Generate .env file
|
||||
ansible.builtin.template:
|
||||
src: env.j2
|
||||
dest: "{{ env_file }}"
|
||||
mode: "0600"
|
||||
notify:
|
||||
- restart worker
|
||||
|
||||
- name: Download Futureporn source code
|
||||
ansible.builtin.git:
|
||||
repo: https://gitea.futureporn.net/futureporn/fp
|
||||
dest: /opt/futureporn
|
||||
version: "{{ our_commit }}"
|
||||
update: true
|
||||
tags:
|
||||
- our
|
||||
notify:
|
||||
- Restart worker
|
||||
|
||||
- name: Install Our packages based on package.json
|
||||
community.general.npm:
|
||||
path: "{{ app_dir }}"
|
||||
|
||||
|
||||
- name: Install passlib
|
||||
ansible.builtin.pip:
|
||||
name: passlib # dependency of Ansible's passwordhash
|
||||
state: present
|
||||
|
||||
- name: Create our-worker service
|
||||
ansible.builtin.template:
|
||||
src: our-worker.service.j2
|
||||
dest: /etc/systemd/system/our-worker.service
|
||||
mode: "0644"
|
||||
notify:
|
||||
- restart worker
|
||||
|
||||
|
||||
- name: Set default UFW policy to deny incoming
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
||||
direction: incoming
|
||||
|
@ -1,30 +0,0 @@
|
||||
ORIGIN=https://future.porn
|
||||
|
||||
COOKIE_SECRET={{ lookup('dotenv', 'COOKIE_SECRET', file='../../../../.env.production')}}
|
||||
DB_USER={{ lookup('dotenv', 'DB_USER', file='../../../../.env.production')}}
|
||||
DB_PASSWORD={{ lookup('dotenv', 'DB_PASSWORD', file='../../../../.env.production')}}
|
||||
DB_NAME=future_porn
|
||||
|
||||
CDN_ORIGIN=https://fp-usc.b-cdn.net
|
||||
CDN_TOKEN_SECRET={{ lookup('dotenv', 'CDN_TOKEN_SECRET', file='../../../../.env.production')}}
|
||||
NODE_ENV=production
|
||||
|
||||
DATABASE_URL={{ lookup('dotenv', 'DATABASE_URL', file='../../../../.env.production')}}
|
||||
PGADMIN_DEFAULT_EMAIL={{ lookup('dotenv', 'PGADMIN_DEFAULT_EMAIL', file='../../../../.env.production')}}
|
||||
PGADMIN_DEFAULT_PASSWORD={{ lookup('dotenv', 'PGADMIN_DEFAULT_PASSWORD', file='../../../../.env.production')}}
|
||||
|
||||
PATREON_CLIENT_ID={{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../../../../.env.production')}}
|
||||
PATREON_CLIENT_SECRET={{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../../../../.env.production')}}
|
||||
|
||||
PATREON_API_ORIGIN=https://www.patreon.com
|
||||
PATREON_AUTHORIZE_PATH=/oauth2/authorize
|
||||
PATREON_TOKEN_PATH=/api/oauth2/token
|
||||
|
||||
S3_BUCKET=fp-usc
|
||||
S3_REGION=us-west-000
|
||||
S3_KEY_ID={{ lookup('dotenv', 'S3_KEY_ID', file='../../../../.env.production') }}
|
||||
S3_APPLICATION_KEY={{ lookup('dotenv', 'S3_APPLICATION_KEY', file='../../../../.env.production')}}
|
||||
S3_ENDPOINT=https://s3.us-west-000.backblazeb2.com
|
||||
|
||||
CACHE_ROOT='/mnt/vfs/futureporn/our'
|
||||
|
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=FuturePorn Our Worker
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory={{ app_dir }}
|
||||
ExecStart=/usr/bin/env /usr/bin/npx tsx src/worker.ts
|
||||
Restart=on-failure
|
||||
User={{ app_user }}
|
||||
EnvironmentFile={{ env_file }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
app_user: futureporn
|
||||
app_dir: /opt/futureporn/services/our
|
||||
app_entry: src/worker.ts
|
||||
env_file: /usr/local/etc/futureporn/our/env
|
||||
nodejs_version: "20.x"
|
||||
our_commit: main
|
@ -1,218 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e # Stop script execution on error
|
||||
|
||||
NGINX_CONF_PATH="./docker/nginx/active_backend.conf"
|
||||
NGINX_CONTAINER="app"
|
||||
ENV_FILE=".env"
|
||||
|
||||
build_containers() {
|
||||
echo "📦 Building Docker containers..."
|
||||
docker compose build
|
||||
echo "✅ Docker containers built successfully."
|
||||
}
|
||||
|
||||
prepare_nginx_config() {
|
||||
if [ ! -d "./docker/nginx" ]; then
|
||||
echo "📂 Nginx directory not found. Creating it..."
|
||||
mkdir -p ./docker/nginx
|
||||
echo "✅ Nginx directory created."
|
||||
fi
|
||||
}
|
||||
|
||||
update_nginx_config() {
|
||||
local active_color=$1
|
||||
echo "🔄 Updating Nginx configuration to route traffic to '$active_color' containers..."
|
||||
|
||||
cat > "$NGINX_CONF_PATH" <<EOL
|
||||
upstream app_backend {
|
||||
server $active_color:9000 max_fails=3 fail_timeout=30s;
|
||||
}
|
||||
EOL
|
||||
|
||||
echo "📋 Copying Nginx configuration to the container..."
|
||||
docker cp "$NGINX_CONF_PATH" "$NGINX_CONTAINER:/etc/nginx/conf.d/active_backend.conf"
|
||||
echo "🔁 Reloading Nginx to apply the new configuration..."
|
||||
docker exec "$NGINX_CONTAINER" nginx -s reload >/dev/null 2>&1
|
||||
echo "✅ Nginx configuration updated and reloaded successfully."
|
||||
}
|
||||
|
||||
wait_for_health() {
|
||||
local container_prefix=$1
|
||||
local retries=5
|
||||
local unhealthy_found
|
||||
echo "⏳ Waiting for containers with prefix '$container_prefix' to become healthy..."
|
||||
|
||||
while (( retries > 0 )); do
|
||||
unhealthy_found=false
|
||||
|
||||
for container_name in $(docker ps --filter "name=$container_prefix" --format "{{.Names}}"); do
|
||||
health_status=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}unknown{{end}}' "$container_name" || echo "unknown")
|
||||
if [[ "$health_status" != "healthy" ]]; then
|
||||
unhealthy_found=true
|
||||
echo "🚧 Container '$container_name' is not ready. Current status: $health_status."
|
||||
fi
|
||||
done
|
||||
|
||||
if ! $unhealthy_found; then
|
||||
echo "✅ All containers with prefix '$container_prefix' are healthy."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "⏳ Retrying... ($retries retries left)"
|
||||
((retries--))
|
||||
sleep 5
|
||||
done
|
||||
|
||||
echo "❌ Error: Some containers with prefix '$container_prefix' are not healthy. Aborting deployment."
|
||||
rollback
|
||||
exit 0
|
||||
}
|
||||
|
||||
rollback() {
|
||||
echo "🛑 Rolling back deployment. Ensuring the active environment remains intact."
|
||||
|
||||
if [ -n "$PREVIOUS_COLOR" ]; then
|
||||
echo "🔄 Restoring CONTAINER_COLOR=$PREVIOUS_COLOR in .env."
|
||||
sed -i.bak "s/^CONTAINER_COLOR=.*/CONTAINER_COLOR=$PREVIOUS_COLOR/" "$ENV_FILE"
|
||||
rm -f "$ENV_FILE.bak"
|
||||
echo "✅ Restored CONTAINER_COLOR=$PREVIOUS_COLOR in .env."
|
||||
else
|
||||
echo "🚧 No previous CONTAINER_COLOR found to restore."
|
||||
fi
|
||||
|
||||
if docker ps --filter "name=green" --format "{{.Names}}" | grep -q "green"; then
|
||||
echo "✅ Active environment 'green' remains intact."
|
||||
echo "🛑 Stopping and removing 'blue' containers..."
|
||||
docker compose stop "blue" >/dev/null 2>&1 || true
|
||||
docker compose rm -f "blue" >/dev/null 2>&1 || true
|
||||
elif docker ps --filter "name=blue" --format "{{.Names}}" | grep -q "blue"; then
|
||||
echo "✅ Active environment 'blue' remains intact."
|
||||
echo "🛑 Stopping and removing 'green' containers..."
|
||||
docker compose stop "green" >/dev/null 2>&1 || true
|
||||
docker compose rm -f "green" >/dev/null 2>&1 || true
|
||||
else
|
||||
echo "❌ No active environment detected after rollback. Manual intervention might be needed."
|
||||
fi
|
||||
|
||||
echo "🔄 Rollback completed."
|
||||
}
|
||||
|
||||
update_env_file() {
|
||||
local active_color=$1
|
||||
|
||||
# check if .env file exists
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "❌ .env file not found. Creating a new one..."
|
||||
echo "CONTAINER_COLOR=$active_color" > "$ENV_FILE"
|
||||
echo "✅ Created .env file with CONTAINER_COLOR=$active_color."
|
||||
return
|
||||
fi
|
||||
|
||||
# backup previous CONTAINER_COLOR value
|
||||
if grep -q "^CONTAINER_COLOR=" "$ENV_FILE"; then
|
||||
PREVIOUS_COLOR=$(grep "^CONTAINER_COLOR=" "$ENV_FILE" | cut -d '=' -f 2)
|
||||
echo "♻️ Backing up previous CONTAINER_COLOR=$PREVIOUS_COLOR."
|
||||
else
|
||||
PREVIOUS_COLOR=""
|
||||
fi
|
||||
|
||||
# update CONTAINER_COLOR value in .env
|
||||
if grep -q "^CONTAINER_COLOR=" "$ENV_FILE"; then
|
||||
sed -i.bak "s/^CONTAINER_COLOR=.*/CONTAINER_COLOR=$active_color/" "$ENV_FILE"
|
||||
echo "🔄 Updated CONTAINER_COLOR=$active_color in .env"
|
||||
else
|
||||
echo "CONTAINER_COLOR=$active_color" >> "$ENV_FILE"
|
||||
echo "🖋️ Added CONTAINER_COLOR=$active_color to .env"
|
||||
fi
|
||||
|
||||
# remove backup file
|
||||
if [ -f "$ENV_FILE.bak" ]; then
|
||||
rm "$ENV_FILE.bak"
|
||||
fi
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
local container=$1
|
||||
echo "📥 Installing dependencies in container '$container'..."
|
||||
|
||||
# Install Laravel dependencies
|
||||
docker exec -u root -it "$container" bash -c "composer install --no-dev --optimize-autoloader"
|
||||
docker exec -u root -it "$container" bash -c "mkdir -p database && touch database/database.sqlite"
|
||||
|
||||
# Permissions setup
|
||||
docker exec -u root -it "$container" bash -c "chown www-data:www-data -R ./storage ./bootstrap ./database"
|
||||
docker exec -u root -it "$container" bash -c "chmod -R 775 ./storage ./bootstrap/cache"
|
||||
|
||||
# Clear caches and run migrations
|
||||
docker exec -u root -it "$container" bash -c "php artisan cache:clear"
|
||||
docker exec -u root -it "$container" bash -c "php artisan config:clear"
|
||||
docker exec -u root -it "$container" bash -c "php artisan route:clear"
|
||||
docker exec -u root -it "$container" bash -c "php artisan view:clear"
|
||||
docker exec -u root -it "$container" bash -c "php artisan migrate --force"
|
||||
|
||||
echo "✅ Dependencies installed and database initialized successfully in container '$container'."
|
||||
}
|
||||
|
||||
deploy() {
|
||||
local active=$1
|
||||
local new=$2
|
||||
|
||||
# Update .env before deploying
|
||||
update_env_file "$new"
|
||||
echo "🚀 Starting deployment. Current active environment: '$active'. Deploying to '$new'..."
|
||||
docker compose --profile "$new" up -d
|
||||
wait_for_health "$new"
|
||||
install_dependencies "$new"
|
||||
update_nginx_config "$new"
|
||||
echo "🗑️ Removing old environment: '$active'..."
|
||||
echo "🛑 Stopping '$active' containers..."
|
||||
docker compose stop $active >/dev/null 2>&1 || true
|
||||
echo "🗑️ Removing '$active' containers..."
|
||||
docker compose rm -f $active >/dev/null 2>&1 || true
|
||||
update_env_file "$new"
|
||||
echo "✅ Deployment to '$new' completed successfully."
|
||||
}
|
||||
|
||||
get_active_container() {
|
||||
if [ -f "$ENV_FILE" ] && grep -q "CONTAINER_COLOR" "$ENV_FILE"; then
|
||||
grep "CONTAINER_COLOR" "$ENV_FILE" | cut -d '=' -f 2
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
prepare_nginx_config
|
||||
build_containers
|
||||
|
||||
ACTIVE_COLOR=$(get_active_container)
|
||||
|
||||
if [ -z "$ACTIVE_COLOR" ]; then
|
||||
# if no active container found, deploy 'blue'
|
||||
echo "🟦 Initial setup. Bringing up 'blue' containers..."
|
||||
docker compose --profile blue up -d
|
||||
wait_for_health "blue"
|
||||
install_dependencies "blue"
|
||||
update_nginx_config "blue"
|
||||
update_env_file "blue"
|
||||
elif [ "$ACTIVE_COLOR" == "green" ]; then
|
||||
# if the active is 'green', deploy 'blue'
|
||||
PREVIOUS_COLOR="green"
|
||||
deploy "green" "blue"
|
||||
elif [ "$ACTIVE_COLOR" == "blue" ]; then
|
||||
# if the active is 'blue', deploy 'green'
|
||||
PREVIOUS_COLOR="blue"
|
||||
deploy "blue" "green"
|
||||
else
|
||||
# if the active is neither 'green' nor 'blue', reset to 'blue'
|
||||
echo "🚧 Unexpected CONTAINER_COLOR value. Resetting to 'blue'..."
|
||||
PREVIOUS_COLOR=""
|
||||
docker compose --profile blue up -d
|
||||
wait_for_health "blue"
|
||||
install_dependencies "blue"
|
||||
update_nginx_config "blue"
|
||||
update_env_file "blue"
|
||||
fi
|
||||
|
||||
echo "🎉 Deployment successful!"
|
@ -1,46 +0,0 @@
|
||||
---
|
||||
# Terraform Vultr provider doesn't expose the mount_tag.
|
||||
# it does however expose the vfs id, which we save to ansible host vars at time of `tofu apply`.
|
||||
# As a workaround, we use Vultr api to fetch the mount_tag, and mount the vfs to the instance.
|
||||
- name: Get the VFS data
|
||||
ansible.builtin.uri:
|
||||
url: https://api.vultr.com/v2/vfs
|
||||
method: GET
|
||||
status_code: 200
|
||||
headers:
|
||||
Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
register: vfs_list
|
||||
|
||||
- name: Get VFS variables
|
||||
ansible.builtin.set_fact:
|
||||
our_vfs_id: "{{ vfs_list.json.vfs | selectattr('tags', 'contains', 'our') | map(attribute='id') | first }}"
|
||||
|
||||
- name: Debug the our VFS id
|
||||
ansible.builtin.debug:
|
||||
msg: "The VFS ID for 'our' is {{ our_vfs_id }}"
|
||||
|
||||
- name: Attach VFS to Vultr instance
|
||||
ansible.builtin.uri:
|
||||
url: https://api.vultr.com/v2/vfs/{{ vultr_vfs_storage_id }}/attachments/{{ hostvars[inventory_hostname]['vultr_instance_id'] }}
|
||||
method: PUT
|
||||
status_code:
|
||||
- 200
|
||||
- 201
|
||||
- 409
|
||||
headers:
|
||||
Authorization: "Bearer {{ lookup('dotenv', 'VULTR_API_KEY', file='../.env') }}"
|
||||
register: vfs_attach
|
||||
changed_when:
|
||||
- vfs_attach.json is defined
|
||||
- "'state' in vfs_attach.json"
|
||||
- vfs_attach.json.state == "ATTACHED"
|
||||
notify:
|
||||
- Mount vfs
|
||||
|
||||
- name: Debug vfs_attach
|
||||
ansible.builtin.debug:
|
||||
var: vfs_attach
|
||||
|
||||
- name: Get the VFS mount_tag
|
||||
ansible.builtin.set_fact:
|
||||
our_vfs_mount_tag: "{{ vfs_attach.json.mount_tag | default('') }}"
|
@ -31,6 +31,19 @@
|
||||
loop:
|
||||
- compose.production.yaml
|
||||
|
||||
- name: Load environment variables
|
||||
set_fact:
|
||||
our_env_vars: "{{ lookup('community.general.read_dotenv', '../../../../.env.production') }}"
|
||||
|
||||
- name: Create Docker secrets dynamically
|
||||
when: inventory_hostname == (groups['swarm'] | first)
|
||||
community.docker.docker_secret:
|
||||
name: "{{ item.key }}"
|
||||
data: "{{ item.value | b64encode }}"
|
||||
data_is_b64: true
|
||||
state: present
|
||||
loop: "{{ our_env_vars | dict2items }}"
|
||||
|
||||
- name: Deploy stack
|
||||
when: inventory_hostname == groups['swarm'] | first
|
||||
community.docker.docker_stack:
|
||||
@ -39,56 +52,55 @@
|
||||
compose:
|
||||
- /etc/futureporn/our/compose.production.yaml
|
||||
- services:
|
||||
postgres:
|
||||
environment:
|
||||
POSTGRES_USER: "{{ lookup('dotenv', 'POSTGRES_USER', file='../../../../.env.production') }}"
|
||||
POSTGRES_PASSWORD: "{{ lookup('dotenv', 'POSTGRES_PASSWORD', file='../../../../.env.production') }}"
|
||||
POSTGRES_DB: "{{ lookup('dotenv', 'POSTGRES_DB', file='../../../../.env.production') }}"
|
||||
worker:
|
||||
environment:
|
||||
DATABASE_URL: "{{ lookup('dotenv', 'DATABASE_URL', file='../../../../.env.production') }}"
|
||||
NODE_ENV: "{{ lookup('dotenv', 'NODE_ENV', file='../../../../.env.production') }}"
|
||||
ORIGIN: "{{ lookup('dotenv', 'ORIGIN', file='../../../../.env.production') }}"
|
||||
PATREON_API_ORIGIN: "{{ lookup('dotenv', 'PATREON_API_ORIGIN', file='../../../../.env.production') }}"
|
||||
PATREON_AUTHORIZE_PATH: "{{ lookup('dotenv', 'PATREON_AUTHORIZE_PATH', file='../../../../.env.production') }}"
|
||||
PATREON_TOKEN_PATH: "{{ lookup('dotenv', 'PATREON_TOKEN_PATH', file='../../../../.env.production') }}"
|
||||
PATREON_CLIENT_ID: "{{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../../../../.env.production') }}"
|
||||
PATREON_CLIENT_SECRET: "{{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../../../../.env.production') }}"
|
||||
COOKIE_SECRET: "{{ lookup('dotenv', 'COOKIE_SECRET', file='../../../../.env.production') }}"
|
||||
S3_REGION: "{{ lookup('dotenv', 'S3_REGION', file='../../../../.env.production') }}"
|
||||
S3_BUCKET: "{{ lookup('dotenv', 'S3_BUCKET', file='../../../../.env.production') }}"
|
||||
S3_APPLICATION_KEY: "{{ lookup('dotenv', 'S3_APPLICATION_KEY', file='../../../../.env.production') }}"
|
||||
S3_KEY_ID: "{{ lookup('dotenv', 'S3_KEY_ID', file='../../../../.env.production') }}"
|
||||
S3_ENDPOINT: "{{ lookup('dotenv', 'S3_ENDPOINT', file='../../../../.env.production') }}"
|
||||
CDN_ORIGIN: "{{ lookup('dotenv', 'CDN_ORIGIN', file='../../../../.env.production') }}"
|
||||
CDN_TOKEN_SECRET: "{{ lookup('dotenv', 'CDN_TOKEN_SECRET', file='../../../../.env.production') }}"
|
||||
WHISPER_DIR: "{{ lookup('dotenv', 'WHISPER_DIR', file='../../../../.env.production') }}"
|
||||
B2_APPLICATION_KEY_ID: "{{ lookup('dotenv', 'B2_APPLICATION_KEY_ID', file='../../../../.env.production') }}"
|
||||
B2_APPLICATION_KEY: "{{ lookup('dotenv', 'B2_APPLICATION_KEY', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_URL: "{{ lookup('dotenv', 'SEEDBOX_SFTP_URL', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_USERNAME: "{{ lookup('dotenv', 'SEEDBOX_SFTP_USERNAME', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_PASSWORD: "{{ lookup('dotenv', 'SEEDBOX_SFTP_PASSWORD', file='../../../../.env.production') }}"
|
||||
server:
|
||||
environment:
|
||||
DATABASE_URL: "{{ lookup('dotenv', 'DATABASE_URL', file='../../../../.env.production') }}"
|
||||
NODE_ENV: "{{ lookup('dotenv', 'NODE_ENV', file='../../../../.env.production') }}"
|
||||
ORIGIN: "{{ lookup('dotenv', 'ORIGIN', file='../../../../.env.production') }}"
|
||||
PATREON_API_ORIGIN: "{{ lookup('dotenv', 'PATREON_API_ORIGIN', file='../../../../.env.production') }}"
|
||||
PATREON_AUTHORIZE_PATH: "{{ lookup('dotenv', 'PATREON_AUTHORIZE_PATH', file='../../../../.env.production') }}"
|
||||
PATREON_TOKEN_PATH: "{{ lookup('dotenv', 'PATREON_TOKEN_PATH', file='../../../../.env.production') }}"
|
||||
PATREON_CLIENT_ID: "{{ lookup('dotenv', 'PATREON_CLIENT_ID', file='../../../../.env.production') }}"
|
||||
PATREON_CLIENT_SECRET: "{{ lookup('dotenv', 'PATREON_CLIENT_SECRET', file='../../../../.env.production') }}"
|
||||
COOKIE_SECRET: "{{ lookup('dotenv', 'COOKIE_SECRET', file='../../../../.env.production') }}"
|
||||
S3_REGION: "{{ lookup('dotenv', 'S3_REGION', file='../../../../.env.production') }}"
|
||||
S3_BUCKET: "{{ lookup('dotenv', 'S3_BUCKET', file='../../../../.env.production') }}"
|
||||
S3_APPLICATION_KEY: "{{ lookup('dotenv', 'S3_APPLICATION_KEY', file='../../../../.env.production') }}"
|
||||
S3_KEY_ID: "{{ lookup('dotenv', 'S3_KEY_ID', file='../../../../.env.production') }}"
|
||||
S3_ENDPOINT: "{{ lookup('dotenv', 'S3_ENDPOINT', file='../../../../.env.production') }}"
|
||||
CDN_ORIGIN: "{{ lookup('dotenv', 'CDN_ORIGIN', file='../../../../.env.production') }}"
|
||||
CDN_TOKEN_SECRET: "{{ lookup('dotenv', 'CDN_TOKEN_SECRET', file='../../../../.env.production') }}"
|
||||
WHISPER_DIR: "{{ lookup('dotenv', 'WHISPER_DIR', file='../../../../.env.production') }}"
|
||||
B2_APPLICATION_KEY_ID: "{{ lookup('dotenv', 'B2_APPLICATION_KEY_ID', file='../../../../.env.production') }}"
|
||||
B2_APPLICATION_KEY: "{{ lookup('dotenv', 'B2_APPLICATION_KEY', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_URL: "{{ lookup('dotenv', 'SEEDBOX_SFTP_URL', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_USERNAME: "{{ lookup('dotenv', 'SEEDBOX_SFTP_USERNAME', file='../../../../.env.production') }}"
|
||||
SEEDBOX_SFTP_PASSWORD: "{{ lookup('dotenv', 'SEEDBOX_SFTP_PASSWORD', file='../../../../.env.production') }}"
|
||||
DATABASE_URL: "{{ our_env_vars.DATABASE_URL }}"
|
||||
NODE_ENV: "{{ our_env_vars.NODE_ENV }}"
|
||||
ORIGIN: "{{ our_env_vars.ORIGIN }}"
|
||||
PATREON_API_ORIGIN: "{{ our_env_vars.PATREON_API_ORIGIN }}"
|
||||
PATREON_AUTHORIZE_PATH: "{{ our_env_vars.PATREON_AUTHORIZE_PATH }}"
|
||||
PATREON_TOKEN_PATH: "{{ our_env_vars.PATREON_TOKEN_PATH }}"
|
||||
PATREON_CLIENT_ID: "{{ our_env_vars.PATREON_CLIENT_ID }}"
|
||||
PATREON_CLIENT_SECRET: "{{ our_env_vars.PATREON_CLIENT_SECRET }}"
|
||||
COOKIE_SECRET: "{{ our_env_vars.COOKIE_SECRET }}"
|
||||
S3_REGION: "{{ our_env_vars.S3_REGION }}"
|
||||
S3_BUCKET: "{{ our_env_vars.S3_BUCKET }}"
|
||||
S3_APPLICATION_KEY: "{{ our_env_vars.S3_APPLICATION_KEY }}"
|
||||
S3_KEY_ID: "{{ our_env_vars.S3_KEY_ID }}"
|
||||
S3_ENDPOINT: "{{ our_env_vars.S3_ENDPOINT }}"
|
||||
CDN_ORIGIN: "{{ our_env_vars.CDN_ORIGIN }}"
|
||||
CDN_TOKEN_SECRET: "{{ our_env_vars.CDN_TOKEN_SECRET }}"
|
||||
WHISPER_DIR: "{{ our_env_vars.WHISPER_DIR }}"
|
||||
B2_APPLICATION_KEY_ID: "{{ our_env_vars.B2_APPLICATION_KEY_ID }}"
|
||||
B2_APPLICATION_KEY: "{{ our_env_vars.B2_APPLICATION_KEY }}"
|
||||
SEEDBOX_SFTP_URL: "{{ our_env_vars.SEEDBOX_SFTP_URL }}"
|
||||
SEEDBOX_SFTP_USERNAME: "{{ our_env_vars.SEEDBOX_SFTP_USERNAME }}"
|
||||
SEEDBOX_SFTP_PASSWORD: "{{ our_env_vars.SEEDBOX_SFTP_PASSWORD }}"
|
||||
worker:
|
||||
DATABASE_URL: "{{ our_env_vars.DATABASE_URL }}"
|
||||
NODE_ENV: "{{ our_env_vars.NODE_ENV }}"
|
||||
ORIGIN: "{{ our_env_vars.ORIGIN }}"
|
||||
PATREON_API_ORIGIN: "{{ our_env_vars.PATREON_API_ORIGIN }}"
|
||||
PATREON_AUTHORIZE_PATH: "{{ our_env_vars.PATREON_AUTHORIZE_PATH }}"
|
||||
PATREON_TOKEN_PATH: "{{ our_env_vars.PATREON_TOKEN_PATH }}"
|
||||
PATREON_CLIENT_ID: "{{ our_env_vars.PATREON_CLIENT_ID }}"
|
||||
PATREON_CLIENT_SECRET: "{{ our_env_vars.PATREON_CLIENT_SECRET }}"
|
||||
COOKIE_SECRET: "{{ our_env_vars.COOKIE_SECRET }}"
|
||||
S3_REGION: "{{ our_env_vars.S3_REGION }}"
|
||||
S3_BUCKET: "{{ our_env_vars.S3_BUCKET }}"
|
||||
S3_APPLICATION_KEY: "{{ our_env_vars.S3_APPLICATION_KEY }}"
|
||||
S3_KEY_ID: "{{ our_env_vars.S3_KEY_ID }}"
|
||||
S3_ENDPOINT: "{{ our_env_vars.S3_ENDPOINT }}"
|
||||
CDN_ORIGIN: "{{ our_env_vars.CDN_ORIGIN }}"
|
||||
CDN_TOKEN_SECRET: "{{ our_env_vars.CDN_TOKEN_SECRET }}"
|
||||
WHISPER_DIR: "{{ our_env_vars.WHISPER_DIR }}"
|
||||
B2_APPLICATION_KEY_ID: "{{ our_env_vars.B2_APPLICATION_KEY_ID }}"
|
||||
B2_APPLICATION_KEY: "{{ our_env_vars.B2_APPLICATION_KEY }}"
|
||||
SEEDBOX_SFTP_URL: "{{ our_env_vars.SEEDBOX_SFTP_URL }}"
|
||||
SEEDBOX_SFTP_USERNAME: "{{ our_env_vars.SEEDBOX_SFTP_USERNAME }}"
|
||||
SEEDBOX_SFTP_PASSWORD: "{{ our_env_vars.SEEDBOX_SFTP_PASSWORD }}"
|
||||
pgadmin:
|
||||
PGADMIN_DEFAULT_EMAIL: "{{ our_env_vars.PGADMIN_DEFAULT_EMAIL }}"
|
||||
PGADMIN_DEFAULT_PASSWORD: "{{ our_env_vars.PGADMIN_DEFAULT_PASSWORD }}"
|
||||
tailscale-pgadmin:
|
||||
TS_AUTHKEY: "{{ our_env_vars.TS_AUTHKEY }}"
|
||||
|
@ -1,49 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Configure firewall
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- 80
|
||||
- 443
|
||||
- 9000
|
||||
|
||||
- name: Allow UDP port 6969
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "6969"
|
||||
proto: udp
|
||||
|
||||
- name: Install Caddy
|
||||
ansible.builtin.import_role:
|
||||
name: nvjacobo.caddy
|
||||
|
||||
|
||||
- name: Configure Caddyfile
|
||||
ansible.builtin.template:
|
||||
src: 'templates/Caddyfile.j2'
|
||||
dest: /etc/caddy/Caddyfile
|
||||
mode: "0644"
|
||||
notify: restart caddy
|
||||
|
||||
|
||||
# @todo performance enhancement is to run aquatic outside of docker.
|
||||
# @see https://github.com/greatest-ape/aquatic/blob/34b45e923f84421181fc43cf5e20709e69ce0dfd/docker/aquatic_udp.Dockerfile#L5
|
||||
- name: Setup docker container
|
||||
community.docker.docker_container:
|
||||
name: tracker
|
||||
image: gitea.futureporn.net/futureporn/tracker:latest
|
||||
pull: always
|
||||
state: started
|
||||
ports:
|
||||
- "6969:6969/udp" # aquatic_udp
|
||||
- "5063:5063" # tracker-helper
|
||||
- "9000:9000" # aquatic metrics
|
||||
env:
|
||||
TRACKER_HELPER_ACCESSLIST_URL: https://tracker.futureporn.net/accesslist
|
||||
TRACKER_HELPER_USERNAME: "{{ lookup('dotenv', 'TRACKER_HELPER_USERNAME', file='../.env') }}"
|
||||
TRACKER_HELPER_PASSWORD: "{{ lookup('dotenv', 'TRACKER_HELPER_PASSWORD', file='../.env') }}"
|
||||
TRACKER_URL: https://tracker.futureporn.net:6969
|
||||
TRACKER_HELPER_ACCESSLIST_PATH: /var/lib/aquatic/accesslist
|
@ -1,13 +0,0 @@
|
||||
tracker.futureporn.net {
|
||||
|
||||
reverse_proxy :5063 {
|
||||
health_uri /health
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
respond "💥 Error -- {err.status_code} {err.status_text}"
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
- name: Configure firewall
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- 80
|
||||
- 443
|
||||
|
||||
- name: Install Caddy
|
||||
ansible.builtin.import_role:
|
||||
name: nvjacobo.caddy
|
||||
|
||||
- name: Configure Caddyfile
|
||||
ansible.builtin.template:
|
||||
src: "templates/Caddyfile.j2"
|
||||
dest: /etc/caddy/Caddyfile
|
||||
mode: "0644"
|
||||
notify: restart caddy # nvjacobo.caddy handles this
|
@ -1,44 +0,0 @@
|
||||
---
|
||||
- name: Setup volume
|
||||
community.docker.docker_volume:
|
||||
name: pg_data
|
||||
|
||||
- name: Setup docker container
|
||||
community.docker.docker_container:
|
||||
name: uppy-companion
|
||||
image: transloadit/companion
|
||||
pull: missing
|
||||
state: started
|
||||
ports:
|
||||
- "3020:3020"
|
||||
env:
|
||||
NODE_ENV: prod
|
||||
COMPANION_PORT: "{{ lookup('dotenv', 'COMPANION_PORT', file='../.env') }}"
|
||||
COMPANION_DOMAIN: "{{ lookup('dotenv', 'COMPANION_DOMAIN', file='../.env') }}"
|
||||
COMPANION_SELF_ENDPOINT: "{{ lookup('dotenv', 'COMPANION_SELF_ENDPOINT', file='../.env') }}"
|
||||
COMPANION_HIDE_METRICS: "{{ lookup('dotenv', 'COMPANION_HIDE_METRICS', file='../.env') }}"
|
||||
COMPANION_HIDE_WELCOME: "{{ lookup('dotenv', 'COMPANION_HIDE_WELCOME', file='../.env') }}"
|
||||
COMPANION_STREAMING_UPLOAD: "{{ lookup('dotenv', 'COMPANION_STREAMING_UPLOAD', file='../.env') }}"
|
||||
COMPANION_TUS_DEFERRED_UPLOAD_LENGTH: "{{ lookup('dotenv', 'COMPANION_TUS_DEFERRED_UPLOAD_LENGTH', file='../.env') }}"
|
||||
COMPANION_CLIENT_ORIGINS: "{{ lookup('dotenv', 'COMPANION_CLIENT_ORIGINS', file='../.env') }}"
|
||||
COMPANION_PROTOCOL: "{{ lookup('dotenv', 'COMPANION_PROTOCOL', file='../.env') }}"
|
||||
COMPANION_DATADIR: /mnt/uppy-server-data
|
||||
COMPANION_SECRET: "{{ lookup('dotenv', 'COMPANION_SECRET', file='../.env') }}"
|
||||
COMPANION_PREAUTH_SECRET: "{{ lookup('dotenv', 'COMPANION_PREAUTH_SECRET', file='../.env') }}"
|
||||
COMPANION_AWS_KEY: "{{ lookup('dotenv', 'COMPANION_AWS_KEY', file='../.env') }}"
|
||||
COMPANION_AWS_SECRET: "{{ lookup('dotenv', 'COMPANION_AWS_SECRET', file='../.env') }}"
|
||||
COMPANION_AWS_BUCKET: "{{ lookup('dotenv', 'COMPANION_AWS_BUCKET', file='../.env') }}"
|
||||
COMPANION_AWS_ENDPOINT: "{{ lookup('dotenv', 'COMPANION_AWS_ENDPOINT', file='../.env') }}"
|
||||
COMPANION_AWS_REGION: "{{ lookup('dotenv', 'COMPANION_AWS_REGION', file='../.env') }}"
|
||||
COMPANION_AWS_FORCE_PATH_STYLE: "false"
|
||||
COMPANION_AWS_PREFIX: usc/
|
||||
mounts:
|
||||
- type: volume
|
||||
target: "/mnt/uppy-server-data"
|
||||
source: "uppy_data"
|
||||
# - name: Allow VPC2.0 network access
|
||||
# community.general.ufw:
|
||||
# rule: allow
|
||||
# port: '5432'
|
||||
# proto: tcp
|
||||
# from: 10.2.128.0/20
|
@ -1,15 +0,0 @@
|
||||
uppy.futureporn.net {
|
||||
|
||||
# Define the upstream servers for load balancing
|
||||
reverse_proxy :3020 {
|
||||
|
||||
# Health checks (optional)
|
||||
health_uri /metrics
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
respond "💥 Error ~ {err.status_code} {err.status_text}"
|
||||
}
|
||||
}
|
@ -64,13 +64,27 @@ services:
|
||||
max_attempts: 5
|
||||
window: 60s
|
||||
|
||||
# pgadmin:
|
||||
# image: dpage/pgadmin4:latest
|
||||
# ports:
|
||||
# - target: 5050
|
||||
# published: 8095
|
||||
# protocol: tcp
|
||||
# mode: ingress
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:latest
|
||||
network_mode: service:tailscale-pgadmin
|
||||
environment:
|
||||
PGADMIN_DISABLE_POSTFIX: 1
|
||||
|
||||
tailscale-pgadmin:
|
||||
image: tailscale/tailscale:latest
|
||||
volumes:
|
||||
- /mnt/vfs/futureporn/tailscale/state:/var/lib/tailscale
|
||||
- /mnt/vfs/futureporn/tailscale/config:/config
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
cap_add:
|
||||
- net_admin
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TS_EXTRA_ARGS: --advertise-tags=tag:container --reset"
|
||||
TS_SERVE_CONFIG: /config/pgadmin.json
|
||||
TS_STATE_DIR: /var/lib/tailscale
|
||||
TS_USERSPACE: false
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
|
Loading…
x
Reference in New Issue
Block a user