Skip to content

Commit d42f598

Browse files
authored
Merge pull request #2 from AlchemyLink/feature/singbox-role-refactor
Feature/singbox role refactor
2 parents 258c87b + 4a15416 commit d42f598

13 files changed

Lines changed: 352 additions & 274 deletions

File tree

.gitignore

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
# Secrets — never commit real credentials
12
vault_password.txt
3+
**/secrets.yml
4+
**/vault_password.txt
5+
**/*.secret
6+
**/*.vault
7+
28
.vscode
39
.ansible
410
roles/hosts.yml
5-
roles/sing-box/defaults/secrets.yml
6-
roles/sing-box-playbook/defaults/secrets.yml
7-
roles/hosts.yml
8-
roles/xray/defaults/secrets.yml
9-
roles/xray/defaults/vic_secret.yml
1011

1112
# Generated by tests/run.sh
1213
tests/.cache/
1314
tests/.output/
1415
tests/fixtures/test_secrets.yml
1516

17+
18+
CLAUDE.md

roles/sing-box-playbook/defaults/main.yml

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Default variables for the sing-box role with Hysteria2
33

44
# --- Sing-box Download Variables ---
5-
singbox_version: "1.12.21"
5+
singbox_version: "1.13.3"
66
singbox_auto_update: true
77
singbox_repo: "SagerNet/sing-box"
88
singbox_architecture: "amd64" # Options: amd64, arm64, armv7
@@ -12,16 +12,9 @@ singbox_config_dir: "/etc/sing-box"
1212
singbox_user: "nobody"
1313

1414
# --- DNS Settings ---
15-
singbox_dns_servers:
16-
- tag: "google"
17-
address: "tls://8.8.8.8"
18-
strategy: "prefer_ipv4"
19-
- tag: "cloudflare"
20-
address: "tls://1.1.1.1"
21-
strategy: "prefer_ipv4"
22-
- tag: "local"
23-
address: "local"
24-
detour: "direct"
15+
# sing-box 1.12+ format: type + server fields (address: prefix is legacy)
16+
singbox_dns_strategy: "prefer_ipv4" # global: prefer_ipv4, prefer_ipv6, ipv4_only, ipv6_only
17+
singbox_dns_final: "local" # default server tag when no rule matches
2518

2619
# --- Log Settings ---
2720
singbox_log_disabled: false
@@ -93,4 +86,15 @@ singbox_geosite_enabled: true
9386
singbox_geosite_url: "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
9487
singbox_geosite_path: "/etc/sing-box/geosite.db"
9588

89+
# --- Raven-subscribe integration ---
90+
# When enabled, Raven-subscribe will sync Hysteria2 users from sing-box config.
91+
# This variable is consumed by the xray role's raven-subscribe/config.json.j2 template.
92+
# Set raven_subscribe_singbox_config to point to sing-box config file.
93+
# Set raven_subscribe_singbox_enabled: true to activate sync.
94+
#
95+
# These variables are only effective when both roles (xray + sing-box) are deployed together.
96+
# If deploying sing-box standalone, configure Raven manually.
97+
raven_subscribe_singbox_config: "{{ singbox_config_dir }}/config.json"
98+
raven_subscribe_singbox_enabled: true
99+
96100
# --- System Packages ---
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
# secrets.yml — encrypt with ansible-vault:
3+
# ansible-vault encrypt roles/sing-box-playbook/defaults/secrets.yml
4+
5+
# --- Hysteria2 users ---
6+
# At least one user required.
7+
singbox_hysteria2_users:
8+
- name: "user@example.com"
9+
password: "change-me-strong-password"
10+
11+
# --- Obfuscation (required when singbox_hysteria2_obfs_enabled: true) ---
12+
singbox_hysteria2_obfs_password: "change-me-obfs-password"
13+
14+
# --- TLS / ACME ---
15+
singbox:
16+
tls_enabled: true
17+
tls_server_name: "your-server.com" # Public domain pointing to this server
18+
tls_acme_domain: "your-server.com" # Domain for Let's Encrypt certificate
19+
tls_acme_email: "admin@your-server.com" # Email for Let's Encrypt notifications
20+
tls_acme_provider: "letsencrypt" # letsencrypt or zerossl
21+
tls_acme_data_directory: "/etc/sing-box/acme"
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
11
# handlers/main.yml
2-
# Handlers for the sing-box role
2+
# IMPORTANT: Ansible executes handlers in definition order, not notification order.
3+
# Validate must come BEFORE Restart so invalid configs are caught before reload.
4+
5+
- name: Validate sing-box config
6+
ansible.builtin.command:
7+
cmd: "{{ singbox_install_dir }}/sing-box check -c {{ singbox_config_dir }}/config.json"
8+
register: singbox_validate_result
9+
changed_when: false
10+
failed_when: singbox_validate_result.rc != 0
11+
when: ansible_facts['service_mgr'] in ['systemd', 'openrc']
312

413
- name: Reload systemd and restart sing-box
514
ansible.builtin.systemd:
615
daemon_reload: true
716
name: sing-box
817
state: restarted
918
enabled: true
19+
when: ansible_facts['service_mgr'] == "systemd"
1020
listen: "Reload systemd and restart sing-box"
1121

