From 32b7c39787c98da3c72508c4a923b96855a0a418 Mon Sep 17 00:00:00 2001 From: Ed Asriyan Date: Sat, 18 Jan 2025 13:50:04 -0800 Subject: [PATCH] Switch from GitHub Pages to Cloudflare Pages --- .github/workflows/CD-production-frontman.yml | 64 --------------- .github/workflows/CD-production-task.yml | 7 ++ .github/workflows/CD-production.yml | 11 +-- .gitignore | 3 +- Dockerfile | 2 +- Makefile | 5 +- README.md | 6 +- config/README.md | 2 +- config/frontman.example.yml | 17 ++++ config/users-configs.example.yml | 11 --- diagram.svg | 2 +- users-configs.yml => frontman.yml | 22 ++--- roles/{users-configs => frontman}/README.md | 0 roles/frontman/defaults/main.yml | 29 +++++++ .../files/robots.txt | 0 roles/frontman/tasks/main.yml | 81 +++++++++++++++++++ roles/frontman/tasks/render_configs.yml | 30 +++++++ .../templates/client-xray-config.json.j2 | 20 ++--- .../templates/frontend-config.json.j2 | 0 .../frontman/templates/frontend-link.json.j2 | 4 + roles/frontman/templates/hiddify.j2 | 12 +++ .../templates/index.html.j2 | 4 +- roles/frontman/templates/socks5.Dockerfile.j2 | 3 + roles/frontman/templates/urls-map.json.j2 | 5 ++ roles/frontman/vars/main.yml | 8 ++ roles/users-configs/defaults/main.yml | 23 ------ roles/users-configs/tasks/main.yml | 73 ----------------- roles/users-configs/tasks/render_configs.yml | 30 ------- .../templates/frontend-link.json.j2 | 4 - roles/users-configs/templates/hiddify.j2 | 13 --- .../templates/socks5.Dockerfile.j2 | 3 - .../users-configs/templates/urls-map.json.j2 | 5 -- roles/users-configs/vars/main.yml | 8 -- 33 files changed, 230 insertions(+), 277 deletions(-) delete mode 100644 .github/workflows/CD-production-frontman.yml create mode 100644 config/frontman.example.yml delete mode 100644 config/users-configs.example.yml rename users-configs.yml => frontman.yml (63%) rename roles/{users-configs => frontman}/README.md (100%) create mode 100644 roles/frontman/defaults/main.yml rename roles/{users-configs => frontman}/files/robots.txt (100%) create mode 100644 roles/frontman/tasks/main.yml create mode 100644 roles/frontman/tasks/render_configs.yml rename roles/{users-configs => frontman}/templates/client-xray-config.json.j2 (77%) rename roles/{users-configs => frontman}/templates/frontend-config.json.j2 (100%) create mode 100644 roles/frontman/templates/frontend-link.json.j2 create mode 100644 roles/frontman/templates/hiddify.j2 rename roles/{users-configs => frontman}/templates/index.html.j2 (84%) create mode 100644 roles/frontman/templates/socks5.Dockerfile.j2 create mode 100644 roles/frontman/templates/urls-map.json.j2 create mode 100644 roles/frontman/vars/main.yml delete mode 100644 roles/users-configs/defaults/main.yml delete mode 100644 roles/users-configs/tasks/main.yml delete mode 100644 roles/users-configs/tasks/render_configs.yml delete mode 100644 roles/users-configs/templates/frontend-link.json.j2 delete mode 100644 roles/users-configs/templates/hiddify.j2 delete mode 100644 roles/users-configs/templates/socks5.Dockerfile.j2 delete mode 100644 roles/users-configs/templates/urls-map.json.j2 delete mode 100644 roles/users-configs/vars/main.yml diff --git a/.github/workflows/CD-production-frontman.yml b/.github/workflows/CD-production-frontman.yml deleted file mode 100644 index c79b3ca..0000000 --- a/.github/workflows/CD-production-frontman.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: CD | Production Frontman - -concurrency: - group: production-frontman - cancel-in-progress: true - -on: - workflow_dispatch: - workflow_call: - -permissions: - contents: read - pages: write - id-token: write - -jobs: - deploy-frontman: - name: Deploy on production - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Render USERS_CONFIGS secret into config/users_configs.yml - env: - USERS_CONFIGS: ${{ secrets.USERS_CONFIGS }} - shell: bash - run: | - echo "$USERS_CONFIGS" > config/users-configs.yml - - - name: Render SERVERS secret into config/servers.yml - env: - SERVERS: ${{ secrets.SERVERS }} - shell: bash - run: | - echo "$SERVERS" > config/servers.yml - - - name: Render SUPABASE secret into config/supabase.yml - env: - SUPABASE: ${{ secrets.SUPABASE }} - shell: bash - run: | - echo "$SUPABASE" > config/supabase.yml - - - name: Run playbook - shell: bash - run: make render_users_configs - - - name: Setup Pages - uses: actions/configure-pages@v3 - - - name: Upload artifact - uses: actions/upload-pages-artifact@v1 - with: - path: 'static' - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v2 - - - uses: geekyeggo/delete-artifact@v2 - if: always() - with: - name: github-pages - failOnError: false diff --git a/.github/workflows/CD-production-task.yml b/.github/workflows/CD-production-task.yml index 981cedd..3d4c707 100644 --- a/.github/workflows/CD-production-task.yml +++ b/.github/workflows/CD-production-task.yml @@ -65,6 +65,13 @@ jobs: run: | echo "$SUPABASE" > config/supabase.yml + - name: Render FRONTMAN secret into config/frontman.yml + env: + FRONTMAN: ${{ secrets.FRONTMAN }} + shell: bash + run: | + echo "$FRONTMAN" > config/frontman.yml + - name: Run playbook shell: bash run: make ${{ inputs.tasks }} diff --git a/.github/workflows/CD-production.yml b/.github/workflows/CD-production.yml index 81586a0..482ee5a 100644 --- a/.github/workflows/CD-production.yml +++ b/.github/workflows/CD-production.yml @@ -10,11 +10,6 @@ on: - master workflow_dispatch: -permissions: - contents: read - pages: write - id-token: write - jobs: deploy-proxies: name: Deploy on production @@ -24,11 +19,7 @@ jobs: task: - deploy_metrics - deploy_proxies + - deploy_frontman with: tasks: ${{ matrix.task }} secrets: inherit - - deploy-frontman: - name: Deploy on production - uses: ./.github/workflows/CD-production-frontman.yml - secrets: inherit diff --git a/.gitignore b/.gitignore index 6bcd13a..c396e3b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,8 @@ vault.txt users.csv id_rsa id_rsa.pub -config/users-configs.yml +known_hosts +config/frontman.yml config/metrics.yml config/servers.yml config/supabase.yml diff --git a/Dockerfile b/Dockerfile index ce99d49..26dd5b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,2 +1,2 @@ FROM alpine/ansible -RUN apk add --no-cache curl make rsync +RUN apk add --no-cache curl make rsync nodejs npm diff --git a/Makefile b/Makefile index 89a337c..bd6fc71 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ USERS_CSV_FILE = users.csv PLAYBOOK_FILE_METRIX = metrics.yml PLAYBOOK_FILE_PROXIES = proxies.yml PLAYBOOK_FILE_USERS_CSV = users-csv.yml -PLAYBOOK_FILE_USERS_CONFIGS = users-configs.yml +PLAYBOOK_FILE_FRONTMAN = frontman.yml HOSTS_FILE = inventory/hosts hosts_encrypt: @@ -11,9 +11,6 @@ hosts_encrypt: hosts_decrypt: ansible-vault decrypt $(HOSTS_FILE) -render_users_configs: - ansible-playbook $(PLAYBOOK_FILE_USERS_CONFIGS) - deploy_frontman: ansible-playbook $(PLAYBOOK_FILE_FRONTMAN) diff --git a/README.md b/README.md index f1f0c3a..62094b1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ https://hiddify.com#app # Architecture ![digram](./diagram.svg) -There are 4 componets: **GH Pages**, **[Supabase](https://supabase.com) instance**, **metrics** and **proxy**. GH Actions that must be configured for this repository. +There are 4 componets: **Cloudflare 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. @@ -16,7 +16,7 @@ Stores list of user configs. Users may generate new user configs (my means of HT 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 +## Cloudflare Pages Serves static content: * static html pages with installation instructions which is being developed in a separate repository: [xray-server-frontend](https://github.com/ed-asriyan/xray-server-frontend). The user is provided with a private instruction link @@ -26,7 +26,7 @@ ShadowSocks client each time before connecting to a ShadowSocks server * personal vless [subscription files](https://hiddify.com/app/URL-Scheme) for each client, which is used by Hiddify to refresh list of available servers -Playbook: [users-configs.yml](./users-configs.yml). It just renders files locally, the should be uploaded got GitHub Pages using +Playbook: [frontman.yml](./frontman.yml). It just renders files locally, the should be uploaded got Cloudflare Pages using Actions. ## Metrics diff --git a/config/README.md b/config/README.md index 0c2b850..e93a95b 100644 --- a/config/README.md +++ b/config/README.md @@ -4,7 +4,7 @@ This directory contains configuration files. ## How to edit ### If you use GitHub Actions Create the following secrets: -* `USERS_CONFIGS`: copy content of [users-configs.example.yml](./users-configs.example.yml) to the secret and fill out each variable +* `FRONTMAN`: copy content of [frontman.example.yml](./frontman.example.yml) to the secret and fill out each variable * `SERVERS`: copy content of [servers.example.yml](./servers.example.yml) to the secret and fill out each variable * `HOSTS`: copy content of [hosts.example.yml](./hosts.example.yml) to the secret and fill out each variable * `METRICS`: copy content of [metrics.example.yml](./metrics.example.yml) to the secret and fill out each variable diff --git a/config/frontman.example.yml b/config/frontman.example.yml new file mode 100644 index 0000000..0bfc409 --- /dev/null +++ b/config/frontman.example.yml @@ -0,0 +1,17 @@ +# where redirect to if user opened index page without valid parameters +config_frontman_default_redirect: + +# title users should we when open hiddify +config_users_title: + +# url where frontman is hosted +config_users_base_url: + +# clouflare pages project name +config_frontman_cloudflare_project_name: + +# cloudflare account id +config_frontman_cloudflare_account_id: + +# cloudflare api token with Account -> Cloudflare Pages -> Write permissions. create at https://dash.cloudflare.com/profile/api-tokens +config_frontman_cloudflare_api_token: diff --git a/config/users-configs.example.yml b/config/users-configs.example.yml deleted file mode 100644 index 74d443d..0000000 --- a/config/users-configs.example.yml +++ /dev/null @@ -1,11 +0,0 @@ -# where redirect to if user opened index page without valid parameters -config_users_configs_default_redirect: - -# title users should we when open hiddify -config_users_title: - -# support url. see https://hiddify.com/app/URL-Scheme -config_users_support_url: - -# url where frontman is hosted -config_users_base_url: diff --git a/diagram.svg b/diagram.svg index 47d78e7..59abe06 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-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
+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
Cloudflare 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
diff --git a/users-configs.yml b/frontman.yml similarity index 63% rename from users-configs.yml rename to frontman.yml index 4191202..79488b6 100644 --- a/users-configs.yml +++ b/frontman.yml @@ -2,7 +2,7 @@ - localhost no_log: true vars_files: - - ./config/users-configs.yml + - ./config/frontman.yml - ./config/servers.yml - ./config/supabase.yml pre_tasks: @@ -36,13 +36,15 @@ set_fact: config_local_users: "{{ supabase_users_response.json | map(attribute='child_uuid') | list }}" roles: - - role: users-configs + - role: frontman vars: - users_configs_default_redirect: "{{ config_users_configs_default_redirect }}" - users_configs_servers: "{{ config_servers }}" - users_configs_configs: "{{ config_local_configs }}" - 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 }}" - users_configs_base_url: "{{ config_users_base_url }}" + frontman_default_redirect: "{{ config_frontman_default_redirect }}" + frontman_servers: "{{ config_servers }}" + frontman_configs: "{{ config_local_configs }}" + frontman_users: "{{ config_local_users }}" + frontman_static_directory_filename: static + frontman_title: "{{ config_users_title }}" + frontman_base_url: "{{ config_users_base_url }}" + frontman_cloudflare_project_name: "{{ config_frontman_cloudflare_project_name }}" + frontman_cloudflare_account_id: "{{ config_frontman_cloudflare_account_id }}" + frontman_cloudflare_api_token: "{{ config_frontman_cloudflare_api_token }}" diff --git a/roles/users-configs/README.md b/roles/frontman/README.md similarity index 100% rename from roles/users-configs/README.md rename to roles/frontman/README.md diff --git a/roles/frontman/defaults/main.yml b/roles/frontman/defaults/main.yml new file mode 100644 index 0000000..ccc10a4 --- /dev/null +++ b/roles/frontman/defaults/main.yml @@ -0,0 +1,29 @@ +# where redirect to if user opened index page without paramneters +frontman_default_redirect: + +# users as described in /users-example.yml +frontman_users: + +# files with redirect url +frontman_configs: + +# servers object as described in /servers-example.yml +frontman_servers: + +# relative path of directory where static content should be stored +frontman_static_directory_filename: + +# title users should we when open hiddify +frontman_title: + +# url where frontman is hosted +frontman_base_url: + +# clouflare pages project name +frontman_cloudflare_project_name: + +# cloudflare account id +frontman_cloudflare_account_id: + +# cloudflare api token with Account -> Cloudflare Pages -> Write permissions. create at https://dash.cloudflare.com/profile/api-tokens +frontman_cloudflare_api_token: diff --git a/roles/users-configs/files/robots.txt b/roles/frontman/files/robots.txt similarity index 100% rename from roles/users-configs/files/robots.txt rename to roles/frontman/files/robots.txt diff --git a/roles/frontman/tasks/main.yml b/roles/frontman/tasks/main.yml new file mode 100644 index 0000000..fc4a49b --- /dev/null +++ b/roles/frontman/tasks/main.yml @@ -0,0 +1,81 @@ +- name: Ensure required variables are defined + assert: + that: + - frontman_default_redirect is string + - frontman_title is string + - frontman_cloudflare_project_name is string + - frontman_cloudflare_account_id is string + - frontman_cloudflare_api_token is string + +- name: Ensure frontman_users is defined correctly + include_tasks: tasks/assert-users.yml + vars: + users: "{{ frontman_users }}" + +- name: Ensure frontman_configs is defined correctly + include_tasks: tasks/assert-configs.yml + vars: + configs: "{{ frontman_configs }}" + +- name: Ensure frontman_servers is defined correctly + include_tasks: tasks/assert-servers.yml + vars: + servers: "{{ frontman_servers }}" + +- set_fact: + frontman_static_root_local: "./{{ frontman_static_directory_filename }}" + frontman_frontend_name: "{{ lookup('community.general.random_string', length=32, special=False) }}" + +- name: Create static directory locally + file: + path: "{{ frontman_static_root_local }}" + state: directory + +- name: Render index.html + template: + src: index.html.j2 + dest: "{{ frontman_static_root_local }}/index.html" + +- name: Create frontend directory locally + file: + path: "{{ frontman_static_root_local }}/{{ frontman_frontend_name }}" + state: directory + +- name: Render frontend.html + get_url: + url: "{{ frontman_frontend_html_url }}" + dest: "{{ frontman_static_root_local }}/{{ frontman_frontend_name }}/index.html" + +- name: Render frontend config + template: + src: frontend-config.json.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_frontend_name }}/config.json" + +- name: Copy robots.txt + copy: + src: robots.txt + dest: "{{ frontman_static_root_local }}/robots.txt" + +- name: Render configs + with_items: "{{ frontman_configs }}" + loop_control: + index_var: loop_index + vars: + frontman_config_uuid: "{{ item }}" + include_tasks: render_configs.yml + +- name: Render redirect configs + with_items: "{{ frontman_users }}" + loop_control: + index_var: loop_index + vars: + frontman_user_uuid: "{{ item }}" + template: + src: frontend-link.json.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_user_uuid }}.json" + +- name: Upload static files to Cloudflare Pages + command: "npx wrangler pages deploy {{ frontman_static_root_local }} --project-name={{ frontman_cloudflare_project_name }} --branch main" + environment: + CLOUDFLARE_ACCOUNT_ID: "{{ frontman_cloudflare_account_id }}" + CLOUDFLARE_API_TOKEN: "{{ frontman_cloudflare_api_token }}" diff --git a/roles/frontman/tasks/render_configs.yml b/roles/frontman/tasks/render_configs.yml new file mode 100644 index 0000000..264a84a --- /dev/null +++ b/roles/frontman/tasks/render_configs.yml @@ -0,0 +1,30 @@ + +- name: Create user's directory + file: + path: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}" + state: directory + +- name: Render hiddify config + template: + src: hiddify.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}/{{ frontman_hiddify_filename }}" + +- name: Render hiddify config (index.html for backward compatibility) + template: + src: hiddify.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}/index.html" + +- name: Render xray-client config + template: + src: client-xray-config.json.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}/{{ frontman_client_xray_config_filename }}" + +- name: Render sock5.Dockerfile + template: + src: socks5.Dockerfile.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}/{{ frontman_socks5_docker_filename }}" + +- name: Render urls map + template: + src: urls-map.json.j2 + dest: "{{ frontman_static_root_local }}/{{ frontman_config_uuid }}/{{ frontman_urls_map_filename }}" diff --git a/roles/users-configs/templates/client-xray-config.json.j2 b/roles/frontman/templates/client-xray-config.json.j2 similarity index 77% rename from roles/users-configs/templates/client-xray-config.json.j2 rename to roles/frontman/templates/client-xray-config.json.j2 index 7bf1f07..68406cd 100644 --- a/roles/users-configs/templates/client-xray-config.json.j2 +++ b/roles/frontman/templates/client-xray-config.json.j2 @@ -16,39 +16,39 @@ } ], "outbounds": [ - {% for server_item in users_configs_servers | dict2items %} - {% set users_configs_server_uuid = server_item.key %} - {% set users_configs_server = server_item.value %} + {% for server_item in frontman_servers | dict2items %} + {% set frontman_server_uuid = server_item.key %} + {% set frontman_server = server_item.value %} {% set server_index = loop.index %} - {% for sni, fingerprint in users_configs_server.supported_snis | product(users_configs_server.fingerprints) %} + {% for sni, fingerprint in frontman_server.supported_snis | product(frontman_server.fingerprints) %} { "protocol": "vless", "sendThrough": "0.0.0.0", "settings": { "vnext": [ { - "address": "{{ users_configs_server.host }}", - "port": {{ users_configs_server.port }}, + "address": "{{ frontman_server.host }}", + "port": {{ frontman_server.port }}, "users": [ { - "id": "{{ users_configs_config_uuid }}", + "id": "{{ frontman_config_uuid }}", "encryption": "none", - "flow": "{{ users_configs_server.flow }}", + "flow": "{{ frontman_server.flow }}", "level": 0 } ] } ] }, - "tag": "outbound-vless-{{ server_index }}-{{ loop.index }}-{{ users_configs_server.name | urlencode }}", + "tag": "outbound-vless-{{ server_index }}-{{ loop.index }}-{{ frontman_server.name | urlencode }}", "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "fingerprint": "{{ fingerprint }}", "serverName": "{{ sni }}", - "publicKey": "{{ users_configs_server.public_key }}", + "publicKey": "{{ frontman_server.public_key }}", "spiderX": "/&", "shortId": "" } diff --git a/roles/users-configs/templates/frontend-config.json.j2 b/roles/frontman/templates/frontend-config.json.j2 similarity index 100% rename from roles/users-configs/templates/frontend-config.json.j2 rename to roles/frontman/templates/frontend-config.json.j2 diff --git a/roles/frontman/templates/frontend-link.json.j2 b/roles/frontman/templates/frontend-link.json.j2 new file mode 100644 index 0000000..4c3bd17 --- /dev/null +++ b/roles/frontman/templates/frontend-link.json.j2 @@ -0,0 +1,4 @@ +{ + {% set instruction_url = '/' + frontman_frontend_name + '#' + frontman_user_uuid %} + "{{ frontman_instruction_url_field_name }}": "{{ instruction_url }}" +} diff --git a/roles/frontman/templates/hiddify.j2 b/roles/frontman/templates/hiddify.j2 new file mode 100644 index 0000000..b26c284 --- /dev/null +++ b/roles/frontman/templates/hiddify.j2 @@ -0,0 +1,12 @@ +#profile-title: {{ frontman_title }} +#profile-update-interval: 1 + +{% for server_item in frontman_servers | dict2items %} +{% set frontman_server_uuid = server_item.key %} +{% set frontman_server = server_item.value %} +{% set server_index = loop.index %} + +{% for sni, fingerprint in frontman_server.supported_snis | product(frontman_server.fingerprints) %} +vless://{{ frontman_config_uuid }}@{{ frontman_server.host }}:{{ frontman_server.port }}?type=tcp&security=reality&pbk={{ frontman_server.public_key }}&fp={{ fingerprint }}&sni={{ sni }}&spx=%2F&flow={{ frontman_server.flow }}#{{ server_index }}.{{ loop.index }}.%20{{ frontman_server.name | urlencode }} +{% endfor %} +{% endfor %} diff --git a/roles/users-configs/templates/index.html.j2 b/roles/frontman/templates/index.html.j2 similarity index 84% rename from roles/users-configs/templates/index.html.j2 rename to roles/frontman/templates/index.html.j2 index a7cdb9c..437896a 100644 --- a/roles/users-configs/templates/index.html.j2 +++ b/roles/frontman/templates/index.html.j2 @@ -6,7 +6,7 @@