Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev to main - 21102024 #9

Merged
merged 21 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Check out the codebase.
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
path: 'v-kamerdinerov.marzban-haproxy-ansible'

- name: Set up Python 3.
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.x'

Expand Down
2 changes: 1 addition & 1 deletion group_vars/marzban/marzban.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ marzban_domain: example-domain.com
marzban_panel_uri: "panel.{{ marzban_domain }}"

# SNI for traffic masking
marzban_sni: "discord.com"
marzban_sni: "awesome.sni"

# Login credentials for panel access
marzban_panel_login: "admin"
Expand Down
3 changes: 3 additions & 0 deletions roles/common/tasks/cert.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
when: item.key.endswith('.cert')
register: _ca_certificates_copied
notify: Update ca-certificates

- name: Flush handlers
meta: flush_handlers
9 changes: 3 additions & 6 deletions roles/common/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
- name: SSH
include_tasks: ssh_port.yml
tags: ssh
- name: Common
include_tasks: common.yml
tags: common
# loop: "{{ groups['marzban'] }}"
# loop_control:
# loop_var: host
- name: Limits
include_tasks: limits.yml
tags: limits
Expand All @@ -14,9 +14,6 @@
- name: Certificate
include_tasks: cert.yml
tags: certificate
- name: SSH
include_tasks: ssh_port.yml
tags: ssh
- name: Kernel
include_tasks: kernel.yml
tags: kernel
Expand Down
7 changes: 7 additions & 0 deletions roles/common/tasks/ssh_port.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@
- 'ansible_distribution'
- 'ansible_distribution_major_version'

- name: "Common | SSH | Ensure ssh enabled and started"
become: true
service:
name: ssh
state: started
enabled: true

# We notified "Restart sshd" if we modified the sshd config.
# By calling flush_handlers, we make sure the handler is run *right now*
- name: "Common | SSH | Ensure SSH is reloaded if need be"
Expand Down
7 changes: 7 additions & 0 deletions roles/marzban/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ marzban_system_dirs:
- vault_dir: "/opt/marzban/credentials"
- work_dir: "/var/lib/marzban"
- certs_dir: "/var/lib/marzban/certs"
- templates_dir: "/var/lib/marzban/templates"

marzban_node_dirs:
- base_dir: "/opt/marzban"
Expand All @@ -13,8 +14,10 @@ marzban_node_dirs:
marzban_ssl_certfile: "{{ vault_ssl_certs.keys() | select('search', 'cert') | list | first }}"
marzban_ssl_keyfile: "{{ vault_ssl_certs.keys() | select('search', 'key') | list | first }}"

marzban_image: "gozargah/marzban"
marzban_image_tag: "latest"

marzban_haproxy_image: "haproxy"
marzban_haproxy_image_tag: "2.4.25"
marzban_haproxy_dirs:
- etc_dir: "/etc/haproxy"
Expand Down Expand Up @@ -82,6 +85,7 @@ marzban_docs: false
### Mysql(mariadb) configuration

marzban_mysql_instance: false
marzban_mysql_image: "mariadb"
marzban_mysql_image_tag: "lts"
marzban_mysql_db_name: "marzban"
marzban_mysql_user_name: "marzban"
Expand All @@ -104,3 +108,6 @@ marzban_backup_cron: { minute: "0", hour: "2", day: "*", month: "*", weekday: "*
marzban_ssl_node_path: "/var/lib/marzban-node/ssl_client_cert.pem"
marzban_ssl_node_certificate: ""
marzban_nodes_host_info: ""

marzban_node_image: "gozargah/marzban-node"
marzban_node_image_tag: "latest"
535 changes: 535 additions & 0 deletions roles/marzban/files/index.html

Large diffs are not rendered by default.

170 changes: 85 additions & 85 deletions roles/marzban/files/marzban_backup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,114 +25,114 @@ HOSTNAME_NODE=$(hostname)

# Logging function with levels and colors
log() {
LEVEL="$1"
MSG="$2"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
case "${LEVEL}" in
INFO)
printf "[${TIMESTAMP}] [${FontColor_Green}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
WARN)
printf "[${TIMESTAMP}] [${FontColor_Yellow}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
ERROR)
printf "[${TIMESTAMP}] [${FontColor_Red}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE" >&2
;;
*)
printf "[${TIMESTAMP}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
esac
LEVEL="$1"
MSG="$2"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
case "${LEVEL}" in
INFO)
printf "[${TIMESTAMP}] [${FontColor_Green}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
WARN)
printf "[${TIMESTAMP}] [${FontColor_Yellow}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
ERROR)
printf "[${TIMESTAMP}] [${FontColor_Red}${LEVEL}${FontColor_Suffix}] %s\n" "${MSG}" | tee -a "$LOG_FILE" >&2
;;
*)
printf "[${TIMESTAMP}] %s\n" "${MSG}" | tee -a "$LOG_FILE"
;;
esac
}

