diff --git a/.github/workflows/CD-production-frontman.yml b/.github/workflows/CD-production-frontman.yml index 3d40a28..2f3f7fc 100644 --- a/.github/workflows/CD-production-frontman.yml +++ b/.github/workflows/CD-production-frontman.yml @@ -34,12 +34,12 @@ jobs: run: | echo "$SERVERS" > config/servers.yml - - name: Render USERS secret into config/users.yml + - name: Render SUPABASE secret into config/supabase.yml env: USERS: ${{ secrets.USERS }} shell: bash run: | - echo "$USERS" > config/users.yml + echo "$SUPABASE" > config/supabase.yml - name: Run playbook shell: bash diff --git a/.github/workflows/CD-production-task.yml b/.github/workflows/CD-production-task.yml index d86f6ae..eca6a5a 100644 --- a/.github/workflows/CD-production-task.yml +++ b/.github/workflows/CD-production-task.yml @@ -58,12 +58,12 @@ jobs: run: | echo "$SERVERS" > config/servers.yml - - name: Render USERS secret into config/users.yml + - name: Render SUPABASE secret into config/supabase.yml env: USERS: ${{ secrets.USERS }} shell: bash run: | - echo "$USERS" > config/users.yml + echo "$SUPABASE" > config/supabase.yml - name: Run playbook shell: bash diff --git a/.gitignore b/.gitignore index 9a97039..6bcd13a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,6 @@ id_rsa.pub config/users-configs.yml config/metrics.yml config/servers.yml -config/users.yml +config/supabase.yml config/hosts.yml static diff --git a/Makefile b/Makefile index c3fac84..89a337c 100644 --- a/Makefile +++ b/Makefile @@ -11,9 +11,6 @@ hosts_encrypt: hosts_decrypt: ansible-vault decrypt $(HOSTS_FILE) -render_users_csv: - ansible-playbook $(PLAYBOOK_FILE_USERS_CSV) - render_users_configs: ansible-playbook $(PLAYBOOK_FILE_USERS_CONFIGS) diff --git a/README.md b/README.md index 44572c2..f1f0c3a 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,15 @@ https://hiddify.com#app # Architecture ![digram](./diagram.svg) -There are 3 types of componets: **GH Pages**, **metrics** and **proxy**. GH Actions that must be configured for this repository. +There are 4 componets: **GH Pages**, **[Supabase](https://supabase.com) instance**, **metrics** and **proxy**. GH Actions that must be configured for this repository. Metrics should be deployed as a single instance (sharding is not allowed). Proxies could be deployed as many instances as needed, each instance should have dedicated IP address and DNS record (if exists). All hosts should be Debian hosts with public IPs. +# [Supabase](https://supabase.com) +Stores list of user configs. Users may generate new user configs (my means of HTML website). Deploymemnt fetch records from there +to render configs for xrays and other components. _The repository with Supabas is not open-source at the moment. It will becore +open-source later_. + ## GH Pages Serves static content: * static html pages with installation instructions which is being developed in a separate repository: @@ -93,11 +98,6 @@ The following GitHub secrets are required for CD: make deploy_proxies deploy_metrics ``` -### Generate user list table -```commandline -make -e DOMAIN= render_users_csv -``` - ### Generate UUID for a new user ```commandline make generate_uuid diff --git a/config/supabase.example.yml b/config/supabase.example.yml new file mode 100644 index 0000000..ac48a94 --- /dev/null +++ b/config/supabase.example.yml @@ -0,0 +1,5 @@ +# supabase `service_role` key (`secret` API key) +config_supabase_api_key: + +# supabase project id +config_supabase_project_id: diff --git a/config/users.example.yml b/config/users.example.yml deleted file mode 100644 index 28cf175..0000000 --- a/config/users.example.yml +++ /dev/null @@ -1,9 +0,0 @@ -config_users: - user1-uuid: - name: user1_name - # optional. preferred server uuid - preferred_server_uuid: server1-uuid - user2-uuid: - name: user2_name - user3-uuid: - name: user3_name diff --git a/diagram.svg b/diagram.svg index 04b5b15..5930d04 100644 --- a/diagram.svg +++ b/diagram.svg @@ -1,4 +1,4 @@ -proxy (instance N-2)proxy (instance N-1)
1. User opens installation instruction
link (one-time action for user)
Static page (index.html) opens in browser
1. User opens installation instruction...
2. Hiddify pulls list of available servers
Hiddify in background fetches list of
servers available for the user
2. Hiddify pulls list of available servers...
proxy (instance N)
xray
xray
node-exporter
node-exporter
nginx
nginx
xray-exporter
xray-exporter
3. Hiddify proxies traffic 
Hiddify proxies traffic via xray
though one of proxy servers which
configuration is provided within
the previous (2) step
3. Hiddify proxies traffic...
User
User
Sends metrics
Sends metrics
CD
CD
Deploys
proxies.yml
Deploys...
Admin
Admin
Monitors
usage
Monitors...
Developer
Devel...
Pushes
to master
Pushes...
GitHub Actions
runner
GitHub Actions...
GitHub
repository
GitHub...
Grafana Cloud
Grafana Cloud
collects metrics
collects metrics
Internet
Internet
Manual
trigger
Manual...
users.json storage
users.json stor...
Makes
updates
Makes...
metrics
prometheus
prometheus
GitHub pages
static html (instructions)
static html (instructions)
vless subscription URLs
vless subscription URLs
Deploys
metrics.yml
Deploys...
Text is not SVG - cannot display
+proxy (instance N-2)proxy (instance N-1)
1. User opens installation instruction
link (one-time action for user)
Static page (index.html) opens in browser
1. User opens installation instruction...
2. Hiddify pulls list of available servers
Hiddify in background fetches list of
servers available for the user
2. Hiddify pulls list of available servers...
proxy (instance N)
xray
xray
node-exporter
node-export...
nginx
nginx
xray-exporter
xray-export...
3. Hiddify proxies traffic 
Hiddify proxies traffic via xray
though one of proxy servers which
configuration is provided within
the previous (2) step
3. Hiddify proxies traffic...
User generates new configs for friends
User generates new configs for friends
User
User
Sends metrics
Sends metrics
CD
CD
Deploys
proxies.yml
Deploys...
Admin
Admin
Monitors
usage
Monitors...
Developer
Devel...
Pushes
to master
Pushes...
GitHub Actions
runner
GitHub Actions...
GitHub
repository
GitHub...
Grafana Cloud
Grafana Cloud
collects metrics
collects metrics
Internet
Internet
Makes
updates
Makes...
metrics
prometheus
prometheus
GitHub pages
static html (instructions)
static html (instructions)
vless subscription URLs
vless subscription URLs
Deploys
metrics.yml
Deploys...
Supabase
users' records
users' records
fetch
user records
fetch...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/proxies.yml b/proxies.yml index 5aee14c..0e62b30 100644 --- a/proxies.yml +++ b/proxies.yml @@ -2,20 +2,37 @@ - proxies no_log: true vars_files: - - ./config/users.yml + - ./config/supabase.yml - ./config/servers.yml vars: # do not worry. these ports are local config_local_xray_metrics_port: 8081 config_local_node_exporter_metrics_port: 8082 config_local_xray_exporter_metrics_port: 8080 + pre_tasks: + - name: Fetch user UUIDs from Supabase + delegate_to: localhost + uri: + url: "https://{{ config_supabase_project_id }}.supabase.co/rest/v1/users?select=child_uuid" + method: GET + headers: + apikey: "{{ config_supabase_api_key }}" + Authorization: "Bearer {{ config_supabase_api_key }}" + register: supabase_response + + - name: Set user UUIDs fact + delegate_to: localhost + set_fact: + config_local_users: "{{ supabase_response.json | map(attribute='child_uuid') | list }}" roles: - role: xray vars: xray_server_uuid: "{{ hosts_server_uuid }}" xray_server: "{{ config_servers[xray_server_uuid] }}" - xray_users: "{{ config_users }}" + xray_users: "{{ config_local_users }}" xray_metrics_port: "{{ config_local_xray_metrics_port }}" + xray_supabase_api_key: "{{ supabase_api_key }}" + xray_supabase_project_id: "{{ supabase_project_id }}" - role: node-exporter vars: node_exporter_port: "{{ config_local_node_exporter_metrics_port }}" diff --git a/roles/users-configs/tasks/main.yml b/roles/users-configs/tasks/main.yml index 9f4cc89..cd0a7f9 100644 --- a/roles/users-configs/tasks/main.yml +++ b/roles/users-configs/tasks/main.yml @@ -40,9 +40,9 @@ dest: "{{ users_configs_static_root_local }}/robots.txt" - name: Render configs - with_items: "{{ users_configs_users | dict2items }}" + with_items: "{{ users_configs_users }}" loop_control: index_var: loop_index vars: - users_configs_user_uuid: "{{ item.key }}" + users_configs_user_uuid: "{{ item }}" include_tasks: render_users_configs.yml diff --git a/roles/users-csv/README.md b/roles/users-csv/README.md deleted file mode 100644 index 4f352a5..0000000 --- a/roles/users-csv/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# users-csv -This role generates CSV file with all instruction link for each user. - -## Mandatory and optional variables -Find them in [./defaults/main.yml](./defaults/main.yml). Empty variables in the file are mandatory, pre-filled variables are optional. diff --git a/roles/users-csv/defaults/main.yml b/roles/users-csv/defaults/main.yml deleted file mode 100644 index a062fb2..0000000 --- a/roles/users-csv/defaults/main.yml +++ /dev/null @@ -1,8 +0,0 @@ -# users object with fields structure as in /users-exaple.yml -users_csv_users: - -# public domain of frontman (with instruction html and config json files) -users_csv_domain: - -# output file name -users_csv_output_file: "users.csv" diff --git a/roles/users-csv/tasks/main.yml b/roles/users-csv/tasks/main.yml deleted file mode 100644 index 38edf4b..0000000 --- a/roles/users-csv/tasks/main.yml +++ /dev/null @@ -1,16 +0,0 @@ -- name: Ensure required variables are defined - assert: - that: - - users_csv_domain is string - - users_csv_output_file is string - -- name: Ensure users_csv_users is defined correctly - include_tasks: tasks/assert-users.yml - vars: - users: "{{ users_csv_users }}" - -- name: Render users.csv - become: false - template: - src: users.csv.j2 - dest: "{{ users_csv_output_file }}" diff --git a/roles/users-csv/templates/users.csv.j2 b/roles/users-csv/templates/users.csv.j2 deleted file mode 100644 index 2af2d2b..0000000 --- a/roles/users-csv/templates/users.csv.j2 +++ /dev/null @@ -1,4 +0,0 @@ -username,uuid,instructions link -{% for user in users_csv_users | dict2items %} -{{ user.value.name }},{{ user.key }},https://{{ users_csv_domain }}#{{ user.key }} -{% endfor %} diff --git a/roles/xray/templates/config.json.j2 b/roles/xray/templates/config.json.j2 index d7fd726..2dd38f1 100644 --- a/roles/xray/templates/config.json.j2 +++ b/roles/xray/templates/config.json.j2 @@ -6,11 +6,11 @@ "protocol": "vless", "settings": { "clients": [ - {% for user in xray_users | dict2items %} + {% for user in xray_users %} { - "email": "{{ user.value.name }}", + "email": "{{ user }}", "flow": "{{ xray_server.flow }}", - "id": "{{ user.key }}" + "id": "{{ user }}" } {% if not loop.last %} , diff --git a/tasks/assert-users.yml b/tasks/assert-users.yml index e0067fe..f4330b5 100644 --- a/tasks/assert-users.yml +++ b/tasks/assert-users.yml @@ -4,6 +4,5 @@ - name: Ensure servers variable is defined correctly assert: that: - - item.value.name is string - - item.value.preferred_server_uuid is not defined or item.value.preferred_server_uuid is string - with_items: "{{ users | dict2items }}" + - item is string + with_items: "{{ users }}" diff --git a/users-configs.yml b/users-configs.yml index ea280b3..c275ab0 100644 --- a/users-configs.yml +++ b/users-configs.yml @@ -4,13 +4,28 @@ vars_files: - ./config/users-configs.yml - ./config/servers.yml - - ./config/users.yml + - ./config/supabase.yml + pre_tasks: + - name: Fetch user UUIDs from Supabase + delegate_to: localhost + uri: + url: "https://{{ config_supabase_project_id }}.supabase.co/rest/v1/users?select=child_uuid" + method: GET + headers: + apikey: "{{ config_supabase_api_key }}" + Authorization: "Bearer {{ config_supabase_api_key }}" + register: supabase_response + + - name: Set user UUIDs fact + delegate_to: localhost + set_fact: + config_local_users: "{{ supabase_response.json | map(attribute='child_uuid') | list }}" roles: - role: users-configs vars: users_configs_default_redirect: "{{ config_users_configs_default_redirect }}" users_configs_servers: "{{ config_servers }}" - users_configs_users: "{{ config_users }}" + users_configs_users: "{{ config_local_users }}" users_configs_static_directory_filename: static users_configs_title: "{{ config_users_title }}" users_configs_support_url: "{{ config_users_support_url }}" diff --git a/users-csv.yml b/users-csv.yml deleted file mode 100644 index f7d201a..0000000 --- a/users-csv.yml +++ /dev/null @@ -1,11 +0,0 @@ -- hosts: - - localhost - no_log: true - vars_files: - - ./config/frontman.yml - - ./config/users.yml - roles: - - role: users-csv - vars: - users_csv_domain: "{{ lookup('env', 'DOMAIN') }}" - users_csv_users: "{{ config_users }}"