1222
- name: Restart sing-box service
1323
ansible.builtin.systemd:
1424
name: sing-box
1525
state: restarted
26+
daemon_reload: true
27+
when: ansible_facts['service_mgr'] == "systemd"
1628
listen: "Restart sing-box service"
1729

1830
- name: Reload sing-box configuration
1931
ansible.builtin.systemd:
2032
name: sing-box
2133
state: reloaded
34+
when: ansible_facts['service_mgr'] == "systemd"
2235
listen: "Reload sing-box configuration"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
- name: sing-box | Create configuration directory
3+
ansible.builtin.file:
4+
path: "{{ singbox_config_dir }}"
5+
state: directory
6+
owner: root
7+
group: root
8+
mode: "0755"
9+
10+
- name: sing-box | Create ACME certificate directory
11+
ansible.builtin.file:
12+
path: "{{ singbox.tls_acme_data_directory }}"
13+
state: directory
14+
owner: root
15+
group: root
16+
mode: "0700"
17+
when: singbox.tls_enabled | default(true)
18+
19+
- name: sing-box | Create log directory
20+
ansible.builtin.file:
21+
path: "{{ singbox_log_output | dirname }}"
22+
state: directory
23+
owner: root
24+
group: root
25+
mode: "0755"
26+
27+
- name: sing-box | Download GeoIP database
28+
ansible.builtin.get_url:
29+
url: "{{ singbox_geoip_url }}"
30+
dest: "{{ singbox_geoip_path }}"
31+
mode: "0644"
32+
timeout: 300
33+
when: singbox_geoip_enabled
34+
35+
- name: sing-box | Download GeoSite database
36+
ansible.builtin.get_url:
37+
url: "{{ singbox_geosite_url }}"
38+
dest: "{{ singbox_geosite_path }}"
39+
mode: "0644"
40+
timeout: 300
41+
when: singbox_geosite_enabled
42+
43+
- name: sing-box | Generate configuration from template
44+
ansible.builtin.template:
45+
src: config.json.j2
46+
dest: "{{ singbox_config_dir }}/config.json"
47+
owner: root
48+
group: root
49+
mode: "0644"
50+
validate: "{{ singbox_install_dir }}/sing-box check -c %s"
51+
notify: Restart sing-box service
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
- name: sing-box | Get latest release from GitHub
3+
ansible.builtin.uri:
4+
url: "https://api.github.com/repos/{{ singbox_repo }}/releases/latest"
5+
return_content: true
6+
headers:
7+
Accept: "application/vnd.github.v3+json"
8+
register: singbox_latest_release
9+
when: singbox_auto_update
10+
ignore_errors: true
11+
12+
- name: sing-box | Set version from latest release
13+
ansible.builtin.set_fact:
14+
singbox_version: "{{ singbox_latest_release.json.tag_name | default(singbox_version) | regex_replace('^v', '') }}"
15+
when: singbox_auto_update and singbox_latest_release is succeeded
16+
17+
- name: sing-box | Display version to be installed
18+
ansible.builtin.debug:
19+
msg: "Installing sing-box version: {{ singbox_version }}"
20+
21+
- name: sing-box | Create installation directory
22+
ansible.builtin.file:
23+
path: "{{ singbox_install_dir }}"
24+
state: directory
25+
mode: "0755"
26+
27+
- name: sing-box | Download archive
28+
ansible.builtin.get_url:
29+
url: "{{ singbox_url }}/v{{ singbox_version }}/sing-box-{{ singbox_version }}-linux-{{ singbox_architecture }}.tar.gz"
30+
dest: "/tmp/sing-box-{{ singbox_version }}.tar.gz"
31+
mode: "0644"
32+
timeout: 300
33+
34+
- name: sing-box | Extract archive
35+
ansible.builtin.unarchive:
36+
src: "/tmp/sing-box-{{ singbox_version }}.tar.gz"
37+
dest: "/tmp"
38+
remote_src: true
39+
40+
- name: sing-box | Install binary
41+
ansible.builtin.copy:
42+
src: "/tmp/sing-box-{{ singbox_version }}-linux-{{ singbox_architecture }}/sing-box"
43+
dest: "{{ singbox_install_dir }}/sing-box"
44+
remote_src: true
45+
mode: "0755"
46+
owner: root
47+
group: root
48+
49+
- name: sing-box | Clean up downloaded files
50+
ansible.builtin.file:
51+
path: "{{ item }}"
52+
state: absent
53+
loop:
54+
- "/tmp/sing-box-{{ singbox_version }}.tar.gz"
55+
- "/tmp/sing-box-{{ singbox_version }}-linux-{{ singbox_architecture }}"
56+
57+
- name: sing-box | Verify installation
58+
ansible.builtin.command: "{{ singbox_install_dir }}/sing-box version"
59+
register: singbox_version_output
60+
changed_when: false
61+
62+
- name: sing-box | Display installed version
63+
ansible.builtin.debug:
64+
msg: "{{ singbox_version_output.stdout }}"

0 commit comments

Comments
 (0)