# Function to create backup directory
create_backup_dir() {
if [ ! -d "$BACKUP_DIR" ]; then
log INFO "Creating backup directory: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
fi
if [ ! -d "$BACKUP_DIR" ]; then
log INFO "Creating backup directory: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
fi
}

# Function to backup directories
backup_directories() {
create_backup_dir
BACKUP_PATH="$BACKUP_DIR/backup_$CURRENT_DATE"
log INFO "Backing up directories to $BACKUP_PATH"
create_backup_dir
BACKUP_PATH="$BACKUP_DIR/backup_$CURRENT_DATE"
log INFO "Backing up directories to $BACKUP_PATH"

# Create directory structure for backup
mkdir -p "$BACKUP_PATH/lib"
mkdir -p "$BACKUP_PATH/opt"
# Create directory structure for backup
mkdir -p "$BACKUP_PATH/lib"
mkdir -p "$BACKUP_PATH/opt"

# Backup contents
cp -r $LIB_SRC_DIR "$BACKUP_PATH/lib/" || log WARN "Failed to backup lib directory."
cp -r $OPT_SRC_DIR "$BACKUP_PATH/opt/" || log WARN "Failed to backup opt directory."
# Backup contents
cp -r $LIB_SRC_DIR "$BACKUP_PATH/lib/" || log WARN "Failed to backup lib directory."
cp -r $OPT_SRC_DIR "$BACKUP_PATH/opt/" || log WARN "Failed to backup opt directory."

log INFO "Directories backed up successfully."
log INFO "Directories backed up successfully."
}

# Function to backup MySQL databases
backup_databases() {
if grep -q "SQLALCHEMY_DATABASE_URL" "$ENV_FILE" && ! grep -q "sqlite" "$ENV_FILE"; then
# Fixed user root
DB_USER="root"

# Extract root password from environment file
DB_PASSWORD=$(grep -oP '(?<=ROOT_PASSWORD=).*' "$ENV_FILE")

# Install mysqldump if not installed
if ! command -v mysqldump &> /dev/null; then
log WARN "mysqldump not found, installing..."
apt-get update && apt-get install -y mysql-client || log ERROR "Failed to install mysql-client."
fi

# Dump databases
DB_BACKUP_PATH="$BACKUP_PATH/db-backup"
mkdir -p "$DB_BACKUP_PATH"

# Get the list of databases and exclude system databases
databases=$(mysql -h 127.0.0.1 --user="$DB_USER" --password="$DB_PASSWORD" -e "SHOW DATABASES;" | tr -d "| " | grep -v -E 'Database|information_schema|mysql|performance_schema|sys')

for db in $databases; do
log INFO "Dumping database: $db"
# Use additional parameters to avoid errors
mysqldump -h 127.0.0.1 --force --opt --user="$DB_USER" --password="$DB_PASSWORD" --single-transaction --skip-lock-tables --no-tablespaces --databases "$db" > "$DB_BACKUP_PATH/$db.sql" || log ERROR "Getting some error while dump database: $db"
done
log INFO "Databases dumped successfully."
else
log INFO "SQLite detected or SQLALCHEMY_DATABASE_URL not found. No MySQL databases to backup."
fi
if grep -q "SQLALCHEMY_DATABASE_URL" "$ENV_FILE" && ! grep -q "sqlite" "$ENV_FILE"; then
# Fixed user root
DB_USER="root"

# Extract root password from environment file
DB_PASSWORD=$(grep -oP '(?<=ROOT_PASSWORD=).*' "$ENV_FILE")

# Install mysqldump if not installed
if ! command -v mysqldump &>/dev/null; then
log WARN "mysqldump not found, installing..."
apt-get update && apt-get install -y mysql-client || log ERROR "Failed to install mysql-client."
fi

# Dump databases
DB_BACKUP_PATH="$BACKUP_PATH/db-backup"
mkdir -p "$DB_BACKUP_PATH"

# Get the list of databases and exclude system databases
databases=$(mysql -h 127.0.0.1 --user="$DB_USER" --password="$DB_PASSWORD" -e "SHOW DATABASES;" | tr -d "| " | grep -v -E 'Database|information_schema|mysql|performance_schema|sys')

for db in $databases; do
log INFO "Dumping database: $db"
# Use additional parameters to avoid errors
mysqldump -h 127.0.0.1 --force --opt --user="$DB_USER" --password="$DB_PASSWORD" --single-transaction --skip-lock-tables --no-tablespaces --databases "$db" >"$DB_BACKUP_PATH/$db.sql" || log ERROR "Getting some error while dump database: $db"
done
log INFO "Databases dumped successfully."
else
log INFO "SQLite detected or SQLALCHEMY_DATABASE_URL not found. No MySQL databases to backup."
fi
}

# Function to send backup to Telegram
send_to_telegram() {
# Extract Telegram bot token and chat ID from environment file
TELEGRAM_BOT_TOKEN=$(grep -oP '(?<=TELEGRAM_BOT_TOKEN=).*' "$ENV_FILE")
TELEGRAM_CHAT_ID=$(grep -oP '(?<=TELEGRAM_CHAT_ID=).*' "$ENV_FILE")

if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
TAR_FILE="$BACKUP_DIR/backup_$CURRENT_DATE.tar.gz"
log INFO "Creating tarball $TAR_FILE"
tar -czf "$TAR_FILE" -C "$BACKUP_DIR" "backup_$CURRENT_DATE" || log ERROR "Failed to create tarball."

log INFO "Sending backup to Telegram chat ID $TELEGRAM_CHAT_ID"
curl -F chat_id="${TELEGRAM_CHAT_ID}" \
-F caption="Backup from $HOSTNAME_NODE at $CURRENT_DATE" \
-F parse_mode="HTML" \
-F document=@"$TAR_FILE" \
https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument || log ERROR "Failed to send backup to Telegram."

log INFO "Backup sent to Telegram successfully."
else
log WARN "Telegram BOT token or chat ID not provided. Skipping upload."
fi
# Extract Telegram bot token and chat ID from environment file
TELEGRAM_BOT_TOKEN=$(grep -oP '(?<=TELEGRAM_BOT_TOKEN=).*' "$ENV_FILE")
TELEGRAM_CHAT_ID=$(grep -oP '(?<=TELEGRAM_CHAT_ID=).*' "$ENV_FILE")

if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
TAR_FILE="$BACKUP_DIR/backup_$CURRENT_DATE.tar.gz"
log INFO "Creating tarball $TAR_FILE"
tar -czf "$TAR_FILE" -C "$BACKUP_DIR" "backup_$CURRENT_DATE" || log ERROR "Failed to create tarball."

log INFO "Sending backup to Telegram chat ID $TELEGRAM_CHAT_ID"
curl -F chat_id="${TELEGRAM_CHAT_ID}" \
-F caption="Backup from $HOSTNAME_NODE at $CURRENT_DATE" \
-F parse_mode="HTML" \
-F document=@"$TAR_FILE" \
https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument || log ERROR "Failed to send backup to Telegram."

log INFO "Backup sent to Telegram successfully."
else
log WARN "Telegram BOT token or chat ID not provided. Skipping upload."
fi
}

# Main backup process
main() {
log INFO "Starting backup process."
backup_directories
backup_databases
send_to_telegram
log INFO "Backup process completed."
log INFO "Starting backup process."
backup_directories
backup_databases
send_to_telegram
log INFO "Backup process completed."
}

# Run the main process
Expand Down
8 changes: 8 additions & 0 deletions roles/marzban/tasks/backup.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
---

- name: "Marzban | Backup | Prepare | Install cli utility"
apt:
name:
- mysql-client
state: present
update_cache: true
when: marzban_mysql_instance is defined and marzban_mysql_instance

- name: "Marzban | Backup | Add backup script"
copy:
src: "marzban_backup.sh"
Expand Down
20 changes: 16 additions & 4 deletions roles/marzban/tasks/conf/panel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@

- name: "Marzban | Configure {{ role | upper() }} | Info"
debug:
msg: "Get gozargah/marzban docker image..."
msg: |
INFO:
--------------------------------------------
Get marzban docker image...
Image name: {{ marzban_image }}
Image tag: {{ marzban_image_tag }}
--------------------------------------------
changed_when: false
when: not key_stat.stat.exists

- name: "Marzban | Configure {{ role | upper() }} | Generate X25519 key if it does not exist"
command: "docker run --rm gozargah/marzban xray x25519"
command: "docker run --rm {{ marzban_image }} xray x25519"
register: generate_key_result
changed_when: false
when: not key_stat.stat.exists
Expand Down Expand Up @@ -75,9 +81,16 @@
src: "{{ item.src }}"
dest: "{{ marzban_system_dirs | json_query('[*].work_dir') | first }}/{{ item.dst }}"
mode: "{{ item.mode }}"
validate: /usr/bin/jq empty %s
loop:
- {src: xray_config.json.j2, dst: xray_config.json, mode: "0644"}

- name: "Marzban | Configure {{ role | upper() }} | Add subscription template"
copy:
src: "index.html"
dest: "{{ marzban_system_dirs | json_query('[*].templates_dir') | first }}/index.html"
mode: "0644"

- name: "Marzban | Configure {{ role | upper() }} | Template ssl certificate"
copy:
dest: "{{ (marzban_system_dirs | json_query('[*].certs_dir') | first) }}/{{ item.key }}"
Expand All @@ -88,7 +101,6 @@
content: "{{ item.value }}"
loop: "{{ vault_ssl_certs | dict2items }}"


- name: "Marzban | Configure {{ role | upper() }} | Create and start services"
community.docker.docker_compose_v2:
project_src: "{{ marzban_system_dirs | json_query('[*].base_dir') | first }}"
Expand All @@ -106,7 +118,7 @@
accept: "application/json"
Content-Type: "application/x-www-form-urlencoded"
body:
grant_type: ""
grant_type: "password"
username: "{{ marzban_panel_login }}"
password: "{{ marzban_panel_password }}"
scope: ""
Expand Down
Loading