Обновление документации по устранению неполадок и тестированию API RegRu
- Улучшена структура и содержание руководства по устранению неполадок API RegRu для большей ясности и согласованности. - Документация по тестированию улучшена за счет подробных инструкций и сравнения методов тестирования. - Улучшено форматирование и читаемость обоих документов. - Обновлена боковая навигация для лучшего доступа к разделам документации.
This commit is contained in:
@@ -1,277 +1,277 @@
|
||||
name: "Deploy scripts to remote server"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "Branch/tag/SHA for deployment"
|
||||
required: false
|
||||
default: "master"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: "Upload and deploy on remote server"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
echo "ERROR: GIT_TOKEN (or GITEA_TOKEN) secret is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REF="${{ github.event.inputs.ref || 'master' }}"
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
|
||||
git clone --branch "${REF}" --depth 1 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN}" || true
|
||||
echo ">>> Source checked out: $(git log --oneline -1)"
|
||||
|
||||
- name: "Validate deployment secrets"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
|
||||
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
|
||||
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
|
||||
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
|
||||
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
|
||||
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
: "${DEPLOY_HOST:?DEPLOY_HOST secret is required}"
|
||||
: "${DEPLOY_PORT:?DEPLOY_PORT secret is required}"
|
||||
: "${DEPLOY_USER:?DEPLOY_USER secret is required}"
|
||||
: "${DEPLOY_PATH:?DEPLOY_PATH secret is required}"
|
||||
: "${DEPLOY_SERVICE:?DEPLOY_SERVICE secret is required}"
|
||||
: "${DEPLOY_SSH_PRIVATE_KEY:?DEPLOY_SSH_PRIVATE_KEY secret is required}"
|
||||
: "${CFG_REGRU_USERNAME:?CFG_REGRU_USERNAME secret is required}"
|
||||
: "${CFG_REGRU_PASSWORD:?CFG_REGRU_PASSWORD secret is required}"
|
||||
: "${CFG_EMAIL:?CFG_EMAIL secret is required}"
|
||||
: "${CFG_DOMAINS:?CFG_DOMAINS secret is required}"
|
||||
|
||||
echo ">>> Secrets validation passed"
|
||||
|
||||
- name: "Create deployment archive"
|
||||
shell: bash
|
||||
env:
|
||||
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
|
||||
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
|
||||
CFG_DOMAIN: ${{ secrets.CFG_DOMAIN }}
|
||||
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
|
||||
CFG_WILDCARD: ${{ secrets.CFG_WILDCARD }}
|
||||
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
|
||||
CFG_CERT_DIR: ${{ secrets.CFG_CERT_DIR }}
|
||||
CFG_LOG_FILE: ${{ secrets.CFG_LOG_FILE }}
|
||||
CFG_DNS_PROPAGATION_WAIT: ${{ secrets.CFG_DNS_PROPAGATION_WAIT }}
|
||||
CFG_DNS_CHECK_ATTEMPTS: ${{ secrets.CFG_DNS_CHECK_ATTEMPTS }}
|
||||
CFG_DNS_CHECK_INTERVAL: ${{ secrets.CFG_DNS_CHECK_INTERVAL }}
|
||||
CFG_RENEWAL_DAYS: ${{ secrets.CFG_RENEWAL_DAYS }}
|
||||
CFG_NPM_ENABLED: ${{ secrets.CFG_NPM_ENABLED }}
|
||||
CFG_NPM_HOST: ${{ secrets.CFG_NPM_HOST }}
|
||||
CFG_NPM_EMAIL: ${{ secrets.CFG_NPM_EMAIL }}
|
||||
CFG_NPM_PASSWORD: ${{ secrets.CFG_NPM_PASSWORD }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
rm -rf .deploy-artifacts
|
||||
mkdir -p .deploy-artifacts
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.src-repo/' \
|
||||
--exclude '.wiki-repo/' \
|
||||
--exclude '.deploy-artifacts/' \
|
||||
./ .deploy-artifacts/repo/
|
||||
else
|
||||
cp -a . .deploy-artifacts/repo
|
||||
rm -rf .deploy-artifacts/repo/.git .deploy-artifacts/repo/.src-repo .deploy-artifacts/repo/.wiki-repo .deploy-artifacts/repo/.deploy-artifacts
|
||||
fi
|
||||
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def to_bool(value, default=False):
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return str(value).strip().lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
def to_int(value, default):
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return int(value)
|
||||
|
||||
|
||||
domains_raw = os.environ.get("CFG_DOMAINS", "").strip()
|
||||
if domains_raw.startswith("["):
|
||||
# JSON array: каждый элемент может содержать запятые для SAN групп
|
||||
# Пример: ["*.example.com,example.com", "gitea.example.com"]
|
||||
domains = json.loads(domains_raw)
|
||||
else:
|
||||
domains = [item.strip() for item in domains_raw.split(",") if item.strip()]
|
||||
|
||||
if not domains:
|
||||
raise RuntimeError("CFG_DOMAINS must contain at least one domain")
|
||||
|
||||
# primary domain: CFG_DOMAIN → первый не-wildcard домен из первой SAN группы
|
||||
first_group_domains = [d.strip() for d in domains[0].split(",") if d.strip()]
|
||||
domain = os.environ.get("CFG_DOMAIN", "").strip() or next(
|
||||
(d for d in first_group_domains if not d.startswith("*.")),
|
||||
first_group_domains[0]
|
||||
)
|
||||
|
||||
config = {
|
||||
"regru_username": os.environ["CFG_REGRU_USERNAME"],
|
||||
"regru_password": os.environ["CFG_REGRU_PASSWORD"],
|
||||
"domain": domain,
|
||||
"domains": domains,
|
||||
"wildcard": to_bool(os.environ.get("CFG_WILDCARD"), True),
|
||||
"email": os.environ["CFG_EMAIL"],
|
||||
"cert_dir": os.environ.get("CFG_CERT_DIR") or "/etc/letsencrypt/live",
|
||||
"log_file": os.environ.get("CFG_LOG_FILE") or "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": to_int(os.environ.get("CFG_DNS_PROPAGATION_WAIT"), 180),
|
||||
"dns_check_attempts": to_int(os.environ.get("CFG_DNS_CHECK_ATTEMPTS"), 20),
|
||||
"dns_check_interval": to_int(os.environ.get("CFG_DNS_CHECK_INTERVAL"), 15),
|
||||
"renewal_days": to_int(os.environ.get("CFG_RENEWAL_DAYS"), 30),
|
||||
"npm_enabled": to_bool(os.environ.get("CFG_NPM_ENABLED"), True),
|
||||
"npm_host": os.environ.get("CFG_NPM_HOST") or "",
|
||||
"npm_email": os.environ.get("CFG_NPM_EMAIL") or "",
|
||||
"npm_password": os.environ.get("CFG_NPM_PASSWORD") or "",
|
||||
}
|
||||
|
||||
output_path = os.path.join(".deploy-artifacts", "repo", "config.json")
|
||||
with open(output_path, "w", encoding="utf-8") as file:
|
||||
json.dump(config, file, ensure_ascii=False, indent=4)
|
||||
PY
|
||||
|
||||
tar -czf .deploy-artifacts/deploy.tar.gz -C .deploy-artifacts repo
|
||||
ls -lh .deploy-artifacts/deploy.tar.gz
|
||||
|
||||
- name: "Configure SSH client"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
# Save private key preserving exact formatting
|
||||
# Use printf with %b to handle \n sequences, strip trailing whitespace issues
|
||||
echo "${DEPLOY_SSH_PRIVATE_KEY}" | sed 's/\r//' > ~/.ssh/id_deploy
|
||||
# Ensure file ends with a newline (required by OpenSSH)
|
||||
echo "" >> ~/.ssh/id_deploy
|
||||
chmod 600 ~/.ssh/id_deploy
|
||||
|
||||
# Validate key and show fingerprint for debugging
|
||||
echo ">>> Private key type: $(ssh-keygen -l -f ~/.ssh/id_deploy 2>&1 || echo 'INVALID KEY')"
|
||||
|
||||
if [ -n "${DEPLOY_SSH_KNOWN_HOSTS:-}" ]; then
|
||||
printf '%s\n' "${DEPLOY_SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
|
||||
echo ">>> known_hosts: loaded from DEPLOY_SSH_KNOWN_HOSTS secret"
|
||||
fi
|
||||
|
||||
# Always run ssh-keyscan to ensure all key types are covered
|
||||
echo ">>> Scanning host keys for ${DEPLOY_HOST}:${DEPLOY_PORT}..."
|
||||
ssh-keyscan -p "${DEPLOY_PORT}" -t ed25519,ecdsa-sha2-nistp256,rsa "${DEPLOY_HOST}" >> ~/.ssh/known_hosts 2>&1 || true
|
||||
echo ">>> known_hosts entries: $(wc -l < ~/.ssh/known_hosts)"
|
||||
|
||||
chmod 644 ~/.ssh/known_hosts
|
||||
|
||||
{
|
||||
echo "Host deploy-target"
|
||||
echo " HostName ${DEPLOY_HOST}"
|
||||
echo " Port ${DEPLOY_PORT}"
|
||||
echo " User ${DEPLOY_USER}"
|
||||
echo " IdentityFile ~/.ssh/id_deploy"
|
||||
echo " UserKnownHostsFile ~/.ssh/known_hosts"
|
||||
echo " StrictHostKeyChecking accept-new"
|
||||
echo " ConnectTimeout 15"
|
||||
echo " ServerAliveInterval 10"
|
||||
echo " ServerAliveCountMax 3"
|
||||
echo " BatchMode yes"
|
||||
} > ~/.ssh/config
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
echo ">>> Testing SSH connection..."
|
||||
ssh deploy-target "echo '>>> SSH connection ok:' \"\$(hostname)\""
|
||||
echo ">>> SSH configured successfully"
|
||||
|
||||
- name: "Upload deployment archive"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
scp .deploy-artifacts/deploy.tar.gz deploy-target:/tmp/configure_nginx_manager_deploy.tar.gz
|
||||
|
||||
- name: "Deploy and restart remote service"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
|
||||
DEPLOY_CONFIG_PATH: ${{ secrets.DEPLOY_CONFIG_PATH }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# DEPLOY_CONFIG_PATH: path to config.json on remote (default: /etc/letsencrypt-regru/config.json)
|
||||
CONFIG_DEST="${DEPLOY_CONFIG_PATH:-/etc/letsencrypt-regru/config.json}"
|
||||
|
||||
ssh deploy-target "set -euo pipefail; \
|
||||
TMP_DIR=\"/tmp/configure_nginx_manager_deploy\"; \
|
||||
sudo rm -rf \"\${TMP_DIR}\"; \
|
||||
sudo mkdir -p \"\${TMP_DIR}\"; \
|
||||
sudo tar -xzf /tmp/configure_nginx_manager_deploy.tar.gz -C \"\${TMP_DIR}\"; \
|
||||
sudo mkdir -p \"${DEPLOY_PATH}\"; \
|
||||
sudo find \"${DEPLOY_PATH}\" -mindepth 1 -maxdepth 1 ! -name 'venv' -exec rm -rf {} + 2>/dev/null || true; \
|
||||
sudo cp -a \"\${TMP_DIR}/repo/.\" \"${DEPLOY_PATH}/\"; \
|
||||
if [ ! -d \"${DEPLOY_PATH}/venv\" ]; then \
|
||||
echo \">>> venv not found, creating...\"; \
|
||||
sudo python3 -m venv \"${DEPLOY_PATH}/venv\"; \
|
||||
fi; \
|
||||
echo \">>> Installing/updating Python dependencies...\"; \
|
||||
sudo \"${DEPLOY_PATH}/venv/bin/pip\" install -q -r \"${DEPLOY_PATH}/requirements.txt\" 2>&1 | tail -5; \
|
||||
sudo mkdir -p \"\$(dirname '${CONFIG_DEST}')\"; \
|
||||
sudo cp -f \"\${TMP_DIR}/repo/config.json\" \"${CONFIG_DEST}\"; \
|
||||
sudo chmod 600 \"${CONFIG_DEST}\"; \
|
||||
echo \">>> config.json deployed to: ${CONFIG_DEST}\"; \
|
||||
sudo rm -rf \"\${TMP_DIR}\" /tmp/configure_nginx_manager_deploy.tar.gz; \
|
||||
sudo systemctl daemon-reload; \
|
||||
sudo systemctl enable \"${DEPLOY_SERVICE}\" || true; \
|
||||
echo \">>> Starting service...\"; \
|
||||
sudo systemctl restart --no-block \"${DEPLOY_SERVICE}\" || true; \
|
||||
sleep 3; \
|
||||
echo \">>> Service status:\"; \
|
||||
sudo systemctl --no-pager --full status \"${DEPLOY_SERVICE}\" | head -n 30 || true; \
|
||||
echo \">>> Last journal entries:\"; \
|
||||
sudo journalctl -u \"${DEPLOY_SERVICE}\" -n 30 --no-pager || true; \
|
||||
echo \">>> Config used:\"; \
|
||||
sudo cat \"${CONFIG_DEST}\" | python3 -c \"import json,sys; c=json.load(sys.stdin); c['regru_password']='***'; c['npm_password']='***'; print(json.dumps(c,indent=2,ensure_ascii=False))\" || true"
|
||||
name: "Deploy scripts to remote server"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "Branch/tag/SHA for deployment"
|
||||
required: false
|
||||
default: "master"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: "Upload and deploy on remote server"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
echo "ERROR: GIT_TOKEN (or GITEA_TOKEN) secret is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REF="${{ github.event.inputs.ref || 'master' }}"
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
|
||||
git clone --branch "${REF}" --depth 1 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN}" || true
|
||||
echo ">>> Source checked out: $(git log --oneline -1)"
|
||||
|
||||
- name: "Validate deployment secrets"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
|
||||
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
|
||||
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
|
||||
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
|
||||
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
|
||||
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
: "${DEPLOY_HOST:?DEPLOY_HOST secret is required}"
|
||||
: "${DEPLOY_PORT:?DEPLOY_PORT secret is required}"
|
||||
: "${DEPLOY_USER:?DEPLOY_USER secret is required}"
|
||||
: "${DEPLOY_PATH:?DEPLOY_PATH secret is required}"
|
||||
: "${DEPLOY_SERVICE:?DEPLOY_SERVICE secret is required}"
|
||||
: "${DEPLOY_SSH_PRIVATE_KEY:?DEPLOY_SSH_PRIVATE_KEY secret is required}"
|
||||
: "${CFG_REGRU_USERNAME:?CFG_REGRU_USERNAME secret is required}"
|
||||
: "${CFG_REGRU_PASSWORD:?CFG_REGRU_PASSWORD secret is required}"
|
||||
: "${CFG_EMAIL:?CFG_EMAIL secret is required}"
|
||||
: "${CFG_DOMAINS:?CFG_DOMAINS secret is required}"
|
||||
|
||||
echo ">>> Secrets validation passed"
|
||||
|
||||
- name: "Create deployment archive"
|
||||
shell: bash
|
||||
env:
|
||||
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
|
||||
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
|
||||
CFG_DOMAIN: ${{ secrets.CFG_DOMAIN }}
|
||||
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
|
||||
CFG_WILDCARD: ${{ secrets.CFG_WILDCARD }}
|
||||
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
|
||||
CFG_CERT_DIR: ${{ secrets.CFG_CERT_DIR }}
|
||||
CFG_LOG_FILE: ${{ secrets.CFG_LOG_FILE }}
|
||||
CFG_DNS_PROPAGATION_WAIT: ${{ secrets.CFG_DNS_PROPAGATION_WAIT }}
|
||||
CFG_DNS_CHECK_ATTEMPTS: ${{ secrets.CFG_DNS_CHECK_ATTEMPTS }}
|
||||
CFG_DNS_CHECK_INTERVAL: ${{ secrets.CFG_DNS_CHECK_INTERVAL }}
|
||||
CFG_RENEWAL_DAYS: ${{ secrets.CFG_RENEWAL_DAYS }}
|
||||
CFG_NPM_ENABLED: ${{ secrets.CFG_NPM_ENABLED }}
|
||||
CFG_NPM_HOST: ${{ secrets.CFG_NPM_HOST }}
|
||||
CFG_NPM_EMAIL: ${{ secrets.CFG_NPM_EMAIL }}
|
||||
CFG_NPM_PASSWORD: ${{ secrets.CFG_NPM_PASSWORD }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
rm -rf .deploy-artifacts
|
||||
mkdir -p .deploy-artifacts
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.src-repo/' \
|
||||
--exclude '.wiki-repo/' \
|
||||
--exclude '.deploy-artifacts/' \
|
||||
./ .deploy-artifacts/repo/
|
||||
else
|
||||
cp -a . .deploy-artifacts/repo
|
||||
rm -rf .deploy-artifacts/repo/.git .deploy-artifacts/repo/.src-repo .deploy-artifacts/repo/.wiki-repo .deploy-artifacts/repo/.deploy-artifacts
|
||||
fi
|
||||
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def to_bool(value, default=False):
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return str(value).strip().lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
def to_int(value, default):
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return int(value)
|
||||
|
||||
|
||||
domains_raw = os.environ.get("CFG_DOMAINS", "").strip()
|
||||
if domains_raw.startswith("["):
|
||||
# JSON array: каждый элемент может содержать запятые для SAN групп
|
||||
# Пример: ["*.example.com,example.com", "gitea.example.com"]
|
||||
domains = json.loads(domains_raw)
|
||||
else:
|
||||
domains = [item.strip() for item in domains_raw.split(",") if item.strip()]
|
||||
|
||||
if not domains:
|
||||
raise RuntimeError("CFG_DOMAINS must contain at least one domain")
|
||||
|
||||
# primary domain: CFG_DOMAIN → первый не-wildcard домен из первой SAN группы
|
||||
first_group_domains = [d.strip() for d in domains[0].split(",") if d.strip()]
|
||||
domain = os.environ.get("CFG_DOMAIN", "").strip() or next(
|
||||
(d for d in first_group_domains if not d.startswith("*.")),
|
||||
first_group_domains[0]
|
||||
)
|
||||
|
||||
config = {
|
||||
"regru_username": os.environ["CFG_REGRU_USERNAME"],
|
||||
"regru_password": os.environ["CFG_REGRU_PASSWORD"],
|
||||
"domain": domain,
|
||||
"domains": domains,
|
||||
"wildcard": to_bool(os.environ.get("CFG_WILDCARD"), True),
|
||||
"email": os.environ["CFG_EMAIL"],
|
||||
"cert_dir": os.environ.get("CFG_CERT_DIR") or "/etc/letsencrypt/live",
|
||||
"log_file": os.environ.get("CFG_LOG_FILE") or "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": to_int(os.environ.get("CFG_DNS_PROPAGATION_WAIT"), 180),
|
||||
"dns_check_attempts": to_int(os.environ.get("CFG_DNS_CHECK_ATTEMPTS"), 20),
|
||||
"dns_check_interval": to_int(os.environ.get("CFG_DNS_CHECK_INTERVAL"), 15),
|
||||
"renewal_days": to_int(os.environ.get("CFG_RENEWAL_DAYS"), 30),
|
||||
"npm_enabled": to_bool(os.environ.get("CFG_NPM_ENABLED"), True),
|
||||
"npm_host": os.environ.get("CFG_NPM_HOST") or "",
|
||||
"npm_email": os.environ.get("CFG_NPM_EMAIL") or "",
|
||||
"npm_password": os.environ.get("CFG_NPM_PASSWORD") or "",
|
||||
}
|
||||
|
||||
output_path = os.path.join(".deploy-artifacts", "repo", "config.json")
|
||||
with open(output_path, "w", encoding="utf-8") as file:
|
||||
json.dump(config, file, ensure_ascii=False, indent=4)
|
||||
PY
|
||||
|
||||
tar -czf .deploy-artifacts/deploy.tar.gz -C .deploy-artifacts repo
|
||||
ls -lh .deploy-artifacts/deploy.tar.gz
|
||||
|
||||
- name: "Configure SSH client"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
# Save private key preserving exact formatting
|
||||
# Use printf with %b to handle \n sequences, strip trailing whitespace issues
|
||||
echo "${DEPLOY_SSH_PRIVATE_KEY}" | sed 's/\r//' > ~/.ssh/id_deploy
|
||||
# Ensure file ends with a newline (required by OpenSSH)
|
||||
echo "" >> ~/.ssh/id_deploy
|
||||
chmod 600 ~/.ssh/id_deploy
|
||||
|
||||
# Validate key and show fingerprint for debugging
|
||||
echo ">>> Private key type: $(ssh-keygen -l -f ~/.ssh/id_deploy 2>&1 || echo 'INVALID KEY')"
|
||||
|
||||
if [ -n "${DEPLOY_SSH_KNOWN_HOSTS:-}" ]; then
|
||||
printf '%s\n' "${DEPLOY_SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
|
||||
echo ">>> known_hosts: loaded from DEPLOY_SSH_KNOWN_HOSTS secret"
|
||||
fi
|
||||
|
||||
# Always run ssh-keyscan to ensure all key types are covered
|
||||
echo ">>> Scanning host keys for ${DEPLOY_HOST}:${DEPLOY_PORT}..."
|
||||
ssh-keyscan -p "${DEPLOY_PORT}" -t ed25519,ecdsa-sha2-nistp256,rsa "${DEPLOY_HOST}" >> ~/.ssh/known_hosts 2>&1 || true
|
||||
echo ">>> known_hosts entries: $(wc -l < ~/.ssh/known_hosts)"
|
||||
|
||||
chmod 644 ~/.ssh/known_hosts
|
||||
|
||||
{
|
||||
echo "Host deploy-target"
|
||||
echo " HostName ${DEPLOY_HOST}"
|
||||
echo " Port ${DEPLOY_PORT}"
|
||||
echo " User ${DEPLOY_USER}"
|
||||
echo " IdentityFile ~/.ssh/id_deploy"
|
||||
echo " UserKnownHostsFile ~/.ssh/known_hosts"
|
||||
echo " StrictHostKeyChecking accept-new"
|
||||
echo " ConnectTimeout 15"
|
||||
echo " ServerAliveInterval 10"
|
||||
echo " ServerAliveCountMax 3"
|
||||
echo " BatchMode yes"
|
||||
} > ~/.ssh/config
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
echo ">>> Testing SSH connection..."
|
||||
ssh deploy-target "echo '>>> SSH connection ok:' \"\$(hostname)\""
|
||||
echo ">>> SSH configured successfully"
|
||||
|
||||
- name: "Upload deployment archive"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
scp .deploy-artifacts/deploy.tar.gz deploy-target:/tmp/configure_nginx_manager_deploy.tar.gz
|
||||
|
||||
- name: "Deploy and restart remote service"
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
|
||||
DEPLOY_CONFIG_PATH: ${{ secrets.DEPLOY_CONFIG_PATH }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# DEPLOY_CONFIG_PATH: path to config.json on remote (default: /etc/letsencrypt-regru/config.json)
|
||||
CONFIG_DEST="${DEPLOY_CONFIG_PATH:-/etc/letsencrypt-regru/config.json}"
|
||||
|
||||
ssh deploy-target "set -euo pipefail; \
|
||||
TMP_DIR=\"/tmp/configure_nginx_manager_deploy\"; \
|
||||
sudo rm -rf \"\${TMP_DIR}\"; \
|
||||
sudo mkdir -p \"\${TMP_DIR}\"; \
|
||||
sudo tar -xzf /tmp/configure_nginx_manager_deploy.tar.gz -C \"\${TMP_DIR}\"; \
|
||||
sudo mkdir -p \"${DEPLOY_PATH}\"; \
|
||||
sudo find \"${DEPLOY_PATH}\" -mindepth 1 -maxdepth 1 ! -name 'venv' -exec rm -rf {} + 2>/dev/null || true; \
|
||||
sudo cp -a \"\${TMP_DIR}/repo/.\" \"${DEPLOY_PATH}/\"; \
|
||||
if [ ! -d \"${DEPLOY_PATH}/venv\" ]; then \
|
||||
echo \">>> venv not found, creating...\"; \
|
||||
sudo python3 -m venv \"${DEPLOY_PATH}/venv\"; \
|
||||
fi; \
|
||||
echo \">>> Installing/updating Python dependencies...\"; \
|
||||
sudo \"${DEPLOY_PATH}/venv/bin/pip\" install -q -r \"${DEPLOY_PATH}/requirements.txt\" 2>&1 | tail -5; \
|
||||
sudo mkdir -p \"\$(dirname '${CONFIG_DEST}')\"; \
|
||||
sudo cp -f \"\${TMP_DIR}/repo/config.json\" \"${CONFIG_DEST}\"; \
|
||||
sudo chmod 600 \"${CONFIG_DEST}\"; \
|
||||
echo \">>> config.json deployed to: ${CONFIG_DEST}\"; \
|
||||
sudo rm -rf \"\${TMP_DIR}\" /tmp/configure_nginx_manager_deploy.tar.gz; \
|
||||
sudo systemctl daemon-reload; \
|
||||
sudo systemctl enable \"${DEPLOY_SERVICE}\" || true; \
|
||||
echo \">>> Starting service...\"; \
|
||||
sudo systemctl restart --no-block \"${DEPLOY_SERVICE}\" || true; \
|
||||
sleep 3; \
|
||||
echo \">>> Service status:\"; \
|
||||
sudo systemctl --no-pager --full status \"${DEPLOY_SERVICE}\" | head -n 30 || true; \
|
||||
echo \">>> Last journal entries:\"; \
|
||||
sudo journalctl -u \"${DEPLOY_SERVICE}\" -n 30 --no-pager || true; \
|
||||
echo \">>> Config used:\"; \
|
||||
sudo cat \"${CONFIG_DEST}\" | python3 -c \"import json,sys; c=json.load(sys.stdin); c['regru_password']='***'; c['npm_password']='***'; print(json.dumps(c,indent=2,ensure_ascii=False))\" || true"
|
||||
|
||||
+388
-388
@@ -1,388 +1,388 @@
|
||||
name: "Релиз: архив исходников"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Тег релиза (например: v2.2.0)"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
DIST_DIR: dist
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: "Упаковка и публикация релиза"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
- name: "Получение исходного кода"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
else
|
||||
TAG="${GITHUB_REF_NAME}"
|
||||
fi
|
||||
|
||||
if [ -z "${TAG}" ]; then
|
||||
echo "ОШИБКА: не удалось определить тег релиза."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> Клонирование ${REPO} (тег: ${TAG})"
|
||||
|
||||
if [ -n "${TOKEN}" ]; then
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
else
|
||||
CLONE_URL="${SERVER}/${REPO}.git"
|
||||
fi
|
||||
|
||||
# Check if tag exists on the remote
|
||||
TAG_EXISTS=false
|
||||
if git ls-remote --exit-code --tags "${CLONE_URL}" "refs/tags/${TAG}" >/dev/null 2>&1; then
|
||||
TAG_EXISTS=true
|
||||
fi
|
||||
|
||||
if [ "${TAG_EXISTS}" = "true" ]; then
|
||||
echo ">>> Тег ${TAG} найден, клонирование..."
|
||||
git clone --branch "${TAG}" --depth 50 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
else
|
||||
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
if [ -z "${DEFAULT_BRANCH}" ] || [ "${DEFAULT_BRANCH}" = "null" ]; then
|
||||
DEFAULT_BRANCH="master"
|
||||
fi
|
||||
echo ">>> Тег ${TAG} не найден, клонирование ветки ${DEFAULT_BRANCH}..."
|
||||
git clone --branch "${DEFAULT_BRANCH}" --depth 50 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
fi
|
||||
|
||||
git fetch --tags --force 2>/dev/null || true
|
||||
|
||||
# If tag doesn't exist locally, create and push it
|
||||
if [ "${TAG_EXISTS}" = "false" ] && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo ">>> Создание тега ${TAG} на текущем коммите ($(git rev-parse --short HEAD))..."
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}" 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
echo ">>> Тег ${TAG} создан и отправлен"
|
||||
fi
|
||||
|
||||
echo "RELEASE_TAG=${TAG}" >> "$GITHUB_ENV"
|
||||
echo ">>> Исходный код получен: $(git log --oneline -1 2>/dev/null || echo 'N/A')"
|
||||
|
||||
- name: "Подготовка метаданных релиза"
|
||||
id: meta
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${RELEASE_TAG}"
|
||||
VERSION="${TAG#v}"
|
||||
PREV_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)
|
||||
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "══════════════════════════════════════"
|
||||
echo " Тег: ${TAG}"
|
||||
echo " Версия: ${VERSION}"
|
||||
echo " Пред. тег: ${PREV_TAG:-<первый релиз>}"
|
||||
echo " Коммит: ${GITHUB_SHA:0:8}"
|
||||
echo "══════════════════════════════════════"
|
||||
|
||||
- name: "Создание архивов исходного кода"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
REPO_NAME="${GITHUB_REPOSITORY##*/}"
|
||||
ARCHIVE_BASE="${REPO_NAME}-${TAG}"
|
||||
|
||||
rm -rf .release-work "${DIST_DIR}"
|
||||
mkdir -p .release-work "${DIST_DIR}"
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.src-repo/' \
|
||||
--exclude '.wiki-repo/' \
|
||||
--exclude '.release-work/' \
|
||||
--exclude "${DIST_DIR}/" \
|
||||
./ ".release-work/${ARCHIVE_BASE}/"
|
||||
else
|
||||
cp -a . ".release-work/${ARCHIVE_BASE}"
|
||||
rm -rf \
|
||||
".release-work/${ARCHIVE_BASE}/.git" \
|
||||
".release-work/${ARCHIVE_BASE}/.src-repo" \
|
||||
".release-work/${ARCHIVE_BASE}/.wiki-repo" \
|
||||
".release-work/${ARCHIVE_BASE}/.release-work" \
|
||||
".release-work/${ARCHIVE_BASE}/${DIST_DIR}"
|
||||
fi
|
||||
|
||||
tar -czf "${DIST_DIR}/${ARCHIVE_BASE}.tar.gz" -C .release-work "${ARCHIVE_BASE}"
|
||||
|
||||
if command -v zip >/dev/null 2>&1; then
|
||||
(
|
||||
cd .release-work
|
||||
zip -qr "../${DIST_DIR}/${ARCHIVE_BASE}.zip" "${ARCHIVE_BASE}"
|
||||
)
|
||||
else
|
||||
ARCHIVE_BASE="${ARCHIVE_BASE}" DIST_DIR="${DIST_DIR}" python3 - <<'PY'
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
base = os.environ["ARCHIVE_BASE"]
|
||||
src = os.path.join(".release-work", base)
|
||||
dst = os.path.join(os.environ["DIST_DIR"], f"{base}.zip")
|
||||
|
||||
with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for root, _, files in os.walk(src):
|
||||
for file_name in files:
|
||||
full = os.path.join(root, file_name)
|
||||
arc = os.path.relpath(full, ".release-work")
|
||||
zf.write(full, arc)
|
||||
PY
|
||||
fi
|
||||
|
||||
sha256sum "${DIST_DIR}"/* > "${DIST_DIR}/checksums-sha256.txt"
|
||||
|
||||
echo "ARCHIVE_BASE=${ARCHIVE_BASE}" >> "$GITHUB_ENV"
|
||||
echo ">>> Артефакты релиза:"
|
||||
ls -lh "${DIST_DIR}"
|
||||
|
||||
- name: "Генерация описания релиза"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
PREV_TAG="${{ steps.meta.outputs.prev_tag }}"
|
||||
DATE_UTC=$(date -u '+%Y-%m-%d %H:%M UTC')
|
||||
|
||||
CHANGELOG_FILE=""
|
||||
if [ -f "wiki/Changelog.md" ]; then
|
||||
CHANGELOG_FILE="wiki/Changelog.md"
|
||||
elif [ -f "docs/ru/CHANGELOG.md" ]; then
|
||||
CHANGELOG_FILE="docs/ru/CHANGELOG.md"
|
||||
elif [ -f "docs/en/CHANGELOG_EN.md" ]; then
|
||||
CHANGELOG_FILE="docs/en/CHANGELOG_EN.md"
|
||||
fi
|
||||
|
||||
CHANGELOG_SECTION=""
|
||||
if [ -n "${CHANGELOG_FILE}" ]; then
|
||||
# Поддерживаем оба формата заголовков: "## [VERSION]" и "### [VERSION] - DATE"
|
||||
CHANGELOG_SECTION=$(awk -v ver="${VERSION}" '
|
||||
$0 ~ "^#{2,3} \\[" ver "\\]" { in_section=1; next }
|
||||
/^#{2,3} \[/ && in_section { exit }
|
||||
in_section { print }
|
||||
' "${CHANGELOG_FILE}")
|
||||
fi
|
||||
|
||||
COMMITS=""
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
if [ -n "${PREV_TAG}" ]; then
|
||||
COMMITS=$(git log --pretty=format:'- %s (%h)' "${PREV_TAG}..${TAG}" --no-merges | head -50)
|
||||
else
|
||||
COMMITS=$(git log --pretty=format:'- %s (%h)' --no-merges | head -50)
|
||||
fi
|
||||
else
|
||||
echo ">>> Предупреждение: .git недоступен, список коммитов будет пропущен"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "## Release ${TAG}"
|
||||
echo ""
|
||||
echo "Релиз скриптового проекта без компиляции бинарников."
|
||||
echo ""
|
||||
echo "### Что входит в релиз"
|
||||
echo "- Исходный код в форматах: ${ARCHIVE_BASE}.tar.gz, ${ARCHIVE_BASE}.zip"
|
||||
echo "- Контрольные суммы: checksums-sha256.txt"
|
||||
echo ""
|
||||
|
||||
if [ -n "${CHANGELOG_SECTION}" ]; then
|
||||
echo "### Что сделано (из CHANGELOG)"
|
||||
echo "${CHANGELOG_SECTION}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "### Коммиты релиза"
|
||||
if [ -n "${COMMITS}" ]; then
|
||||
echo "${COMMITS}"
|
||||
else
|
||||
echo "- Недоступно (runner без .git)"
|
||||
fi
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "- Тег: ${TAG}"
|
||||
echo "- Коммит: ${GITHUB_SHA}"
|
||||
echo "- Дата (UTC): ${DATE_UTC}"
|
||||
} > /tmp/release_body.md
|
||||
|
||||
echo ">>> Сформировано описание релиза: /tmp/release_body.md"
|
||||
|
||||
- name: "Создание релиза и загрузка архивов"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
echo "ОШИБКА: не задан секрет GIT_TOKEN (или GITEA_TOKEN)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
|
||||
# Set up API URLs and auth header early (needed for tag check below)
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CREATE_URL="https://api.github.com/repos/${REPO}/releases"
|
||||
AUTH_HEADER="Authorization: Bearer ${TOKEN}"
|
||||
EXTRA_HEADERS=(-H "Accept: application/vnd.github+json")
|
||||
else
|
||||
CREATE_URL="${SERVER}/api/v1/repos/${REPO}/releases"
|
||||
AUTH_HEADER="Authorization: token ${TOKEN}"
|
||||
EXTRA_HEADERS=()
|
||||
fi
|
||||
|
||||
TARGET_COMMITISH="${RELEASE_REF:-${{ github.event.repository.default_branch }}}"
|
||||
if [ -z "${TARGET_COMMITISH}" ] || [ "${TARGET_COMMITISH}" = "null" ]; then
|
||||
TARGET_COMMITISH="master"
|
||||
fi
|
||||
if [ -n "${GITHUB_SHA:-}" ]; then
|
||||
TARGET_COMMITISH="${GITHUB_SHA}"
|
||||
fi
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
TARGET_COMMITISH="$(git rev-list -n 1 "${TAG}" 2>/dev/null || echo "${TARGET_COMMITISH}")"
|
||||
fi
|
||||
|
||||
# Ensure the tag exists on the remote (Gitea requires it before creating a release)
|
||||
if [ "${HOST}" != "github.com" ]; then
|
||||
TAG_HTTP_CODE=$(curl -sS -o /dev/null -w '%{http_code}' \
|
||||
-H "${AUTH_HEADER}" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/tags/${TAG}")
|
||||
if [ "${TAG_HTTP_CODE}" != "200" ]; then
|
||||
echo ">>> Тег ${TAG} не найден на сервере (HTTP ${TAG_HTTP_CODE}), создание через API..."
|
||||
TAG_CREATE_RESP=$(curl -sS -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/tags" \
|
||||
-d "{\"tag_name\":\"${TAG}\",\"target\":\"${TARGET_COMMITISH}\"}")
|
||||
echo ">>> Ответ создания тега: ${TAG_CREATE_RESP}"
|
||||
else
|
||||
echo ">>> Тег ${TAG} существует на сервере"
|
||||
fi
|
||||
fi
|
||||
|
||||
BODY_JSON=$(python3 - <<'PY'
|
||||
import json
|
||||
|
||||
with open('/tmp/release_body.md', 'r', encoding='utf-8') as f:
|
||||
print(json.dumps(f.read(), ensure_ascii=False))
|
||||
PY
|
||||
)
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
RELEASE_PAYLOAD="{\"tag_name\":\"${TAG}\",\"target_commitish\":\"${TARGET_COMMITISH}\",\"name\":\"Release ${TAG}\",\"body\":${BODY_JSON},\"draft\":false,\"prerelease\":false}"
|
||||
else
|
||||
RELEASE_PAYLOAD="{\"tag_name\":\"${TAG}\",\"target\":\"${TARGET_COMMITISH}\",\"title\":\"Release ${TAG}\",\"note\":${BODY_JSON},\"draft\":false,\"prerelease\":false}"
|
||||
fi
|
||||
|
||||
echo ">>> Создание релиза для тега ${TAG}..."
|
||||
RELEASE_JSON=$(curl -sS -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${EXTRA_HEADERS[@]}" \
|
||||
"${CREATE_URL}" \
|
||||
-d "${RELEASE_PAYLOAD}")
|
||||
|
||||
if ! printf '%s' "${RELEASE_JSON}" | python3 -c "import sys, json; j=json.load(sys.stdin); print(j.get('id',''));" >/tmp/release_id.txt 2>/dev/null; then
|
||||
echo "ОШИБКА: API вернул не-JSON при создании релиза"
|
||||
echo "Ответ: ${RELEASE_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_ID=$(cat /tmp/release_id.txt)
|
||||
rm -f /tmp/release_id.txt
|
||||
|
||||
if [ -z "${RELEASE_ID}" ] && [ "${HOST}" != "github.com" ]; then
|
||||
echo ">>> Не удалось получить ID из create-response, пытаемся найти существующий релиз по тегу ${TAG}..."
|
||||
RELEASE_JSON=$(curl -sS \
|
||||
-H "${AUTH_HEADER}" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/releases/tags/${TAG}")
|
||||
|
||||
if printf '%s' "${RELEASE_JSON}" | python3 -c "import sys, json; j=json.load(sys.stdin); print(j.get('id',''));" >/tmp/release_id.txt 2>/dev/null; then
|
||||
RELEASE_ID=$(cat /tmp/release_id.txt)
|
||||
fi
|
||||
rm -f /tmp/release_id.txt
|
||||
fi
|
||||
|
||||
if [ -z "${RELEASE_ID}" ]; then
|
||||
echo "ОШИБКА: не удалось получить ID релиза"
|
||||
echo "${RELEASE_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
UPLOAD_BASE=$(printf '%s' "${RELEASE_JSON}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('upload_url','').split('{')[0])")
|
||||
RELEASE_URL="https://github.com/${REPO}/releases/tag/${TAG}"
|
||||
else
|
||||
UPLOAD_BASE="${SERVER}/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets"
|
||||
RELEASE_URL="${SERVER}/${REPO}/releases/tag/${TAG}"
|
||||
fi
|
||||
|
||||
echo ">>> Загрузка файлов в релиз ${TAG}"
|
||||
for file in "${DIST_DIR}"/*; do
|
||||
[ -f "${file}" ] || continue
|
||||
name=$(basename "${file}")
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
curl -sf -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
"${EXTRA_HEADERS[@]}" \
|
||||
--data-binary @"${file}" \
|
||||
"${UPLOAD_BASE}?name=${name}" >/dev/null
|
||||
else
|
||||
curl -sf -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"${file}" \
|
||||
"${UPLOAD_BASE}?name=${name}" >/dev/null
|
||||
fi
|
||||
|
||||
echo " ✓ ${name}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo ">>> Релиз опубликован: ${RELEASE_URL}"
|
||||
name: "Релиз: архив исходников"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Тег релиза (например: v2.2.0)"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
DIST_DIR: dist
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: "Упаковка и публикация релиза"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
- name: "Получение исходного кода"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
else
|
||||
TAG="${GITHUB_REF_NAME}"
|
||||
fi
|
||||
|
||||
if [ -z "${TAG}" ]; then
|
||||
echo "ОШИБКА: не удалось определить тег релиза."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> Клонирование ${REPO} (тег: ${TAG})"
|
||||
|
||||
if [ -n "${TOKEN}" ]; then
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
else
|
||||
CLONE_URL="${SERVER}/${REPO}.git"
|
||||
fi
|
||||
|
||||
# Check if tag exists on the remote
|
||||
TAG_EXISTS=false
|
||||
if git ls-remote --exit-code --tags "${CLONE_URL}" "refs/tags/${TAG}" >/dev/null 2>&1; then
|
||||
TAG_EXISTS=true
|
||||
fi
|
||||
|
||||
if [ "${TAG_EXISTS}" = "true" ]; then
|
||||
echo ">>> Тег ${TAG} найден, клонирование..."
|
||||
git clone --branch "${TAG}" --depth 50 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
else
|
||||
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
if [ -z "${DEFAULT_BRANCH}" ] || [ "${DEFAULT_BRANCH}" = "null" ]; then
|
||||
DEFAULT_BRANCH="master"
|
||||
fi
|
||||
echo ">>> Тег ${TAG} не найден, клонирование ветки ${DEFAULT_BRANCH}..."
|
||||
git clone --branch "${DEFAULT_BRANCH}" --depth 50 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
fi
|
||||
|
||||
git fetch --tags --force 2>/dev/null || true
|
||||
|
||||
# If tag doesn't exist locally, create and push it
|
||||
if [ "${TAG_EXISTS}" = "false" ] && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo ">>> Создание тега ${TAG} на текущем коммите ($(git rev-parse --short HEAD))..."
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}" 2>&1 | grep -F -v "${TOKEN:-}" || true
|
||||
echo ">>> Тег ${TAG} создан и отправлен"
|
||||
fi
|
||||
|
||||
echo "RELEASE_TAG=${TAG}" >> "$GITHUB_ENV"
|
||||
echo ">>> Исходный код получен: $(git log --oneline -1 2>/dev/null || echo 'N/A')"
|
||||
|
||||
- name: "Подготовка метаданных релиза"
|
||||
id: meta
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${RELEASE_TAG}"
|
||||
VERSION="${TAG#v}"
|
||||
PREV_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)
|
||||
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "══════════════════════════════════════"
|
||||
echo " Тег: ${TAG}"
|
||||
echo " Версия: ${VERSION}"
|
||||
echo " Пред. тег: ${PREV_TAG:-<первый релиз>}"
|
||||
echo " Коммит: ${GITHUB_SHA:0:8}"
|
||||
echo "══════════════════════════════════════"
|
||||
|
||||
- name: "Создание архивов исходного кода"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
REPO_NAME="${GITHUB_REPOSITORY##*/}"
|
||||
ARCHIVE_BASE="${REPO_NAME}-${TAG}"
|
||||
|
||||
rm -rf .release-work "${DIST_DIR}"
|
||||
mkdir -p .release-work "${DIST_DIR}"
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a \
|
||||
--exclude '.git/' \
|
||||
--exclude '.src-repo/' \
|
||||
--exclude '.wiki-repo/' \
|
||||
--exclude '.release-work/' \
|
||||
--exclude "${DIST_DIR}/" \
|
||||
./ ".release-work/${ARCHIVE_BASE}/"
|
||||
else
|
||||
cp -a . ".release-work/${ARCHIVE_BASE}"
|
||||
rm -rf \
|
||||
".release-work/${ARCHIVE_BASE}/.git" \
|
||||
".release-work/${ARCHIVE_BASE}/.src-repo" \
|
||||
".release-work/${ARCHIVE_BASE}/.wiki-repo" \
|
||||
".release-work/${ARCHIVE_BASE}/.release-work" \
|
||||
".release-work/${ARCHIVE_BASE}/${DIST_DIR}"
|
||||
fi
|
||||
|
||||
tar -czf "${DIST_DIR}/${ARCHIVE_BASE}.tar.gz" -C .release-work "${ARCHIVE_BASE}"
|
||||
|
||||
if command -v zip >/dev/null 2>&1; then
|
||||
(
|
||||
cd .release-work
|
||||
zip -qr "../${DIST_DIR}/${ARCHIVE_BASE}.zip" "${ARCHIVE_BASE}"
|
||||
)
|
||||
else
|
||||
ARCHIVE_BASE="${ARCHIVE_BASE}" DIST_DIR="${DIST_DIR}" python3 - <<'PY'
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
base = os.environ["ARCHIVE_BASE"]
|
||||
src = os.path.join(".release-work", base)
|
||||
dst = os.path.join(os.environ["DIST_DIR"], f"{base}.zip")
|
||||
|
||||
with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for root, _, files in os.walk(src):
|
||||
for file_name in files:
|
||||
full = os.path.join(root, file_name)
|
||||
arc = os.path.relpath(full, ".release-work")
|
||||
zf.write(full, arc)
|
||||
PY
|
||||
fi
|
||||
|
||||
sha256sum "${DIST_DIR}"/* > "${DIST_DIR}/checksums-sha256.txt"
|
||||
|
||||
echo "ARCHIVE_BASE=${ARCHIVE_BASE}" >> "$GITHUB_ENV"
|
||||
echo ">>> Артефакты релиза:"
|
||||
ls -lh "${DIST_DIR}"
|
||||
|
||||
- name: "Генерация описания релиза"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
PREV_TAG="${{ steps.meta.outputs.prev_tag }}"
|
||||
DATE_UTC=$(date -u '+%Y-%m-%d %H:%M UTC')
|
||||
|
||||
CHANGELOG_FILE=""
|
||||
if [ -f "wiki/Changelog.md" ]; then
|
||||
CHANGELOG_FILE="wiki/Changelog.md"
|
||||
elif [ -f "docs/ru/CHANGELOG.md" ]; then
|
||||
CHANGELOG_FILE="docs/ru/CHANGELOG.md"
|
||||
elif [ -f "docs/en/CHANGELOG_EN.md" ]; then
|
||||
CHANGELOG_FILE="docs/en/CHANGELOG_EN.md"
|
||||
fi
|
||||
|
||||
CHANGELOG_SECTION=""
|
||||
if [ -n "${CHANGELOG_FILE}" ]; then
|
||||
# Поддерживаем оба формата заголовков: "## [VERSION]" и "### [VERSION] - DATE"
|
||||
CHANGELOG_SECTION=$(awk -v ver="${VERSION}" '
|
||||
$0 ~ "^#{2,3} \\[" ver "\\]" { in_section=1; next }
|
||||
/^#{2,3} \[/ && in_section { exit }
|
||||
in_section { print }
|
||||
' "${CHANGELOG_FILE}")
|
||||
fi
|
||||
|
||||
COMMITS=""
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
if [ -n "${PREV_TAG}" ]; then
|
||||
COMMITS=$(git log --pretty=format:'- %s (%h)' "${PREV_TAG}..${TAG}" --no-merges | head -50)
|
||||
else
|
||||
COMMITS=$(git log --pretty=format:'- %s (%h)' --no-merges | head -50)
|
||||
fi
|
||||
else
|
||||
echo ">>> Предупреждение: .git недоступен, список коммитов будет пропущен"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "## Release ${TAG}"
|
||||
echo ""
|
||||
echo "Релиз скриптового проекта без компиляции бинарников."
|
||||
echo ""
|
||||
echo "### Что входит в релиз"
|
||||
echo "- Исходный код в форматах: ${ARCHIVE_BASE}.tar.gz, ${ARCHIVE_BASE}.zip"
|
||||
echo "- Контрольные суммы: checksums-sha256.txt"
|
||||
echo ""
|
||||
|
||||
if [ -n "${CHANGELOG_SECTION}" ]; then
|
||||
echo "### Что сделано (из CHANGELOG)"
|
||||
echo "${CHANGELOG_SECTION}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "### Коммиты релиза"
|
||||
if [ -n "${COMMITS}" ]; then
|
||||
echo "${COMMITS}"
|
||||
else
|
||||
echo "- Недоступно (runner без .git)"
|
||||
fi
|
||||
echo ""
|
||||
echo "---"
|
||||
echo ""
|
||||
echo "- Тег: ${TAG}"
|
||||
echo "- Коммит: ${GITHUB_SHA}"
|
||||
echo "- Дата (UTC): ${DATE_UTC}"
|
||||
} > /tmp/release_body.md
|
||||
|
||||
echo ">>> Сформировано описание релиза: /tmp/release_body.md"
|
||||
|
||||
- name: "Создание релиза и загрузка архивов"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
echo "ОШИБКА: не задан секрет GIT_TOKEN (или GITEA_TOKEN)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
|
||||
# Set up API URLs and auth header early (needed for tag check below)
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CREATE_URL="https://api.github.com/repos/${REPO}/releases"
|
||||
AUTH_HEADER="Authorization: Bearer ${TOKEN}"
|
||||
EXTRA_HEADERS=(-H "Accept: application/vnd.github+json")
|
||||
else
|
||||
CREATE_URL="${SERVER}/api/v1/repos/${REPO}/releases"
|
||||
AUTH_HEADER="Authorization: token ${TOKEN}"
|
||||
EXTRA_HEADERS=()
|
||||
fi
|
||||
|
||||
TARGET_COMMITISH="${RELEASE_REF:-${{ github.event.repository.default_branch }}}"
|
||||
if [ -z "${TARGET_COMMITISH}" ] || [ "${TARGET_COMMITISH}" = "null" ]; then
|
||||
TARGET_COMMITISH="master"
|
||||
fi
|
||||
if [ -n "${GITHUB_SHA:-}" ]; then
|
||||
TARGET_COMMITISH="${GITHUB_SHA}"
|
||||
fi
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
TARGET_COMMITISH="$(git rev-list -n 1 "${TAG}" 2>/dev/null || echo "${TARGET_COMMITISH}")"
|
||||
fi
|
||||
|
||||
# Ensure the tag exists on the remote (Gitea requires it before creating a release)
|
||||
if [ "${HOST}" != "github.com" ]; then
|
||||
TAG_HTTP_CODE=$(curl -sS -o /dev/null -w '%{http_code}' \
|
||||
-H "${AUTH_HEADER}" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/tags/${TAG}")
|
||||
if [ "${TAG_HTTP_CODE}" != "200" ]; then
|
||||
echo ">>> Тег ${TAG} не найден на сервере (HTTP ${TAG_HTTP_CODE}), создание через API..."
|
||||
TAG_CREATE_RESP=$(curl -sS -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/tags" \
|
||||
-d "{\"tag_name\":\"${TAG}\",\"target\":\"${TARGET_COMMITISH}\"}")
|
||||
echo ">>> Ответ создания тега: ${TAG_CREATE_RESP}"
|
||||
else
|
||||
echo ">>> Тег ${TAG} существует на сервере"
|
||||
fi
|
||||
fi
|
||||
|
||||
BODY_JSON=$(python3 - <<'PY'
|
||||
import json
|
||||
|
||||
with open('/tmp/release_body.md', 'r', encoding='utf-8') as f:
|
||||
print(json.dumps(f.read(), ensure_ascii=False))
|
||||
PY
|
||||
)
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
RELEASE_PAYLOAD="{\"tag_name\":\"${TAG}\",\"target_commitish\":\"${TARGET_COMMITISH}\",\"name\":\"Release ${TAG}\",\"body\":${BODY_JSON},\"draft\":false,\"prerelease\":false}"
|
||||
else
|
||||
RELEASE_PAYLOAD="{\"tag_name\":\"${TAG}\",\"target\":\"${TARGET_COMMITISH}\",\"title\":\"Release ${TAG}\",\"note\":${BODY_JSON},\"draft\":false,\"prerelease\":false}"
|
||||
fi
|
||||
|
||||
echo ">>> Создание релиза для тега ${TAG}..."
|
||||
RELEASE_JSON=$(curl -sS -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${EXTRA_HEADERS[@]}" \
|
||||
"${CREATE_URL}" \
|
||||
-d "${RELEASE_PAYLOAD}")
|
||||
|
||||
if ! printf '%s' "${RELEASE_JSON}" | python3 -c "import sys, json; j=json.load(sys.stdin); print(j.get('id',''));" >/tmp/release_id.txt 2>/dev/null; then
|
||||
echo "ОШИБКА: API вернул не-JSON при создании релиза"
|
||||
echo "Ответ: ${RELEASE_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_ID=$(cat /tmp/release_id.txt)
|
||||
rm -f /tmp/release_id.txt
|
||||
|
||||
if [ -z "${RELEASE_ID}" ] && [ "${HOST}" != "github.com" ]; then
|
||||
echo ">>> Не удалось получить ID из create-response, пытаемся найти существующий релиз по тегу ${TAG}..."
|
||||
RELEASE_JSON=$(curl -sS \
|
||||
-H "${AUTH_HEADER}" \
|
||||
"${SERVER}/api/v1/repos/${REPO}/releases/tags/${TAG}")
|
||||
|
||||
if printf '%s' "${RELEASE_JSON}" | python3 -c "import sys, json; j=json.load(sys.stdin); print(j.get('id',''));" >/tmp/release_id.txt 2>/dev/null; then
|
||||
RELEASE_ID=$(cat /tmp/release_id.txt)
|
||||
fi
|
||||
rm -f /tmp/release_id.txt
|
||||
fi
|
||||
|
||||
if [ -z "${RELEASE_ID}" ]; then
|
||||
echo "ОШИБКА: не удалось получить ID релиза"
|
||||
echo "${RELEASE_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
UPLOAD_BASE=$(printf '%s' "${RELEASE_JSON}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('upload_url','').split('{')[0])")
|
||||
RELEASE_URL="https://github.com/${REPO}/releases/tag/${TAG}"
|
||||
else
|
||||
UPLOAD_BASE="${SERVER}/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets"
|
||||
RELEASE_URL="${SERVER}/${REPO}/releases/tag/${TAG}"
|
||||
fi
|
||||
|
||||
echo ">>> Загрузка файлов в релиз ${TAG}"
|
||||
for file in "${DIST_DIR}"/*; do
|
||||
[ -f "${file}" ] || continue
|
||||
name=$(basename "${file}")
|
||||
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
curl -sf -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
"${EXTRA_HEADERS[@]}" \
|
||||
--data-binary @"${file}" \
|
||||
"${UPLOAD_BASE}?name=${name}" >/dev/null
|
||||
else
|
||||
curl -sf -X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"${file}" \
|
||||
"${UPLOAD_BASE}?name=${name}" >/dev/null
|
||||
fi
|
||||
|
||||
echo " ✓ ${name}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo ">>> Релиз опубликован: ${RELEASE_URL}"
|
||||
|
||||
+141
-141
@@ -1,141 +1,141 @@
|
||||
name: "Синхронизация Wiki"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "Branch or tag to run wiki sync from"
|
||||
required: false
|
||||
default: "master"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'wiki/**'
|
||||
|
||||
jobs:
|
||||
sync-wiki:
|
||||
name: "Синхронизация Wiki"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
# ── Получение исходного кода (без actions/checkout) ────────────────
|
||||
- name: "Получение исходного кода"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
redact() {
|
||||
local token="$1"
|
||||
if [ -n "${token}" ]; then
|
||||
grep -F -v "${token}" || true
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
echo ">>> Клонирование ${REPO}..."
|
||||
|
||||
if [ -d ".src-repo" ]; then
|
||||
rm -rf .src-repo
|
||||
fi
|
||||
|
||||
if [ -n "${GIT_TOKEN}" ]; then
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${GIT_TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
else
|
||||
CLONE_URL="${SERVER}/${REPO}.git"
|
||||
fi
|
||||
|
||||
git clone --depth 1 "${CLONE_URL}" .src-repo 2>&1 | redact "${GIT_TOKEN}"
|
||||
echo ">>> Исходный код получен: $(cd .src-repo && git log --oneline -1)"
|
||||
|
||||
- name: "Проверка папки wiki/"
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -d ".src-repo/wiki" ]; then
|
||||
echo "Папка wiki/ не найдена — синхронизация не требуется."
|
||||
exit 0
|
||||
fi
|
||||
echo ">>> Найдено файлов wiki: $(find .src-repo/wiki -type f | wc -l)"
|
||||
|
||||
- name: "Синхронизация wiki в DFGit Wiki"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
redact() {
|
||||
local token="$1"
|
||||
if [ -n "${token}" ]; then
|
||||
grep -F -v "${token}" || true
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "${GIT_TOKEN}" ]; then
|
||||
echo "GIT_TOKEN не задан. Добавьте секрет в настройках: Settings -> Secrets -> Actions."
|
||||
echo "Пропуск синхронизации wiki без ошибки."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
WIKI_REPO_URL="${SERVER}/${REPO}.wiki.git"
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
AUTH_WIKI_REPO_URL="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO}.wiki.git"
|
||||
else
|
||||
AUTH_WIKI_REPO_URL="https://oauth2:${GIT_TOKEN}@${HOST}/${REPO}.wiki.git"
|
||||
fi
|
||||
|
||||
echo ">>> Клонируем wiki-репозиторий..."
|
||||
if ! git clone --depth 1 "${AUTH_WIKI_REPO_URL}" .wiki-repo 2>&1 | redact "${GIT_TOKEN}"; then
|
||||
echo "Wiki-репозиторий недоступен или ещё не инициализирован: ${WIKI_REPO_URL}"
|
||||
echo "Пропуск синхронизации без ошибки."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# rsync или резервный вариант через cp
|
||||
if command -v rsync &>/dev/null; then
|
||||
rsync -a --delete --exclude '.git/' .src-repo/wiki/ .wiki-repo/
|
||||
else
|
||||
# Удаляем старые файлы (кроме .git) и копируем новые
|
||||
find .wiki-repo -mindepth 1 -not -path '.wiki-repo/.git/*' -not -name '.git' -delete 2>/dev/null || true
|
||||
cp -a .src-repo/wiki/* .wiki-repo/
|
||||
fi
|
||||
|
||||
cd .wiki-repo
|
||||
git add -A
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo ">>> Изменений в wiki нет — пуш не требуется."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "dfgit-actions[bot]"
|
||||
git config user.email "dfgit-actions@local"
|
||||
|
||||
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | sed -n '/HEAD branch/s/.*: //p')
|
||||
if [ -z "${DEFAULT_BRANCH}" ]; then
|
||||
DEFAULT_BRANCH="master"
|
||||
fi
|
||||
|
||||
git commit -m "docs(wiki): синхронизация из master @ ${{ github.sha }}"
|
||||
git push origin "HEAD:${DEFAULT_BRANCH}" 2>&1 | redact "${GIT_TOKEN}"
|
||||
|
||||
echo ">>> Wiki синхронизирована в ветку ${DEFAULT_BRANCH}."
|
||||
name: "Синхронизация Wiki"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "Branch or tag to run wiki sync from"
|
||||
required: false
|
||||
default: "master"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'wiki/**'
|
||||
|
||||
jobs:
|
||||
sync-wiki:
|
||||
name: "Синхронизация Wiki"
|
||||
runs-on: native
|
||||
|
||||
steps:
|
||||
# ── Получение исходного кода (без actions/checkout) ────────────────
|
||||
- name: "Получение исходного кода"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
redact() {
|
||||
local token="$1"
|
||||
if [ -n "${token}" ]; then
|
||||
grep -F -v "${token}" || true
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
echo ">>> Клонирование ${REPO}..."
|
||||
|
||||
if [ -d ".src-repo" ]; then
|
||||
rm -rf .src-repo
|
||||
fi
|
||||
|
||||
if [ -n "${GIT_TOKEN}" ]; then
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
CLONE_URL="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO}.git"
|
||||
else
|
||||
CLONE_URL="https://${GIT_TOKEN}@${HOST}/${REPO}.git"
|
||||
fi
|
||||
else
|
||||
CLONE_URL="${SERVER}/${REPO}.git"
|
||||
fi
|
||||
|
||||
git clone --depth 1 "${CLONE_URL}" .src-repo 2>&1 | redact "${GIT_TOKEN}"
|
||||
echo ">>> Исходный код получен: $(cd .src-repo && git log --oneline -1)"
|
||||
|
||||
- name: "Проверка папки wiki/"
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -d ".src-repo/wiki" ]; then
|
||||
echo "Папка wiki/ не найдена — синхронизация не требуется."
|
||||
exit 0
|
||||
fi
|
||||
echo ">>> Найдено файлов wiki: $(find .src-repo/wiki -type f | wc -l)"
|
||||
|
||||
- name: "Синхронизация wiki в DFGit Wiki"
|
||||
shell: bash
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
redact() {
|
||||
local token="$1"
|
||||
if [ -n "${token}" ]; then
|
||||
grep -F -v "${token}" || true
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "${GIT_TOKEN}" ]; then
|
||||
echo "GIT_TOKEN не задан. Добавьте секрет в настройках: Settings -> Secrets -> Actions."
|
||||
echo "Пропуск синхронизации wiki без ошибки."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SERVER="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
HOST="${SERVER#https://}"
|
||||
HOST="${HOST#http://}"
|
||||
|
||||
WIKI_REPO_URL="${SERVER}/${REPO}.wiki.git"
|
||||
if [ "${HOST}" = "github.com" ]; then
|
||||
AUTH_WIKI_REPO_URL="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO}.wiki.git"
|
||||
else
|
||||
AUTH_WIKI_REPO_URL="https://oauth2:${GIT_TOKEN}@${HOST}/${REPO}.wiki.git"
|
||||
fi
|
||||
|
||||
echo ">>> Клонируем wiki-репозиторий..."
|
||||
if ! git clone --depth 1 "${AUTH_WIKI_REPO_URL}" .wiki-repo 2>&1 | redact "${GIT_TOKEN}"; then
|
||||
echo "Wiki-репозиторий недоступен или ещё не инициализирован: ${WIKI_REPO_URL}"
|
||||
echo "Пропуск синхронизации без ошибки."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# rsync или резервный вариант через cp
|
||||
if command -v rsync &>/dev/null; then
|
||||
rsync -a --delete --exclude '.git/' .src-repo/wiki/ .wiki-repo/
|
||||
else
|
||||
# Удаляем старые файлы (кроме .git) и копируем новые
|
||||
find .wiki-repo -mindepth 1 -not -path '.wiki-repo/.git/*' -not -name '.git' -delete 2>/dev/null || true
|
||||
cp -a .src-repo/wiki/* .wiki-repo/
|
||||
fi
|
||||
|
||||
cd .wiki-repo
|
||||
git add -A
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo ">>> Изменений в wiki нет — пуш не требуется."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "dfgit-actions[bot]"
|
||||
git config user.email "dfgit-actions@local"
|
||||
|
||||
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | sed -n '/HEAD branch/s/.*: //p')
|
||||
if [ -z "${DEFAULT_BRANCH}" ]; then
|
||||
DEFAULT_BRANCH="master"
|
||||
fi
|
||||
|
||||
git commit -m "docs(wiki): синхронизация из master @ ${{ github.sha }}"
|
||||
git push origin "HEAD:${DEFAULT_BRANCH}" 2>&1 | redact "${GIT_TOKEN}"
|
||||
|
||||
echo ">>> Wiki синхронизирована в ветку ${DEFAULT_BRANCH}."
|
||||
|
||||
+193
-193
@@ -1,193 +1,193 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
PIPE_MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# PyInstaller build artifacts
|
||||
build/
|
||||
dist/
|
||||
*.tar.gz
|
||||
*.zip
|
||||
*.sha256
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
Pipfile.lock
|
||||
|
||||
# poetry
|
||||
poetry.lock
|
||||
|
||||
# pdm
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# SSL Certificates and Keys (CRITICAL - DO NOT COMMIT!)
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.csr
|
||||
*.pfx
|
||||
*.p12
|
||||
/ssl/
|
||||
/certs/
|
||||
|
||||
# Configuration files with credentials
|
||||
config.yml
|
||||
config.json
|
||||
.regru_credentials
|
||||
credentials.txt
|
||||
*.secret
|
||||
config.json
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
/var/log/
|
||||
|
||||
# OS-specific
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
|
||||
# Test certificates
|
||||
test_certs/
|
||||
*.test.pem
|
||||
*.test.key
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
*.backup
|
||||
*~
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
PIPE_MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# PyInstaller build artifacts
|
||||
build/
|
||||
dist/
|
||||
*.tar.gz
|
||||
*.zip
|
||||
*.sha256
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
Pipfile.lock
|
||||
|
||||
# poetry
|
||||
poetry.lock
|
||||
|
||||
# pdm
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# SSL Certificates and Keys (CRITICAL - DO NOT COMMIT!)
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.csr
|
||||
*.pfx
|
||||
*.p12
|
||||
/ssl/
|
||||
/certs/
|
||||
|
||||
# Configuration files with credentials
|
||||
config.yml
|
||||
config.json
|
||||
.regru_credentials
|
||||
credentials.txt
|
||||
*.secret
|
||||
config.json
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
/var/log/
|
||||
|
||||
# OS-specific
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
|
||||
# Test certificates
|
||||
test_certs/
|
||||
*.test.pem
|
||||
*.test.key
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
*.backup
|
||||
*~
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
|
||||
+21
-21
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"domains": [
|
||||
"*.example.com,example.com",
|
||||
"gitea.example.com"
|
||||
],
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://192.0.2.1:81",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "changeme"
|
||||
}
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"domains": [
|
||||
"*.example.com,example.com",
|
||||
"gitea.example.com"
|
||||
],
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://192.0.2.1:81",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "changeme"
|
||||
}
|
||||
|
||||
+168
-168
@@ -1,168 +1,168 @@
|
||||
# Git Hooks для Gitea
|
||||
|
||||
Автоматическая синхронизация с GitHub после push в Gitea.
|
||||
|
||||
## 📁 Файлы
|
||||
|
||||
- **post-receive** - Hook для автоматического push в GitHub
|
||||
|
||||
## 🚀 Установка
|
||||
|
||||
### 1. Найдите путь к репозиторию на сервере Gitea
|
||||
|
||||
```bash
|
||||
# Обычно это один из путей:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
# или
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
### 2. Скопируйте hook
|
||||
|
||||
```bash
|
||||
# На сервере Gitea
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
# Скопируйте файл
|
||||
cp /path/to/this/repo/gitea-hooks/post-receive ./
|
||||
|
||||
# Или загрузите напрямую
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
```
|
||||
|
||||
### 3. Настройте hook
|
||||
|
||||
```bash
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
Измените:
|
||||
```bash
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
### 4. Сделайте исполняемым
|
||||
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
chown git:git post-receive
|
||||
```
|
||||
|
||||
### 5. Создайте директорию для логов
|
||||
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
## 🔑 Настройка аутентификации
|
||||
|
||||
### Вариант A: SSH (Рекомендуется)
|
||||
|
||||
```bash
|
||||
# На сервере Gitea под пользователем git
|
||||
sudo su - git
|
||||
ssh-keygen -t ed25519 -C "gitea-sync"
|
||||
|
||||
# Скопируйте публичный ключ
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
|
||||
# Добавьте на GitHub:
|
||||
# Settings → SSH and GPG keys → New SSH key
|
||||
|
||||
# Проверьте
|
||||
ssh -T git@github.com
|
||||
```
|
||||
|
||||
### Вариант B: HTTPS с токеном
|
||||
|
||||
1. Создайте Personal Access Token на GitHub
|
||||
- Settings → Developer settings → Personal access tokens
|
||||
- Scope: `repo`
|
||||
|
||||
2. Используйте в hook:
|
||||
```bash
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
## ✅ Проверка
|
||||
|
||||
```bash
|
||||
# Тестовый push
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync"
|
||||
git push
|
||||
|
||||
# Проверьте лог
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Проверьте GitHub - изменения должны появиться через 1-2 секунды
|
||||
```
|
||||
|
||||
## 📊 Что делает hook
|
||||
|
||||
1. ✅ Отслеживает push в ветки `main` и `master`
|
||||
2. ✅ Автоматически пушит в GitHub
|
||||
3. ✅ Синхронизирует теги
|
||||
4. ✅ Логирует все операции
|
||||
5. ✅ Показывает красивый вывод с эмодзи
|
||||
|
||||
## 🐛 Устранение проблем
|
||||
|
||||
### Hook не срабатывает
|
||||
|
||||
```bash
|
||||
# Проверьте права
|
||||
ls -la post-receive
|
||||
# Должно быть: -rwxr-xr-x
|
||||
|
||||
# Проверьте владельца
|
||||
chown git:git post-receive
|
||||
|
||||
# Проверьте синтаксис
|
||||
bash -n post-receive
|
||||
```
|
||||
|
||||
### Permission denied
|
||||
|
||||
```bash
|
||||
# Для SSH
|
||||
ssh -T git@github.com
|
||||
|
||||
# Проверьте права на ключ
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
|
||||
# Для HTTPS - проверьте токен
|
||||
```
|
||||
|
||||
### Не находит git
|
||||
|
||||
```bash
|
||||
# Добавьте PATH в начало hook:
|
||||
export PATH=/usr/bin:/usr/local/bin:$PATH
|
||||
```
|
||||
|
||||
## 📝 Логи
|
||||
|
||||
```bash
|
||||
# Просмотр логов синхронизации
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Очистка старых логов
|
||||
> /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
## 🔄 Альтернативы
|
||||
|
||||
Если Git Hook не подходит, см. другие методы в [GITEA_SYNC.md](../GITEA_SYNC.md):
|
||||
- GitHub Actions (каждый час)
|
||||
- Gitea Mirror (встроенная функция)
|
||||
- Двойной remote (локально)
|
||||
|
||||
---
|
||||
|
||||
**См. также**: [GITEA_SYNC.md](../GITEA_SYNC.md) для подробной документации
|
||||
# Git Hooks для Gitea
|
||||
|
||||
Автоматическая синхронизация с GitHub после push в Gitea.
|
||||
|
||||
## 📁 Файлы
|
||||
|
||||
- **post-receive** - Hook для автоматического push в GitHub
|
||||
|
||||
## 🚀 Установка
|
||||
|
||||
### 1. Найдите путь к репозиторию на сервере Gitea
|
||||
|
||||
```bash
|
||||
# Обычно это один из путей:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
# или
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
### 2. Скопируйте hook
|
||||
|
||||
```bash
|
||||
# На сервере Gitea
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
# Скопируйте файл
|
||||
cp /path/to/this/repo/gitea-hooks/post-receive ./
|
||||
|
||||
# Или загрузите напрямую
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
```
|
||||
|
||||
### 3. Настройте hook
|
||||
|
||||
```bash
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
Измените:
|
||||
```bash
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
### 4. Сделайте исполняемым
|
||||
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
chown git:git post-receive
|
||||
```
|
||||
|
||||
### 5. Создайте директорию для логов
|
||||
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
## 🔑 Настройка аутентификации
|
||||
|
||||
### Вариант A: SSH (Рекомендуется)
|
||||
|
||||
```bash
|
||||
# На сервере Gitea под пользователем git
|
||||
sudo su - git
|
||||
ssh-keygen -t ed25519 -C "gitea-sync"
|
||||
|
||||
# Скопируйте публичный ключ
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
|
||||
# Добавьте на GitHub:
|
||||
# Settings → SSH and GPG keys → New SSH key
|
||||
|
||||
# Проверьте
|
||||
ssh -T git@github.com
|
||||
```
|
||||
|
||||
### Вариант B: HTTPS с токеном
|
||||
|
||||
1. Создайте Personal Access Token на GitHub
|
||||
- Settings → Developer settings → Personal access tokens
|
||||
- Scope: `repo`
|
||||
|
||||
2. Используйте в hook:
|
||||
```bash
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
## ✅ Проверка
|
||||
|
||||
```bash
|
||||
# Тестовый push
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync"
|
||||
git push
|
||||
|
||||
# Проверьте лог
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Проверьте GitHub - изменения должны появиться через 1-2 секунды
|
||||
```
|
||||
|
||||
## 📊 Что делает hook
|
||||
|
||||
1. ✅ Отслеживает push в ветки `main` и `master`
|
||||
2. ✅ Автоматически пушит в GitHub
|
||||
3. ✅ Синхронизирует теги
|
||||
4. ✅ Логирует все операции
|
||||
5. ✅ Показывает красивый вывод с эмодзи
|
||||
|
||||
## 🐛 Устранение проблем
|
||||
|
||||
### Hook не срабатывает
|
||||
|
||||
```bash
|
||||
# Проверьте права
|
||||
ls -la post-receive
|
||||
# Должно быть: -rwxr-xr-x
|
||||
|
||||
# Проверьте владельца
|
||||
chown git:git post-receive
|
||||
|
||||
# Проверьте синтаксис
|
||||
bash -n post-receive
|
||||
```
|
||||
|
||||
### Permission denied
|
||||
|
||||
```bash
|
||||
# Для SSH
|
||||
ssh -T git@github.com
|
||||
|
||||
# Проверьте права на ключ
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
|
||||
# Для HTTPS - проверьте токен
|
||||
```
|
||||
|
||||
### Не находит git
|
||||
|
||||
```bash
|
||||
# Добавьте PATH в начало hook:
|
||||
export PATH=/usr/bin:/usr/local/bin:$PATH
|
||||
```
|
||||
|
||||
## 📝 Логи
|
||||
|
||||
```bash
|
||||
# Просмотр логов синхронизации
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Очистка старых логов
|
||||
> /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
## 🔄 Альтернативы
|
||||
|
||||
Если Git Hook не подходит, см. другие методы в [GITEA_SYNC.md](../GITEA_SYNC.md):
|
||||
- GitHub Actions (каждый час)
|
||||
- Gitea Mirror (встроенная функция)
|
||||
- Двойной remote (локально)
|
||||
|
||||
---
|
||||
|
||||
**См. также**: [GITEA_SYNC.md](../GITEA_SYNC.md) для подробной документации
|
||||
|
||||
+168
-168
@@ -1,168 +1,168 @@
|
||||
# Git Hooks for Gitea
|
||||
|
||||
Automatic synchronization with GitHub after push to Gitea.
|
||||
|
||||
## 📁 Files
|
||||
|
||||
- **post-receive** - Hook for automatic push to GitHub
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Find Repository Path on Gitea Server
|
||||
|
||||
```bash
|
||||
# Usually one of these paths:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
# or
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
### 2. Copy Hook
|
||||
|
||||
```bash
|
||||
# On Gitea server
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
# Copy file
|
||||
cp /path/to/this/repo/gitea-hooks/post-receive ./
|
||||
|
||||
# Or download directly
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
```
|
||||
|
||||
### 3. Configure Hook
|
||||
|
||||
```bash
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
Change:
|
||||
```bash
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
### 4. Make Executable
|
||||
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
chown git:git post-receive
|
||||
```
|
||||
|
||||
### 5. Create Log Directory
|
||||
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
## 🔑 Authentication Setup
|
||||
|
||||
### Option A: SSH (Recommended)
|
||||
|
||||
```bash
|
||||
# On Gitea server as git user
|
||||
sudo su - git
|
||||
ssh-keygen -t ed25519 -C "gitea-sync"
|
||||
|
||||
# Copy public key
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
|
||||
# Add to GitHub:
|
||||
# Settings → SSH and GPG keys → New SSH key
|
||||
|
||||
# Verify
|
||||
ssh -T git@github.com
|
||||
```
|
||||
|
||||
### Option B: HTTPS with Token
|
||||
|
||||
1. Create Personal Access Token on GitHub
|
||||
- Settings → Developer settings → Personal access tokens
|
||||
- Scope: `repo`
|
||||
|
||||
2. Use in hook:
|
||||
```bash
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
```bash
|
||||
# Test push
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync"
|
||||
git push
|
||||
|
||||
# Check log
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Check GitHub - changes should appear in 1-2 seconds
|
||||
```
|
||||
|
||||
## 📊 What Hook Does
|
||||
|
||||
1. ✅ Monitors pushes to `main` and `master` branches
|
||||
2. ✅ Automatically pushes to GitHub
|
||||
3. ✅ Synchronizes tags
|
||||
4. ✅ Logs all operations
|
||||
5. ✅ Shows beautiful output with emojis
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Hook Not Firing
|
||||
|
||||
```bash
|
||||
# Check permissions
|
||||
ls -la post-receive
|
||||
# Should be: -rwxr-xr-x
|
||||
|
||||
# Check owner
|
||||
chown git:git post-receive
|
||||
|
||||
# Check syntax
|
||||
bash -n post-receive
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
|
||||
```bash
|
||||
# For SSH
|
||||
ssh -T git@github.com
|
||||
|
||||
# Check key permissions
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
|
||||
# For HTTPS - check token
|
||||
```
|
||||
|
||||
### Can't Find Git
|
||||
|
||||
```bash
|
||||
# Add PATH to beginning of hook:
|
||||
export PATH=/usr/bin:/usr/local/bin:$PATH
|
||||
```
|
||||
|
||||
## 📝 Logs
|
||||
|
||||
```bash
|
||||
# View sync logs
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Clear old logs
|
||||
> /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
## 🔄 Alternatives
|
||||
|
||||
If Git Hook doesn't work, see other methods in [GITEA_SYNC_EN.md](../GITEA_SYNC_EN.md):
|
||||
- GitHub Actions (every hour)
|
||||
- Gitea Mirror (built-in feature)
|
||||
- Double remote (locally)
|
||||
|
||||
---
|
||||
|
||||
**See also**: [GITEA_SYNC_EN.md](../GITEA_SYNC_EN.md) for detailed documentation
|
||||
# Git Hooks for Gitea
|
||||
|
||||
Automatic synchronization with GitHub after push to Gitea.
|
||||
|
||||
## 📁 Files
|
||||
|
||||
- **post-receive** - Hook for automatic push to GitHub
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Find Repository Path on Gitea Server
|
||||
|
||||
```bash
|
||||
# Usually one of these paths:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
# or
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
### 2. Copy Hook
|
||||
|
||||
```bash
|
||||
# On Gitea server
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
# Copy file
|
||||
cp /path/to/this/repo/gitea-hooks/post-receive ./
|
||||
|
||||
# Or download directly
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
```
|
||||
|
||||
### 3. Configure Hook
|
||||
|
||||
```bash
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
Change:
|
||||
```bash
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
### 4. Make Executable
|
||||
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
chown git:git post-receive
|
||||
```
|
||||
|
||||
### 5. Create Log Directory
|
||||
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
## 🔑 Authentication Setup
|
||||
|
||||
### Option A: SSH (Recommended)
|
||||
|
||||
```bash
|
||||
# On Gitea server as git user
|
||||
sudo su - git
|
||||
ssh-keygen -t ed25519 -C "gitea-sync"
|
||||
|
||||
# Copy public key
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
|
||||
# Add to GitHub:
|
||||
# Settings → SSH and GPG keys → New SSH key
|
||||
|
||||
# Verify
|
||||
ssh -T git@github.com
|
||||
```
|
||||
|
||||
### Option B: HTTPS with Token
|
||||
|
||||
1. Create Personal Access Token on GitHub
|
||||
- Settings → Developer settings → Personal access tokens
|
||||
- Scope: `repo`
|
||||
|
||||
2. Use in hook:
|
||||
```bash
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
```bash
|
||||
# Test push
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync"
|
||||
git push
|
||||
|
||||
# Check log
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Check GitHub - changes should appear in 1-2 seconds
|
||||
```
|
||||
|
||||
## 📊 What Hook Does
|
||||
|
||||
1. ✅ Monitors pushes to `main` and `master` branches
|
||||
2. ✅ Automatically pushes to GitHub
|
||||
3. ✅ Synchronizes tags
|
||||
4. ✅ Logs all operations
|
||||
5. ✅ Shows beautiful output with emojis
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Hook Not Firing
|
||||
|
||||
```bash
|
||||
# Check permissions
|
||||
ls -la post-receive
|
||||
# Should be: -rwxr-xr-x
|
||||
|
||||
# Check owner
|
||||
chown git:git post-receive
|
||||
|
||||
# Check syntax
|
||||
bash -n post-receive
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
|
||||
```bash
|
||||
# For SSH
|
||||
ssh -T git@github.com
|
||||
|
||||
# Check key permissions
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
|
||||
# For HTTPS - check token
|
||||
```
|
||||
|
||||
### Can't Find Git
|
||||
|
||||
```bash
|
||||
# Add PATH to beginning of hook:
|
||||
export PATH=/usr/bin:/usr/local/bin:$PATH
|
||||
```
|
||||
|
||||
## 📝 Logs
|
||||
|
||||
```bash
|
||||
# View sync logs
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
# Clear old logs
|
||||
> /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
## 🔄 Alternatives
|
||||
|
||||
If Git Hook doesn't work, see other methods in [GITEA_SYNC_EN.md](../GITEA_SYNC_EN.md):
|
||||
- GitHub Actions (every hour)
|
||||
- Gitea Mirror (built-in feature)
|
||||
- Double remote (locally)
|
||||
|
||||
---
|
||||
|
||||
**See also**: [GITEA_SYNC_EN.md](../GITEA_SYNC_EN.md) for detailed documentation
|
||||
|
||||
+83
-83
@@ -1,83 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Post-receive hook для Gitea
|
||||
# Автоматически синхронизирует изменения с GitHub после push
|
||||
#
|
||||
# Установка:
|
||||
# 1. Разместить в: /path/to/gitea/data/gitea-repositories/username/repo.git/hooks/
|
||||
# 2. Переименовать в: post-receive
|
||||
# 3. chmod +x post-receive
|
||||
# 4. Настроить переменные ниже
|
||||
# ==============================================================================
|
||||
|
||||
# Конфигурация
|
||||
GITHUB_REPO="git@github.com:username/configure_nginx_manager.git"
|
||||
# Или с HTTPS и токеном:
|
||||
# GITHUB_REPO="https://YOUR_GITHUB_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
|
||||
LOG_FILE="/var/log/gitea/github-sync.log"
|
||||
|
||||
# Цвета для логов
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ==============================================================================
|
||||
# Функция логирования
|
||||
# ==============================================================================
|
||||
log() {
|
||||
echo -e "${2:-$NC}[$(date +'%d.%m.%Y %H:%M:%S')] $1${NC}" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Основная логика
|
||||
# ==============================================================================
|
||||
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
log "🔄 Начало синхронизации с GitHub" "$GREEN"
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
|
||||
# Читаем информацию о push
|
||||
while read oldrev newrev refname; do
|
||||
log "📝 Изменения обнаружены:" "$YELLOW"
|
||||
log " Branch: ${refname#refs/heads/}"
|
||||
log " Old commit: ${oldrev:0:8}"
|
||||
log " New commit: ${newrev:0:8}"
|
||||
|
||||
# Проверяем наличие GitHub remote
|
||||
if ! git remote | grep -q github; then
|
||||
log "➕ Добавление GitHub remote..." "$YELLOW"
|
||||
git remote add github "$GITHUB_REPO" 2>&1 | tee -a "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Пушим в GitHub
|
||||
log "⬆️ Отправка изменений в GitHub..." "$YELLOW"
|
||||
|
||||
# Только для main/master веток
|
||||
if [[ "$refname" == "refs/heads/main" ]] || [[ "$refname" == "refs/heads/master" ]]; then
|
||||
if git push github "$refname" --force 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "✅ Успешно синхронизировано с GitHub" "$GREEN"
|
||||
else
|
||||
log "❌ Ошибка при синхронизации с GitHub" "$RED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Пушим теги
|
||||
log "🏷️ Отправка тегов..." "$YELLOW"
|
||||
if git push github --tags 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "✅ Теги синхронизированы" "$GREEN"
|
||||
else
|
||||
log "⚠️ Не удалось синхронизировать теги" "$YELLOW"
|
||||
fi
|
||||
else
|
||||
log "ℹ️ Ветка ${refname#refs/heads/} игнорируется (не main/master)" "$YELLOW"
|
||||
fi
|
||||
done
|
||||
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
log "✅ Синхронизация завершена" "$GREEN"
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
|
||||
exit 0
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Post-receive hook для Gitea
|
||||
# Автоматически синхронизирует изменения с GitHub после push
|
||||
#
|
||||
# Установка:
|
||||
# 1. Разместить в: /path/to/gitea/data/gitea-repositories/username/repo.git/hooks/
|
||||
# 2. Переименовать в: post-receive
|
||||
# 3. chmod +x post-receive
|
||||
# 4. Настроить переменные ниже
|
||||
# ==============================================================================
|
||||
|
||||
# Конфигурация
|
||||
GITHUB_REPO="git@github.com:username/configure_nginx_manager.git"
|
||||
# Или с HTTPS и токеном:
|
||||
# GITHUB_REPO="https://YOUR_GITHUB_TOKEN@github.com/username/configure_nginx_manager.git"
|
||||
|
||||
LOG_FILE="/var/log/gitea/github-sync.log"
|
||||
|
||||
# Цвета для логов
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ==============================================================================
|
||||
# Функция логирования
|
||||
# ==============================================================================
|
||||
log() {
|
||||
echo -e "${2:-$NC}[$(date +'%d.%m.%Y %H:%M:%S')] $1${NC}" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# Основная логика
|
||||
# ==============================================================================
|
||||
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
log "🔄 Начало синхронизации с GitHub" "$GREEN"
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
|
||||
# Читаем информацию о push
|
||||
while read oldrev newrev refname; do
|
||||
log "📝 Изменения обнаружены:" "$YELLOW"
|
||||
log " Branch: ${refname#refs/heads/}"
|
||||
log " Old commit: ${oldrev:0:8}"
|
||||
log " New commit: ${newrev:0:8}"
|
||||
|
||||
# Проверяем наличие GitHub remote
|
||||
if ! git remote | grep -q github; then
|
||||
log "➕ Добавление GitHub remote..." "$YELLOW"
|
||||
git remote add github "$GITHUB_REPO" 2>&1 | tee -a "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Пушим в GitHub
|
||||
log "⬆️ Отправка изменений в GitHub..." "$YELLOW"
|
||||
|
||||
# Только для main/master веток
|
||||
if [[ "$refname" == "refs/heads/main" ]] || [[ "$refname" == "refs/heads/master" ]]; then
|
||||
if git push github "$refname" --force 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "✅ Успешно синхронизировано с GitHub" "$GREEN"
|
||||
else
|
||||
log "❌ Ошибка при синхронизации с GitHub" "$RED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Пушим теги
|
||||
log "🏷️ Отправка тегов..." "$YELLOW"
|
||||
if git push github --tags 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "✅ Теги синхронизированы" "$GREEN"
|
||||
else
|
||||
log "⚠️ Не удалось синхронизировать теги" "$YELLOW"
|
||||
fi
|
||||
else
|
||||
log "ℹ️ Ветка ${refname#refs/heads/} игнорируется (не main/master)" "$YELLOW"
|
||||
fi
|
||||
done
|
||||
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
log "✅ Синхронизация завершена" "$GREEN"
|
||||
log "═══════════════════════════════════════════════════════════════" "$GREEN"
|
||||
|
||||
exit 0
|
||||
|
||||
+556
-556
File diff suppressed because it is too large
Load Diff
+695
-695
File diff suppressed because it is too large
Load Diff
+3608
-3608
File diff suppressed because it is too large
Load Diff
+290
-290
@@ -1,290 +1,290 @@
|
||||
#!/bin/bash
|
||||
|
||||
###############################################################################
|
||||
# Скрипт для создания и обновления SSL сертификата Let's Encrypt
|
||||
# с использованием DNS-валидации через API reg.ru
|
||||
#
|
||||
# Автор: Фофанов Дмитрий
|
||||
# Дата: 27.10.2025
|
||||
# Описание: Автоматизация получения wildcard сертификата через Certbot
|
||||
# с использованием DNS-01 challenge и API reg.ru
|
||||
###############################################################################
|
||||
|
||||
# ==============================================================================
|
||||
# КОНФИГУРАЦИЯ
|
||||
# ==============================================================================
|
||||
|
||||
# Учетные данные API reg.ru (получить на https://www.reg.ru/user/account/)
|
||||
REGRU_USERNAME="your_username" # Имя пользователя reg.ru
|
||||
REGRU_PASSWORD="your_password" # Пароль от аккаунта reg.ru
|
||||
|
||||
# Параметры домена и сертификата
|
||||
DOMAIN="example.com" # Основной домен
|
||||
WILDCARD_DOMAIN="*.example.com" # Wildcard домен
|
||||
EMAIL="admin@example.com" # Email для уведомлений Let's Encrypt
|
||||
|
||||
# Директории для хранения сертификатов
|
||||
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
|
||||
CREDENTIALS_DIR="/etc/letsencrypt/credentials"
|
||||
CREDENTIALS_FILE="$CREDENTIALS_DIR/regru.ini"
|
||||
|
||||
# Логирование
|
||||
LOG_FILE="/var/log/letsencrypt_regru.log"
|
||||
TIMESTAMP=$(date '+%d.%m.%Y %H:%M:%S')
|
||||
|
||||
# ==============================================================================
|
||||
# ФУНКЦИИ
|
||||
# ==============================================================================
|
||||
|
||||
# Логирование сообщений
|
||||
log() {
|
||||
echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Проверка установки необходимых пакетов
|
||||
check_dependencies() {
|
||||
log "Проверка зависимостей..."
|
||||
|
||||
# Проверка certbot
|
||||
if ! command -v certbot &> /dev/null; then
|
||||
log "ОШИБКА: certbot не установлен. Установите: apt-get install certbot"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка curl
|
||||
if ! command -v curl &> /dev/null; then
|
||||
log "ОШИБКА: curl не установлен. Установите: apt-get install curl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка jq для обработки JSON
|
||||
if ! command -v jq &> /dev/null; then
|
||||
log "ОШИБКА: jq не установлен. Установите: apt-get install jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Все зависимости установлены"
|
||||
}
|
||||
|
||||
# Создание директории для credentials
|
||||
setup_credentials_dir() {
|
||||
log "Настройка директории для учетных данных..."
|
||||
|
||||
if [ ! -d "$CREDENTIALS_DIR" ]; then
|
||||
mkdir -p "$CREDENTIALS_DIR"
|
||||
chmod 700 "$CREDENTIALS_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Создание файла с учетными данными для certbot-dns-regru
|
||||
create_credentials_file() {
|
||||
log "Создание файла с учетными данными reg.ru..."
|
||||
|
||||
cat > "$CREDENTIALS_FILE" <<EOF
|
||||
# Учетные данные API reg.ru для DNS-валидации
|
||||
dns_regru_username = $REGRU_USERNAME
|
||||
dns_regru_password = $REGRU_PASSWORD
|
||||
EOF
|
||||
|
||||
chmod 600 "$CREDENTIALS_FILE"
|
||||
log "Файл учетных данных создан: $CREDENTIALS_FILE"
|
||||
}
|
||||
|
||||
# Установка плагина certbot-dns-regru (если еще не установлен)
|
||||
install_certbot_plugin() {
|
||||
log "Проверка плагина certbot-dns-regru..."
|
||||
|
||||
if ! pip3 list | grep -q certbot-dns-regru; then
|
||||
log "Установка certbot-dns-regru..."
|
||||
pip3 install certbot-dns-regru
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Плагин certbot-dns-regru успешно установлен"
|
||||
else
|
||||
log "ОШИБКА: Не удалось установить certbot-dns-regru"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "Плагин certbot-dns-regru уже установлен"
|
||||
fi
|
||||
}
|
||||
|
||||
# Получение нового сертификата
|
||||
obtain_certificate() {
|
||||
log "Запрос нового SSL сертификата для домена: $DOMAIN и $WILDCARD_DOMAIN"
|
||||
|
||||
certbot certonly \
|
||||
--dns-regru \
|
||||
--dns-regru-credentials "$CREDENTIALS_FILE" \
|
||||
--dns-regru-propagation-seconds 60 \
|
||||
-d "$DOMAIN" \
|
||||
-d "$WILDCARD_DOMAIN" \
|
||||
--email "$EMAIL" \
|
||||
--agree-tos \
|
||||
--non-interactive \
|
||||
--preferred-challenges dns-01
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Сертификат успешно получен!"
|
||||
log "Путь к сертификатам: $CERT_DIR"
|
||||
return 0
|
||||
else
|
||||
log "ОШИБКА: Не удалось получить сертификат"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Обновление существующего сертификата
|
||||
renew_certificate() {
|
||||
log "Проверка и обновление существующих сертификатов..."
|
||||
|
||||
certbot renew \
|
||||
--dns-regru \
|
||||
--dns-regru-credentials "$CREDENTIALS_FILE" \
|
||||
--dns-regru-propagation-seconds 60 \
|
||||
--non-interactive
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Проверка обновления завершена успешно"
|
||||
return 0
|
||||
else
|
||||
log "ОШИБКА: Проблема при обновлении сертификата"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Проверка срока действия сертификата
|
||||
check_certificate_expiry() {
|
||||
log "Проверка срока действия сертификата..."
|
||||
|
||||
if [ -f "$CERT_DIR/cert.pem" ]; then
|
||||
EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$CERT_DIR/cert.pem" | cut -d= -f2)
|
||||
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
|
||||
CURRENT_EPOCH=$(date +%s)
|
||||
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
|
||||
|
||||
log "Сертификат истекает: $EXPIRY_DATE (осталось дней: $DAYS_LEFT)"
|
||||
|
||||
if [ $DAYS_LEFT -lt 30 ]; then
|
||||
log "ВНИМАНИЕ: Сертификат истекает менее чем через 30 дней. Требуется обновление!"
|
||||
return 1
|
||||
else
|
||||
log "Сертификат действителен"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
log "Сертификат не найден. Требуется создание нового сертификата."
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
# Перезагрузка веб-сервера (Nginx/Apache)
|
||||
reload_webserver() {
|
||||
log "Перезагрузка веб-сервера..."
|
||||
|
||||
# Определяем, какой веб-сервер используется
|
||||
if systemctl is-active --quiet nginx; then
|
||||
systemctl reload nginx
|
||||
log "Nginx перезагружен"
|
||||
elif systemctl is-active --quiet apache2; then
|
||||
systemctl reload apache2
|
||||
log "Apache перезагружен"
|
||||
elif systemctl is-active --quiet httpd; then
|
||||
systemctl reload httpd
|
||||
log "Apache (httpd) перезагружен"
|
||||
else
|
||||
log "ВНИМАНИЕ: Веб-сервер не найден или не активен. Пропускаем перезагрузку."
|
||||
fi
|
||||
}
|
||||
|
||||
# Отправка уведомления (опционально)
|
||||
send_notification() {
|
||||
local MESSAGE=$1
|
||||
log "Уведомление: $MESSAGE"
|
||||
|
||||
# Здесь можно добавить отправку email, Telegram, Slack и т.д.
|
||||
# Пример: echo "$MESSAGE" | mail -s "SSL Certificate Update" admin@example.com
|
||||
}
|
||||
|
||||
# Вывод информации о сертификате
|
||||
display_certificate_info() {
|
||||
if [ -f "$CERT_DIR/cert.pem" ]; then
|
||||
log "=========================================="
|
||||
log "Информация о сертификате:"
|
||||
log "=========================================="
|
||||
openssl x509 -in "$CERT_DIR/cert.pem" -text -noout | grep -E "(Subject:|Issuer:|Not Before|Not After|DNS:)" | tee -a "$LOG_FILE"
|
||||
log "=========================================="
|
||||
log "Пути к файлам сертификата:"
|
||||
log " Сертификат: $CERT_DIR/cert.pem"
|
||||
log " Приватный ключ: $CERT_DIR/privkey.pem"
|
||||
log " Цепочка: $CERT_DIR/chain.pem"
|
||||
log " Полная цепочка: $CERT_DIR/fullchain.pem"
|
||||
log "=========================================="
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# ОСНОВНАЯ ЛОГИКА
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
log "=========================================="
|
||||
log "Запуск скрипта управления SSL сертификатом"
|
||||
log "=========================================="
|
||||
|
||||
# Проверка, что скрипт запущен от root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
log "ОШИБКА: Скрипт должен быть запущен от имени root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка зависимостей
|
||||
check_dependencies
|
||||
|
||||
# Настройка директории и файла учетных данных
|
||||
setup_credentials_dir
|
||||
create_credentials_file
|
||||
|
||||
# Установка плагина certbot-dns-regru
|
||||
install_certbot_plugin
|
||||
|
||||
# Проверка существования сертификата
|
||||
check_certificate_expiry
|
||||
CERT_STATUS=$?
|
||||
|
||||
if [ $CERT_STATUS -eq 2 ]; then
|
||||
# Сертификат не существует - создаем новый
|
||||
obtain_certificate
|
||||
if [ $? -eq 0 ]; then
|
||||
display_certificate_info
|
||||
reload_webserver
|
||||
send_notification "Новый SSL сертификат успешно создан для $DOMAIN"
|
||||
else
|
||||
send_notification "ОШИБКА: Не удалось создать SSL сертификат для $DOMAIN"
|
||||
exit 1
|
||||
fi
|
||||
elif [ $CERT_STATUS -eq 1 ]; then
|
||||
# Сертификат скоро истекает - обновляем
|
||||
renew_certificate
|
||||
if [ $? -eq 0 ]; then
|
||||
display_certificate_info
|
||||
reload_webserver
|
||||
send_notification "SSL сертификат успешно обновлен для $DOMAIN"
|
||||
else
|
||||
send_notification "ОШИБКА: Не удалось обновить SSL сертификат для $DOMAIN"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Сертификат действителен - только проверяем обновление
|
||||
log "Сертификат действителен. Выполняем проверку на наличие обновлений..."
|
||||
renew_certificate
|
||||
display_certificate_info
|
||||
fi
|
||||
|
||||
log "=========================================="
|
||||
log "Скрипт завершен успешно"
|
||||
log "=========================================="
|
||||
}
|
||||
|
||||
# Запуск основной функции
|
||||
main
|
||||
#!/bin/bash
|
||||
|
||||
###############################################################################
|
||||
# Скрипт для создания и обновления SSL сертификата Let's Encrypt
|
||||
# с использованием DNS-валидации через API reg.ru
|
||||
#
|
||||
# Автор: Фофанов Дмитрий
|
||||
# Дата: 27.10.2025
|
||||
# Описание: Автоматизация получения wildcard сертификата через Certbot
|
||||
# с использованием DNS-01 challenge и API reg.ru
|
||||
###############################################################################
|
||||
|
||||
# ==============================================================================
|
||||
# КОНФИГУРАЦИЯ
|
||||
# ==============================================================================
|
||||
|
||||
# Учетные данные API reg.ru (получить на https://www.reg.ru/user/account/)
|
||||
REGRU_USERNAME="your_username" # Имя пользователя reg.ru
|
||||
REGRU_PASSWORD="your_password" # Пароль от аккаунта reg.ru
|
||||
|
||||
# Параметры домена и сертификата
|
||||
DOMAIN="example.com" # Основной домен
|
||||
WILDCARD_DOMAIN="*.example.com" # Wildcard домен
|
||||
EMAIL="admin@example.com" # Email для уведомлений Let's Encrypt
|
||||
|
||||
# Директории для хранения сертификатов
|
||||
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
|
||||
CREDENTIALS_DIR="/etc/letsencrypt/credentials"
|
||||
CREDENTIALS_FILE="$CREDENTIALS_DIR/regru.ini"
|
||||
|
||||
# Логирование
|
||||
LOG_FILE="/var/log/letsencrypt_regru.log"
|
||||
TIMESTAMP=$(date '+%d.%m.%Y %H:%M:%S')
|
||||
|
||||
# ==============================================================================
|
||||
# ФУНКЦИИ
|
||||
# ==============================================================================
|
||||
|
||||
# Логирование сообщений
|
||||
log() {
|
||||
echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Проверка установки необходимых пакетов
|
||||
check_dependencies() {
|
||||
log "Проверка зависимостей..."
|
||||
|
||||
# Проверка certbot
|
||||
if ! command -v certbot &> /dev/null; then
|
||||
log "ОШИБКА: certbot не установлен. Установите: apt-get install certbot"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка curl
|
||||
if ! command -v curl &> /dev/null; then
|
||||
log "ОШИБКА: curl не установлен. Установите: apt-get install curl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка jq для обработки JSON
|
||||
if ! command -v jq &> /dev/null; then
|
||||
log "ОШИБКА: jq не установлен. Установите: apt-get install jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Все зависимости установлены"
|
||||
}
|
||||
|
||||
# Создание директории для credentials
|
||||
setup_credentials_dir() {
|
||||
log "Настройка директории для учетных данных..."
|
||||
|
||||
if [ ! -d "$CREDENTIALS_DIR" ]; then
|
||||
mkdir -p "$CREDENTIALS_DIR"
|
||||
chmod 700 "$CREDENTIALS_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Создание файла с учетными данными для certbot-dns-regru
|
||||
create_credentials_file() {
|
||||
log "Создание файла с учетными данными reg.ru..."
|
||||
|
||||
cat > "$CREDENTIALS_FILE" <<EOF
|
||||
# Учетные данные API reg.ru для DNS-валидации
|
||||
dns_regru_username = $REGRU_USERNAME
|
||||
dns_regru_password = $REGRU_PASSWORD
|
||||
EOF
|
||||
|
||||
chmod 600 "$CREDENTIALS_FILE"
|
||||
log "Файл учетных данных создан: $CREDENTIALS_FILE"
|
||||
}
|
||||
|
||||
# Установка плагина certbot-dns-regru (если еще не установлен)
|
||||
install_certbot_plugin() {
|
||||
log "Проверка плагина certbot-dns-regru..."
|
||||
|
||||
if ! pip3 list | grep -q certbot-dns-regru; then
|
||||
log "Установка certbot-dns-regru..."
|
||||
pip3 install certbot-dns-regru
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Плагин certbot-dns-regru успешно установлен"
|
||||
else
|
||||
log "ОШИБКА: Не удалось установить certbot-dns-regru"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "Плагин certbot-dns-regru уже установлен"
|
||||
fi
|
||||
}
|
||||
|
||||
# Получение нового сертификата
|
||||
obtain_certificate() {
|
||||
log "Запрос нового SSL сертификата для домена: $DOMAIN и $WILDCARD_DOMAIN"
|
||||
|
||||
certbot certonly \
|
||||
--dns-regru \
|
||||
--dns-regru-credentials "$CREDENTIALS_FILE" \
|
||||
--dns-regru-propagation-seconds 60 \
|
||||
-d "$DOMAIN" \
|
||||
-d "$WILDCARD_DOMAIN" \
|
||||
--email "$EMAIL" \
|
||||
--agree-tos \
|
||||
--non-interactive \
|
||||
--preferred-challenges dns-01
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Сертификат успешно получен!"
|
||||
log "Путь к сертификатам: $CERT_DIR"
|
||||
return 0
|
||||
else
|
||||
log "ОШИБКА: Не удалось получить сертификат"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Обновление существующего сертификата
|
||||
renew_certificate() {
|
||||
log "Проверка и обновление существующих сертификатов..."
|
||||
|
||||
certbot renew \
|
||||
--dns-regru \
|
||||
--dns-regru-credentials "$CREDENTIALS_FILE" \
|
||||
--dns-regru-propagation-seconds 60 \
|
||||
--non-interactive
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Проверка обновления завершена успешно"
|
||||
return 0
|
||||
else
|
||||
log "ОШИБКА: Проблема при обновлении сертификата"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Проверка срока действия сертификата
|
||||
check_certificate_expiry() {
|
||||
log "Проверка срока действия сертификата..."
|
||||
|
||||
if [ -f "$CERT_DIR/cert.pem" ]; then
|
||||
EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$CERT_DIR/cert.pem" | cut -d= -f2)
|
||||
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
|
||||
CURRENT_EPOCH=$(date +%s)
|
||||
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
|
||||
|
||||
log "Сертификат истекает: $EXPIRY_DATE (осталось дней: $DAYS_LEFT)"
|
||||
|
||||
if [ $DAYS_LEFT -lt 30 ]; then
|
||||
log "ВНИМАНИЕ: Сертификат истекает менее чем через 30 дней. Требуется обновление!"
|
||||
return 1
|
||||
else
|
||||
log "Сертификат действителен"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
log "Сертификат не найден. Требуется создание нового сертификата."
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
# Перезагрузка веб-сервера (Nginx/Apache)
|
||||
reload_webserver() {
|
||||
log "Перезагрузка веб-сервера..."
|
||||
|
||||
# Определяем, какой веб-сервер используется
|
||||
if systemctl is-active --quiet nginx; then
|
||||
systemctl reload nginx
|
||||
log "Nginx перезагружен"
|
||||
elif systemctl is-active --quiet apache2; then
|
||||
systemctl reload apache2
|
||||
log "Apache перезагружен"
|
||||
elif systemctl is-active --quiet httpd; then
|
||||
systemctl reload httpd
|
||||
log "Apache (httpd) перезагружен"
|
||||
else
|
||||
log "ВНИМАНИЕ: Веб-сервер не найден или не активен. Пропускаем перезагрузку."
|
||||
fi
|
||||
}
|
||||
|
||||
# Отправка уведомления (опционально)
|
||||
send_notification() {
|
||||
local MESSAGE=$1
|
||||
log "Уведомление: $MESSAGE"
|
||||
|
||||
# Здесь можно добавить отправку email, Telegram, Slack и т.д.
|
||||
# Пример: echo "$MESSAGE" | mail -s "SSL Certificate Update" admin@example.com
|
||||
}
|
||||
|
||||
# Вывод информации о сертификате
|
||||
display_certificate_info() {
|
||||
if [ -f "$CERT_DIR/cert.pem" ]; then
|
||||
log "=========================================="
|
||||
log "Информация о сертификате:"
|
||||
log "=========================================="
|
||||
openssl x509 -in "$CERT_DIR/cert.pem" -text -noout | grep -E "(Subject:|Issuer:|Not Before|Not After|DNS:)" | tee -a "$LOG_FILE"
|
||||
log "=========================================="
|
||||
log "Пути к файлам сертификата:"
|
||||
log " Сертификат: $CERT_DIR/cert.pem"
|
||||
log " Приватный ключ: $CERT_DIR/privkey.pem"
|
||||
log " Цепочка: $CERT_DIR/chain.pem"
|
||||
log " Полная цепочка: $CERT_DIR/fullchain.pem"
|
||||
log "=========================================="
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# ОСНОВНАЯ ЛОГИКА
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
log "=========================================="
|
||||
log "Запуск скрипта управления SSL сертификатом"
|
||||
log "=========================================="
|
||||
|
||||
# Проверка, что скрипт запущен от root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
log "ОШИБКА: Скрипт должен быть запущен от имени root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка зависимостей
|
||||
check_dependencies
|
||||
|
||||
# Настройка директории и файла учетных данных
|
||||
setup_credentials_dir
|
||||
create_credentials_file
|
||||
|
||||
# Установка плагина certbot-dns-regru
|
||||
install_certbot_plugin
|
||||
|
||||
# Проверка существования сертификата
|
||||
check_certificate_expiry
|
||||
CERT_STATUS=$?
|
||||
|
||||
if [ $CERT_STATUS -eq 2 ]; then
|
||||
# Сертификат не существует - создаем новый
|
||||
obtain_certificate
|
||||
if [ $? -eq 0 ]; then
|
||||
display_certificate_info
|
||||
reload_webserver
|
||||
send_notification "Новый SSL сертификат успешно создан для $DOMAIN"
|
||||
else
|
||||
send_notification "ОШИБКА: Не удалось создать SSL сертификат для $DOMAIN"
|
||||
exit 1
|
||||
fi
|
||||
elif [ $CERT_STATUS -eq 1 ]; then
|
||||
# Сертификат скоро истекает - обновляем
|
||||
renew_certificate
|
||||
if [ $? -eq 0 ]; then
|
||||
display_certificate_info
|
||||
reload_webserver
|
||||
send_notification "SSL сертификат успешно обновлен для $DOMAIN"
|
||||
else
|
||||
send_notification "ОШИБКА: Не удалось обновить SSL сертификат для $DOMAIN"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Сертификат действителен - только проверяем обновление
|
||||
log "Сертификат действителен. Выполняем проверку на наличие обновлений..."
|
||||
renew_certificate
|
||||
display_certificate_info
|
||||
fi
|
||||
|
||||
log "=========================================="
|
||||
log "Скрипт завершен успешно"
|
||||
log "=========================================="
|
||||
}
|
||||
|
||||
# Запуск основной функции
|
||||
main
|
||||
|
||||
+179
-179
@@ -1,179 +1,179 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2025 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://nginxproxymanager.com/
|
||||
|
||||
APP="Nginx Proxy Manager"
|
||||
var_tags="${var_tags:-proxy}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-1024}"
|
||||
var_disk="${var_disk:-4}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -f /lib/systemd/system/npm.service ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if command -v node &> /dev/null; then
|
||||
CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
if [[ "$CURRENT_NODE_VERSION" != "22" ]]; then
|
||||
systemctl stop openresty
|
||||
apt-get purge -y nodejs npm
|
||||
apt-get autoremove -y
|
||||
rm -rf /usr/local/bin/node /usr/local/bin/npm
|
||||
rm -rf /usr/local/lib/node_modules
|
||||
rm -rf ~/.npm
|
||||
rm -rf /root/.npm
|
||||
fi
|
||||
fi
|
||||
|
||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||
export NODE_OPTIONS="--openssl-legacy-provider"
|
||||
|
||||
RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
|
||||
grep "tag_name" |
|
||||
awk '{print substr($2, 3, length($2)-4) }')
|
||||
|
||||
msg_info "Downloading NPM v${RELEASE}"
|
||||
curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz
|
||||
cd nginx-proxy-manager-"${RELEASE}" || exit
|
||||
msg_ok "Downloaded NPM v${RELEASE}"
|
||||
|
||||
msg_info "Building Frontend"
|
||||
(
|
||||
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json
|
||||
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json
|
||||
cd ./frontend || exit
|
||||
# Replace node-sass with sass in package.json before installation
|
||||
sed -i 's/"node-sass".*$/"sass": "^1.92.1",/g' package.json
|
||||
$STD yarn install --network-timeout 600000
|
||||
$STD yarn build
|
||||
)
|
||||
msg_ok "Built Frontend"
|
||||
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop openresty
|
||||
systemctl stop npm
|
||||
msg_ok "Stopped Services"
|
||||
|
||||
msg_info "Cleaning Old Files"
|
||||
rm -rf /app \
|
||||
/var/www/html \
|
||||
/etc/nginx \
|
||||
/var/log/nginx \
|
||||
/var/lib/nginx \
|
||||
"$STD" /var/cache/nginx
|
||||
msg_ok "Cleaned Old Files"
|
||||
|
||||
msg_info "Setting up Environment"
|
||||
ln -sf /usr/bin/python3 /usr/bin/python
|
||||
ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot
|
||||
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
|
||||
ln -sf /usr/local/openresty/nginx/ /etc/nginx
|
||||
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
|
||||
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
|
||||
for NGINX_CONF in $NGINX_CONFS; do
|
||||
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
||||
done
|
||||
mkdir -p /var/www/html /etc/nginx/logs
|
||||
cp -r docker/rootfs/var/www/html/* /var/www/html/
|
||||
cp -r docker/rootfs/etc/nginx/* /etc/nginx/
|
||||
cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
|
||||
cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
|
||||
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
|
||||
rm -f /etc/nginx/conf.d/dev.conf
|
||||
mkdir -p /tmp/nginx/body \
|
||||
/run/nginx \
|
||||
/data/nginx \
|
||||
/data/custom_ssl \
|
||||
/data/logs \
|
||||
/data/access \
|
||||
/data/nginx/default_host \
|
||||
/data/nginx/default_www \
|
||||
/data/nginx/proxy_host \
|
||||
/data/nginx/redirection_host \
|
||||
/data/nginx/stream \
|
||||
/data/nginx/dead_host \
|
||||
/data/nginx/temp \
|
||||
/var/lib/nginx/cache/public \
|
||||
/var/lib/nginx/cache/private \
|
||||
/var/cache/nginx/proxy_temp
|
||||
chmod -R 777 /var/cache/nginx
|
||||
chown root /tmp/nginx
|
||||
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf
|
||||
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
|
||||
$STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem
|
||||
fi
|
||||
mkdir -p /app/global /app/frontend/images
|
||||
cp -r frontend/dist/* /app/frontend
|
||||
cp -r frontend/app-images/* /app/frontend/images
|
||||
cp -r backend/* /app
|
||||
cp -r global/* /app/global
|
||||
|
||||
# Update Certbot and plugins in virtual environment
|
||||
if [ -d /opt/certbot ]; then
|
||||
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
|
||||
$STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare
|
||||
fi
|
||||
msg_ok "Setup Environment"
|
||||
|
||||
msg_info "Initializing Backend"
|
||||
$STD rm -rf /app/config/default.json
|
||||
if [ ! -f /app/config/production.json ]; then
|
||||
cat <<'EOF' >/app/config/production.json
|
||||
{
|
||||
"database": {
|
||||
"engine": "knex-native",
|
||||
"knex": {
|
||||
"client": "sqlite3",
|
||||
"connection": {
|
||||
"filename": "/data/database.sqlite"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
cd /app || exit
|
||||
export NODE_OPTIONS="--openssl-legacy-provider"
|
||||
$STD yarn install --network-timeout 600000
|
||||
msg_ok "Initialized Backend"
|
||||
|
||||
msg_info "Starting Services"
|
||||
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||
sed -i 's/su npm npm/su root root/g' /etc/logrotate.d/nginx-proxy-manager
|
||||
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
|
||||
systemctl enable -q --now openresty
|
||||
systemctl enable -q --now npm
|
||||
msg_ok "Started Services"
|
||||
|
||||
msg_info "Cleaning up"
|
||||
rm -rf ~/nginx-proxy-manager-*
|
||||
msg_ok "Cleaned"
|
||||
|
||||
msg_ok "Updated Successfully"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:81${CL}"
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2025 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://nginxproxymanager.com/
|
||||
|
||||
APP="Nginx Proxy Manager"
|
||||
var_tags="${var_tags:-proxy}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-1024}"
|
||||
var_disk="${var_disk:-4}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -f /lib/systemd/system/npm.service ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if command -v node &> /dev/null; then
|
||||
CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
if [[ "$CURRENT_NODE_VERSION" != "22" ]]; then
|
||||
systemctl stop openresty
|
||||
apt-get purge -y nodejs npm
|
||||
apt-get autoremove -y
|
||||
rm -rf /usr/local/bin/node /usr/local/bin/npm
|
||||
rm -rf /usr/local/lib/node_modules
|
||||
rm -rf ~/.npm
|
||||
rm -rf /root/.npm
|
||||
fi
|
||||
fi
|
||||
|
||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||
export NODE_OPTIONS="--openssl-legacy-provider"
|
||||
|
||||
RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
|
||||
grep "tag_name" |
|
||||
awk '{print substr($2, 3, length($2)-4) }')
|
||||
|
||||
msg_info "Downloading NPM v${RELEASE}"
|
||||
curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz
|
||||
cd nginx-proxy-manager-"${RELEASE}" || exit
|
||||
msg_ok "Downloaded NPM v${RELEASE}"
|
||||
|
||||
msg_info "Building Frontend"
|
||||
(
|
||||
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json
|
||||
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json
|
||||
cd ./frontend || exit
|
||||
# Replace node-sass with sass in package.json before installation
|
||||
sed -i 's/"node-sass".*$/"sass": "^1.92.1",/g' package.json
|
||||
$STD yarn install --network-timeout 600000
|
||||
$STD yarn build
|
||||
)
|
||||
msg_ok "Built Frontend"
|
||||
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop openresty
|
||||
systemctl stop npm
|
||||
msg_ok "Stopped Services"
|
||||
|
||||
msg_info "Cleaning Old Files"
|
||||
rm -rf /app \
|
||||
/var/www/html \
|
||||
/etc/nginx \
|
||||
/var/log/nginx \
|
||||
/var/lib/nginx \
|
||||
"$STD" /var/cache/nginx
|
||||
msg_ok "Cleaned Old Files"
|
||||
|
||||
msg_info "Setting up Environment"
|
||||
ln -sf /usr/bin/python3 /usr/bin/python
|
||||
ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot
|
||||
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
|
||||
ln -sf /usr/local/openresty/nginx/ /etc/nginx
|
||||
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
|
||||
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
|
||||
for NGINX_CONF in $NGINX_CONFS; do
|
||||
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
||||
done
|
||||
mkdir -p /var/www/html /etc/nginx/logs
|
||||
cp -r docker/rootfs/var/www/html/* /var/www/html/
|
||||
cp -r docker/rootfs/etc/nginx/* /etc/nginx/
|
||||
cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
|
||||
cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
|
||||
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
|
||||
rm -f /etc/nginx/conf.d/dev.conf
|
||||
mkdir -p /tmp/nginx/body \
|
||||
/run/nginx \
|
||||
/data/nginx \
|
||||
/data/custom_ssl \
|
||||
/data/logs \
|
||||
/data/access \
|
||||
/data/nginx/default_host \
|
||||
/data/nginx/default_www \
|
||||
/data/nginx/proxy_host \
|
||||
/data/nginx/redirection_host \
|
||||
/data/nginx/stream \
|
||||
/data/nginx/dead_host \
|
||||
/data/nginx/temp \
|
||||
/var/lib/nginx/cache/public \
|
||||
/var/lib/nginx/cache/private \
|
||||
/var/cache/nginx/proxy_temp
|
||||
chmod -R 777 /var/cache/nginx
|
||||
chown root /tmp/nginx
|
||||
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf
|
||||
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
|
||||
$STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem
|
||||
fi
|
||||
mkdir -p /app/global /app/frontend/images
|
||||
cp -r frontend/dist/* /app/frontend
|
||||
cp -r frontend/app-images/* /app/frontend/images
|
||||
cp -r backend/* /app
|
||||
cp -r global/* /app/global
|
||||
|
||||
# Update Certbot and plugins in virtual environment
|
||||
if [ -d /opt/certbot ]; then
|
||||
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
|
||||
$STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare
|
||||
fi
|
||||
msg_ok "Setup Environment"
|
||||
|
||||
msg_info "Initializing Backend"
|
||||
$STD rm -rf /app/config/default.json
|
||||
if [ ! -f /app/config/production.json ]; then
|
||||
cat <<'EOF' >/app/config/production.json
|
||||
{
|
||||
"database": {
|
||||
"engine": "knex-native",
|
||||
"knex": {
|
||||
"client": "sqlite3",
|
||||
"connection": {
|
||||
"filename": "/data/database.sqlite"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
cd /app || exit
|
||||
export NODE_OPTIONS="--openssl-legacy-provider"
|
||||
$STD yarn install --network-timeout 600000
|
||||
msg_ok "Initialized Backend"
|
||||
|
||||
msg_info "Starting Services"
|
||||
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||
sed -i 's/su npm npm/su root root/g' /etc/logrotate.d/nginx-proxy-manager
|
||||
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
|
||||
systemctl enable -q --now openresty
|
||||
systemctl enable -q --now npm
|
||||
msg_ok "Started Services"
|
||||
|
||||
msg_info "Cleaning up"
|
||||
rm -rf ~/nginx-proxy-manager-*
|
||||
msg_ok "Cleaned"
|
||||
|
||||
msg_ok "Updated Successfully"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:81${CL}"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Test</h1>
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
# Зависимости для Let's Encrypt RegRu Manager
|
||||
|
||||
# HTTP запросы к API
|
||||
requests>=2.25.0
|
||||
|
||||
# Работа с SSL сертификатами
|
||||
cryptography>=3.4.0
|
||||
|
||||
# Let's Encrypt клиент
|
||||
certbot>=1.12.0
|
||||
|
||||
# Опционально: для сборки исполняемых файлов
|
||||
pyinstaller>=4.10
|
||||
# Зависимости для Let's Encrypt RegRu Manager
|
||||
|
||||
# HTTP запросы к API
|
||||
requests>=2.25.0
|
||||
|
||||
# Работа с SSL сертификатами
|
||||
cryptography>=3.4.0
|
||||
|
||||
# Let's Encrypt клиент
|
||||
certbot>=1.12.0
|
||||
|
||||
# Опционально: для сборки исполняемых файлов
|
||||
pyinstaller>=4.10
|
||||
|
||||
+137
-137
@@ -1,137 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from subprocess import PIPE, run
|
||||
|
||||
|
||||
def get_env(name: str, default: str = "") -> str:
|
||||
value = os.getenv(name, default)
|
||||
return value.strip() if isinstance(value, str) else default
|
||||
|
||||
|
||||
def fail(message: str, code: int = 1) -> None:
|
||||
print(f"✗ {message}")
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Dispatch Gitea Actions workflow")
|
||||
parser.add_argument("--workflow", default="wiki-sync.yml", help="Workflow file name (e.g. wiki-sync.yml)")
|
||||
parser.add_argument("--ref", default="master", help="Git ref for workflow dispatch")
|
||||
parser.add_argument(
|
||||
"--input",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Workflow input in key=value format. Can be provided multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--require-input",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Required input key(s). Fails if key is missing or empty.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def parse_inputs(items: list[str]) -> dict[str, str]:
|
||||
result: dict[str, str] = {}
|
||||
for item in items:
|
||||
if "=" not in item:
|
||||
fail(f"Неверный формат --input '{item}'. Используйте key=value")
|
||||
key, value = item.split("=", 1)
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
if not key:
|
||||
fail(f"Пустой ключ в --input '{item}'")
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_repo_path() -> str:
|
||||
result = run(["git", "config", "--get", "remote.origin.url"], stdout=PIPE, stderr=PIPE, text=True)
|
||||
origin_url = (result.stdout or "").strip()
|
||||
if result.returncode != 0 or not origin_url:
|
||||
fail("remote.origin.url не найден. Проверьте, что команда запущена внутри git-репозитория.")
|
||||
|
||||
repo_path = re.sub(r"^(https?://[^/]+/|git@[^:]+:)", "", origin_url)
|
||||
repo_path = re.sub(r"\.git$", "", repo_path)
|
||||
if not repo_path:
|
||||
fail(f"Не удалось вычислить owner/repo из remote.origin.url: {origin_url}")
|
||||
return repo_path
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
|
||||
token = get_env("DFGIT_TOKEN") or get_env("GIT_TOKEN")
|
||||
if not token:
|
||||
fail("не задан DFGIT_TOKEN (или GIT_TOKEN).")
|
||||
|
||||
dfgit_url = get_env("DFGIT_URL", "http://dfgit").rstrip("/")
|
||||
workflow = args.workflow.strip() or "wiki-sync.yml"
|
||||
ref = args.ref.strip() or "master"
|
||||
inputs = parse_inputs(args.input)
|
||||
|
||||
for required_key in args.require_input:
|
||||
required_key = required_key.strip()
|
||||
if required_key and not inputs.get(required_key, "").strip():
|
||||
fail(
|
||||
f"Обязательный input '{required_key}' не задан. "
|
||||
f"Передайте --input {required_key}=..."
|
||||
)
|
||||
|
||||
repo_path = get_repo_path()
|
||||
dispatch_url = f"{dfgit_url}/api/v1/repos/{repo_path}/actions/workflows/{workflow}/dispatches"
|
||||
|
||||
payload_data: dict[str, object] = {"ref": ref}
|
||||
if inputs:
|
||||
payload_data["inputs"] = inputs
|
||||
|
||||
payload = json.dumps(payload_data).encode("utf-8")
|
||||
|
||||
print(f"→ Репозиторий: {repo_path}")
|
||||
print(f"→ Workflow: {workflow}, ref: {ref}")
|
||||
if inputs:
|
||||
print(f"→ Inputs: {json.dumps(inputs, ensure_ascii=False)}")
|
||||
print(f"→ Запрос: {dispatch_url}")
|
||||
|
||||
request = urllib.request.Request(
|
||||
dispatch_url,
|
||||
data=payload,
|
||||
method="POST",
|
||||
headers={
|
||||
"Authorization": f"token {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
status = response.getcode()
|
||||
body = response.read().decode("utf-8", errors="replace").strip()
|
||||
except urllib.error.HTTPError as error:
|
||||
status = error.code
|
||||
body = error.read().decode("utf-8", errors="replace").strip()
|
||||
except urllib.error.URLError as error:
|
||||
fail(f"Ошибка сети при обращении к dfgit: {error}")
|
||||
|
||||
if status in (200, 201, 204):
|
||||
print("✓ Workflow успешно запущен")
|
||||
print("Проверьте статус в Actions на сервере dfgit.")
|
||||
return
|
||||
|
||||
print(f"✗ Ошибка запуска workflow (HTTP {status})")
|
||||
if body:
|
||||
print("Ответ API:")
|
||||
print(body)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from subprocess import PIPE, run
|
||||
|
||||
|
||||
def get_env(name: str, default: str = "") -> str:
|
||||
value = os.getenv(name, default)
|
||||
return value.strip() if isinstance(value, str) else default
|
||||
|
||||
|
||||
def fail(message: str, code: int = 1) -> None:
|
||||
print(f"✗ {message}")
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Dispatch Gitea Actions workflow")
|
||||
parser.add_argument("--workflow", default="wiki-sync.yml", help="Workflow file name (e.g. wiki-sync.yml)")
|
||||
parser.add_argument("--ref", default="master", help="Git ref for workflow dispatch")
|
||||
parser.add_argument(
|
||||
"--input",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Workflow input in key=value format. Can be provided multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--require-input",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Required input key(s). Fails if key is missing or empty.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def parse_inputs(items: list[str]) -> dict[str, str]:
|
||||
result: dict[str, str] = {}
|
||||
for item in items:
|
||||
if "=" not in item:
|
||||
fail(f"Неверный формат --input '{item}'. Используйте key=value")
|
||||
key, value = item.split("=", 1)
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
if not key:
|
||||
fail(f"Пустой ключ в --input '{item}'")
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_repo_path() -> str:
|
||||
result = run(["git", "config", "--get", "remote.origin.url"], stdout=PIPE, stderr=PIPE, text=True)
|
||||
origin_url = (result.stdout or "").strip()
|
||||
if result.returncode != 0 or not origin_url:
|
||||
fail("remote.origin.url не найден. Проверьте, что команда запущена внутри git-репозитория.")
|
||||
|
||||
repo_path = re.sub(r"^(https?://[^/]+/|git@[^:]+:)", "", origin_url)
|
||||
repo_path = re.sub(r"\.git$", "", repo_path)
|
||||
if not repo_path:
|
||||
fail(f"Не удалось вычислить owner/repo из remote.origin.url: {origin_url}")
|
||||
return repo_path
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
|
||||
token = get_env("DFGIT_TOKEN") or get_env("GIT_TOKEN")
|
||||
if not token:
|
||||
fail("не задан DFGIT_TOKEN (или GIT_TOKEN).")
|
||||
|
||||
dfgit_url = get_env("DFGIT_URL", "http://dfgit").rstrip("/")
|
||||
workflow = args.workflow.strip() or "wiki-sync.yml"
|
||||
ref = args.ref.strip() or "master"
|
||||
inputs = parse_inputs(args.input)
|
||||
|
||||
for required_key in args.require_input:
|
||||
required_key = required_key.strip()
|
||||
if required_key and not inputs.get(required_key, "").strip():
|
||||
fail(
|
||||
f"Обязательный input '{required_key}' не задан. "
|
||||
f"Передайте --input {required_key}=..."
|
||||
)
|
||||
|
||||
repo_path = get_repo_path()
|
||||
dispatch_url = f"{dfgit_url}/api/v1/repos/{repo_path}/actions/workflows/{workflow}/dispatches"
|
||||
|
||||
payload_data: dict[str, object] = {"ref": ref}
|
||||
if inputs:
|
||||
payload_data["inputs"] = inputs
|
||||
|
||||
payload = json.dumps(payload_data).encode("utf-8")
|
||||
|
||||
print(f"→ Репозиторий: {repo_path}")
|
||||
print(f"→ Workflow: {workflow}, ref: {ref}")
|
||||
if inputs:
|
||||
print(f"→ Inputs: {json.dumps(inputs, ensure_ascii=False)}")
|
||||
print(f"→ Запрос: {dispatch_url}")
|
||||
|
||||
request = urllib.request.Request(
|
||||
dispatch_url,
|
||||
data=payload,
|
||||
method="POST",
|
||||
headers={
|
||||
"Authorization": f"token {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
status = response.getcode()
|
||||
body = response.read().decode("utf-8", errors="replace").strip()
|
||||
except urllib.error.HTTPError as error:
|
||||
status = error.code
|
||||
body = error.read().decode("utf-8", errors="replace").strip()
|
||||
except urllib.error.URLError as error:
|
||||
fail(f"Ошибка сети при обращении к dfgit: {error}")
|
||||
|
||||
if status in (200, 201, 204):
|
||||
print("✓ Workflow успешно запущен")
|
||||
print("Проверьте статус в Actions на сервере dfgit.")
|
||||
return
|
||||
|
||||
print(f"✗ Ошибка запуска workflow (HTTP {status})")
|
||||
if body:
|
||||
print("Ответ API:")
|
||||
print(body)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
[Unit]
|
||||
Description=Let's Encrypt Certificate Manager for reg.ru
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
WorkingDirectory=/opt/letsencrypt-regru
|
||||
ExecStart=/opt/letsencrypt-regru/venv/bin/python /opt/letsencrypt-regru/letsencrypt_regru_api.py --config /etc/letsencrypt-regru/config.json --auto
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=letsencrypt-regru
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
[Unit]
|
||||
Description=Let's Encrypt Certificate Manager for reg.ru
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
WorkingDirectory=/opt/letsencrypt-regru
|
||||
ExecStart=/opt/letsencrypt-regru/venv/bin/python /opt/letsencrypt-regru/letsencrypt_regru_api.py --config /etc/letsencrypt-regru/config.json --auto
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=letsencrypt-regru
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
[Unit]
|
||||
Description=Let's Encrypt Certificate Auto-Renewal Timer
|
||||
Requires=letsencrypt-regru.service
|
||||
|
||||
[Timer]
|
||||
# Запустить через 15 минут после загрузки системы
|
||||
OnBootSec=15min
|
||||
|
||||
# Запускать каждые 12 часов
|
||||
OnUnitActiveSec=12h
|
||||
|
||||
# Добавить случайную задержку до 1 часа
|
||||
RandomizedDelaySec=1h
|
||||
|
||||
# Сохранять информацию о последнем запуске
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
[Unit]
|
||||
Description=Let's Encrypt Certificate Auto-Renewal Timer
|
||||
Requires=letsencrypt-regru.service
|
||||
|
||||
[Timer]
|
||||
# Запустить через 15 минут после загрузки системы
|
||||
OnBootSec=15min
|
||||
|
||||
# Запускать каждые 12 часов
|
||||
OnUnitActiveSec=12h
|
||||
|
||||
# Добавить случайную задержку до 1 часа
|
||||
RandomizedDelaySec=1h
|
||||
|
||||
# Сохранять информацию о последнем запуске
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
+143
-143
@@ -1,143 +1,143 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Скрипт для быстрого создания тестового самоподписанного SSL сертификата
|
||||
# Использует: openssl (альтернатива Python скрипту)
|
||||
# ==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Цвета
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Параметры по умолчанию
|
||||
DOMAIN="${1:-example.com}"
|
||||
WILDCARD="${2:-yes}"
|
||||
CERT_DIR="/etc/letsencrypt/live/${DOMAIN}"
|
||||
VALIDITY_DAYS=90
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Создание тестового самоподписанного SSL сертификата ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Параметры:${NC}"
|
||||
echo -e " Домен: ${GREEN}${DOMAIN}${NC}"
|
||||
echo -e " Wildcard: ${GREEN}${WILDCARD}${NC}"
|
||||
echo -e " Срок действия: ${GREEN}${VALIDITY_DAYS} дней${NC}"
|
||||
echo -e " Директория: ${GREEN}${CERT_DIR}${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ ВНИМАНИЕ: Это тестовый сертификат для разработки!${NC}"
|
||||
echo -e "${YELLOW} Браузеры будут показывать предупреждение безопасности.${NC}"
|
||||
echo ""
|
||||
|
||||
# Проверка прав root
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo -e "${RED}✗ Требуются права root${NC}"
|
||||
echo -e "Запустите: sudo $0 $@"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Создание директории
|
||||
echo -e "${YELLOW}→ Создание директории...${NC}"
|
||||
mkdir -p "${CERT_DIR}"
|
||||
cd "${CERT_DIR}"
|
||||
|
||||
# Подготовка конфигурации для альтернативных имен (SAN)
|
||||
if [ "${WILDCARD}" = "yes" ]; then
|
||||
SAN="DNS:${DOMAIN},DNS:*.${DOMAIN}"
|
||||
else
|
||||
SAN="DNS:${DOMAIN}"
|
||||
fi
|
||||
|
||||
# Создание конфигурации OpenSSL
|
||||
cat > openssl.cnf <<EOF
|
||||
[req]
|
||||
default_bits = 2048
|
||||
prompt = no
|
||||
default_md = sha256
|
||||
distinguished_name = dn
|
||||
req_extensions = v3_req
|
||||
|
||||
[dn]
|
||||
C=RU
|
||||
ST=Moscow
|
||||
L=Moscow
|
||||
O=Test Certificate
|
||||
CN=${DOMAIN}
|
||||
|
||||
[v3_req]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth, clientAuth
|
||||
subjectAltName = ${SAN}
|
||||
EOF
|
||||
|
||||
# Генерация приватного ключа
|
||||
echo -e "${YELLOW}→ Генерация приватного ключа RSA 2048 бит...${NC}"
|
||||
openssl genrsa -out privkey.pem 2048 2>/dev/null
|
||||
chmod 600 privkey.pem
|
||||
echo -e "${GREEN}✓ Приватный ключ сохранен: ${CERT_DIR}/privkey.pem${NC}"
|
||||
|
||||
# Генерация сертификата
|
||||
echo -e "${YELLOW}→ Генерация самоподписанного сертификата...${NC}"
|
||||
openssl req \
|
||||
-new \
|
||||
-x509 \
|
||||
-key privkey.pem \
|
||||
-out cert.pem \
|
||||
-days ${VALIDITY_DAYS} \
|
||||
-config openssl.cnf \
|
||||
-extensions v3_req \
|
||||
2>/dev/null
|
||||
|
||||
echo -e "${GREEN}✓ Сертификат сохранен: ${CERT_DIR}/cert.pem${NC}"
|
||||
|
||||
# Создание fullchain (копия cert для самоподписанного)
|
||||
cp cert.pem fullchain.pem
|
||||
echo -e "${GREEN}✓ Fullchain сохранен: ${CERT_DIR}/fullchain.pem${NC}"
|
||||
|
||||
# Создание пустого chain.pem
|
||||
touch chain.pem
|
||||
echo -e "${GREEN}✓ Chain файл создан: ${CERT_DIR}/chain.pem${NC}"
|
||||
|
||||
# Удаление временного файла конфигурации
|
||||
rm -f openssl.cnf
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Информация о сертификате ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
# Вывод информации о сертификате
|
||||
openssl x509 -in cert.pem -noout -subject -dates -ext subjectAltName
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ ✓ Тестовый сертификат успешно создан ║${NC}"
|
||||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}📁 Файлы сертификата:${NC}"
|
||||
echo -e " • Приватный ключ: ${CERT_DIR}/privkey.pem"
|
||||
echo -e " • Сертификат: ${CERT_DIR}/cert.pem"
|
||||
echo -e " • Fullchain: ${CERT_DIR}/fullchain.pem"
|
||||
echo -e " • Chain: ${CERT_DIR}/chain.pem"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ ВНИМАНИЕ:${NC}"
|
||||
echo -e " Это самоподписанный тестовый сертификат!"
|
||||
echo -e " Браузеры будут показывать предупреждение о безопасности."
|
||||
echo -e " Используйте ТОЛЬКО для тестирования и разработки!"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Использование в Nginx:${NC}"
|
||||
echo -e " ssl_certificate ${CERT_DIR}/fullchain.pem;"
|
||||
echo -e " ssl_certificate_key ${CERT_DIR}/privkey.pem;"
|
||||
echo ""
|
||||
|
||||
# Предложение загрузить в NPM
|
||||
echo -e "${YELLOW}Загрузить в Nginx Proxy Manager?${NC}"
|
||||
echo -e " Используйте Python скрипт с опцией --test-cert"
|
||||
echo -e " или загрузите вручную через веб-интерфейс NPM"
|
||||
echo ""
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Скрипт для быстрого создания тестового самоподписанного SSL сертификата
|
||||
# Использует: openssl (альтернатива Python скрипту)
|
||||
# ==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Цвета
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Параметры по умолчанию
|
||||
DOMAIN="${1:-example.com}"
|
||||
WILDCARD="${2:-yes}"
|
||||
CERT_DIR="/etc/letsencrypt/live/${DOMAIN}"
|
||||
VALIDITY_DAYS=90
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Создание тестового самоподписанного SSL сертификата ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Параметры:${NC}"
|
||||
echo -e " Домен: ${GREEN}${DOMAIN}${NC}"
|
||||
echo -e " Wildcard: ${GREEN}${WILDCARD}${NC}"
|
||||
echo -e " Срок действия: ${GREEN}${VALIDITY_DAYS} дней${NC}"
|
||||
echo -e " Директория: ${GREEN}${CERT_DIR}${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ ВНИМАНИЕ: Это тестовый сертификат для разработки!${NC}"
|
||||
echo -e "${YELLOW} Браузеры будут показывать предупреждение безопасности.${NC}"
|
||||
echo ""
|
||||
|
||||
# Проверка прав root
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo -e "${RED}✗ Требуются права root${NC}"
|
||||
echo -e "Запустите: sudo $0 $@"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Создание директории
|
||||
echo -e "${YELLOW}→ Создание директории...${NC}"
|
||||
mkdir -p "${CERT_DIR}"
|
||||
cd "${CERT_DIR}"
|
||||
|
||||
# Подготовка конфигурации для альтернативных имен (SAN)
|
||||
if [ "${WILDCARD}" = "yes" ]; then
|
||||
SAN="DNS:${DOMAIN},DNS:*.${DOMAIN}"
|
||||
else
|
||||
SAN="DNS:${DOMAIN}"
|
||||
fi
|
||||
|
||||
# Создание конфигурации OpenSSL
|
||||
cat > openssl.cnf <<EOF
|
||||
[req]
|
||||
default_bits = 2048
|
||||
prompt = no
|
||||
default_md = sha256
|
||||
distinguished_name = dn
|
||||
req_extensions = v3_req
|
||||
|
||||
[dn]
|
||||
C=RU
|
||||
ST=Moscow
|
||||
L=Moscow
|
||||
O=Test Certificate
|
||||
CN=${DOMAIN}
|
||||
|
||||
[v3_req]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth, clientAuth
|
||||
subjectAltName = ${SAN}
|
||||
EOF
|
||||
|
||||
# Генерация приватного ключа
|
||||
echo -e "${YELLOW}→ Генерация приватного ключа RSA 2048 бит...${NC}"
|
||||
openssl genrsa -out privkey.pem 2048 2>/dev/null
|
||||
chmod 600 privkey.pem
|
||||
echo -e "${GREEN}✓ Приватный ключ сохранен: ${CERT_DIR}/privkey.pem${NC}"
|
||||
|
||||
# Генерация сертификата
|
||||
echo -e "${YELLOW}→ Генерация самоподписанного сертификата...${NC}"
|
||||
openssl req \
|
||||
-new \
|
||||
-x509 \
|
||||
-key privkey.pem \
|
||||
-out cert.pem \
|
||||
-days ${VALIDITY_DAYS} \
|
||||
-config openssl.cnf \
|
||||
-extensions v3_req \
|
||||
2>/dev/null
|
||||
|
||||
echo -e "${GREEN}✓ Сертификат сохранен: ${CERT_DIR}/cert.pem${NC}"
|
||||
|
||||
# Создание fullchain (копия cert для самоподписанного)
|
||||
cp cert.pem fullchain.pem
|
||||
echo -e "${GREEN}✓ Fullchain сохранен: ${CERT_DIR}/fullchain.pem${NC}"
|
||||
|
||||
# Создание пустого chain.pem
|
||||
touch chain.pem
|
||||
echo -e "${GREEN}✓ Chain файл создан: ${CERT_DIR}/chain.pem${NC}"
|
||||
|
||||
# Удаление временного файла конфигурации
|
||||
rm -f openssl.cnf
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Информация о сертификате ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
# Вывод информации о сертификате
|
||||
openssl x509 -in cert.pem -noout -subject -dates -ext subjectAltName
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ ✓ Тестовый сертификат успешно создан ║${NC}"
|
||||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}📁 Файлы сертификата:${NC}"
|
||||
echo -e " • Приватный ключ: ${CERT_DIR}/privkey.pem"
|
||||
echo -e " • Сертификат: ${CERT_DIR}/cert.pem"
|
||||
echo -e " • Fullchain: ${CERT_DIR}/fullchain.pem"
|
||||
echo -e " • Chain: ${CERT_DIR}/chain.pem"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ ВНИМАНИЕ:${NC}"
|
||||
echo -e " Это самоподписанный тестовый сертификат!"
|
||||
echo -e " Браузеры будут показывать предупреждение о безопасности."
|
||||
echo -e " Используйте ТОЛЬКО для тестирования и разработки!"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Использование в Nginx:${NC}"
|
||||
echo -e " ssl_certificate ${CERT_DIR}/fullchain.pem;"
|
||||
echo -e " ssl_certificate_key ${CERT_DIR}/privkey.pem;"
|
||||
echo ""
|
||||
|
||||
# Предложение загрузить в NPM
|
||||
echo -e "${YELLOW}Загрузить в Nginx Proxy Manager?${NC}"
|
||||
echo -e " Используйте Python скрипт с опцией --test-cert"
|
||||
echo -e " или загрузите вручную через веб-интерфейс NPM"
|
||||
echo ""
|
||||
|
||||
+797
-797
File diff suppressed because it is too large
Load Diff
+178
-178
@@ -1,178 +1,178 @@
|
||||
# Changelog
|
||||
|
||||
Краткое резюме по основным версиям (подробности — ниже на этой странице).
|
||||
|
||||
## 2.1.0 (2025‑10‑27)
|
||||
|
||||
- Добавлена генерация тестовых самоподписанных сертификатов (`--test-cert`, `make test-cert`, `test_certificate.sh`)
|
||||
- Расширена документация (testing guide, cheatsheet, project structure)
|
||||
|
||||
## 2.0.0 (2025‑10‑27)
|
||||
|
||||
- Интеграция с Nginx Proxy Manager (API)
|
||||
- Makefile, systemd timer/service, авто-режим
|
||||
|
||||
## 1.0.0 (2025‑10‑26)
|
||||
|
||||
- Первый релиз: LE+reg.ru DNS-01, bash/ps1 версии
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/CHANGELOG.md)
|
||||
<!-- MIGRATED_FROM_DOCS:CHANGELOG.md -->
|
||||
|
||||
## 📋 Журнал изменений (Changelog)
|
||||
|
||||
### [2.1.0] - 2025-10-27
|
||||
|
||||
#### 🆕 Добавлено
|
||||
|
||||
##### Генерация тестовых SSL сертификатов
|
||||
- ✨ **Новый класс `TestCertificateGenerator`** - генерация самоподписанных сертификатов
|
||||
- ✨ **Команда `--test-cert`** в Python скрипте для создания тестовых сертификатов
|
||||
- ✨ **Скрипт `test_certificate.sh`** - автономное создание через OpenSSL
|
||||
- ✨ **Команда `make test-cert`** в Makefile для быстрого тестирования
|
||||
|
||||
##### Документация
|
||||
- 📘 **TESTING_GUIDE.md** (370+ строк) - полное руководство по тестированию
|
||||
- Обход лимитов Let's Encrypt (5 сертификатов в неделю)
|
||||
- Сравнение методов создания сертификатов
|
||||
- Примеры для CI/CD и Docker
|
||||
- Переход с тестовых на production
|
||||
- Частые вопросы и решения
|
||||
|
||||
- 📘 **PROJECT_STRUCTURE.md** - структура проекта
|
||||
- Описание всех файлов
|
||||
- Список возможностей
|
||||
- Технологии
|
||||
|
||||
- 📘 **CHEATSHEET.md** - быстрая шпаргалка
|
||||
- Основные команды
|
||||
- Сценарии использования
|
||||
- Частые ошибки и решения
|
||||
- Workflow разработки
|
||||
|
||||
##### Функциональность
|
||||
- ✨ Поддержка **неограниченного количества** тестовых сертификатов
|
||||
- ✨ **Мгновенное создание** (1-2 секунды) без DNS валидации
|
||||
- ✨ **Автоматическая загрузка** тестовых сертификатов в NPM
|
||||
- ✨ **Полная совместимость** структуры с Let's Encrypt
|
||||
- ✨ **Wildcard поддержка** для тестовых сертификатов
|
||||
|
||||
#### 🔧 Улучшено
|
||||
|
||||
##### Python скрипт
|
||||
- Добавлен импорт библиотеки `cryptography` с проверкой установки
|
||||
- Новые параметры командной строки:
|
||||
- `--test-cert` - создание тестового сертификата
|
||||
- `--auto` - явное указание автоматического режима
|
||||
- Улучшенная обработка тестовых сертификатов в NPM
|
||||
- Детальное логирование процесса генерации
|
||||
|
||||
##### Makefile
|
||||
- Добавлена команда `make test-cert` с красивым выводом
|
||||
- Информационные сообщения о преимуществах тестовых сертификатов
|
||||
- Предупреждения о безопасности
|
||||
|
||||
##### README.md
|
||||
- Раздел "Создание тестового самоподписанного сертификата"
|
||||
- Обновленное содержание с ссылкой на тестовые сертификаты
|
||||
- Примеры использования тестовых сертификатов
|
||||
- Интеграция с NPM для тестовых сертификатов
|
||||
- Ссылки на дополнительную документацию
|
||||
|
||||
#### 🎯 Преимущества
|
||||
|
||||
##### Для разработчиков
|
||||
- ✅ **Нет лимитов** - неограниченное количество сертификатов
|
||||
- ✅ **Быстро** - создание за 1-2 секунды
|
||||
- ✅ **Офлайн** - работает без интернета
|
||||
- ✅ **Идентичная структура** - те же файлы что и Let's Encrypt
|
||||
|
||||
##### Для тестирования
|
||||
- ✅ **CI/CD friendly** - быстрое создание в pipeline
|
||||
- ✅ **Docker ready** - легко встраивается в контейнеры
|
||||
- ✅ **Staging окружения** - идеально для тестовых серверов
|
||||
- ✅ **Локальная разработка** - HTTPS на localhost
|
||||
|
||||
#### 📊 Статистика
|
||||
|
||||
- **Строк кода**: 1,411 (Python скрипт)
|
||||
- **Строк в Makefile**: 415
|
||||
- **Строк документации**: 2,200+
|
||||
- **Команд в Makefile**: 13
|
||||
- **Режимов работы**: 4 (obtain, renew, auto, test-cert)
|
||||
|
||||
---
|
||||
|
||||
### [2.0.0] - 2025-10-27
|
||||
|
||||
#### 🆕 Добавлено
|
||||
- ✨ Интеграция с Nginx Proxy Manager (NPM)
|
||||
- ✨ Класс `NginxProxyManagerAPI` для управления сертификатами через API
|
||||
- ✨ Автоматическая загрузка сертификатов в NPM
|
||||
- ✨ Автоматическое обновление сертификатов в NPM
|
||||
- ✨ Автоматическая проверка срока действия
|
||||
- ✨ Настраиваемый порог обновления (`renewal_days`)
|
||||
- ✨ Makefile для автоматизации установки/удаления
|
||||
- ✨ Systemd service + timer
|
||||
- ✨ Cron автоматизация
|
||||
|
||||
#### 🔧 Улучшено
|
||||
- Консолидация документации в единый README.md
|
||||
- Подробное логирование с статусами операций
|
||||
- Валидация конфигурации
|
||||
- Улучшенная обработка ошибок
|
||||
|
||||
#### 📘 Документация
|
||||
- Полное руководство по NPM интеграции
|
||||
- Быстрый старт за 3 команды
|
||||
- Примеры автоматизации
|
||||
|
||||
---
|
||||
|
||||
### [1.0.0] - 2025-10-26
|
||||
|
||||
#### 🆕 Первый релиз
|
||||
- Python скрипт для Let's Encrypt через reg.ru API
|
||||
- Bash скрипт с certbot-dns-regru
|
||||
- PowerShell версия для Windows
|
||||
- DNS-01 валидация
|
||||
- Wildcard сертификаты
|
||||
- Базовая документация
|
||||
|
||||
---
|
||||
|
||||
### Roadmap (Планы)
|
||||
|
||||
#### [2.2.0] - Планируется
|
||||
- [ ] Веб-интерфейс для управления
|
||||
- [ ] Поддержка множественных доменов
|
||||
- [ ] Notifications (email, telegram)
|
||||
- [ ] Grafana dashboard для мониторинга
|
||||
- [ ] Backup сертификатов
|
||||
|
||||
#### [3.0.0] - Будущее
|
||||
- [ ] Поддержка других DNS провайдеров
|
||||
- [ ] Cloudflare API
|
||||
- [ ] Route53 (AWS)
|
||||
- [ ] Google Cloud DNS
|
||||
|
||||
---
|
||||
|
||||
### Типы изменений
|
||||
- `🆕 Добавлено` - новый функционал
|
||||
- `🔧 Улучшено` - улучшения существующего функционала
|
||||
- `🐛 Исправлено` - исправление багов
|
||||
- `🗑️ Удалено` - удаленный функционал
|
||||
- `🔒 Безопасность` - изменения безопасности
|
||||
- `📘 Документация` - изменения в документации
|
||||
|
||||
---
|
||||
|
||||
**Версионирование**: Semantic Versioning (MAJOR.MINOR.PATCH)
|
||||
- **MAJOR**: Несовместимые изменения API
|
||||
- **MINOR**: Новый функционал с обратной совместимостью
|
||||
- **PATCH**: Исправления багов
|
||||
|
||||
# Changelog
|
||||
|
||||
Краткое резюме по основным версиям (подробности — ниже на этой странице).
|
||||
|
||||
## 2.1.0 (2025‑10‑27)
|
||||
|
||||
- Добавлена генерация тестовых самоподписанных сертификатов (`--test-cert`, `make test-cert`, `test_certificate.sh`)
|
||||
- Расширена документация (testing guide, cheatsheet, project structure)
|
||||
|
||||
## 2.0.0 (2025‑10‑27)
|
||||
|
||||
- Интеграция с Nginx Proxy Manager (API)
|
||||
- Makefile, systemd timer/service, авто-режим
|
||||
|
||||
## 1.0.0 (2025‑10‑26)
|
||||
|
||||
- Первый релиз: LE+reg.ru DNS-01, bash/ps1 версии
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/CHANGELOG.md)
|
||||
<!-- MIGRATED_FROM_DOCS:CHANGELOG.md -->
|
||||
|
||||
## 📋 Журнал изменений (Changelog)
|
||||
|
||||
### [2.1.0] - 2025-10-27
|
||||
|
||||
#### 🆕 Добавлено
|
||||
|
||||
##### Генерация тестовых SSL сертификатов
|
||||
- ✨ **Новый класс `TestCertificateGenerator`** - генерация самоподписанных сертификатов
|
||||
- ✨ **Команда `--test-cert`** в Python скрипте для создания тестовых сертификатов
|
||||
- ✨ **Скрипт `test_certificate.sh`** - автономное создание через OpenSSL
|
||||
- ✨ **Команда `make test-cert`** в Makefile для быстрого тестирования
|
||||
|
||||
##### Документация
|
||||
- 📘 **TESTING_GUIDE.md** (370+ строк) - полное руководство по тестированию
|
||||
- Обход лимитов Let's Encrypt (5 сертификатов в неделю)
|
||||
- Сравнение методов создания сертификатов
|
||||
- Примеры для CI/CD и Docker
|
||||
- Переход с тестовых на production
|
||||
- Частые вопросы и решения
|
||||
|
||||
- 📘 **PROJECT_STRUCTURE.md** - структура проекта
|
||||
- Описание всех файлов
|
||||
- Список возможностей
|
||||
- Технологии
|
||||
|
||||
- 📘 **CHEATSHEET.md** - быстрая шпаргалка
|
||||
- Основные команды
|
||||
- Сценарии использования
|
||||
- Частые ошибки и решения
|
||||
- Workflow разработки
|
||||
|
||||
##### Функциональность
|
||||
- ✨ Поддержка **неограниченного количества** тестовых сертификатов
|
||||
- ✨ **Мгновенное создание** (1-2 секунды) без DNS валидации
|
||||
- ✨ **Автоматическая загрузка** тестовых сертификатов в NPM
|
||||
- ✨ **Полная совместимость** структуры с Let's Encrypt
|
||||
- ✨ **Wildcard поддержка** для тестовых сертификатов
|
||||
|
||||
#### 🔧 Улучшено
|
||||
|
||||
##### Python скрипт
|
||||
- Добавлен импорт библиотеки `cryptography` с проверкой установки
|
||||
- Новые параметры командной строки:
|
||||
- `--test-cert` - создание тестового сертификата
|
||||
- `--auto` - явное указание автоматического режима
|
||||
- Улучшенная обработка тестовых сертификатов в NPM
|
||||
- Детальное логирование процесса генерации
|
||||
|
||||
##### Makefile
|
||||
- Добавлена команда `make test-cert` с красивым выводом
|
||||
- Информационные сообщения о преимуществах тестовых сертификатов
|
||||
- Предупреждения о безопасности
|
||||
|
||||
##### README.md
|
||||
- Раздел "Создание тестового самоподписанного сертификата"
|
||||
- Обновленное содержание с ссылкой на тестовые сертификаты
|
||||
- Примеры использования тестовых сертификатов
|
||||
- Интеграция с NPM для тестовых сертификатов
|
||||
- Ссылки на дополнительную документацию
|
||||
|
||||
#### 🎯 Преимущества
|
||||
|
||||
##### Для разработчиков
|
||||
- ✅ **Нет лимитов** - неограниченное количество сертификатов
|
||||
- ✅ **Быстро** - создание за 1-2 секунды
|
||||
- ✅ **Офлайн** - работает без интернета
|
||||
- ✅ **Идентичная структура** - те же файлы что и Let's Encrypt
|
||||
|
||||
##### Для тестирования
|
||||
- ✅ **CI/CD friendly** - быстрое создание в pipeline
|
||||
- ✅ **Docker ready** - легко встраивается в контейнеры
|
||||
- ✅ **Staging окружения** - идеально для тестовых серверов
|
||||
- ✅ **Локальная разработка** - HTTPS на localhost
|
||||
|
||||
#### 📊 Статистика
|
||||
|
||||
- **Строк кода**: 1,411 (Python скрипт)
|
||||
- **Строк в Makefile**: 415
|
||||
- **Строк документации**: 2,200+
|
||||
- **Команд в Makefile**: 13
|
||||
- **Режимов работы**: 4 (obtain, renew, auto, test-cert)
|
||||
|
||||
---
|
||||
|
||||
### [2.0.0] - 2025-10-27
|
||||
|
||||
#### 🆕 Добавлено
|
||||
- ✨ Интеграция с Nginx Proxy Manager (NPM)
|
||||
- ✨ Класс `NginxProxyManagerAPI` для управления сертификатами через API
|
||||
- ✨ Автоматическая загрузка сертификатов в NPM
|
||||
- ✨ Автоматическое обновление сертификатов в NPM
|
||||
- ✨ Автоматическая проверка срока действия
|
||||
- ✨ Настраиваемый порог обновления (`renewal_days`)
|
||||
- ✨ Makefile для автоматизации установки/удаления
|
||||
- ✨ Systemd service + timer
|
||||
- ✨ Cron автоматизация
|
||||
|
||||
#### 🔧 Улучшено
|
||||
- Консолидация документации в единый README.md
|
||||
- Подробное логирование с статусами операций
|
||||
- Валидация конфигурации
|
||||
- Улучшенная обработка ошибок
|
||||
|
||||
#### 📘 Документация
|
||||
- Полное руководство по NPM интеграции
|
||||
- Быстрый старт за 3 команды
|
||||
- Примеры автоматизации
|
||||
|
||||
---
|
||||
|
||||
### [1.0.0] - 2025-10-26
|
||||
|
||||
#### 🆕 Первый релиз
|
||||
- Python скрипт для Let's Encrypt через reg.ru API
|
||||
- Bash скрипт с certbot-dns-regru
|
||||
- PowerShell версия для Windows
|
||||
- DNS-01 валидация
|
||||
- Wildcard сертификаты
|
||||
- Базовая документация
|
||||
|
||||
---
|
||||
|
||||
### Roadmap (Планы)
|
||||
|
||||
#### [2.2.0] - Планируется
|
||||
- [ ] Веб-интерфейс для управления
|
||||
- [ ] Поддержка множественных доменов
|
||||
- [ ] Notifications (email, telegram)
|
||||
- [ ] Grafana dashboard для мониторинга
|
||||
- [ ] Backup сертификатов
|
||||
|
||||
#### [3.0.0] - Будущее
|
||||
- [ ] Поддержка других DNS провайдеров
|
||||
- [ ] Cloudflare API
|
||||
- [ ] Route53 (AWS)
|
||||
- [ ] Google Cloud DNS
|
||||
|
||||
---
|
||||
|
||||
### Типы изменений
|
||||
- `🆕 Добавлено` - новый функционал
|
||||
- `🔧 Улучшено` - улучшения существующего функционала
|
||||
- `🐛 Исправлено` - исправление багов
|
||||
- `🗑️ Удалено` - удаленный функционал
|
||||
- `🔒 Безопасность` - изменения безопасности
|
||||
- `📘 Документация` - изменения в документации
|
||||
|
||||
---
|
||||
|
||||
**Версионирование**: Semantic Versioning (MAJOR.MINOR.PATCH)
|
||||
- **MAJOR**: Несовместимые изменения API
|
||||
- **MINOR**: Новый функционал с обратной совместимостью
|
||||
- **PATCH**: Исправления багов
|
||||
|
||||
|
||||
+547
-547
File diff suppressed because it is too large
Load Diff
+92
-92
@@ -1,92 +1,92 @@
|
||||
# Конфигурация
|
||||
|
||||
Проект использует JSON конфиг (пример: `config.json.example`).
|
||||
|
||||
## Важно про мультидоменный режим
|
||||
|
||||
Скрипт поддерживает:
|
||||
|
||||
- один домен в поле `domain`
|
||||
- список доменов в поле `domains` (массив строк)
|
||||
- оба поля одновременно (будет объединение без дублей)
|
||||
|
||||
Пример:
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"domains": [
|
||||
"example.com",
|
||||
"pages.gitea.example.com"
|
||||
],
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://192.0.2.1:81",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "changeme"
|
||||
}
|
||||
```
|
||||
|
||||
## Параметры конфигурации
|
||||
|
||||
### reg.ru API
|
||||
|
||||
- `regru_username`, `regru_password`
|
||||
- учётные данные для API reg.ru
|
||||
- IP должен быть разрешён в настройках API (см. [RegRu_API_Troubleshooting](RegRu_API_Troubleshooting.md))
|
||||
|
||||
### Домены
|
||||
|
||||
- `domain`: основной домен (строка)
|
||||
- `domains`: массив доменов
|
||||
- `wildcard`: если `true`, скрипт будет запрашивать `-d <domain>` и `-d *.<domain>`
|
||||
- обратите внимание: этот флаг сейчас общий для всех доменов из массива
|
||||
|
||||
### Let’s Encrypt
|
||||
|
||||
- `email`: email для регистрации в Let’s Encrypt
|
||||
- `renewal_days`: порог автопродления (например, 30)
|
||||
|
||||
### DNS ожидание/проверки
|
||||
|
||||
- `dns_propagation_wait`: сколько секунд ждать после добавления TXT
|
||||
- `dns_check_attempts`: сколько попыток проверки через `nslookup`
|
||||
- `dns_check_interval`: интервал между попытками
|
||||
|
||||
### Пути
|
||||
|
||||
- `cert_dir`: базовая папка сертификатов (обычно `/etc/letsencrypt/live`)
|
||||
- `log_file`: файл логов
|
||||
|
||||
### Nginx Proxy Manager (опционально)
|
||||
|
||||
- `npm_enabled`: включить синхронизацию сертификатов в NPM
|
||||
- `npm_host`: URL NPM (пример: `http://10.10.10.14:81`)
|
||||
- `npm_email`, `npm_password`: учётные данные
|
||||
|
||||
Подробности: [Nginx_Proxy_Manager](Nginx_Proxy_Manager.md).
|
||||
|
||||
## Проверка конфига
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
- `letsencrypt-regru --check -v`
|
||||
|
||||
## Где хранить конфиг
|
||||
|
||||
- храните конфиг с правами `600`
|
||||
- владелец: root
|
||||
|
||||
Пример:
|
||||
|
||||
- `sudo chmod 600 /etc/letsencrypt/regru_config.json`
|
||||
- `sudo chown root:root /etc/letsencrypt/regru_config.json`
|
||||
# Конфигурация
|
||||
|
||||
Проект использует JSON конфиг (пример: `config.json.example`).
|
||||
|
||||
## Важно про мультидоменный режим
|
||||
|
||||
Скрипт поддерживает:
|
||||
|
||||
- один домен в поле `domain`
|
||||
- список доменов в поле `domains` (массив строк)
|
||||
- оба поля одновременно (будет объединение без дублей)
|
||||
|
||||
Пример:
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"domains": [
|
||||
"example.com",
|
||||
"pages.gitea.example.com"
|
||||
],
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://192.0.2.1:81",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "changeme"
|
||||
}
|
||||
```
|
||||
|
||||
## Параметры конфигурации
|
||||
|
||||
### reg.ru API
|
||||
|
||||
- `regru_username`, `regru_password`
|
||||
- учётные данные для API reg.ru
|
||||
- IP должен быть разрешён в настройках API (см. [RegRu_API_Troubleshooting](RegRu_API_Troubleshooting.md))
|
||||
|
||||
### Домены
|
||||
|
||||
- `domain`: основной домен (строка)
|
||||
- `domains`: массив доменов
|
||||
- `wildcard`: если `true`, скрипт будет запрашивать `-d <domain>` и `-d *.<domain>`
|
||||
- обратите внимание: этот флаг сейчас общий для всех доменов из массива
|
||||
|
||||
### Let’s Encrypt
|
||||
|
||||
- `email`: email для регистрации в Let’s Encrypt
|
||||
- `renewal_days`: порог автопродления (например, 30)
|
||||
|
||||
### DNS ожидание/проверки
|
||||
|
||||
- `dns_propagation_wait`: сколько секунд ждать после добавления TXT
|
||||
- `dns_check_attempts`: сколько попыток проверки через `nslookup`
|
||||
- `dns_check_interval`: интервал между попытками
|
||||
|
||||
### Пути
|
||||
|
||||
- `cert_dir`: базовая папка сертификатов (обычно `/etc/letsencrypt/live`)
|
||||
- `log_file`: файл логов
|
||||
|
||||
### Nginx Proxy Manager (опционально)
|
||||
|
||||
- `npm_enabled`: включить синхронизацию сертификатов в NPM
|
||||
- `npm_host`: URL NPM (пример: `http://10.10.10.14:81`)
|
||||
- `npm_email`, `npm_password`: учётные данные
|
||||
|
||||
Подробности: [Nginx_Proxy_Manager](Nginx_Proxy_Manager.md).
|
||||
|
||||
## Проверка конфига
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
- `letsencrypt-regru --check -v`
|
||||
|
||||
## Где хранить конфиг
|
||||
|
||||
- храните конфиг с правами `600`
|
||||
- владелец: root
|
||||
|
||||
Пример:
|
||||
|
||||
- `sudo chmod 600 /etc/letsencrypt/regru_config.json`
|
||||
- `sudo chown root:root /etc/letsencrypt/regru_config.json`
|
||||
|
||||
+124
-124
@@ -1,124 +1,124 @@
|
||||
# Deploy через Actions и Secrets
|
||||
|
||||
Эта страница описывает деплой через workflow `.github/workflows/deploy-service.yml`.
|
||||
|
||||
## Триггеры (когда запускается)
|
||||
|
||||
1) Автоматически по push
|
||||
|
||||
- ветка: `master`
|
||||
- только если изменились файлы:
|
||||
- `letsencrypt_regru_api.py`, `letsencrypt_regru*.sh`, `letsencrypt_regru.ps1`
|
||||
- `requirements.txt`
|
||||
- `systemd/**`
|
||||
- `.github/workflows/deploy-service.yml`
|
||||
|
||||
2) Вручную (workflow_dispatch)
|
||||
|
||||
- из UI Actions
|
||||
- или через Makefile командой `make deploy-service` (Makefile делает API dispatch)
|
||||
|
||||
## Что делает workflow
|
||||
|
||||
- деплоит проект на сервер `192.0.2.1` по SSH (ключ)
|
||||
- перед деплоем генерирует `config.json` из secrets
|
||||
- копирует архив на сервер, распаковывает в `DEPLOY_PATH`
|
||||
- перезапускает systemd сервис `DEPLOY_SERVICE`
|
||||
|
||||
## Обязательные secrets
|
||||
|
||||
### Доступ к репозиторию
|
||||
|
||||
- `GIT_TOKEN` (или `GITEA_TOKEN`)
|
||||
|
||||
### SSH и деплой
|
||||
|
||||
- `DEPLOY_HOST` — должен быть `192.0.2.1`
|
||||
- `DEPLOY_PORT` — обычно `22`
|
||||
- `DEPLOY_USER`
|
||||
- `DEPLOY_SSH_PRIVATE_KEY`
|
||||
- `DEPLOY_PATH`
|
||||
- `DEPLOY_SERVICE`
|
||||
|
||||
### Генерация config.json
|
||||
|
||||
- `CFG_REGRU_USERNAME`
|
||||
- `CFG_REGRU_PASSWORD`
|
||||
- `CFG_EMAIL`
|
||||
- `CFG_DOMAINS`
|
||||
|
||||
`CFG_DOMAINS` поддерживает два формата:
|
||||
|
||||
1) JSON массив:
|
||||
|
||||
```json
|
||||
["example.com", "pages.gitea.example.com"]
|
||||
```
|
||||
|
||||
2) строка через запятую:
|
||||
|
||||
```text
|
||||
example.com,pages.gitea.example.com
|
||||
```
|
||||
|
||||
Если `CFG_DOMAIN` не указан, в поле `domain` берётся первый домен из `CFG_DOMAINS`.
|
||||
|
||||
## Опциональные secrets
|
||||
|
||||
- `DEPLOY_SSH_KNOWN_HOSTS`
|
||||
- `CFG_DOMAIN`
|
||||
- `CFG_WILDCARD`
|
||||
- `CFG_CERT_DIR`
|
||||
- `CFG_LOG_FILE`
|
||||
- `CFG_DNS_PROPAGATION_WAIT`
|
||||
- `CFG_DNS_CHECK_ATTEMPTS`
|
||||
- `CFG_DNS_CHECK_INTERVAL`
|
||||
- `CFG_RENEWAL_DAYS`
|
||||
- `CFG_NPM_ENABLED`
|
||||
- `CFG_NPM_HOST`
|
||||
- `CFG_NPM_EMAIL`
|
||||
- `CFG_NPM_PASSWORD`
|
||||
|
||||
## Соответствие полей config.json
|
||||
|
||||
- `CFG_REGRU_USERNAME` → `regru_username`
|
||||
- `CFG_REGRU_PASSWORD` → `regru_password`
|
||||
- `CFG_DOMAIN` / первый из `CFG_DOMAINS` → `domain`
|
||||
- `CFG_DOMAINS` → `domains`
|
||||
- `CFG_WILDCARD` → `wildcard`
|
||||
- `CFG_EMAIL` → `email`
|
||||
- `CFG_CERT_DIR` → `cert_dir`
|
||||
- `CFG_LOG_FILE` → `log_file`
|
||||
- `CFG_DNS_PROPAGATION_WAIT` → `dns_propagation_wait`
|
||||
- `CFG_DNS_CHECK_ATTEMPTS` → `dns_check_attempts`
|
||||
- `CFG_DNS_CHECK_INTERVAL` → `dns_check_interval`
|
||||
- `CFG_RENEWAL_DAYS` → `renewal_days`
|
||||
- `CFG_NPM_ENABLED` → `npm_enabled`
|
||||
- `CFG_NPM_HOST` → `npm_host`
|
||||
- `CFG_NPM_EMAIL` → `npm_email`
|
||||
- `CFG_NPM_PASSWORD` → `npm_password`
|
||||
|
||||
## Как запустить деплой
|
||||
|
||||
1. Откройте Actions
|
||||
2. Запустите workflow `Deploy scripts to remote server`
|
||||
3. При необходимости задайте `ref` (ветка/тег/коммит)
|
||||
|
||||
### Запуск через Makefile
|
||||
|
||||
Makefile умеет запускать workflow через API на `gitea.example.com`:
|
||||
|
||||
- `make deploy-service` — деплой `master`
|
||||
- `make deploy-service REF=<branch_or_tag>` — деплой указанной ветки/тега
|
||||
|
||||
Нужен токен (любой из): `DFGIT_TOKEN` / `GIT_TOKEN` / `GITEA_TOKEN` / `GITEA_ACCESS_TOKEN`.
|
||||
|
||||
Важно: токен для **запуска** workflow (Makefile) и секреты для **выполнения** workflow (Actions secrets)
|
||||
— это разные вещи. Workflow внутри всё равно требует `GIT_TOKEN` (или `GITEA_TOKEN`) secret,
|
||||
SSH ключ и остальные secrets из списка выше.
|
||||
|
||||
После завершения проверьте статус сервиса на сервере:
|
||||
|
||||
```bash
|
||||
sudo systemctl status letsencrypt-regru.service
|
||||
```
|
||||
# Deploy через Actions и Secrets
|
||||
|
||||
Эта страница описывает деплой через workflow `.github/workflows/deploy-service.yml`.
|
||||
|
||||
## Триггеры (когда запускается)
|
||||
|
||||
1) Автоматически по push
|
||||
|
||||
- ветка: `master`
|
||||
- только если изменились файлы:
|
||||
- `letsencrypt_regru_api.py`, `letsencrypt_regru*.sh`, `letsencrypt_regru.ps1`
|
||||
- `requirements.txt`
|
||||
- `systemd/**`
|
||||
- `.github/workflows/deploy-service.yml`
|
||||
|
||||
2) Вручную (workflow_dispatch)
|
||||
|
||||
- из UI Actions
|
||||
- или через Makefile командой `make deploy-service` (Makefile делает API dispatch)
|
||||
|
||||
## Что делает workflow
|
||||
|
||||
- деплоит проект на сервер `192.0.2.1` по SSH (ключ)
|
||||
- перед деплоем генерирует `config.json` из secrets
|
||||
- копирует архив на сервер, распаковывает в `DEPLOY_PATH`
|
||||
- перезапускает systemd сервис `DEPLOY_SERVICE`
|
||||
|
||||
## Обязательные secrets
|
||||
|
||||
### Доступ к репозиторию
|
||||
|
||||
- `GIT_TOKEN` (или `GITEA_TOKEN`)
|
||||
|
||||
### SSH и деплой
|
||||
|
||||
- `DEPLOY_HOST` — должен быть `192.0.2.1`
|
||||
- `DEPLOY_PORT` — обычно `22`
|
||||
- `DEPLOY_USER`
|
||||
- `DEPLOY_SSH_PRIVATE_KEY`
|
||||
- `DEPLOY_PATH`
|
||||
- `DEPLOY_SERVICE`
|
||||
|
||||
### Генерация config.json
|
||||
|
||||
- `CFG_REGRU_USERNAME`
|
||||
- `CFG_REGRU_PASSWORD`
|
||||
- `CFG_EMAIL`
|
||||
- `CFG_DOMAINS`
|
||||
|
||||
`CFG_DOMAINS` поддерживает два формата:
|
||||
|
||||
1) JSON массив:
|
||||
|
||||
```json
|
||||
["example.com", "pages.gitea.example.com"]
|
||||
```
|
||||
|
||||
2) строка через запятую:
|
||||
|
||||
```text
|
||||
example.com,pages.gitea.example.com
|
||||
```
|
||||
|
||||
Если `CFG_DOMAIN` не указан, в поле `domain` берётся первый домен из `CFG_DOMAINS`.
|
||||
|
||||
## Опциональные secrets
|
||||
|
||||
- `DEPLOY_SSH_KNOWN_HOSTS`
|
||||
- `CFG_DOMAIN`
|
||||
- `CFG_WILDCARD`
|
||||
- `CFG_CERT_DIR`
|
||||
- `CFG_LOG_FILE`
|
||||
- `CFG_DNS_PROPAGATION_WAIT`
|
||||
- `CFG_DNS_CHECK_ATTEMPTS`
|
||||
- `CFG_DNS_CHECK_INTERVAL`
|
||||
- `CFG_RENEWAL_DAYS`
|
||||
- `CFG_NPM_ENABLED`
|
||||
- `CFG_NPM_HOST`
|
||||
- `CFG_NPM_EMAIL`
|
||||
- `CFG_NPM_PASSWORD`
|
||||
|
||||
## Соответствие полей config.json
|
||||
|
||||
- `CFG_REGRU_USERNAME` → `regru_username`
|
||||
- `CFG_REGRU_PASSWORD` → `regru_password`
|
||||
- `CFG_DOMAIN` / первый из `CFG_DOMAINS` → `domain`
|
||||
- `CFG_DOMAINS` → `domains`
|
||||
- `CFG_WILDCARD` → `wildcard`
|
||||
- `CFG_EMAIL` → `email`
|
||||
- `CFG_CERT_DIR` → `cert_dir`
|
||||
- `CFG_LOG_FILE` → `log_file`
|
||||
- `CFG_DNS_PROPAGATION_WAIT` → `dns_propagation_wait`
|
||||
- `CFG_DNS_CHECK_ATTEMPTS` → `dns_check_attempts`
|
||||
- `CFG_DNS_CHECK_INTERVAL` → `dns_check_interval`
|
||||
- `CFG_RENEWAL_DAYS` → `renewal_days`
|
||||
- `CFG_NPM_ENABLED` → `npm_enabled`
|
||||
- `CFG_NPM_HOST` → `npm_host`
|
||||
- `CFG_NPM_EMAIL` → `npm_email`
|
||||
- `CFG_NPM_PASSWORD` → `npm_password`
|
||||
|
||||
## Как запустить деплой
|
||||
|
||||
1. Откройте Actions
|
||||
2. Запустите workflow `Deploy scripts to remote server`
|
||||
3. При необходимости задайте `ref` (ветка/тег/коммит)
|
||||
|
||||
### Запуск через Makefile
|
||||
|
||||
Makefile умеет запускать workflow через API на `gitea.example.com`:
|
||||
|
||||
- `make deploy-service` — деплой `master`
|
||||
- `make deploy-service REF=<branch_or_tag>` — деплой указанной ветки/тега
|
||||
|
||||
Нужен токен (любой из): `DFGIT_TOKEN` / `GIT_TOKEN` / `GITEA_TOKEN` / `GITEA_ACCESS_TOKEN`.
|
||||
|
||||
Важно: токен для **запуска** workflow (Makefile) и секреты для **выполнения** workflow (Actions secrets)
|
||||
— это разные вещи. Workflow внутри всё равно требует `GIT_TOKEN` (или `GITEA_TOKEN`) secret,
|
||||
SSH ключ и остальные secrets из списка выше.
|
||||
|
||||
После завершения проверьте статус сервиса на сервере:
|
||||
|
||||
```bash
|
||||
sudo systemctl status letsencrypt-regru.service
|
||||
```
|
||||
|
||||
+462
-462
@@ -1,462 +1,462 @@
|
||||
# Синхронизация Gitea → GitHub
|
||||
|
||||
Проект описывает несколько способов синхронизировать репозиторий из Gitea в GitHub после push.
|
||||
|
||||
## Варианты
|
||||
|
||||
1) Git Hooks (рекомендуется) — мгновенно
|
||||
2) GitHub Actions — 1–5 минут, гибко
|
||||
3) Gitea Mirror — просто, но по расписанию
|
||||
4) Два remote — локальный рабочий процесс
|
||||
|
||||
## Рекомендуемый способ: Git Hooks
|
||||
|
||||
Идея: на сервере Gitea в `hooks/post-receive` выполнить `git push` в GitHub.
|
||||
|
||||
Ключевые шаги:
|
||||
|
||||
- найти путь к bare репозиторию на сервере Gitea
|
||||
- установить `post-receive` из `gitea-hooks/post-receive`
|
||||
- настроить аутентификацию (SSH ключ или HTTPS token)
|
||||
- вести лог (например `/var/log/gitea/github-sync.log`)
|
||||
|
||||
## Вариант: GitHub Actions
|
||||
|
||||
- настроить секреты (`GITEA_URL`, `GITEA_TOKEN`)
|
||||
- workflow по расписанию/ручному триггеру
|
||||
- опционально webhook из Gitea
|
||||
|
||||
Подробные пошаговые инструкции — см. Appendix ниже.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/GITEA_SYNC.md)
|
||||
<!-- MIGRATED_FROM_DOCS:GITEA_SYNC.md -->
|
||||
|
||||
## 🔄 Синхронизация Gitea → GitHub
|
||||
|
||||
Автоматическая синхронизация репозитория из Gitea в GitHub после каждого push.
|
||||
|
||||
---
|
||||
|
||||
### 📋 Доступные методы
|
||||
|
||||
| Метод | Сложность | Скорость | Надежность | Рекомендация |
|
||||
|-------|-----------|----------|------------|--------------|
|
||||
| **1. Git Hooks** | ⭐⭐ | ⚡ Мгновенно | ✅ Высокая | Рекомендуется |
|
||||
| **2. GitHub Actions** | ⭐⭐⭐ | ⏱️ 1-5 мин | ✅ Высокая | Для сложных сценариев |
|
||||
| **3. Gitea Mirror** | ⭐ | ⏱️ По расписанию | ⭐⭐ Средняя | Самый простой |
|
||||
| **4. Двойной Remote** | ⭐ | ⚡ Мгновенно | ⭐⭐ Средняя | Локальная работа |
|
||||
|
||||
---
|
||||
|
||||
### 🚀 Метод 1: Git Hooks (Рекомендуется)
|
||||
|
||||
#### Установка
|
||||
|
||||
**1. На сервере Gitea найдите путь к репозиторию:**
|
||||
```bash
|
||||
## Обычно это:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
## Или
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
**2. Создайте post-receive hook:**
|
||||
```bash
|
||||
cd /path/to/gitea/repos/username/configure_nginx_manager.git/hooks/
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
**3. Вставьте содержимое** из файла `gitea-hooks/post-receive` (в этом репозитории)
|
||||
|
||||
**4. Настройте параметры:**
|
||||
```bash
|
||||
## В файле post-receive измените:
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
## Или для HTTPS с токеном:
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
**5. Сделайте скрипт исполняемым:**
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
```
|
||||
|
||||
**6. Создайте директорию для логов:**
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
#### Настройка SSH ключей (для git@github.com)
|
||||
|
||||
**На сервере Gitea:**
|
||||
|
||||
**Шаг 1: Определите пользователя Gitea**
|
||||
```bash
|
||||
## Проверьте под каким пользователем запущен Gitea
|
||||
ps aux | grep gitea | grep -v grep
|
||||
|
||||
## Обычно это один из:
|
||||
## - git (стандартная установка)
|
||||
## - gitea (установка через Docker/LXC)
|
||||
```
|
||||
|
||||
**Шаг 2: Переключитесь на этого пользователя**
|
||||
```bash
|
||||
## Попробуйте git:
|
||||
sudo su - git
|
||||
|
||||
## Если не работает, попробуйте gitea:
|
||||
sudo su - gitea
|
||||
|
||||
## Проверьте текущего пользователя
|
||||
whoami # Должно быть: git или gitea
|
||||
```
|
||||
|
||||
**Шаг 3: Создайте SSH ключ**
|
||||
```bash
|
||||
## Создайте SSH ключ (если его ещё нет)
|
||||
ssh-keygen -t ed25519 -C "gitea-to-github-sync" -f ~/.ssh/id_ed25519 -N ""
|
||||
|
||||
## Скопируйте публичный ключ
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
**На GitHub:**
|
||||
1. Settings → SSH and GPG keys
|
||||
2. New SSH key
|
||||
3. Вставьте публичный ключ
|
||||
4. Save
|
||||
|
||||
**⚠️ ВАЖНО: Добавьте GitHub в known_hosts:**
|
||||
```bash
|
||||
## От того же пользователя (git или gitea)
|
||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||
|
||||
## Проверьте что ключ добавлен
|
||||
cat ~/.ssh/known_hosts | grep github.com
|
||||
```
|
||||
|
||||
**Проверка подключения:**
|
||||
```bash
|
||||
ssh -T git@github.com
|
||||
## Должно вывести: Hi username! You've successfully authenticated...
|
||||
```
|
||||
|
||||
#### Настройка токена (для HTTPS)
|
||||
|
||||
**На GitHub:**
|
||||
1. Settings → Developer settings → Personal access tokens → Tokens (classic)
|
||||
2. Generate new token
|
||||
3. Выберите scope: `repo` (полный доступ к репозиториям)
|
||||
4. Скопируйте токен
|
||||
|
||||
**В hook файле:**
|
||||
```bash
|
||||
GITHUB_REPO="https://ghp_YOUR_TOKEN_HERE@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
#### Тестирование
|
||||
|
||||
```bash
|
||||
## Сделайте тестовый commit в Gitea
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync to GitHub"
|
||||
git push
|
||||
|
||||
## Проверьте лог
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
## Проверьте GitHub - изменения должны появиться
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 Метод 2: GitHub Actions
|
||||
|
||||
#### Установка
|
||||
|
||||
**1. Создайте workflow в GitHub репозитории:**
|
||||
|
||||
Файл уже создан: `.github/workflows/sync-from-gitea.yml`
|
||||
|
||||
**2. Настройте секреты в GitHub:**
|
||||
|
||||
GitHub Repository → Settings → Secrets and variables → Actions → New repository secret
|
||||
|
||||
Добавьте:
|
||||
- **Name**: `GITEA_URL`
|
||||
- **Value**: `https://gitea.example.com/username/configure_nginx_manager.git`
|
||||
|
||||
- **Name**: `GITEA_TOKEN`
|
||||
- **Value**: Токен доступа Gitea
|
||||
|
||||
#### Получение токена Gitea
|
||||
|
||||
**В Gitea:**
|
||||
1. Settings → Applications → Generate New Token
|
||||
2. Token Name: "GitHub Sync"
|
||||
3. Select permissions: `read:repository`
|
||||
4. Generate Token
|
||||
5. Скопируйте токен
|
||||
|
||||
#### Запуск синхронизации
|
||||
|
||||
**Автоматически (по расписанию):**
|
||||
- Каждый час проверяет изменения
|
||||
|
||||
**Вручную:**
|
||||
1. GitHub → Actions
|
||||
2. Выберите workflow "Sync from Gitea"
|
||||
3. Run workflow
|
||||
|
||||
**Через webhook от Gitea:**
|
||||
|
||||
В Gitea репозитории:
|
||||
1. Settings → Webhooks → Add Webhook → Gitea
|
||||
2. Target URL: `https://api.github.com/repos/USERNAME/configure_nginx_manager/dispatches`
|
||||
3. HTTP Method: `POST`
|
||||
4. POST Content Type: `application/json`
|
||||
5. Secret: оставьте пустым или используйте
|
||||
6. Trigger On: `Push events`
|
||||
7. Body:
|
||||
```json
|
||||
{
|
||||
"event_type": "gitea-push"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🪞 Метод 3: Gitea Mirror (Встроенная функция)
|
||||
|
||||
#### Настройка
|
||||
|
||||
**В Gitea репозитории:**
|
||||
1. Settings → Repository
|
||||
2. Прокрутите до "Mirror Settings"
|
||||
3. Нажмите "Add Push Mirror"
|
||||
4. Заполните:
|
||||
- **Git Remote Repository URL**: `https://github.com/username/configure_nginx_manager.git`
|
||||
- **Username**: ваш GitHub username
|
||||
- **Password**: GitHub Personal Access Token
|
||||
- **Sync Interval**: `8h` (каждые 8 часов) или `0` (только вручную)
|
||||
5. Save
|
||||
|
||||
#### Ручная синхронизация
|
||||
|
||||
Settings → Repository → Mirror Settings → Sync Now
|
||||
|
||||
#### Преимущества
|
||||
- ✅ Встроенная функция
|
||||
- ✅ Не требует скриптов
|
||||
- ✅ Управление через веб-интерфейс
|
||||
|
||||
#### Недостатки
|
||||
- ⚠️ Работает по расписанию (не мгновенно)
|
||||
- ⚠️ Доступно не во всех версиях Gitea
|
||||
|
||||
---
|
||||
|
||||
### 🔀 Метод 4: Двойной Remote
|
||||
|
||||
#### Для локальной работы
|
||||
|
||||
**Настройка:**
|
||||
```bash
|
||||
## В вашем локальном репозитории
|
||||
cd configure_nginx_manager
|
||||
|
||||
## Добавьте GitHub как второй remote
|
||||
git remote add github git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Или настройте push в оба репозитория одновременно
|
||||
git remote set-url --add --push origin git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Проверьте
|
||||
git remote -v
|
||||
```
|
||||
|
||||
**Использование:**
|
||||
```bash
|
||||
## Обычный push (только в Gitea)
|
||||
git push origin main
|
||||
|
||||
## Push в GitHub
|
||||
git push github main
|
||||
|
||||
## Push в оба репозитория
|
||||
git push origin main
|
||||
git push github main
|
||||
|
||||
## Или создайте alias
|
||||
git config alias.pushall '!git push origin main && git push github main'
|
||||
git pushall
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔍 Проверка синхронизации
|
||||
|
||||
#### Проверка через Git
|
||||
|
||||
```bash
|
||||
## Сравнить коммиты
|
||||
git ls-remote git@gitea.example.com:username/configure_nginx_manager.git
|
||||
git ls-remote git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Должны быть одинаковые SHA
|
||||
```
|
||||
|
||||
#### Проверка логов (Метод 1 - Hooks)
|
||||
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
#### Проверка GitHub Actions (Метод 2)
|
||||
|
||||
1. GitHub Repository → Actions
|
||||
2. Смотрите последние запуски
|
||||
3. Проверьте логи выполнения
|
||||
|
||||
---
|
||||
|
||||
### ⚙️ Рекомендованная конфигурация
|
||||
|
||||
Для максимальной надежности используйте **комбинацию методов**:
|
||||
|
||||
1. **Git Hook** (основной) - мгновенная синхронизация
|
||||
2. **GitHub Actions** (резервный) - проверка каждый час на случай сбоя hook
|
||||
|
||||
#### Установка обоих методов
|
||||
|
||||
```bash
|
||||
## 1. Установите Git Hook на сервере Gitea
|
||||
## (см. Метод 1)
|
||||
|
||||
## 2. Настройте GitHub Actions
|
||||
## (см. Метод 2)
|
||||
|
||||
## 3. GitHub Actions будет подхватывать пропущенные изменения
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🐛 Устранение проблем
|
||||
|
||||
#### Проблема: Hook не срабатывает
|
||||
|
||||
**Проверка:**
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
ls -la /path/to/repo.git/hooks/post-receive
|
||||
## Должно быть -rwxr-xr-x
|
||||
|
||||
## Проверьте права
|
||||
chmod +x /path/to/repo.git/hooks/post-receive
|
||||
chown git:git /path/to/repo.git/hooks/post-receive
|
||||
|
||||
## Проверьте лог ошибок Gitea
|
||||
tail -f /var/log/gitea/gitea.log
|
||||
```
|
||||
|
||||
#### Проблема: Permission denied (SSH)
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
## Убедитесь что SSH ключ добавлен в GitHub
|
||||
ssh -T git@github.com
|
||||
|
||||
## Проверьте права на .ssh
|
||||
chmod 700 ~/.ssh
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
#### Проблема: Authentication failed (HTTPS)
|
||||
|
||||
**Решение:**
|
||||
- Проверьте токен GitHub (должен иметь scope `repo`)
|
||||
- Токен не истёк
|
||||
- Правильный формат URL: `https://TOKEN@github.com/user/repo.git`
|
||||
|
||||
#### Проблема: GitHub Actions не запускается
|
||||
|
||||
**Решение:**
|
||||
1. Проверьте секреты в Settings → Secrets
|
||||
2. Проверьте формат webhook от Gitea
|
||||
3. Запустите вручную для теста
|
||||
|
||||
---
|
||||
|
||||
### 📊 Сравнение методов
|
||||
|
||||
#### Скорость синхронизации
|
||||
- **Git Hooks**: ⚡ < 1 секунды
|
||||
- **GitHub Actions (webhook)**: ⏱️ 10-30 секунд
|
||||
- **GitHub Actions (schedule)**: ⏱️ до 1 часа
|
||||
- **Gitea Mirror**: ⏱️ по расписанию
|
||||
|
||||
#### Надежность
|
||||
- **Git Hooks**: ⭐⭐⭐⭐⭐ (при правильной настройке)
|
||||
- **GitHub Actions**: ⭐⭐⭐⭐⭐ (очень надежно)
|
||||
- **Gitea Mirror**: ⭐⭐⭐ (зависит от версии Gitea)
|
||||
- **Двойной Remote**: ⭐⭐ (требует ручного действия)
|
||||
|
||||
---
|
||||
|
||||
### 🎯 Итоговая рекомендация
|
||||
|
||||
Для проекта `configure_nginx_manager`:
|
||||
|
||||
**1. Основной метод: Git Hook**
|
||||
- Быстро
|
||||
- Надежно
|
||||
- Автоматически
|
||||
|
||||
**2. Резервный метод: GitHub Actions**
|
||||
- Проверка каждый час
|
||||
- Подхватит пропущенные изменения
|
||||
- Можно запустить вручную
|
||||
|
||||
**3. Мониторинг:**
|
||||
```bash
|
||||
## Еженедельная проверка
|
||||
git ls-remote origin | head -1
|
||||
git ls-remote github | head -1
|
||||
## SHA должны совпадать
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📝 Быстрая установка
|
||||
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
sudo su - git
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
## Скачайте hook
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
|
||||
## Настройте
|
||||
nano post-receive
|
||||
## Измените GITHUB_REPO
|
||||
|
||||
## Права
|
||||
chmod +x post-receive
|
||||
|
||||
## Тест
|
||||
echo "test" | ./post-receive
|
||||
```
|
||||
|
||||
Готово! 🎉
|
||||
|
||||
# Синхронизация Gitea → GitHub
|
||||
|
||||
Проект описывает несколько способов синхронизировать репозиторий из Gitea в GitHub после push.
|
||||
|
||||
## Варианты
|
||||
|
||||
1) Git Hooks (рекомендуется) — мгновенно
|
||||
2) GitHub Actions — 1–5 минут, гибко
|
||||
3) Gitea Mirror — просто, но по расписанию
|
||||
4) Два remote — локальный рабочий процесс
|
||||
|
||||
## Рекомендуемый способ: Git Hooks
|
||||
|
||||
Идея: на сервере Gitea в `hooks/post-receive` выполнить `git push` в GitHub.
|
||||
|
||||
Ключевые шаги:
|
||||
|
||||
- найти путь к bare репозиторию на сервере Gitea
|
||||
- установить `post-receive` из `gitea-hooks/post-receive`
|
||||
- настроить аутентификацию (SSH ключ или HTTPS token)
|
||||
- вести лог (например `/var/log/gitea/github-sync.log`)
|
||||
|
||||
## Вариант: GitHub Actions
|
||||
|
||||
- настроить секреты (`GITEA_URL`, `GITEA_TOKEN`)
|
||||
- workflow по расписанию/ручному триггеру
|
||||
- опционально webhook из Gitea
|
||||
|
||||
Подробные пошаговые инструкции — см. Appendix ниже.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/GITEA_SYNC.md)
|
||||
<!-- MIGRATED_FROM_DOCS:GITEA_SYNC.md -->
|
||||
|
||||
## 🔄 Синхронизация Gitea → GitHub
|
||||
|
||||
Автоматическая синхронизация репозитория из Gitea в GitHub после каждого push.
|
||||
|
||||
---
|
||||
|
||||
### 📋 Доступные методы
|
||||
|
||||
| Метод | Сложность | Скорость | Надежность | Рекомендация |
|
||||
|-------|-----------|----------|------------|--------------|
|
||||
| **1. Git Hooks** | ⭐⭐ | ⚡ Мгновенно | ✅ Высокая | Рекомендуется |
|
||||
| **2. GitHub Actions** | ⭐⭐⭐ | ⏱️ 1-5 мин | ✅ Высокая | Для сложных сценариев |
|
||||
| **3. Gitea Mirror** | ⭐ | ⏱️ По расписанию | ⭐⭐ Средняя | Самый простой |
|
||||
| **4. Двойной Remote** | ⭐ | ⚡ Мгновенно | ⭐⭐ Средняя | Локальная работа |
|
||||
|
||||
---
|
||||
|
||||
### 🚀 Метод 1: Git Hooks (Рекомендуется)
|
||||
|
||||
#### Установка
|
||||
|
||||
**1. На сервере Gitea найдите путь к репозиторию:**
|
||||
```bash
|
||||
## Обычно это:
|
||||
/var/lib/gitea/data/gitea-repositories/username/configure_nginx_manager.git
|
||||
## Или
|
||||
/home/git/gitea-repositories/username/configure_nginx_manager.git
|
||||
```
|
||||
|
||||
**2. Создайте post-receive hook:**
|
||||
```bash
|
||||
cd /path/to/gitea/repos/username/configure_nginx_manager.git/hooks/
|
||||
nano post-receive
|
||||
```
|
||||
|
||||
**3. Вставьте содержимое** из файла `gitea-hooks/post-receive` (в этом репозитории)
|
||||
|
||||
**4. Настройте параметры:**
|
||||
```bash
|
||||
## В файле post-receive измените:
|
||||
GITHUB_REPO="git@github.com:YOUR_USERNAME/configure_nginx_manager.git"
|
||||
## Или для HTTPS с токеном:
|
||||
GITHUB_REPO="https://YOUR_TOKEN@github.com/YOUR_USERNAME/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
**5. Сделайте скрипт исполняемым:**
|
||||
```bash
|
||||
chmod +x post-receive
|
||||
```
|
||||
|
||||
**6. Создайте директорию для логов:**
|
||||
```bash
|
||||
mkdir -p /var/log/gitea
|
||||
chown git:git /var/log/gitea
|
||||
```
|
||||
|
||||
#### Настройка SSH ключей (для git@github.com)
|
||||
|
||||
**На сервере Gitea:**
|
||||
|
||||
**Шаг 1: Определите пользователя Gitea**
|
||||
```bash
|
||||
## Проверьте под каким пользователем запущен Gitea
|
||||
ps aux | grep gitea | grep -v grep
|
||||
|
||||
## Обычно это один из:
|
||||
## - git (стандартная установка)
|
||||
## - gitea (установка через Docker/LXC)
|
||||
```
|
||||
|
||||
**Шаг 2: Переключитесь на этого пользователя**
|
||||
```bash
|
||||
## Попробуйте git:
|
||||
sudo su - git
|
||||
|
||||
## Если не работает, попробуйте gitea:
|
||||
sudo su - gitea
|
||||
|
||||
## Проверьте текущего пользователя
|
||||
whoami # Должно быть: git или gitea
|
||||
```
|
||||
|
||||
**Шаг 3: Создайте SSH ключ**
|
||||
```bash
|
||||
## Создайте SSH ключ (если его ещё нет)
|
||||
ssh-keygen -t ed25519 -C "gitea-to-github-sync" -f ~/.ssh/id_ed25519 -N ""
|
||||
|
||||
## Скопируйте публичный ключ
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
**На GitHub:**
|
||||
1. Settings → SSH and GPG keys
|
||||
2. New SSH key
|
||||
3. Вставьте публичный ключ
|
||||
4. Save
|
||||
|
||||
**⚠️ ВАЖНО: Добавьте GitHub в known_hosts:**
|
||||
```bash
|
||||
## От того же пользователя (git или gitea)
|
||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||
|
||||
## Проверьте что ключ добавлен
|
||||
cat ~/.ssh/known_hosts | grep github.com
|
||||
```
|
||||
|
||||
**Проверка подключения:**
|
||||
```bash
|
||||
ssh -T git@github.com
|
||||
## Должно вывести: Hi username! You've successfully authenticated...
|
||||
```
|
||||
|
||||
#### Настройка токена (для HTTPS)
|
||||
|
||||
**На GitHub:**
|
||||
1. Settings → Developer settings → Personal access tokens → Tokens (classic)
|
||||
2. Generate new token
|
||||
3. Выберите scope: `repo` (полный доступ к репозиториям)
|
||||
4. Скопируйте токен
|
||||
|
||||
**В hook файле:**
|
||||
```bash
|
||||
GITHUB_REPO="https://ghp_YOUR_TOKEN_HERE@github.com/username/configure_nginx_manager.git"
|
||||
```
|
||||
|
||||
#### Тестирование
|
||||
|
||||
```bash
|
||||
## Сделайте тестовый commit в Gitea
|
||||
cd /tmp
|
||||
git clone http://gitea.example.com/username/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
echo "test" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test sync to GitHub"
|
||||
git push
|
||||
|
||||
## Проверьте лог
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
|
||||
## Проверьте GitHub - изменения должны появиться
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 Метод 2: GitHub Actions
|
||||
|
||||
#### Установка
|
||||
|
||||
**1. Создайте workflow в GitHub репозитории:**
|
||||
|
||||
Файл уже создан: `.github/workflows/sync-from-gitea.yml`
|
||||
|
||||
**2. Настройте секреты в GitHub:**
|
||||
|
||||
GitHub Repository → Settings → Secrets and variables → Actions → New repository secret
|
||||
|
||||
Добавьте:
|
||||
- **Name**: `GITEA_URL`
|
||||
- **Value**: `https://gitea.example.com/username/configure_nginx_manager.git`
|
||||
|
||||
- **Name**: `GITEA_TOKEN`
|
||||
- **Value**: Токен доступа Gitea
|
||||
|
||||
#### Получение токена Gitea
|
||||
|
||||
**В Gitea:**
|
||||
1. Settings → Applications → Generate New Token
|
||||
2. Token Name: "GitHub Sync"
|
||||
3. Select permissions: `read:repository`
|
||||
4. Generate Token
|
||||
5. Скопируйте токен
|
||||
|
||||
#### Запуск синхронизации
|
||||
|
||||
**Автоматически (по расписанию):**
|
||||
- Каждый час проверяет изменения
|
||||
|
||||
**Вручную:**
|
||||
1. GitHub → Actions
|
||||
2. Выберите workflow "Sync from Gitea"
|
||||
3. Run workflow
|
||||
|
||||
**Через webhook от Gitea:**
|
||||
|
||||
В Gitea репозитории:
|
||||
1. Settings → Webhooks → Add Webhook → Gitea
|
||||
2. Target URL: `https://api.github.com/repos/USERNAME/configure_nginx_manager/dispatches`
|
||||
3. HTTP Method: `POST`
|
||||
4. POST Content Type: `application/json`
|
||||
5. Secret: оставьте пустым или используйте
|
||||
6. Trigger On: `Push events`
|
||||
7. Body:
|
||||
```json
|
||||
{
|
||||
"event_type": "gitea-push"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🪞 Метод 3: Gitea Mirror (Встроенная функция)
|
||||
|
||||
#### Настройка
|
||||
|
||||
**В Gitea репозитории:**
|
||||
1. Settings → Repository
|
||||
2. Прокрутите до "Mirror Settings"
|
||||
3. Нажмите "Add Push Mirror"
|
||||
4. Заполните:
|
||||
- **Git Remote Repository URL**: `https://github.com/username/configure_nginx_manager.git`
|
||||
- **Username**: ваш GitHub username
|
||||
- **Password**: GitHub Personal Access Token
|
||||
- **Sync Interval**: `8h` (каждые 8 часов) или `0` (только вручную)
|
||||
5. Save
|
||||
|
||||
#### Ручная синхронизация
|
||||
|
||||
Settings → Repository → Mirror Settings → Sync Now
|
||||
|
||||
#### Преимущества
|
||||
- ✅ Встроенная функция
|
||||
- ✅ Не требует скриптов
|
||||
- ✅ Управление через веб-интерфейс
|
||||
|
||||
#### Недостатки
|
||||
- ⚠️ Работает по расписанию (не мгновенно)
|
||||
- ⚠️ Доступно не во всех версиях Gitea
|
||||
|
||||
---
|
||||
|
||||
### 🔀 Метод 4: Двойной Remote
|
||||
|
||||
#### Для локальной работы
|
||||
|
||||
**Настройка:**
|
||||
```bash
|
||||
## В вашем локальном репозитории
|
||||
cd configure_nginx_manager
|
||||
|
||||
## Добавьте GitHub как второй remote
|
||||
git remote add github git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Или настройте push в оба репозитория одновременно
|
||||
git remote set-url --add --push origin git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Проверьте
|
||||
git remote -v
|
||||
```
|
||||
|
||||
**Использование:**
|
||||
```bash
|
||||
## Обычный push (только в Gitea)
|
||||
git push origin main
|
||||
|
||||
## Push в GitHub
|
||||
git push github main
|
||||
|
||||
## Push в оба репозитория
|
||||
git push origin main
|
||||
git push github main
|
||||
|
||||
## Или создайте alias
|
||||
git config alias.pushall '!git push origin main && git push github main'
|
||||
git pushall
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔍 Проверка синхронизации
|
||||
|
||||
#### Проверка через Git
|
||||
|
||||
```bash
|
||||
## Сравнить коммиты
|
||||
git ls-remote git@gitea.example.com:username/configure_nginx_manager.git
|
||||
git ls-remote git@github.com:username/configure_nginx_manager.git
|
||||
|
||||
## Должны быть одинаковые SHA
|
||||
```
|
||||
|
||||
#### Проверка логов (Метод 1 - Hooks)
|
||||
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
tail -f /var/log/gitea/github-sync.log
|
||||
```
|
||||
|
||||
#### Проверка GitHub Actions (Метод 2)
|
||||
|
||||
1. GitHub Repository → Actions
|
||||
2. Смотрите последние запуски
|
||||
3. Проверьте логи выполнения
|
||||
|
||||
---
|
||||
|
||||
### ⚙️ Рекомендованная конфигурация
|
||||
|
||||
Для максимальной надежности используйте **комбинацию методов**:
|
||||
|
||||
1. **Git Hook** (основной) - мгновенная синхронизация
|
||||
2. **GitHub Actions** (резервный) - проверка каждый час на случай сбоя hook
|
||||
|
||||
#### Установка обоих методов
|
||||
|
||||
```bash
|
||||
## 1. Установите Git Hook на сервере Gitea
|
||||
## (см. Метод 1)
|
||||
|
||||
## 2. Настройте GitHub Actions
|
||||
## (см. Метод 2)
|
||||
|
||||
## 3. GitHub Actions будет подхватывать пропущенные изменения
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🐛 Устранение проблем
|
||||
|
||||
#### Проблема: Hook не срабатывает
|
||||
|
||||
**Проверка:**
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
ls -la /path/to/repo.git/hooks/post-receive
|
||||
## Должно быть -rwxr-xr-x
|
||||
|
||||
## Проверьте права
|
||||
chmod +x /path/to/repo.git/hooks/post-receive
|
||||
chown git:git /path/to/repo.git/hooks/post-receive
|
||||
|
||||
## Проверьте лог ошибок Gitea
|
||||
tail -f /var/log/gitea/gitea.log
|
||||
```
|
||||
|
||||
#### Проблема: Permission denied (SSH)
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
## Убедитесь что SSH ключ добавлен в GitHub
|
||||
ssh -T git@github.com
|
||||
|
||||
## Проверьте права на .ssh
|
||||
chmod 700 ~/.ssh
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
#### Проблема: Authentication failed (HTTPS)
|
||||
|
||||
**Решение:**
|
||||
- Проверьте токен GitHub (должен иметь scope `repo`)
|
||||
- Токен не истёк
|
||||
- Правильный формат URL: `https://TOKEN@github.com/user/repo.git`
|
||||
|
||||
#### Проблема: GitHub Actions не запускается
|
||||
|
||||
**Решение:**
|
||||
1. Проверьте секреты в Settings → Secrets
|
||||
2. Проверьте формат webhook от Gitea
|
||||
3. Запустите вручную для теста
|
||||
|
||||
---
|
||||
|
||||
### 📊 Сравнение методов
|
||||
|
||||
#### Скорость синхронизации
|
||||
- **Git Hooks**: ⚡ < 1 секунды
|
||||
- **GitHub Actions (webhook)**: ⏱️ 10-30 секунд
|
||||
- **GitHub Actions (schedule)**: ⏱️ до 1 часа
|
||||
- **Gitea Mirror**: ⏱️ по расписанию
|
||||
|
||||
#### Надежность
|
||||
- **Git Hooks**: ⭐⭐⭐⭐⭐ (при правильной настройке)
|
||||
- **GitHub Actions**: ⭐⭐⭐⭐⭐ (очень надежно)
|
||||
- **Gitea Mirror**: ⭐⭐⭐ (зависит от версии Gitea)
|
||||
- **Двойной Remote**: ⭐⭐ (требует ручного действия)
|
||||
|
||||
---
|
||||
|
||||
### 🎯 Итоговая рекомендация
|
||||
|
||||
Для проекта `configure_nginx_manager`:
|
||||
|
||||
**1. Основной метод: Git Hook**
|
||||
- Быстро
|
||||
- Надежно
|
||||
- Автоматически
|
||||
|
||||
**2. Резервный метод: GitHub Actions**
|
||||
- Проверка каждый час
|
||||
- Подхватит пропущенные изменения
|
||||
- Можно запустить вручную
|
||||
|
||||
**3. Мониторинг:**
|
||||
```bash
|
||||
## Еженедельная проверка
|
||||
git ls-remote origin | head -1
|
||||
git ls-remote github | head -1
|
||||
## SHA должны совпадать
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📝 Быстрая установка
|
||||
|
||||
```bash
|
||||
## На сервере Gitea
|
||||
sudo su - git
|
||||
cd /path/to/gitea-repositories/username/configure_nginx_manager.git/hooks/
|
||||
|
||||
## Скачайте hook
|
||||
wget https://raw.githubusercontent.com/username/configure_nginx_manager/main/gitea-hooks/post-receive
|
||||
|
||||
## Настройте
|
||||
nano post-receive
|
||||
## Измените GITHUB_REPO
|
||||
|
||||
## Права
|
||||
chmod +x post-receive
|
||||
|
||||
## Тест
|
||||
echo "test" | ./post-receive
|
||||
```
|
||||
|
||||
Готово! 🎉
|
||||
|
||||
|
||||
+379
-379
@@ -1,379 +1,379 @@
|
||||
# SSL Certificate Manager (Let's Encrypt + reg.ru) — Wiki (RU)
|
||||
|
||||
Это Wiki проекта **configure_nginx_manager**: автоматическое получение и продление SSL сертификатов Let's Encrypt через **DNS-01** (API **reg.ru**) с опциональной синхронизацией сертификатов в **Nginx Proxy Manager (NPM)**.
|
||||
|
||||
## Что умеет проект
|
||||
|
||||
- Получение **production** сертификатов Let's Encrypt (DNS-01) для доменов reg.ru
|
||||
- Поддержка **wildcard** (например, `*.example.com`)
|
||||
- Автопроверка и автопродление (cron/systemd)
|
||||
- Диагностика: `--test-api`, `--test-dns`
|
||||
- Тестовые самоподписанные сертификаты для разработки: `--test-cert` (без лимитов LE)
|
||||
- (Опционально) Автозагрузка/обновление сертификатов в NPM по API
|
||||
- **Мультидоменный режим**: один конфиг → несколько доменов (`domains[]`)
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
1) Установка
|
||||
- См. страницу: [Installation](Installation.md)
|
||||
|
||||
2) Конфигурация
|
||||
- См. страницу: [Configuration](Configuration.md)
|
||||
|
||||
3) Проверка доступа к API и DNS
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
4) Тестирование без лимитов
|
||||
- `letsencrypt-regru --test-cert`
|
||||
|
||||
5) Production сертификат
|
||||
- `letsencrypt-regru --obtain`
|
||||
|
||||
6) Автопродление
|
||||
- `letsencrypt-regru --auto` (обычно запускается systemd timer'ом)
|
||||
|
||||
## Навигация
|
||||
|
||||
- [Installation](Installation.md)
|
||||
- [Configuration](Configuration.md)
|
||||
- [Commands](Commands.md)
|
||||
- [LetsEncrypt Workflow](LetsEncrypt_Workflow.md)
|
||||
- [Nginx Proxy Manager](Nginx_Proxy_Manager.md)
|
||||
- [Testing](Testing.md)
|
||||
- [Reg.ru API Troubleshooting](RegRu_API_Troubleshooting.md)
|
||||
- [Build & Release](Build_and_Release.md)
|
||||
- [Deploy и Secrets](Deploy_Actions_Secrets.md)
|
||||
- [Project Structure](Project_Structure.md)
|
||||
- [Gitea → GitHub Sync](Gitea_Sync.md)
|
||||
- [Changelog](Changelog.md)
|
||||
|
||||
## Примечания по лимитам Let's Encrypt
|
||||
|
||||
- Production: обычно **до 5 сертификатов/неделю на домен**
|
||||
- Для отладки автоматизации используйте:
|
||||
- `--staging` (LE staging, без лимитов)
|
||||
- `--test-cert` (самоподписанный, мгновенно)
|
||||
|
||||
---
|
||||
|
||||
Источник: страницы Wiki этого репозитория и актуальное поведение CLI.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/DESCRIPTION.md)
|
||||
<!-- MIGRATED_FROM_DOCS:DESCRIPTION.md -->
|
||||
|
||||
## 🔒 SSL Certificate Manager для Let's Encrypt + reg.ru
|
||||
|
||||
**Автоматическое управление SSL сертификатами Let's Encrypt с DNS валидацией через API reg.ru и интеграцией с Nginx Proxy Manager**
|
||||
|
||||
### 📖 Описание
|
||||
|
||||
Комплексное решение для автоматизации создания, обновления и управления SSL сертификатами Let's Encrypt для доменов, зарегистрированных на reg.ru. Поддерживает DNS-01 валидацию, wildcard сертификаты, автоматическую загрузку в Nginx Proxy Manager и генерацию тестовых сертификатов для разработки.
|
||||
|
||||
#### ✨ Основные возможности
|
||||
|
||||
- 🔐 **Автоматическое получение SSL сертификатов** через Let's Encrypt
|
||||
- 🌐 **DNS-01 валидация** через API reg.ru (поддержка wildcard доменов)
|
||||
- 🔄 **Автоматическое обновление** сертификатов с настраиваемым порогом
|
||||
- 📦 **Интеграция с Nginx Proxy Manager** - автоматическая загрузка и обновление
|
||||
- 🧪 **Тестовые сертификаты** - обход лимитов Let's Encrypt (5 в неделю)
|
||||
- ⚙️ **Полная автоматизация** через systemd/cron
|
||||
- 🔀 **Синхронизация репозиториев** - автоматическая синхронизация Gitea → GitHub
|
||||
|
||||
#### 🚀 Быстрый старт
|
||||
|
||||
```bash
|
||||
## Установка через Makefile
|
||||
sudo make install
|
||||
|
||||
## Настройка конфигурации
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Создание тестового сертификата (без лимитов)
|
||||
sudo make test-cert
|
||||
|
||||
## Получение production сертификата
|
||||
sudo make obtain
|
||||
```
|
||||
|
||||
#### 📋 Требования
|
||||
|
||||
- **ОС**: Linux (Ubuntu/Debian/CentOS)
|
||||
- **Python**: 3.6+
|
||||
- **Зависимости**: certbot, requests, cryptography
|
||||
- **API**: reg.ru (доступ к DNS управлению)
|
||||
- **Опционально**: Nginx Proxy Manager
|
||||
|
||||
#### 🎯 Сценарии использования
|
||||
|
||||
- ✅ Автоматизация SSL сертификатов для web серверов
|
||||
- ✅ Централизованное управление через Nginx Proxy Manager
|
||||
- ✅ Тестирование и разработка с самоподписанными сертификатами
|
||||
- ✅ CI/CD интеграция
|
||||
- ✅ Мультидоменные конфигурации с wildcard
|
||||
|
||||
#### 📚 Документация
|
||||
|
||||
- [README.md](README.md) - Полное руководство (1400+ строк)
|
||||
- [TESTING_GUIDE.md](Testing.md) - Руководство по тестированию
|
||||
- [GITEA_SYNC.md](Gitea_Sync.md) - Синхронизация Gitea → GitHub
|
||||
- [CHEATSHEET.md](Commands.md) - Быстрая шпаргалка
|
||||
|
||||
---
|
||||
|
||||
### 📖 Description (English)
|
||||
|
||||
**Automated Let's Encrypt SSL Certificate Manager with DNS validation via reg.ru API and Nginx Proxy Manager integration**
|
||||
|
||||
Comprehensive solution for automating the creation, renewal, and management of Let's Encrypt SSL certificates for domains registered with reg.ru. Supports DNS-01 validation, wildcard certificates, automatic upload to Nginx Proxy Manager, and test certificate generation for development.
|
||||
|
||||
#### ✨ Key Features
|
||||
|
||||
- 🔐 **Automatic SSL certificate** issuance via Let's Encrypt
|
||||
- 🌐 **DNS-01 validation** via reg.ru API (wildcard domain support)
|
||||
- 🔄 **Automatic renewal** with configurable threshold
|
||||
- 📦 **Nginx Proxy Manager integration** - automatic upload and update
|
||||
- 🧪 **Test certificates** - bypass Let's Encrypt rate limits (5 per week)
|
||||
- ⚙️ **Full automation** via systemd/cron
|
||||
- 🔀 **Repository sync** - automatic Gitea → GitHub synchronization
|
||||
|
||||
#### 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
## Install via Makefile
|
||||
sudo make install
|
||||
|
||||
## Configure
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Create test certificate (no limits)
|
||||
sudo make test-cert
|
||||
|
||||
## Get production certificate
|
||||
sudo make obtain
|
||||
```
|
||||
|
||||
#### 📋 Requirements
|
||||
|
||||
- **OS**: Linux (Ubuntu/Debian/CentOS)
|
||||
- **Python**: 3.6+
|
||||
- **Dependencies**: certbot, requests, cryptography
|
||||
- **API**: reg.ru (DNS management access)
|
||||
- **Optional**: Nginx Proxy Manager
|
||||
|
||||
#### 🎯 Use Cases
|
||||
|
||||
- ✅ SSL certificate automation for web servers
|
||||
- ✅ Centralized management via Nginx Proxy Manager
|
||||
- ✅ Development and testing with self-signed certificates
|
||||
- ✅ CI/CD integration
|
||||
- ✅ Multi-domain configurations with wildcards
|
||||
|
||||
#### 📚 Documentation
|
||||
|
||||
- [README.md](README.md) - Complete guide (1400+ lines)
|
||||
- [TESTING_GUIDE.md](Testing.md) - Testing guide
|
||||
- [GITEA_SYNC.md](Gitea_Sync.md) - Gitea → GitHub sync
|
||||
- [CHEATSHEET.md](Commands.md) - Quick reference
|
||||
|
||||
---
|
||||
|
||||
### 👤 Автор / Author
|
||||
|
||||
**Фофанов Дмитрий** @ 2025
|
||||
|
||||
### 📄 Лицензия / License
|
||||
|
||||
Open Source - Free to use
|
||||
|
||||
### 🤝 Вклад / Contributing
|
||||
|
||||
Pull requests приветствуются / Pull requests are welcome!
|
||||
|
||||
### 🔗 Ссылки / Links
|
||||
|
||||
- **Документация reg.ru API**: https://www.reg.ru/support/api
|
||||
- **Let's Encrypt**: https://letsencrypt.org/
|
||||
- **Nginx Proxy Manager**: https://nginxproxymanager.com/
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/SSL_SCRIPTS_README.md)
|
||||
<!-- MIGRATED_FROM_DOCS:SSL_SCRIPTS_README.md -->
|
||||
|
||||
## Автоматизация SSL сертификатов Let's Encrypt для reg.ru
|
||||
|
||||
Набор скриптов для автоматического создания и обновления SSL сертификатов Let's Encrypt с использованием DNS валидации через API reg.ru.
|
||||
|
||||
### 📁 Содержимое проекта
|
||||
|
||||
- **letsencrypt_regru_dns.sh** - Bash скрипт (Linux) с certbot-dns-regru
|
||||
- **letsencrypt_regru_api.py** - Python скрипт с прямым API интеграцией
|
||||
- **letsencrypt_regru.ps1** - PowerShell скрипт (Windows)
|
||||
- **config.json.example** - Пример файла конфигурации
|
||||
- **USAGE.md** - Подробная инструкция по использованию
|
||||
|
||||
### 🚀 Быстрый старт
|
||||
|
||||
#### Linux (Bash)
|
||||
|
||||
```bash
|
||||
## 1. Отредактируйте конфигурацию в скрипте
|
||||
nano letsencrypt_regru_dns.sh
|
||||
|
||||
## 2. Установите права
|
||||
chmod +x letsencrypt_regru_dns.sh
|
||||
|
||||
## 3. Запустите
|
||||
sudo ./letsencrypt_regru_dns.sh
|
||||
```
|
||||
|
||||
#### Linux (Python)
|
||||
|
||||
```bash
|
||||
## 1. Создайте конфигурацию
|
||||
sudo python3 letsencrypt_regru_api.py --create-config /etc/letsencrypt/regru_config.json
|
||||
|
||||
## 2. Отредактируйте конфигурацию
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## 3. Получите сертификат
|
||||
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json --obtain
|
||||
```
|
||||
|
||||
#### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
## 1. Создайте файл конфигурации config.json на основе config.json.example
|
||||
|
||||
## 2. Запустите скрипт
|
||||
.\letsencrypt_regru.ps1 -ConfigFile .\config.json
|
||||
```
|
||||
|
||||
### ⚙️ Конфигурация
|
||||
|
||||
Отредактируйте `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "ваш_логин",
|
||||
"regru_password": "ваш_пароль",
|
||||
"domain": "example.com",
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### 📋 Требования
|
||||
|
||||
#### Linux
|
||||
- certbot
|
||||
- Python 3.6+
|
||||
- pip3
|
||||
- requests, cryptography (Python модули)
|
||||
- certbot-dns-regru (опционально)
|
||||
|
||||
#### Windows
|
||||
- certbot
|
||||
- PowerShell 5.1+
|
||||
- openssl (для проверки сертификатов)
|
||||
|
||||
### 🔄 Автоматическое обновление
|
||||
|
||||
#### Через cron (Linux)
|
||||
|
||||
```bash
|
||||
## Добавьте в crontab
|
||||
sudo crontab -e
|
||||
|
||||
## Проверка каждый день в 3:00
|
||||
0 3 * * * /usr/bin/python3 /path/to/letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json
|
||||
```
|
||||
|
||||
#### Через Task Scheduler (Windows)
|
||||
|
||||
1. Откройте Task Scheduler
|
||||
2. Создайте новую задачу
|
||||
3. Триггер: Ежедневно в 3:00
|
||||
4. Действие: Запуск PowerShell скрипта
|
||||
|
||||
### 📖 Функции
|
||||
|
||||
✅ Создание wildcard сертификатов (*.domain.com)
|
||||
✅ Автоматическая DNS валидация через API reg.ru
|
||||
✅ Проверка срока действия сертификата
|
||||
✅ Автоматическое обновление перед истечением
|
||||
✅ Перезагрузка веб-сервера после обновления
|
||||
✅ Подробное логирование всех операций
|
||||
|
||||
### 🔧 Использование с Nginx Proxy Manager
|
||||
|
||||
После получения сертификата:
|
||||
|
||||
1. Войдите в NPM: http://192.0.2.1:81/
|
||||
2. SSL Certificates → Add SSL Certificate → Custom
|
||||
3. Вставьте содержимое:
|
||||
- Certificate Key: `/etc/letsencrypt/live/domain.com/privkey.pem`
|
||||
- Certificate: `/etc/letsencrypt/live/domain.com/fullchain.pem`
|
||||
|
||||
### 📝 Логи
|
||||
|
||||
- Bash: `/var/log/letsencrypt_regru.log`
|
||||
- Python: `/var/log/letsencrypt_regru.log`
|
||||
- PowerShell: `.\letsencrypt_regru.log`
|
||||
- Certbot: `/var/log/letsencrypt/letsencrypt.log`
|
||||
|
||||
### 🆘 Устранение неполадок
|
||||
|
||||
#### Ошибка аутентификации API
|
||||
- Проверьте учетные данные reg.ru
|
||||
- Убедитесь, что домен под вашим управлением
|
||||
|
||||
#### DNS запись не распространяется
|
||||
- Увеличьте `dns_propagation_wait` до 120 секунд
|
||||
- Проверьте DNS: `nslookup -type=TXT _acme-challenge.domain.com`
|
||||
|
||||
#### Certbot не найден
|
||||
```bash
|
||||
## Ubuntu/Debian
|
||||
sudo apt-get install certbot
|
||||
|
||||
## Или через snap
|
||||
sudo snap install --classic certbot
|
||||
```
|
||||
|
||||
### 📚 Документация
|
||||
|
||||
Подробная документация в файле [USAGE.md](USAGE.md)
|
||||
|
||||
### 🔐 Безопасность
|
||||
|
||||
- Храните учетные данные в безопасности
|
||||
- Используйте `chmod 600` для конфигурационных файлов
|
||||
- Регулярно обновляйте пароли
|
||||
|
||||
### ⚠️ Важно
|
||||
|
||||
- Let's Encrypt сертификаты действительны 90 дней
|
||||
- Рекомендуется настроить автоматическое обновление
|
||||
- Для wildcard сертификатов требуется DNS валидация
|
||||
|
||||
### 📞 Поддержка
|
||||
|
||||
- [Документация reg.ru API](https://www.reg.ru/support/api)
|
||||
- [Документация Let's Encrypt](https://letsencrypt.org/docs/)
|
||||
- [Certbot Documentation](https://certbot.eff.org/docs/)
|
||||
|
||||
### 📄 Лицензия
|
||||
|
||||
Скрипты предоставляются "как есть" для свободного использования.
|
||||
|
||||
---
|
||||
|
||||
**Успешной автоматизации! 🔒**
|
||||
|
||||
# SSL Certificate Manager (Let's Encrypt + reg.ru) — Wiki (RU)
|
||||
|
||||
Это Wiki проекта **configure_nginx_manager**: автоматическое получение и продление SSL сертификатов Let's Encrypt через **DNS-01** (API **reg.ru**) с опциональной синхронизацией сертификатов в **Nginx Proxy Manager (NPM)**.
|
||||
|
||||
## Что умеет проект
|
||||
|
||||
- Получение **production** сертификатов Let's Encrypt (DNS-01) для доменов reg.ru
|
||||
- Поддержка **wildcard** (например, `*.example.com`)
|
||||
- Автопроверка и автопродление (cron/systemd)
|
||||
- Диагностика: `--test-api`, `--test-dns`
|
||||
- Тестовые самоподписанные сертификаты для разработки: `--test-cert` (без лимитов LE)
|
||||
- (Опционально) Автозагрузка/обновление сертификатов в NPM по API
|
||||
- **Мультидоменный режим**: один конфиг → несколько доменов (`domains[]`)
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
1) Установка
|
||||
- См. страницу: [Installation](Installation.md)
|
||||
|
||||
2) Конфигурация
|
||||
- См. страницу: [Configuration](Configuration.md)
|
||||
|
||||
3) Проверка доступа к API и DNS
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
4) Тестирование без лимитов
|
||||
- `letsencrypt-regru --test-cert`
|
||||
|
||||
5) Production сертификат
|
||||
- `letsencrypt-regru --obtain`
|
||||
|
||||
6) Автопродление
|
||||
- `letsencrypt-regru --auto` (обычно запускается systemd timer'ом)
|
||||
|
||||
## Навигация
|
||||
|
||||
- [Installation](Installation.md)
|
||||
- [Configuration](Configuration.md)
|
||||
- [Commands](Commands.md)
|
||||
- [LetsEncrypt Workflow](LetsEncrypt_Workflow.md)
|
||||
- [Nginx Proxy Manager](Nginx_Proxy_Manager.md)
|
||||
- [Testing](Testing.md)
|
||||
- [Reg.ru API Troubleshooting](RegRu_API_Troubleshooting.md)
|
||||
- [Build & Release](Build_and_Release.md)
|
||||
- [Deploy и Secrets](Deploy_Actions_Secrets.md)
|
||||
- [Project Structure](Project_Structure.md)
|
||||
- [Gitea → GitHub Sync](Gitea_Sync.md)
|
||||
- [Changelog](Changelog.md)
|
||||
|
||||
## Примечания по лимитам Let's Encrypt
|
||||
|
||||
- Production: обычно **до 5 сертификатов/неделю на домен**
|
||||
- Для отладки автоматизации используйте:
|
||||
- `--staging` (LE staging, без лимитов)
|
||||
- `--test-cert` (самоподписанный, мгновенно)
|
||||
|
||||
---
|
||||
|
||||
Источник: страницы Wiki этого репозитория и актуальное поведение CLI.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/DESCRIPTION.md)
|
||||
<!-- MIGRATED_FROM_DOCS:DESCRIPTION.md -->
|
||||
|
||||
## 🔒 SSL Certificate Manager для Let's Encrypt + reg.ru
|
||||
|
||||
**Автоматическое управление SSL сертификатами Let's Encrypt с DNS валидацией через API reg.ru и интеграцией с Nginx Proxy Manager**
|
||||
|
||||
### 📖 Описание
|
||||
|
||||
Комплексное решение для автоматизации создания, обновления и управления SSL сертификатами Let's Encrypt для доменов, зарегистрированных на reg.ru. Поддерживает DNS-01 валидацию, wildcard сертификаты, автоматическую загрузку в Nginx Proxy Manager и генерацию тестовых сертификатов для разработки.
|
||||
|
||||
#### ✨ Основные возможности
|
||||
|
||||
- 🔐 **Автоматическое получение SSL сертификатов** через Let's Encrypt
|
||||
- 🌐 **DNS-01 валидация** через API reg.ru (поддержка wildcard доменов)
|
||||
- 🔄 **Автоматическое обновление** сертификатов с настраиваемым порогом
|
||||
- 📦 **Интеграция с Nginx Proxy Manager** - автоматическая загрузка и обновление
|
||||
- 🧪 **Тестовые сертификаты** - обход лимитов Let's Encrypt (5 в неделю)
|
||||
- ⚙️ **Полная автоматизация** через systemd/cron
|
||||
- 🔀 **Синхронизация репозиториев** - автоматическая синхронизация Gitea → GitHub
|
||||
|
||||
#### 🚀 Быстрый старт
|
||||
|
||||
```bash
|
||||
## Установка через Makefile
|
||||
sudo make install
|
||||
|
||||
## Настройка конфигурации
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Создание тестового сертификата (без лимитов)
|
||||
sudo make test-cert
|
||||
|
||||
## Получение production сертификата
|
||||
sudo make obtain
|
||||
```
|
||||
|
||||
#### 📋 Требования
|
||||
|
||||
- **ОС**: Linux (Ubuntu/Debian/CentOS)
|
||||
- **Python**: 3.6+
|
||||
- **Зависимости**: certbot, requests, cryptography
|
||||
- **API**: reg.ru (доступ к DNS управлению)
|
||||
- **Опционально**: Nginx Proxy Manager
|
||||
|
||||
#### 🎯 Сценарии использования
|
||||
|
||||
- ✅ Автоматизация SSL сертификатов для web серверов
|
||||
- ✅ Централизованное управление через Nginx Proxy Manager
|
||||
- ✅ Тестирование и разработка с самоподписанными сертификатами
|
||||
- ✅ CI/CD интеграция
|
||||
- ✅ Мультидоменные конфигурации с wildcard
|
||||
|
||||
#### 📚 Документация
|
||||
|
||||
- [README.md](README.md) - Полное руководство (1400+ строк)
|
||||
- [TESTING_GUIDE.md](Testing.md) - Руководство по тестированию
|
||||
- [GITEA_SYNC.md](Gitea_Sync.md) - Синхронизация Gitea → GitHub
|
||||
- [CHEATSHEET.md](Commands.md) - Быстрая шпаргалка
|
||||
|
||||
---
|
||||
|
||||
### 📖 Description (English)
|
||||
|
||||
**Automated Let's Encrypt SSL Certificate Manager with DNS validation via reg.ru API and Nginx Proxy Manager integration**
|
||||
|
||||
Comprehensive solution for automating the creation, renewal, and management of Let's Encrypt SSL certificates for domains registered with reg.ru. Supports DNS-01 validation, wildcard certificates, automatic upload to Nginx Proxy Manager, and test certificate generation for development.
|
||||
|
||||
#### ✨ Key Features
|
||||
|
||||
- 🔐 **Automatic SSL certificate** issuance via Let's Encrypt
|
||||
- 🌐 **DNS-01 validation** via reg.ru API (wildcard domain support)
|
||||
- 🔄 **Automatic renewal** with configurable threshold
|
||||
- 📦 **Nginx Proxy Manager integration** - automatic upload and update
|
||||
- 🧪 **Test certificates** - bypass Let's Encrypt rate limits (5 per week)
|
||||
- ⚙️ **Full automation** via systemd/cron
|
||||
- 🔀 **Repository sync** - automatic Gitea → GitHub synchronization
|
||||
|
||||
#### 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
## Install via Makefile
|
||||
sudo make install
|
||||
|
||||
## Configure
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Create test certificate (no limits)
|
||||
sudo make test-cert
|
||||
|
||||
## Get production certificate
|
||||
sudo make obtain
|
||||
```
|
||||
|
||||
#### 📋 Requirements
|
||||
|
||||
- **OS**: Linux (Ubuntu/Debian/CentOS)
|
||||
- **Python**: 3.6+
|
||||
- **Dependencies**: certbot, requests, cryptography
|
||||
- **API**: reg.ru (DNS management access)
|
||||
- **Optional**: Nginx Proxy Manager
|
||||
|
||||
#### 🎯 Use Cases
|
||||
|
||||
- ✅ SSL certificate automation for web servers
|
||||
- ✅ Centralized management via Nginx Proxy Manager
|
||||
- ✅ Development and testing with self-signed certificates
|
||||
- ✅ CI/CD integration
|
||||
- ✅ Multi-domain configurations with wildcards
|
||||
|
||||
#### 📚 Documentation
|
||||
|
||||
- [README.md](README.md) - Complete guide (1400+ lines)
|
||||
- [TESTING_GUIDE.md](Testing.md) - Testing guide
|
||||
- [GITEA_SYNC.md](Gitea_Sync.md) - Gitea → GitHub sync
|
||||
- [CHEATSHEET.md](Commands.md) - Quick reference
|
||||
|
||||
---
|
||||
|
||||
### 👤 Автор / Author
|
||||
|
||||
**Фофанов Дмитрий** @ 2025
|
||||
|
||||
### 📄 Лицензия / License
|
||||
|
||||
Open Source - Free to use
|
||||
|
||||
### 🤝 Вклад / Contributing
|
||||
|
||||
Pull requests приветствуются / Pull requests are welcome!
|
||||
|
||||
### 🔗 Ссылки / Links
|
||||
|
||||
- **Документация reg.ru API**: https://www.reg.ru/support/api
|
||||
- **Let's Encrypt**: https://letsencrypt.org/
|
||||
- **Nginx Proxy Manager**: https://nginxproxymanager.com/
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/SSL_SCRIPTS_README.md)
|
||||
<!-- MIGRATED_FROM_DOCS:SSL_SCRIPTS_README.md -->
|
||||
|
||||
## Автоматизация SSL сертификатов Let's Encrypt для reg.ru
|
||||
|
||||
Набор скриптов для автоматического создания и обновления SSL сертификатов Let's Encrypt с использованием DNS валидации через API reg.ru.
|
||||
|
||||
### 📁 Содержимое проекта
|
||||
|
||||
- **letsencrypt_regru_dns.sh** - Bash скрипт (Linux) с certbot-dns-regru
|
||||
- **letsencrypt_regru_api.py** - Python скрипт с прямым API интеграцией
|
||||
- **letsencrypt_regru.ps1** - PowerShell скрипт (Windows)
|
||||
- **config.json.example** - Пример файла конфигурации
|
||||
- **USAGE.md** - Подробная инструкция по использованию
|
||||
|
||||
### 🚀 Быстрый старт
|
||||
|
||||
#### Linux (Bash)
|
||||
|
||||
```bash
|
||||
## 1. Отредактируйте конфигурацию в скрипте
|
||||
nano letsencrypt_regru_dns.sh
|
||||
|
||||
## 2. Установите права
|
||||
chmod +x letsencrypt_regru_dns.sh
|
||||
|
||||
## 3. Запустите
|
||||
sudo ./letsencrypt_regru_dns.sh
|
||||
```
|
||||
|
||||
#### Linux (Python)
|
||||
|
||||
```bash
|
||||
## 1. Создайте конфигурацию
|
||||
sudo python3 letsencrypt_regru_api.py --create-config /etc/letsencrypt/regru_config.json
|
||||
|
||||
## 2. Отредактируйте конфигурацию
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## 3. Получите сертификат
|
||||
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json --obtain
|
||||
```
|
||||
|
||||
#### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
## 1. Создайте файл конфигурации config.json на основе config.json.example
|
||||
|
||||
## 2. Запустите скрипт
|
||||
.\letsencrypt_regru.ps1 -ConfigFile .\config.json
|
||||
```
|
||||
|
||||
### ⚙️ Конфигурация
|
||||
|
||||
Отредактируйте `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "ваш_логин",
|
||||
"regru_password": "ваш_пароль",
|
||||
"domain": "example.com",
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### 📋 Требования
|
||||
|
||||
#### Linux
|
||||
- certbot
|
||||
- Python 3.6+
|
||||
- pip3
|
||||
- requests, cryptography (Python модули)
|
||||
- certbot-dns-regru (опционально)
|
||||
|
||||
#### Windows
|
||||
- certbot
|
||||
- PowerShell 5.1+
|
||||
- openssl (для проверки сертификатов)
|
||||
|
||||
### 🔄 Автоматическое обновление
|
||||
|
||||
#### Через cron (Linux)
|
||||
|
||||
```bash
|
||||
## Добавьте в crontab
|
||||
sudo crontab -e
|
||||
|
||||
## Проверка каждый день в 3:00
|
||||
0 3 * * * /usr/bin/python3 /path/to/letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json
|
||||
```
|
||||
|
||||
#### Через Task Scheduler (Windows)
|
||||
|
||||
1. Откройте Task Scheduler
|
||||
2. Создайте новую задачу
|
||||
3. Триггер: Ежедневно в 3:00
|
||||
4. Действие: Запуск PowerShell скрипта
|
||||
|
||||
### 📖 Функции
|
||||
|
||||
✅ Создание wildcard сертификатов (*.domain.com)
|
||||
✅ Автоматическая DNS валидация через API reg.ru
|
||||
✅ Проверка срока действия сертификата
|
||||
✅ Автоматическое обновление перед истечением
|
||||
✅ Перезагрузка веб-сервера после обновления
|
||||
✅ Подробное логирование всех операций
|
||||
|
||||
### 🔧 Использование с Nginx Proxy Manager
|
||||
|
||||
После получения сертификата:
|
||||
|
||||
1. Войдите в NPM: http://192.0.2.1:81/
|
||||
2. SSL Certificates → Add SSL Certificate → Custom
|
||||
3. Вставьте содержимое:
|
||||
- Certificate Key: `/etc/letsencrypt/live/domain.com/privkey.pem`
|
||||
- Certificate: `/etc/letsencrypt/live/domain.com/fullchain.pem`
|
||||
|
||||
### 📝 Логи
|
||||
|
||||
- Bash: `/var/log/letsencrypt_regru.log`
|
||||
- Python: `/var/log/letsencrypt_regru.log`
|
||||
- PowerShell: `.\letsencrypt_regru.log`
|
||||
- Certbot: `/var/log/letsencrypt/letsencrypt.log`
|
||||
|
||||
### 🆘 Устранение неполадок
|
||||
|
||||
#### Ошибка аутентификации API
|
||||
- Проверьте учетные данные reg.ru
|
||||
- Убедитесь, что домен под вашим управлением
|
||||
|
||||
#### DNS запись не распространяется
|
||||
- Увеличьте `dns_propagation_wait` до 120 секунд
|
||||
- Проверьте DNS: `nslookup -type=TXT _acme-challenge.domain.com`
|
||||
|
||||
#### Certbot не найден
|
||||
```bash
|
||||
## Ubuntu/Debian
|
||||
sudo apt-get install certbot
|
||||
|
||||
## Или через snap
|
||||
sudo snap install --classic certbot
|
||||
```
|
||||
|
||||
### 📚 Документация
|
||||
|
||||
Подробная документация в файле [USAGE.md](USAGE.md)
|
||||
|
||||
### 🔐 Безопасность
|
||||
|
||||
- Храните учетные данные в безопасности
|
||||
- Используйте `chmod 600` для конфигурационных файлов
|
||||
- Регулярно обновляйте пароли
|
||||
|
||||
### ⚠️ Важно
|
||||
|
||||
- Let's Encrypt сертификаты действительны 90 дней
|
||||
- Рекомендуется настроить автоматическое обновление
|
||||
- Для wildcard сертификатов требуется DNS валидация
|
||||
|
||||
### 📞 Поддержка
|
||||
|
||||
- [Документация reg.ru API](https://www.reg.ru/support/api)
|
||||
- [Документация Let's Encrypt](https://letsencrypt.org/docs/)
|
||||
- [Certbot Documentation](https://certbot.eff.org/docs/)
|
||||
|
||||
### 📄 Лицензия
|
||||
|
||||
Скрипты предоставляются "как есть" для свободного использования.
|
||||
|
||||
---
|
||||
|
||||
**Успешной автоматизации! 🔒**
|
||||
|
||||
|
||||
+482
-482
@@ -1,482 +1,482 @@
|
||||
# Установка
|
||||
|
||||
Есть два основных пути установки:
|
||||
|
||||
1) Автоустановщик `letsencrypt_regru.sh` (самый простой)
|
||||
2) Установка через `Makefile` (контролируемый сценарий)
|
||||
|
||||
## Требования
|
||||
|
||||
- Linux (Debian/Ubuntu/CentOS/RHEL/Fedora)
|
||||
- Root (запуск через `sudo`)
|
||||
- Python 3.6+ (для исходников) или готовый бинарник
|
||||
- certbot (системный)
|
||||
- Доступ к API reg.ru (разрешённый IP, корректные учётные данные)
|
||||
|
||||
## Вариант A — автоустановщик (рекомендуется)
|
||||
|
||||
### Установка одной командой
|
||||
|
||||
- Через `curl`:
|
||||
|
||||
`sudo bash -c "$(curl -fsSL https://github.com/DFofanov/configure_nginx_manager/raw/refs/heads/master/letsencrypt_regru.sh)"`
|
||||
|
||||
### Что делает установщик
|
||||
|
||||
- Ставит зависимости
|
||||
- Создаёт виртуальное окружение
|
||||
- Помогает интерактивно собрать конфиг
|
||||
- Настраивает systemd service/timer
|
||||
- Добавляет глобальную команду `letsencrypt-regru`
|
||||
|
||||
## Вариант B — через Makefile
|
||||
|
||||
Типовой сценарий:
|
||||
|
||||
- `sudo make install`
|
||||
- отредактировать конфиг (см. [Configuration](Configuration.md))
|
||||
- `sudo make test-cert` (проверка без лимитов)
|
||||
- `sudo make obtain` (production сертификат)
|
||||
|
||||
Полный список команд: [Commands](Commands.md).
|
||||
|
||||
## Где лежат файлы после установки
|
||||
|
||||
(типовая структура, может отличаться от ваших путей)
|
||||
|
||||
- Приложение: `/opt/letsencrypt-regru/`
|
||||
- Конфиг: `/etc/letsencrypt/regru_config.json` (или `/etc/letsencrypt-regru/config.json` — зависит от сценария)
|
||||
- Сертификаты: `/etc/letsencrypt/live/<domain>/`
|
||||
- Логи: `/var/log/letsencrypt_regru.log` (или `/var/log/letsencrypt-regru/letsencrypt_regru.log`)
|
||||
- systemd units: `/etc/systemd/system/letsencrypt-regru.service` и `.timer`
|
||||
|
||||
## Проверка после установки
|
||||
|
||||
- `letsencrypt-regru --help`
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
Если ловите ошибку `Access to API from this IP denied`, см. [RegRu_API_Troubleshooting](RegRu_API_Troubleshooting.md).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/INSTALL_GUIDE.md)
|
||||
<!-- MIGRATED_FROM_DOCS:INSTALL_GUIDE.md -->
|
||||
|
||||
## Руководство по использованию letsencrypt_regru.sh
|
||||
|
||||
**Автор:** Фофанов Дмитрий
|
||||
**Дата:** 28.10.2025
|
||||
|
||||
### Описание
|
||||
|
||||
`letsencrypt_regru.sh` - это автоматический установщик для Let's Encrypt Manager с интеграцией reg.ru и Nginx Proxy Manager.
|
||||
|
||||
Скрипт автоматизирует:
|
||||
- Установку всех системных зависимостей
|
||||
- Создание виртуального окружения Python
|
||||
- Установку Python библиотек (requests, cryptography, certbot)
|
||||
- Интерактивную настройку конфигурации
|
||||
- Создание и настройку systemd сервисов
|
||||
- Настройку автоматического обновления сертификатов
|
||||
|
||||
### Требования
|
||||
|
||||
- Linux (Debian/Ubuntu, CentOS/RHEL/Fedora)
|
||||
- Root доступ (sudo)
|
||||
- Минимум 512MB RAM
|
||||
- Минимум 1GB свободного места на диске
|
||||
- Интернет соединение
|
||||
|
||||
### Быстрая установка
|
||||
|
||||
**Способ 1: Автоматическая установка (рекомендуется)**
|
||||
|
||||
Самый быстрый способ - запустить установку напрямую с GitHub:
|
||||
|
||||
```bash
|
||||
sudo bash -c "$(curl -fsSL https://github.com/DFofanov/configure_nginx_manager/raw/refs/heads/master/letsencrypt_regru.sh)"
|
||||
```
|
||||
|
||||
Эта команда:
|
||||
- Автоматически скачает установочный скрипт
|
||||
- Запустит его с правами root
|
||||
- Проведет через интерактивную настройку
|
||||
|
||||
**Способ 2: Через клонирование репозитория**
|
||||
|
||||
Если вы хотите изучить код перед установкой:
|
||||
|
||||
```bash
|
||||
## 1. Скачайте репозиторий
|
||||
git clone https://github.com/DFofanov/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
|
||||
## 2. Дайте права на выполнение
|
||||
chmod +x letsencrypt_regru.sh
|
||||
|
||||
## 3. Запустите установку
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
### Интерактивная настройка
|
||||
|
||||
Во время установки скрипт спросит:
|
||||
|
||||
1. **Домен** - ваш основной домен (например, `example.com`)
|
||||
2. **Email** - для уведомлений Let's Encrypt
|
||||
3. **Учетные данные reg.ru:**
|
||||
- Имя пользователя
|
||||
- Пароль
|
||||
4. **Wildcard сертификат** - создавать ли `*.example.com` (рекомендуется: Да)
|
||||
5. **Интеграция с NPM** (опционально):
|
||||
- Адрес NPM (например, `http://10.10.10.14:81`)
|
||||
- Email для входа в NPM
|
||||
- Пароль NPM
|
||||
|
||||
### Структура после установки
|
||||
|
||||
```
|
||||
/opt/letsencrypt-regru/ # Приложение
|
||||
├── letsencrypt_regru_api.py # Основной скрипт
|
||||
├── venv/ # Виртуальное окружение Python
|
||||
└── (docs) # Документация — см. Wiki/README репозитория
|
||||
|
||||
/etc/letsencrypt-regru/ # Конфигурация
|
||||
└── config.json # Настройки (credentials, домен, NPM)
|
||||
|
||||
/var/log/letsencrypt-regru/ # Логи
|
||||
└── letsencrypt_regru.log
|
||||
|
||||
/etc/letsencrypt/live/ # Сертификаты Let's Encrypt
|
||||
└── example.com/
|
||||
├── privkey.pem
|
||||
├── cert.pem
|
||||
├── chain.pem
|
||||
└── fullchain.pem
|
||||
|
||||
/etc/systemd/system/ # Systemd сервисы
|
||||
├── letsencrypt-regru.service # Сервис обновления
|
||||
└── letsencrypt-regru.timer # Таймер (каждые 12 часов)
|
||||
|
||||
/usr/local/bin/
|
||||
└── letsencrypt-regru # Глобальная команда
|
||||
```
|
||||
|
||||
### Использование команды letsencrypt-regru
|
||||
|
||||
После установки доступна удобная глобальная команда с множеством функций:
|
||||
|
||||
#### 🔧 Основные команды
|
||||
|
||||
```bash
|
||||
## Проверить срок действия текущего сертификата
|
||||
letsencrypt-regru --check
|
||||
|
||||
## Получить новый сертификат Let's Encrypt
|
||||
letsencrypt-regru --obtain
|
||||
|
||||
## Обновить существующий сертификат
|
||||
letsencrypt-regru --renew
|
||||
|
||||
## Автоматически проверить и обновить при необходимости
|
||||
letsencrypt-regru --auto
|
||||
|
||||
## Создать тестовый самоподписанный сертификат
|
||||
letsencrypt-regru --test-cert
|
||||
```
|
||||
|
||||
#### 🧪 Команды диагностики и тестирования
|
||||
|
||||
```bash
|
||||
## Проверить доступ к API reg.ru
|
||||
## - Показывает текущий IP
|
||||
## - Тестирует подключение к API
|
||||
## - Отображает баланс аккаунта
|
||||
letsencrypt-regru --test-api
|
||||
|
||||
## Тестовое создание DNS записи TXT
|
||||
## - Полная симуляция процесса SSL сертификации
|
||||
## - Создает временную TXT запись _acme-challenge
|
||||
## - Ожидает распространения DNS (60 секунд)
|
||||
## - Проверяет через публичные DNS серверы
|
||||
## - Автоматически удаляет тестовую запись
|
||||
letsencrypt-regru --test-dns
|
||||
|
||||
## Показать справку по всем командам
|
||||
letsencrypt-regru --help
|
||||
|
||||
## Включить подробный вывод (verbose mode)
|
||||
letsencrypt-regru --obtain -v
|
||||
letsencrypt-regru --check -v
|
||||
```
|
||||
|
||||
#### ⚙️ Служебные команды (внутреннее использование)
|
||||
|
||||
```bash
|
||||
## Certbot authentication hook (используется certbot автоматически)
|
||||
letsencrypt-regru --auth-hook
|
||||
|
||||
## Certbot cleanup hook (используется certbot автоматически)
|
||||
letsencrypt-regru --cleanup-hook
|
||||
```
|
||||
|
||||
#### 📋 Описание команд
|
||||
|
||||
| Команда | Описание | Использование |
|
||||
|---------|----------|---------------|
|
||||
| `--check` | Проверяет срок действия сертификата | Регулярная проверка |
|
||||
| `--obtain` | Получает новый сертификат от Let's Encrypt | Первое создание |
|
||||
| `--renew` | Обновляет существующий сертификат | Продление срока |
|
||||
| `--auto` | Автоматическая проверка и обновление | Для cron/systemd |
|
||||
| `--test-cert` | Создает тестовый самоподписанный сертификат | Разработка/тестирование |
|
||||
| `--test-api` | Проверяет доступ к API reg.ru | Диагностика подключения |
|
||||
| `--test-dns` | Тестирует создание DNS записи | Проверка перед SSL |
|
||||
| `--auth-hook` | Hook для certbot (создание DNS) | Внутреннее |
|
||||
| `--cleanup-hook` | Hook для certbot (удаление DNS) | Внутреннее |
|
||||
| `--help` | Показывает справку | Помощь |
|
||||
| `-v` | Подробный вывод | Отладка |
|
||||
|
||||
### Автоматическое обновление
|
||||
|
||||
Установщик настраивает systemd timer для автоматической проверки:
|
||||
|
||||
```bash
|
||||
## Проверить статус таймера
|
||||
systemctl status letsencrypt-regru.timer
|
||||
|
||||
## Когда следующий запуск
|
||||
systemctl list-timers letsencrypt-regru.timer
|
||||
|
||||
## Посмотреть историю запусков
|
||||
journalctl -u letsencrypt-regru
|
||||
|
||||
## Следить за логами в реальном времени
|
||||
journalctl -u letsencrypt-regru -f
|
||||
```
|
||||
|
||||
#### Настройки таймера
|
||||
|
||||
По умолчанию:
|
||||
- Первый запуск: через 15 минут после загрузки системы
|
||||
- Периодичность: каждые 12 часов
|
||||
- Случайная задержка: до 1 часа (чтобы не создавать нагрузку)
|
||||
|
||||
Изменить можно в `/etc/systemd/system/letsencrypt-regru.timer`.
|
||||
|
||||
### Редактирование конфигурации
|
||||
|
||||
```bash
|
||||
## Открыть конфигурацию в редакторе
|
||||
sudo nano /etc/letsencrypt-regru/config.json
|
||||
|
||||
## После изменений перезапустите таймер
|
||||
sudo systemctl restart letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
#### Пример config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt-regru/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://10.10.10.14:81",
|
||||
"npm_email": "admin@npm.local",
|
||||
"npm_password": "secure_password"
|
||||
}
|
||||
```
|
||||
|
||||
### Обновление приложения
|
||||
|
||||
```bash
|
||||
## Скачайте последнюю версию
|
||||
cd configure_nginx_manager
|
||||
git pull
|
||||
|
||||
## Запустите обновление
|
||||
sudo ./letsencrypt_regru.sh update
|
||||
```
|
||||
|
||||
Обновление:
|
||||
- Остановит таймер
|
||||
- Обновит скрипт
|
||||
- Обновит Python зависимости
|
||||
- Перезапустит таймер
|
||||
|
||||
### Удаление
|
||||
|
||||
```bash
|
||||
## Полное удаление приложения
|
||||
sudo ./letsencrypt_regru.sh uninstall
|
||||
```
|
||||
|
||||
Скрипт удалит:
|
||||
- Приложение из `/opt/letsencrypt-regru/`
|
||||
- Systemd сервисы
|
||||
- Глобальную команду
|
||||
|
||||
Сертификаты в `/etc/letsencrypt/live/` сохраняются!
|
||||
|
||||
Опционально можно удалить:
|
||||
- Конфигурацию `/etc/letsencrypt-regru/`
|
||||
- Логи `/var/log/letsencrypt-regru/`
|
||||
|
||||
### Просмотр логов
|
||||
|
||||
```bash
|
||||
## Логи systemd (рекомендуется)
|
||||
journalctl -u letsencrypt-regru -f
|
||||
|
||||
## Файл лога
|
||||
tail -f /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Последние 100 строк
|
||||
tail -n 100 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
```
|
||||
|
||||
### Устранение проблем
|
||||
|
||||
#### Проверка установки
|
||||
|
||||
```bash
|
||||
## Проверить наличие команды
|
||||
which letsencrypt-regru
|
||||
|
||||
## Проверить Python окружение
|
||||
ls -la /opt/letsencrypt-regru/venv/
|
||||
|
||||
## Проверить systemd сервисы
|
||||
systemctl list-unit-files | grep letsencrypt-regru
|
||||
```
|
||||
|
||||
#### Ошибки при установке
|
||||
|
||||
**Ошибка: "Permission denied"**
|
||||
```bash
|
||||
## Запустите с sudo
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
**Ошибка: "Package not found"**
|
||||
```bash
|
||||
## Обновите списки пакетов
|
||||
sudo apt-get update # Debian/Ubuntu
|
||||
sudo yum update # CentOS/RHEL
|
||||
```
|
||||
|
||||
**Ошибка: "Python module not found"**
|
||||
```bash
|
||||
## Переустановите виртуальное окружение
|
||||
sudo rm -rf /opt/letsencrypt-regru/venv
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
#### Проблемы с сертификатами
|
||||
|
||||
**Сертификат не создается**
|
||||
```bash
|
||||
## Проверьте логи
|
||||
tail -n 50 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Проверьте конфигурацию
|
||||
cat /etc/letsencrypt-regru/config.json
|
||||
|
||||
## Попробуйте вручную
|
||||
letsencrypt-regru --obtain -v
|
||||
```
|
||||
|
||||
**DNS не обновляется**
|
||||
```bash
|
||||
## Увеличьте время ожидания в config.json
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20
|
||||
```
|
||||
|
||||
#### Проблемы с NPM
|
||||
|
||||
**Не загружается в NPM**
|
||||
```bash
|
||||
## Проверьте доступность NPM
|
||||
curl http://192.0.2.1:81
|
||||
|
||||
## Проверьте учетные данные в config.json
|
||||
## Попробуйте вручную
|
||||
letsencrypt-regru --test-cert -v
|
||||
```
|
||||
|
||||
### Поддерживаемые ОС
|
||||
|
||||
✅ Debian 10, 11, 12
|
||||
✅ Ubuntu 20.04, 22.04, 24.04
|
||||
✅ CentOS 7, 8
|
||||
✅ RHEL 7, 8, 9
|
||||
✅ Fedora 35+
|
||||
|
||||
### Дополнительные возможности
|
||||
|
||||
#### Тестовый сертификат
|
||||
|
||||
Для тестирования без лимитов Let's Encrypt:
|
||||
|
||||
```bash
|
||||
letsencrypt-regru --test-cert
|
||||
```
|
||||
|
||||
Создаст самоподписанный сертификат на 90 дней.
|
||||
|
||||
#### Ручной запуск обновления
|
||||
|
||||
```bash
|
||||
## Запустить сервис вручную
|
||||
sudo systemctl start letsencrypt-regru.service
|
||||
|
||||
## Посмотреть статус
|
||||
systemctl status letsencrypt-regru.service
|
||||
```
|
||||
|
||||
#### Изменить периодичность проверки
|
||||
|
||||
Отредактируйте `/etc/systemd/system/letsencrypt-regru.timer`:
|
||||
|
||||
```ini
|
||||
[Timer]
|
||||
## Каждые 6 часов вместо 12
|
||||
OnUnitActiveSec=6h
|
||||
```
|
||||
|
||||
Затем:
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
### Безопасность
|
||||
|
||||
- Конфигурация с паролями имеет права `600` (только root)
|
||||
- Приватные ключи сертификатов имеют права `600`
|
||||
- Все операции выполняются от root
|
||||
- Логи доступны только root
|
||||
|
||||
### Поддержка
|
||||
|
||||
- GitHub Issues: https://github.com/YOUR_USERNAME/configure_nginx_manager/issues
|
||||
- Документация: Wiki/README в этом репозитории
|
||||
- Email: admin@example.com
|
||||
|
||||
---
|
||||
|
||||
**Разработано:** Фофанов Дмитрий
|
||||
**Дата:** 28.10.2025
|
||||
**Версия:** 2.0
|
||||
|
||||
# Установка
|
||||
|
||||
Есть два основных пути установки:
|
||||
|
||||
1) Автоустановщик `letsencrypt_regru.sh` (самый простой)
|
||||
2) Установка через `Makefile` (контролируемый сценарий)
|
||||
|
||||
## Требования
|
||||
|
||||
- Linux (Debian/Ubuntu/CentOS/RHEL/Fedora)
|
||||
- Root (запуск через `sudo`)
|
||||
- Python 3.6+ (для исходников) или готовый бинарник
|
||||
- certbot (системный)
|
||||
- Доступ к API reg.ru (разрешённый IP, корректные учётные данные)
|
||||
|
||||
## Вариант A — автоустановщик (рекомендуется)
|
||||
|
||||
### Установка одной командой
|
||||
|
||||
- Через `curl`:
|
||||
|
||||
`sudo bash -c "$(curl -fsSL https://github.com/DFofanov/configure_nginx_manager/raw/refs/heads/master/letsencrypt_regru.sh)"`
|
||||
|
||||
### Что делает установщик
|
||||
|
||||
- Ставит зависимости
|
||||
- Создаёт виртуальное окружение
|
||||
- Помогает интерактивно собрать конфиг
|
||||
- Настраивает systemd service/timer
|
||||
- Добавляет глобальную команду `letsencrypt-regru`
|
||||
|
||||
## Вариант B — через Makefile
|
||||
|
||||
Типовой сценарий:
|
||||
|
||||
- `sudo make install`
|
||||
- отредактировать конфиг (см. [Configuration](Configuration.md))
|
||||
- `sudo make test-cert` (проверка без лимитов)
|
||||
- `sudo make obtain` (production сертификат)
|
||||
|
||||
Полный список команд: [Commands](Commands.md).
|
||||
|
||||
## Где лежат файлы после установки
|
||||
|
||||
(типовая структура, может отличаться от ваших путей)
|
||||
|
||||
- Приложение: `/opt/letsencrypt-regru/`
|
||||
- Конфиг: `/etc/letsencrypt/regru_config.json` (или `/etc/letsencrypt-regru/config.json` — зависит от сценария)
|
||||
- Сертификаты: `/etc/letsencrypt/live/<domain>/`
|
||||
- Логи: `/var/log/letsencrypt_regru.log` (или `/var/log/letsencrypt-regru/letsencrypt_regru.log`)
|
||||
- systemd units: `/etc/systemd/system/letsencrypt-regru.service` и `.timer`
|
||||
|
||||
## Проверка после установки
|
||||
|
||||
- `letsencrypt-regru --help`
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
Если ловите ошибку `Access to API from this IP denied`, см. [RegRu_API_Troubleshooting](RegRu_API_Troubleshooting.md).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/INSTALL_GUIDE.md)
|
||||
<!-- MIGRATED_FROM_DOCS:INSTALL_GUIDE.md -->
|
||||
|
||||
## Руководство по использованию letsencrypt_regru.sh
|
||||
|
||||
**Автор:** Фофанов Дмитрий
|
||||
**Дата:** 28.10.2025
|
||||
|
||||
### Описание
|
||||
|
||||
`letsencrypt_regru.sh` - это автоматический установщик для Let's Encrypt Manager с интеграцией reg.ru и Nginx Proxy Manager.
|
||||
|
||||
Скрипт автоматизирует:
|
||||
- Установку всех системных зависимостей
|
||||
- Создание виртуального окружения Python
|
||||
- Установку Python библиотек (requests, cryptography, certbot)
|
||||
- Интерактивную настройку конфигурации
|
||||
- Создание и настройку systemd сервисов
|
||||
- Настройку автоматического обновления сертификатов
|
||||
|
||||
### Требования
|
||||
|
||||
- Linux (Debian/Ubuntu, CentOS/RHEL/Fedora)
|
||||
- Root доступ (sudo)
|
||||
- Минимум 512MB RAM
|
||||
- Минимум 1GB свободного места на диске
|
||||
- Интернет соединение
|
||||
|
||||
### Быстрая установка
|
||||
|
||||
**Способ 1: Автоматическая установка (рекомендуется)**
|
||||
|
||||
Самый быстрый способ - запустить установку напрямую с GitHub:
|
||||
|
||||
```bash
|
||||
sudo bash -c "$(curl -fsSL https://github.com/DFofanov/configure_nginx_manager/raw/refs/heads/master/letsencrypt_regru.sh)"
|
||||
```
|
||||
|
||||
Эта команда:
|
||||
- Автоматически скачает установочный скрипт
|
||||
- Запустит его с правами root
|
||||
- Проведет через интерактивную настройку
|
||||
|
||||
**Способ 2: Через клонирование репозитория**
|
||||
|
||||
Если вы хотите изучить код перед установкой:
|
||||
|
||||
```bash
|
||||
## 1. Скачайте репозиторий
|
||||
git clone https://github.com/DFofanov/configure_nginx_manager.git
|
||||
cd configure_nginx_manager
|
||||
|
||||
## 2. Дайте права на выполнение
|
||||
chmod +x letsencrypt_regru.sh
|
||||
|
||||
## 3. Запустите установку
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
### Интерактивная настройка
|
||||
|
||||
Во время установки скрипт спросит:
|
||||
|
||||
1. **Домен** - ваш основной домен (например, `example.com`)
|
||||
2. **Email** - для уведомлений Let's Encrypt
|
||||
3. **Учетные данные reg.ru:**
|
||||
- Имя пользователя
|
||||
- Пароль
|
||||
4. **Wildcard сертификат** - создавать ли `*.example.com` (рекомендуется: Да)
|
||||
5. **Интеграция с NPM** (опционально):
|
||||
- Адрес NPM (например, `http://10.10.10.14:81`)
|
||||
- Email для входа в NPM
|
||||
- Пароль NPM
|
||||
|
||||
### Структура после установки
|
||||
|
||||
```
|
||||
/opt/letsencrypt-regru/ # Приложение
|
||||
├── letsencrypt_regru_api.py # Основной скрипт
|
||||
├── venv/ # Виртуальное окружение Python
|
||||
└── (docs) # Документация — см. Wiki/README репозитория
|
||||
|
||||
/etc/letsencrypt-regru/ # Конфигурация
|
||||
└── config.json # Настройки (credentials, домен, NPM)
|
||||
|
||||
/var/log/letsencrypt-regru/ # Логи
|
||||
└── letsencrypt_regru.log
|
||||
|
||||
/etc/letsencrypt/live/ # Сертификаты Let's Encrypt
|
||||
└── example.com/
|
||||
├── privkey.pem
|
||||
├── cert.pem
|
||||
├── chain.pem
|
||||
└── fullchain.pem
|
||||
|
||||
/etc/systemd/system/ # Systemd сервисы
|
||||
├── letsencrypt-regru.service # Сервис обновления
|
||||
└── letsencrypt-regru.timer # Таймер (каждые 12 часов)
|
||||
|
||||
/usr/local/bin/
|
||||
└── letsencrypt-regru # Глобальная команда
|
||||
```
|
||||
|
||||
### Использование команды letsencrypt-regru
|
||||
|
||||
После установки доступна удобная глобальная команда с множеством функций:
|
||||
|
||||
#### 🔧 Основные команды
|
||||
|
||||
```bash
|
||||
## Проверить срок действия текущего сертификата
|
||||
letsencrypt-regru --check
|
||||
|
||||
## Получить новый сертификат Let's Encrypt
|
||||
letsencrypt-regru --obtain
|
||||
|
||||
## Обновить существующий сертификат
|
||||
letsencrypt-regru --renew
|
||||
|
||||
## Автоматически проверить и обновить при необходимости
|
||||
letsencrypt-regru --auto
|
||||
|
||||
## Создать тестовый самоподписанный сертификат
|
||||
letsencrypt-regru --test-cert
|
||||
```
|
||||
|
||||
#### 🧪 Команды диагностики и тестирования
|
||||
|
||||
```bash
|
||||
## Проверить доступ к API reg.ru
|
||||
## - Показывает текущий IP
|
||||
## - Тестирует подключение к API
|
||||
## - Отображает баланс аккаунта
|
||||
letsencrypt-regru --test-api
|
||||
|
||||
## Тестовое создание DNS записи TXT
|
||||
## - Полная симуляция процесса SSL сертификации
|
||||
## - Создает временную TXT запись _acme-challenge
|
||||
## - Ожидает распространения DNS (60 секунд)
|
||||
## - Проверяет через публичные DNS серверы
|
||||
## - Автоматически удаляет тестовую запись
|
||||
letsencrypt-regru --test-dns
|
||||
|
||||
## Показать справку по всем командам
|
||||
letsencrypt-regru --help
|
||||
|
||||
## Включить подробный вывод (verbose mode)
|
||||
letsencrypt-regru --obtain -v
|
||||
letsencrypt-regru --check -v
|
||||
```
|
||||
|
||||
#### ⚙️ Служебные команды (внутреннее использование)
|
||||
|
||||
```bash
|
||||
## Certbot authentication hook (используется certbot автоматически)
|
||||
letsencrypt-regru --auth-hook
|
||||
|
||||
## Certbot cleanup hook (используется certbot автоматически)
|
||||
letsencrypt-regru --cleanup-hook
|
||||
```
|
||||
|
||||
#### 📋 Описание команд
|
||||
|
||||
| Команда | Описание | Использование |
|
||||
|---------|----------|---------------|
|
||||
| `--check` | Проверяет срок действия сертификата | Регулярная проверка |
|
||||
| `--obtain` | Получает новый сертификат от Let's Encrypt | Первое создание |
|
||||
| `--renew` | Обновляет существующий сертификат | Продление срока |
|
||||
| `--auto` | Автоматическая проверка и обновление | Для cron/systemd |
|
||||
| `--test-cert` | Создает тестовый самоподписанный сертификат | Разработка/тестирование |
|
||||
| `--test-api` | Проверяет доступ к API reg.ru | Диагностика подключения |
|
||||
| `--test-dns` | Тестирует создание DNS записи | Проверка перед SSL |
|
||||
| `--auth-hook` | Hook для certbot (создание DNS) | Внутреннее |
|
||||
| `--cleanup-hook` | Hook для certbot (удаление DNS) | Внутреннее |
|
||||
| `--help` | Показывает справку | Помощь |
|
||||
| `-v` | Подробный вывод | Отладка |
|
||||
|
||||
### Автоматическое обновление
|
||||
|
||||
Установщик настраивает systemd timer для автоматической проверки:
|
||||
|
||||
```bash
|
||||
## Проверить статус таймера
|
||||
systemctl status letsencrypt-regru.timer
|
||||
|
||||
## Когда следующий запуск
|
||||
systemctl list-timers letsencrypt-regru.timer
|
||||
|
||||
## Посмотреть историю запусков
|
||||
journalctl -u letsencrypt-regru
|
||||
|
||||
## Следить за логами в реальном времени
|
||||
journalctl -u letsencrypt-regru -f
|
||||
```
|
||||
|
||||
#### Настройки таймера
|
||||
|
||||
По умолчанию:
|
||||
- Первый запуск: через 15 минут после загрузки системы
|
||||
- Периодичность: каждые 12 часов
|
||||
- Случайная задержка: до 1 часа (чтобы не создавать нагрузку)
|
||||
|
||||
Изменить можно в `/etc/systemd/system/letsencrypt-regru.timer`.
|
||||
|
||||
### Редактирование конфигурации
|
||||
|
||||
```bash
|
||||
## Открыть конфигурацию в редакторе
|
||||
sudo nano /etc/letsencrypt-regru/config.json
|
||||
|
||||
## После изменений перезапустите таймер
|
||||
sudo systemctl restart letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
#### Пример config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"regru_username": "your_username",
|
||||
"regru_password": "your_password",
|
||||
"domain": "example.com",
|
||||
"wildcard": true,
|
||||
"email": "admin@example.com",
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"log_file": "/var/log/letsencrypt-regru/letsencrypt_regru.log",
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20,
|
||||
"dns_check_interval": 15,
|
||||
"renewal_days": 30,
|
||||
"npm_enabled": true,
|
||||
"npm_host": "http://10.10.10.14:81",
|
||||
"npm_email": "admin@npm.local",
|
||||
"npm_password": "secure_password"
|
||||
}
|
||||
```
|
||||
|
||||
### Обновление приложения
|
||||
|
||||
```bash
|
||||
## Скачайте последнюю версию
|
||||
cd configure_nginx_manager
|
||||
git pull
|
||||
|
||||
## Запустите обновление
|
||||
sudo ./letsencrypt_regru.sh update
|
||||
```
|
||||
|
||||
Обновление:
|
||||
- Остановит таймер
|
||||
- Обновит скрипт
|
||||
- Обновит Python зависимости
|
||||
- Перезапустит таймер
|
||||
|
||||
### Удаление
|
||||
|
||||
```bash
|
||||
## Полное удаление приложения
|
||||
sudo ./letsencrypt_regru.sh uninstall
|
||||
```
|
||||
|
||||
Скрипт удалит:
|
||||
- Приложение из `/opt/letsencrypt-regru/`
|
||||
- Systemd сервисы
|
||||
- Глобальную команду
|
||||
|
||||
Сертификаты в `/etc/letsencrypt/live/` сохраняются!
|
||||
|
||||
Опционально можно удалить:
|
||||
- Конфигурацию `/etc/letsencrypt-regru/`
|
||||
- Логи `/var/log/letsencrypt-regru/`
|
||||
|
||||
### Просмотр логов
|
||||
|
||||
```bash
|
||||
## Логи systemd (рекомендуется)
|
||||
journalctl -u letsencrypt-regru -f
|
||||
|
||||
## Файл лога
|
||||
tail -f /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Последние 100 строк
|
||||
tail -n 100 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
```
|
||||
|
||||
### Устранение проблем
|
||||
|
||||
#### Проверка установки
|
||||
|
||||
```bash
|
||||
## Проверить наличие команды
|
||||
which letsencrypt-regru
|
||||
|
||||
## Проверить Python окружение
|
||||
ls -la /opt/letsencrypt-regru/venv/
|
||||
|
||||
## Проверить systemd сервисы
|
||||
systemctl list-unit-files | grep letsencrypt-regru
|
||||
```
|
||||
|
||||
#### Ошибки при установке
|
||||
|
||||
**Ошибка: "Permission denied"**
|
||||
```bash
|
||||
## Запустите с sudo
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
**Ошибка: "Package not found"**
|
||||
```bash
|
||||
## Обновите списки пакетов
|
||||
sudo apt-get update # Debian/Ubuntu
|
||||
sudo yum update # CentOS/RHEL
|
||||
```
|
||||
|
||||
**Ошибка: "Python module not found"**
|
||||
```bash
|
||||
## Переустановите виртуальное окружение
|
||||
sudo rm -rf /opt/letsencrypt-regru/venv
|
||||
sudo ./letsencrypt_regru.sh
|
||||
```
|
||||
|
||||
#### Проблемы с сертификатами
|
||||
|
||||
**Сертификат не создается**
|
||||
```bash
|
||||
## Проверьте логи
|
||||
tail -n 50 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Проверьте конфигурацию
|
||||
cat /etc/letsencrypt-regru/config.json
|
||||
|
||||
## Попробуйте вручную
|
||||
letsencrypt-regru --obtain -v
|
||||
```
|
||||
|
||||
**DNS не обновляется**
|
||||
```bash
|
||||
## Увеличьте время ожидания в config.json
|
||||
"dns_propagation_wait": 180,
|
||||
"dns_check_attempts": 20
|
||||
```
|
||||
|
||||
#### Проблемы с NPM
|
||||
|
||||
**Не загружается в NPM**
|
||||
```bash
|
||||
## Проверьте доступность NPM
|
||||
curl http://192.0.2.1:81
|
||||
|
||||
## Проверьте учетные данные в config.json
|
||||
## Попробуйте вручную
|
||||
letsencrypt-regru --test-cert -v
|
||||
```
|
||||
|
||||
### Поддерживаемые ОС
|
||||
|
||||
✅ Debian 10, 11, 12
|
||||
✅ Ubuntu 20.04, 22.04, 24.04
|
||||
✅ CentOS 7, 8
|
||||
✅ RHEL 7, 8, 9
|
||||
✅ Fedora 35+
|
||||
|
||||
### Дополнительные возможности
|
||||
|
||||
#### Тестовый сертификат
|
||||
|
||||
Для тестирования без лимитов Let's Encrypt:
|
||||
|
||||
```bash
|
||||
letsencrypt-regru --test-cert
|
||||
```
|
||||
|
||||
Создаст самоподписанный сертификат на 90 дней.
|
||||
|
||||
#### Ручной запуск обновления
|
||||
|
||||
```bash
|
||||
## Запустить сервис вручную
|
||||
sudo systemctl start letsencrypt-regru.service
|
||||
|
||||
## Посмотреть статус
|
||||
systemctl status letsencrypt-regru.service
|
||||
```
|
||||
|
||||
#### Изменить периодичность проверки
|
||||
|
||||
Отредактируйте `/etc/systemd/system/letsencrypt-regru.timer`:
|
||||
|
||||
```ini
|
||||
[Timer]
|
||||
## Каждые 6 часов вместо 12
|
||||
OnUnitActiveSec=6h
|
||||
```
|
||||
|
||||
Затем:
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
### Безопасность
|
||||
|
||||
- Конфигурация с паролями имеет права `600` (только root)
|
||||
- Приватные ключи сертификатов имеют права `600`
|
||||
- Все операции выполняются от root
|
||||
- Логи доступны только root
|
||||
|
||||
### Поддержка
|
||||
|
||||
- GitHub Issues: https://github.com/YOUR_USERNAME/configure_nginx_manager/issues
|
||||
- Документация: Wiki/README в этом репозитории
|
||||
- Email: admin@example.com
|
||||
|
||||
---
|
||||
|
||||
**Разработано:** Фофанов Дмитрий
|
||||
**Дата:** 28.10.2025
|
||||
**Версия:** 2.0
|
||||
|
||||
|
||||
+207
-207
@@ -1,67 +1,67 @@
|
||||
# Алгоритм получения и продления сертификата
|
||||
|
||||
Эта страница описывает реальный алгоритм работы скрипта (по документации и текущему коду).
|
||||
|
||||
## Получение сертификата (production / staging)
|
||||
|
||||
Команды:
|
||||
|
||||
- production: `--obtain`
|
||||
- staging: `--staging`
|
||||
|
||||
Шаги:
|
||||
|
||||
1) Проверка наличия certbot
|
||||
2) Формирование списка доменов для certbot:
|
||||
- всегда: `<domain>`
|
||||
- если `wildcard=true`: `*.<domain>`
|
||||
3) Запуск `certbot certonly --manual --preferred-challenges dns`
|
||||
4) Certbot вызывает hook'и:
|
||||
- auth-hook: добавляет TXT запись `_acme-challenge` через API reg.ru
|
||||
- cleanup-hook: удаляет TXT запись
|
||||
5) После успеха сертификаты появляются в `cert_dir/<domain>/`:
|
||||
- `privkey.pem`, `cert.pem`, `chain.pem`, `fullchain.pem`
|
||||
6) (опционально) синхронизация в NPM
|
||||
7) (опционально) перезагрузка веб-сервиса (nginx/apache)
|
||||
|
||||
### Про TXT для поддоменов
|
||||
|
||||
Если вы выпускаете сертификат для поддомена вида `pages.github.example.com`, TXT должен создаваться в зоне зарегистрированного домена `example.com` как:
|
||||
|
||||
- `_acme-challenge.pages.github.example.com`
|
||||
|
||||
Скрипт учитывает это, выбирая зарегистрированный домен по списку доменов в конфиге.
|
||||
|
||||
## Продление сертификата
|
||||
|
||||
Команда:
|
||||
|
||||
- `--renew`
|
||||
|
||||
Скрипт запускает `certbot renew` для конкретного `--cert-name <domain>` и использует те же hook'и (auth/cleanup) с корректным `--config`.
|
||||
|
||||
## Авто-режим
|
||||
|
||||
Команда:
|
||||
|
||||
- `--auto`
|
||||
|
||||
Логика по каждому домену из конфига:
|
||||
|
||||
- если сертификата нет → получить новый
|
||||
- если срок меньше `renewal_days` → продлить
|
||||
- иначе → ничего не делать (опционально проверить наличие в NPM)
|
||||
|
||||
Возврат кода:
|
||||
|
||||
- `0` — всё успешно
|
||||
- `1` — были ошибки
|
||||
|
||||
## Где смотреть логи
|
||||
|
||||
- Логи скрипта: путь `log_file` из конфига
|
||||
- Логи certbot: обычно `/var/log/letsencrypt/letsencrypt.log`
|
||||
- systemd: `journalctl -u letsencrypt-regru -f`
|
||||
# Алгоритм получения и продления сертификата
|
||||
|
||||
Эта страница описывает реальный алгоритм работы скрипта (по документации и текущему коду).
|
||||
|
||||
## Получение сертификата (production / staging)
|
||||
|
||||
Команды:
|
||||
|
||||
- production: `--obtain`
|
||||
- staging: `--staging`
|
||||
|
||||
Шаги:
|
||||
|
||||
1) Проверка наличия certbot
|
||||
2) Формирование списка доменов для certbot:
|
||||
- всегда: `<domain>`
|
||||
- если `wildcard=true`: `*.<domain>`
|
||||
3) Запуск `certbot certonly --manual --preferred-challenges dns`
|
||||
4) Certbot вызывает hook'и:
|
||||
- auth-hook: добавляет TXT запись `_acme-challenge` через API reg.ru
|
||||
- cleanup-hook: удаляет TXT запись
|
||||
5) После успеха сертификаты появляются в `cert_dir/<domain>/`:
|
||||
- `privkey.pem`, `cert.pem`, `chain.pem`, `fullchain.pem`
|
||||
6) (опционально) синхронизация в NPM
|
||||
7) (опционально) перезагрузка веб-сервиса (nginx/apache)
|
||||
|
||||
### Про TXT для поддоменов
|
||||
|
||||
Если вы выпускаете сертификат для поддомена вида `pages.github.example.com`, TXT должен создаваться в зоне зарегистрированного домена `example.com` как:
|
||||
|
||||
- `_acme-challenge.pages.github.example.com`
|
||||
|
||||
Скрипт учитывает это, выбирая зарегистрированный домен по списку доменов в конфиге.
|
||||
|
||||
## Продление сертификата
|
||||
|
||||
Команда:
|
||||
|
||||
- `--renew`
|
||||
|
||||
Скрипт запускает `certbot renew` для конкретного `--cert-name <domain>` и использует те же hook'и (auth/cleanup) с корректным `--config`.
|
||||
|
||||
## Авто-режим
|
||||
|
||||
Команда:
|
||||
|
||||
- `--auto`
|
||||
|
||||
Логика по каждому домену из конфига:
|
||||
|
||||
- если сертификата нет → получить новый
|
||||
- если срок меньше `renewal_days` → продлить
|
||||
- иначе → ничего не делать (опционально проверить наличие в NPM)
|
||||
|
||||
Возврат кода:
|
||||
|
||||
- `0` — всё успешно
|
||||
- `1` — были ошибки
|
||||
|
||||
## Где смотреть логи
|
||||
|
||||
- Логи скрипта: путь `log_file` из конфига
|
||||
- Логи certbot: обычно `/var/log/letsencrypt/letsencrypt.log`
|
||||
- systemd: `journalctl -u letsencrypt-regru -f`
|
||||
|
||||
|
||||
---
|
||||
@@ -69,92 +69,92 @@
|
||||
## Appendix (migrated from: Создание и продление SSL сертификата)
|
||||
<!-- MIGRATED_FROM_DOCS: Создание и продление SSL сертификата -->
|
||||
|
||||
## Инструкция по созданию wildcard сертификата *.example.com в Nginx Proxy Manager и настройке автоматического продления SSL
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Подготовка
|
||||
|
||||
- Убедитесь, что Nginx Proxy Manager (NPM) установлен и доступен по адресу http://192.0.2.1:81/
|
||||
- У вас есть доступ к DNS записям домена example.com в панели управления reg.ru или у другого регистратора
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Создание Wildcard SSL сертификата в Nginx Proxy Manager
|
||||
|
||||
1. Войдите в админку Nginx Proxy Manager по адресу http://192.0.2.1:81/
|
||||
|
||||
2. Перейдите в раздел **SSL Certificates** → нажмите кнопку **Add SSL Certificate**
|
||||
|
||||
3. Выберите пункт **Let's Encrypt**
|
||||
|
||||
4. Заполните поля:
|
||||
- **Domain Names:**
|
||||
Введите `*.example.com` — для wildcard сертификата
|
||||
Также рекомендуется добавить основной домен `example.com` (через запятую или в новом поле)
|
||||
- **Email Address:**
|
||||
Укажите ваш Email для уведомлений от Let's Encrypt (обязательно)
|
||||
- **HTTP Challenge:**
|
||||
Оставьте проверку HTTP, если NPM доступен из интернета по порту 80 и 443, или настройте DNS Challenge если поддерживается вашим DNS
|
||||
|
||||
5. Отметьте галочку "Agree to the Let's Encrypt Terms of Service"
|
||||
|
||||
6. Нажмите **Save**
|
||||
|
||||
- NPM начнёт процесс получения сертификата с проверкой домена.
|
||||
- При успешном запросе сертификата вы увидите новый сертификат в списке.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Настройка автоматического продления
|
||||
|
||||
- Nginx Proxy Manager автоматически заботится о продлении сертификатов Let's Encrypt.
|
||||
- Для этого сервер должен быть доступен из интернета по портам 80 и 443, и DNS записи правильно указывать на ваш сервер.
|
||||
- NPM периодически (обычно за 30 дней до окончания) запрашивает обновление сертификата.
|
||||
- В случае использования DNS Challenge необходимо чтобы в NPM была настроена интеграция с DNS провайдером (если поддерживается).
|
||||
|
||||
---
|
||||
|
||||
### Шаг 4. Использование wildcard сертификата в Proxy Hosts
|
||||
|
||||
1. Перейдите в **Proxy Hosts** → Создайте или отредактируйте запись прокси
|
||||
|
||||
2. В поле **Domain Names** укажите нужный поддомен из example.com, например:
|
||||
`api.example.com` или `www.example.com`
|
||||
|
||||
3. В разделе **SSL** выберите ваш wildcard сертификат `*.example.com`, который вы получили на шаге 2
|
||||
|
||||
4. Включите опции:
|
||||
- Use SSL
|
||||
- Force SSL
|
||||
- HSTS (при необходимости)
|
||||
|
||||
5. Сохраните изменения.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 5. Проверка
|
||||
|
||||
1. Проверьте, что для всех поддоменов используется единый сертификат
|
||||
2. Посетите https://api.example.com или другие поддомены из браузера
|
||||
3. Убедитесь, что сертификат валиден, не просрочен и выдан на *.example.com
|
||||
4. Проверяйте в разделе SSL Certificates статус продления сертификата
|
||||
|
||||
---
|
||||
|
||||
### Дополнительно
|
||||
|
||||
- Если Let's Encrypt не может выполнить HTTP Challenge из-за закрытого порта, настройте DNS Challenge (может потребоваться ключ API DNS провайдера)
|
||||
- Для безопасности и уведомлений держите Email в актуальном состоянии
|
||||
- Проверяйте логи Nginx Proxy Manager для выявления ошибок продления
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Nginx Proxy Manager позволяет легко получать и автоматически обновлять wildcard SSL сертификаты для домена *.example.com с помощью Let's Encrypt.
|
||||
Главное — правильно настроить DNS записи и обеспечить интернет доступ на HTTP/HTTPS порты.
|
||||
Далее используйте один глобальный сертификат для всех ваших поддоменов через настройки Proxy Hosts.
|
||||
## Инструкция по созданию wildcard сертификата *.example.com в Nginx Proxy Manager и настройке автоматического продления SSL
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Подготовка
|
||||
|
||||
- Убедитесь, что Nginx Proxy Manager (NPM) установлен и доступен по адресу http://192.0.2.1:81/
|
||||
- У вас есть доступ к DNS записям домена example.com в панели управления reg.ru или у другого регистратора
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Создание Wildcard SSL сертификата в Nginx Proxy Manager
|
||||
|
||||
1. Войдите в админку Nginx Proxy Manager по адресу http://192.0.2.1:81/
|
||||
|
||||
2. Перейдите в раздел **SSL Certificates** → нажмите кнопку **Add SSL Certificate**
|
||||
|
||||
3. Выберите пункт **Let's Encrypt**
|
||||
|
||||
4. Заполните поля:
|
||||
- **Domain Names:**
|
||||
Введите `*.example.com` — для wildcard сертификата
|
||||
Также рекомендуется добавить основной домен `example.com` (через запятую или в новом поле)
|
||||
- **Email Address:**
|
||||
Укажите ваш Email для уведомлений от Let's Encrypt (обязательно)
|
||||
- **HTTP Challenge:**
|
||||
Оставьте проверку HTTP, если NPM доступен из интернета по порту 80 и 443, или настройте DNS Challenge если поддерживается вашим DNS
|
||||
|
||||
5. Отметьте галочку "Agree to the Let's Encrypt Terms of Service"
|
||||
|
||||
6. Нажмите **Save**
|
||||
|
||||
- NPM начнёт процесс получения сертификата с проверкой домена.
|
||||
- При успешном запросе сертификата вы увидите новый сертификат в списке.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Настройка автоматического продления
|
||||
|
||||
- Nginx Proxy Manager автоматически заботится о продлении сертификатов Let's Encrypt.
|
||||
- Для этого сервер должен быть доступен из интернета по портам 80 и 443, и DNS записи правильно указывать на ваш сервер.
|
||||
- NPM периодически (обычно за 30 дней до окончания) запрашивает обновление сертификата.
|
||||
- В случае использования DNS Challenge необходимо чтобы в NPM была настроена интеграция с DNS провайдером (если поддерживается).
|
||||
|
||||
---
|
||||
|
||||
### Шаг 4. Использование wildcard сертификата в Proxy Hosts
|
||||
|
||||
1. Перейдите в **Proxy Hosts** → Создайте или отредактируйте запись прокси
|
||||
|
||||
2. В поле **Domain Names** укажите нужный поддомен из example.com, например:
|
||||
`api.example.com` или `www.example.com`
|
||||
|
||||
3. В разделе **SSL** выберите ваш wildcard сертификат `*.example.com`, который вы получили на шаге 2
|
||||
|
||||
4. Включите опции:
|
||||
- Use SSL
|
||||
- Force SSL
|
||||
- HSTS (при необходимости)
|
||||
|
||||
5. Сохраните изменения.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 5. Проверка
|
||||
|
||||
1. Проверьте, что для всех поддоменов используется единый сертификат
|
||||
2. Посетите https://api.example.com или другие поддомены из браузера
|
||||
3. Убедитесь, что сертификат валиден, не просрочен и выдан на *.example.com
|
||||
4. Проверяйте в разделе SSL Certificates статус продления сертификата
|
||||
|
||||
---
|
||||
|
||||
### Дополнительно
|
||||
|
||||
- Если Let's Encrypt не может выполнить HTTP Challenge из-за закрытого порта, настройте DNS Challenge (может потребоваться ключ API DNS провайдера)
|
||||
- Для безопасности и уведомлений держите Email в актуальном состоянии
|
||||
- Проверяйте логи Nginx Proxy Manager для выявления ошибок продления
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Nginx Proxy Manager позволяет легко получать и автоматически обновлять wildcard SSL сертификаты для домена *.example.com с помощью Let's Encrypt.
|
||||
Главное — правильно настроить DNS записи и обеспечить интернет доступ на HTTP/HTTPS порты.
|
||||
Далее используйте один глобальный сертификат для всех ваших поддоменов через настройки Proxy Hosts.
|
||||
|
||||
|
||||
---
|
||||
@@ -162,60 +162,60 @@ Nginx Proxy Manager позволяет легко получать и автом
|
||||
## Appendix (migrated from docs/Add Let's Encrypt Certificate для провайдера reg.ru.md)
|
||||
<!-- MIGRATED_FROM_DOCS:Add Let's Encrypt Certificate для провайдера reg.ru.md -->
|
||||
|
||||
## Инструкция по созданию Let's Encrypt сертификата с DNS Challenge для провайдера reg.ru в Nginx Proxy Manager
|
||||
|
||||
---
|
||||
|
||||
### Предпосылки
|
||||
- Доступ к Nginx Proxy Manager (NPM)
|
||||
- Доступ к аккаунту reg.ru с правами управления DNS записями
|
||||
- API ключ для управления DNS в reg.ru (если есть автоматическая интеграция)
|
||||
- Нужно получить сертификат для `*.example.com` (wildcard сертификат)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Получение API ключа для reg.ru
|
||||
|
||||
1. Войдите в панель управления reg.ru
|
||||
2. Перейдите в раздел управления API (если поддерживается)
|
||||
3. Создайте или найдите API ключ с правом редактирования DNS записей
|
||||
4. Сохраните API ключ и секрет (Client ID и API Token)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Настройка Nginx Proxy Manager для использования DNS Challenge reg.ru
|
||||
|
||||
1. В админке NPM перейдите в **SSL Certificates → Add SSL Certificate**
|
||||
2. Выберите **Let's Encrypt** -> **DNS Challenge**
|
||||
3. В поле **Provider** выберите `reg_ru` или `custom` (если провайдера нет, потребуется писать скрипт)
|
||||
4. В поля API впишите необходимые параметры:
|
||||
- Client ID
|
||||
- API Token
|
||||
5. В поле **Domain Names** укажите:
|
||||
`*.example.com` (для wildcard сертификата)
|
||||
и основной домен `example.com`
|
||||
6. Включите остальные опции (Terms of Service, Email)
|
||||
7. Нажмите **Save** для запроса сертификата
|
||||
8. NPM автоматически добавит DNS TXT записи для подтверждения владения доменом через API reg.ru
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Проверка и автоматическое продление
|
||||
|
||||
- После успешного создания сертификата NPM будет автоматически обновлять его через DNS Challenge.
|
||||
- Для успешного продления важно, чтобы API ключ был действующим, а NPM имел доступ к DNS управлению.
|
||||
|
||||
---
|
||||
|
||||
### Если в NPM нет готовой интеграции с reg.ru
|
||||
|
||||
- Используйте внешний скрипт для обновления TXT записей DNS в reg.ru, настраиваемый в NPM через **Custom DNS Provider**.
|
||||
- Нужна настройка curl запросов к API reg.ru для добавления/удаления TXT записей.
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Для wildcard сертификатов Let's Encrypt у reg.ru необходимо использовать DNS Challenge, используя API провайдера для автоматического управления DNS записями.
|
||||
В Nginx Proxy Manager настройте DNS Challenge с учётом особенностей reg.ru для бесшовного получения и продления сертификатов.
|
||||
|
||||
## Инструкция по созданию Let's Encrypt сертификата с DNS Challenge для провайдера reg.ru в Nginx Proxy Manager
|
||||
|
||||
---
|
||||
|
||||
### Предпосылки
|
||||
- Доступ к Nginx Proxy Manager (NPM)
|
||||
- Доступ к аккаунту reg.ru с правами управления DNS записями
|
||||
- API ключ для управления DNS в reg.ru (если есть автоматическая интеграция)
|
||||
- Нужно получить сертификат для `*.example.com` (wildcard сертификат)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Получение API ключа для reg.ru
|
||||
|
||||
1. Войдите в панель управления reg.ru
|
||||
2. Перейдите в раздел управления API (если поддерживается)
|
||||
3. Создайте или найдите API ключ с правом редактирования DNS записей
|
||||
4. Сохраните API ключ и секрет (Client ID и API Token)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Настройка Nginx Proxy Manager для использования DNS Challenge reg.ru
|
||||
|
||||
1. В админке NPM перейдите в **SSL Certificates → Add SSL Certificate**
|
||||
2. Выберите **Let's Encrypt** -> **DNS Challenge**
|
||||
3. В поле **Provider** выберите `reg_ru` или `custom` (если провайдера нет, потребуется писать скрипт)
|
||||
4. В поля API впишите необходимые параметры:
|
||||
- Client ID
|
||||
- API Token
|
||||
5. В поле **Domain Names** укажите:
|
||||
`*.example.com` (для wildcard сертификата)
|
||||
и основной домен `example.com`
|
||||
6. Включите остальные опции (Terms of Service, Email)
|
||||
7. Нажмите **Save** для запроса сертификата
|
||||
8. NPM автоматически добавит DNS TXT записи для подтверждения владения доменом через API reg.ru
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Проверка и автоматическое продление
|
||||
|
||||
- После успешного создания сертификата NPM будет автоматически обновлять его через DNS Challenge.
|
||||
- Для успешного продления важно, чтобы API ключ был действующим, а NPM имел доступ к DNS управлению.
|
||||
|
||||
---
|
||||
|
||||
### Если в NPM нет готовой интеграции с reg.ru
|
||||
|
||||
- Используйте внешний скрипт для обновления TXT записей DNS в reg.ru, настраиваемый в NPM через **Custom DNS Provider**.
|
||||
- Нужна настройка curl запросов к API reg.ru для добавления/удаления TXT записей.
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Для wildcard сертификатов Let's Encrypt у reg.ru необходимо использовать DNS Challenge, используя API провайдера для автоматического управления DNS записями.
|
||||
В Nginx Proxy Manager настройте DNS Challenge с учётом особенностей reg.ru для бесшовного получения и продления сертификатов.
|
||||
|
||||
|
||||
+199
-199
@@ -1,199 +1,199 @@
|
||||
# Интеграция с Nginx Proxy Manager (NPM)
|
||||
|
||||
Проект умеет автоматически загружать (или обновлять) сертификаты в NPM через его API.
|
||||
|
||||
## Включение
|
||||
|
||||
В конфиге:
|
||||
|
||||
- `npm_enabled: true`
|
||||
- `npm_host`: например `http://192.0.2.1:81`
|
||||
- `npm_email`, `npm_password`
|
||||
|
||||
После этого:
|
||||
|
||||
- `--obtain`, `--renew`, `--auto`, `--test-cert` будут пытаться синхронизировать сертификат в NPM.
|
||||
|
||||
## Как работает синхронизация
|
||||
|
||||
1) Скрипт логинится в NPM (`/api/tokens`)
|
||||
2) Получает список сертификатов
|
||||
3) Ищет сертификат по домену (учитывает `<domain>` и `*.<domain>`)
|
||||
4) Если найден — обновляет, иначе — загружает новый
|
||||
|
||||
### Про “дубликаты” сертификатов
|
||||
|
||||
Иногда NPM сразу после загрузки ещё не распарсил домены (поле `domain_names` пустое). Скрипт дополнительно пытается сопоставлять по `nice_name`, чтобы не плодить дубли.
|
||||
|
||||
Команда для диагностики:
|
||||
|
||||
- `--list-npm` — показывает сертификаты и подсвечивает дубликаты
|
||||
- `--delete-npm <ID>` — удаляет сертификат по ID
|
||||
|
||||
## Ручная загрузка существующего сертификата
|
||||
|
||||
- `--upload-npm <DOMAIN>`
|
||||
|
||||
Скрипт возьмёт `fullchain.pem` и `privkey.pem` из `cert_dir/<DOMAIN>/` и загрузит/обновит сертификат в NPM.
|
||||
|
||||
## Один wildcard сертификат на много поддоменов
|
||||
|
||||
Практический сценарий:
|
||||
|
||||
- Получить сертификат на `example.com` + `*.example.com`
|
||||
- В NPM импортировать/использовать этот сертификат для всех Proxy Hosts
|
||||
|
||||
Обратите внимание:
|
||||
|
||||
- для wildcard Let’s Encrypt нужен DNS-01 challenge
|
||||
- в NPM можно использовать либо встроенный Let’s Encrypt, либо этот проект как внешний менеджер и синхронизатор
|
||||
|
||||
## Пошагово: использовать один wildcard сертификат для всех Proxy Hosts
|
||||
|
||||
Ниже — практический сценарий, когда вам нужен один сертификат (например, `*.example.com`) и вы хотите назначать его на все хосты.
|
||||
|
||||
### Вариант A: сертификат выдаёт этот проект (рекомендуется при reg.ru DNS-01)
|
||||
|
||||
1) Убедитесь, что DNS API reg.ru работает:
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
2) Получите production сертификат:
|
||||
|
||||
- `letsencrypt-regru --obtain`
|
||||
|
||||
3) Если `npm_enabled=true`, сертификат автоматически появится в NPM.
|
||||
|
||||
4) В NPM:
|
||||
|
||||
- Proxy Hosts → Add/Edit Proxy Host
|
||||
- SSL → выберите сертификат (обычно “Custom/Other”)
|
||||
- включите нужные опции (Force SSL, HSTS по необходимости)
|
||||
|
||||
### Вариант B: сертификат выдаёт сам NPM
|
||||
|
||||
Этот вариант подходит, если NPM может сам пройти challenge.
|
||||
|
||||
1) SSL Certificates → Add SSL Certificate → Let’s Encrypt
|
||||
2) Domain Names: добавьте `example.com` и `*.example.com`
|
||||
3) Выберите challenge:
|
||||
|
||||
- HTTP-01: требует доступности NPM из интернета по 80/443 и корректных A/AAAA записей
|
||||
- DNS-01: требует поддерживаемого DNS provider в NPM
|
||||
|
||||
Если нужного DNS провайдера нет (или нет корректной интеграции для reg.ru), проще использовать этот проект как внешний DNS-01 менеджер.
|
||||
|
||||
### Вариант C: импорт уже существующего wildcard сертификата (Custom)
|
||||
|
||||
Если вы приобрели wildcard сертификат у CA или получили его другим способом:
|
||||
|
||||
1) SSL Certificates → Add SSL Certificate → Custom
|
||||
2) Вставьте:
|
||||
|
||||
- Certificate: сертификат + intermediate chain (если отдельно — добавьте подряд)
|
||||
- Key: приватный ключ
|
||||
|
||||
3) Сохраните и назначайте этот сертификат на Proxy Hosts.
|
||||
|
||||
## DNS записи для wildcard
|
||||
|
||||
Для проксирования поддоменов часто достаточно, чтобы DNS указывал на NPM:
|
||||
|
||||
- `example.com` → IP NPM
|
||||
- `*.example.com` → IP NPM
|
||||
|
||||
Точная схема зависит от вашей инфраструктуры.
|
||||
|
||||
## Траблшутинг
|
||||
|
||||
- “не логинится” → проверьте `npm_host` (http/https), креды, доступность
|
||||
- “сертификат не появился” → проверьте `npm_enabled`, логи скрипта
|
||||
- staging сертификаты: не предназначены для production (браузер не доверяет)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from: Настройке Nginx Manager с SSL)
|
||||
<!-- MIGRATED_FROM_DOCS: Настройке Nginx Manager с SSL -->
|
||||
|
||||
## Подробная инструкция по настройке Nginx Proxy Manager с одним глобальным SSL сертификатом для всех доменов example.com
|
||||
|
||||
### Предпосылки
|
||||
- Установлен и запущен [Nginx Proxy Manager](http://192.0.2.1:81/)
|
||||
- Основной домен: example.com
|
||||
- Хостинг и DNS записи домена находятся на reg.ru
|
||||
- Нужно использовать один SSL сертификат (например, wildcard) для всех поддоменов example.com
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Покупка и получение SSL Wildcard сертификата для example.com
|
||||
1. На reg.ru или любом другом удостоверяющем центре (CA) закажите wildcard сертификат на домен вида `*.example.com`.
|
||||
2. Получите файлы сертификата:
|
||||
- Главный сертификат (CRT)
|
||||
- Промежуточные сертификаты (CA Bundle)
|
||||
- Приватный ключ (KEY)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Импорт вашего SSL сертификата в Nginx Proxy Manager
|
||||
1. Авторизуйтесь в Nginx Proxy Manager на http://192.0.2.1:81/
|
||||
2. Перейдите в раздел **SSL Certificates** → кнопку **Add SSL Certificate**
|
||||
3. Выберите **Custom** (пользовательский сертификат)
|
||||
4. В поля вставьте:
|
||||
- **Certificate** — основной CRT + CA Bundle (если CA Bundle раздельно, склейте в один файл или вставляйте последовательно)
|
||||
- **Key** — содержимое приватного ключа
|
||||
- Имя сертификата задайте, например, `dfv24_wildcard`
|
||||
5. Сохраните
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Настройка прокси-хостов с использованием глобального сертификата
|
||||
|
||||
1. Перейдите в **Proxy Hosts** → **Add Proxy Host**
|
||||
2. Заполните поля:
|
||||
- **Domain Names**: Например, `sub1.example.com` (для первого поддомена)
|
||||
- **Scheme**: http или https, в зависимости от бекенда
|
||||
- **Forward Hostname / IP**: IP или DNS адрес вашего внутреннего сервиса
|
||||
- **Forward Port**: порт сервиса (например, 80 или 443)
|
||||
3. Включите **SSL** → Отметьте **Use a shared SSL certificate** (если такая опция доступна) или выберите ранее импортированный сертификат из списка
|
||||
4. Активируйте: **Block Common Exploits**, **Websockets Support**, выставьте Redirect HTTP to HTTPS, если требуется
|
||||
5. Сохраните прокси-хост
|
||||
|
||||
6. Повторите для всех поддоменов, указывая нужные домены и выбирая тот же wildcard SSL сертификат
|
||||
|
||||
---
|
||||
|
||||
### Шаг 4. Настройка DNS записей на reg.ru
|
||||
|
||||
1. Войдите в панель управления доменом на reg.ru
|
||||
2. Создайте или отредактируйте DNS записи типа A:
|
||||
- `example.com` → IP вашего Nginx Proxy Manager (например, 192.0.2.1)
|
||||
- `*.example.com` → тот же IP или конкретные поддомены, если есть специальные
|
||||
3. Сохраните изменения
|
||||
4. Дождитесь обновления DNS (от нескольких минут до 24 часов)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 5. Тест и проверка работы
|
||||
|
||||
1. В браузере откройте любой из поддоменов `https://sub1.example.com`
|
||||
2. Сертификат должен быть валидным, выданным на wildcard `*.example.com`
|
||||
3. Проверьте работу прокси и корректность подстановки сертификата
|
||||
4. При необходимости проверьте логи Nginx Proxy Manager и исправьте ошибки
|
||||
|
||||
---
|
||||
|
||||
### Дополнительно
|
||||
|
||||
- Если в Nginx Proxy Manager нет GUI опции выбора общего сертификата, можно вручную сконфигурировать конфиги через директорий `/data/nginx/proxy_host` и прописать SSL сертификат для всех хостов.
|
||||
- При обновлении сертификата — повторно импортировать его в Nginx Proxy Manager.
|
||||
- Можно использовать LetsEncrypt для автоматического получения wildcard сертификата с помощью DNS валидации (если поддерживается вашим DNS провайдером).
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Используйте один wildcard сертификат для всех поддоменов, импортируйте его как пользовательский сертификат в Nginx Proxy Manager, при создании прокси-хостов выбирайте его в настройках SSL. Управляйте DNS записями на reg.ru, направляя домен на IP Nginx Proxy Manager.
|
||||
Это позволит юридически использовать единый сертификат для всех сервисов с различными поддоменами под вашим доменом example.com.
|
||||
|
||||
# Интеграция с Nginx Proxy Manager (NPM)
|
||||
|
||||
Проект умеет автоматически загружать (или обновлять) сертификаты в NPM через его API.
|
||||
|
||||
## Включение
|
||||
|
||||
В конфиге:
|
||||
|
||||
- `npm_enabled: true`
|
||||
- `npm_host`: например `http://192.0.2.1:81`
|
||||
- `npm_email`, `npm_password`
|
||||
|
||||
После этого:
|
||||
|
||||
- `--obtain`, `--renew`, `--auto`, `--test-cert` будут пытаться синхронизировать сертификат в NPM.
|
||||
|
||||
## Как работает синхронизация
|
||||
|
||||
1) Скрипт логинится в NPM (`/api/tokens`)
|
||||
2) Получает список сертификатов
|
||||
3) Ищет сертификат по домену (учитывает `<domain>` и `*.<domain>`)
|
||||
4) Если найден — обновляет, иначе — загружает новый
|
||||
|
||||
### Про “дубликаты” сертификатов
|
||||
|
||||
Иногда NPM сразу после загрузки ещё не распарсил домены (поле `domain_names` пустое). Скрипт дополнительно пытается сопоставлять по `nice_name`, чтобы не плодить дубли.
|
||||
|
||||
Команда для диагностики:
|
||||
|
||||
- `--list-npm` — показывает сертификаты и подсвечивает дубликаты
|
||||
- `--delete-npm <ID>` — удаляет сертификат по ID
|
||||
|
||||
## Ручная загрузка существующего сертификата
|
||||
|
||||
- `--upload-npm <DOMAIN>`
|
||||
|
||||
Скрипт возьмёт `fullchain.pem` и `privkey.pem` из `cert_dir/<DOMAIN>/` и загрузит/обновит сертификат в NPM.
|
||||
|
||||
## Один wildcard сертификат на много поддоменов
|
||||
|
||||
Практический сценарий:
|
||||
|
||||
- Получить сертификат на `example.com` + `*.example.com`
|
||||
- В NPM импортировать/использовать этот сертификат для всех Proxy Hosts
|
||||
|
||||
Обратите внимание:
|
||||
|
||||
- для wildcard Let’s Encrypt нужен DNS-01 challenge
|
||||
- в NPM можно использовать либо встроенный Let’s Encrypt, либо этот проект как внешний менеджер и синхронизатор
|
||||
|
||||
## Пошагово: использовать один wildcard сертификат для всех Proxy Hosts
|
||||
|
||||
Ниже — практический сценарий, когда вам нужен один сертификат (например, `*.example.com`) и вы хотите назначать его на все хосты.
|
||||
|
||||
### Вариант A: сертификат выдаёт этот проект (рекомендуется при reg.ru DNS-01)
|
||||
|
||||
1) Убедитесь, что DNS API reg.ru работает:
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
2) Получите production сертификат:
|
||||
|
||||
- `letsencrypt-regru --obtain`
|
||||
|
||||
3) Если `npm_enabled=true`, сертификат автоматически появится в NPM.
|
||||
|
||||
4) В NPM:
|
||||
|
||||
- Proxy Hosts → Add/Edit Proxy Host
|
||||
- SSL → выберите сертификат (обычно “Custom/Other”)
|
||||
- включите нужные опции (Force SSL, HSTS по необходимости)
|
||||
|
||||
### Вариант B: сертификат выдаёт сам NPM
|
||||
|
||||
Этот вариант подходит, если NPM может сам пройти challenge.
|
||||
|
||||
1) SSL Certificates → Add SSL Certificate → Let’s Encrypt
|
||||
2) Domain Names: добавьте `example.com` и `*.example.com`
|
||||
3) Выберите challenge:
|
||||
|
||||
- HTTP-01: требует доступности NPM из интернета по 80/443 и корректных A/AAAA записей
|
||||
- DNS-01: требует поддерживаемого DNS provider в NPM
|
||||
|
||||
Если нужного DNS провайдера нет (или нет корректной интеграции для reg.ru), проще использовать этот проект как внешний DNS-01 менеджер.
|
||||
|
||||
### Вариант C: импорт уже существующего wildcard сертификата (Custom)
|
||||
|
||||
Если вы приобрели wildcard сертификат у CA или получили его другим способом:
|
||||
|
||||
1) SSL Certificates → Add SSL Certificate → Custom
|
||||
2) Вставьте:
|
||||
|
||||
- Certificate: сертификат + intermediate chain (если отдельно — добавьте подряд)
|
||||
- Key: приватный ключ
|
||||
|
||||
3) Сохраните и назначайте этот сертификат на Proxy Hosts.
|
||||
|
||||
## DNS записи для wildcard
|
||||
|
||||
Для проксирования поддоменов часто достаточно, чтобы DNS указывал на NPM:
|
||||
|
||||
- `example.com` → IP NPM
|
||||
- `*.example.com` → IP NPM
|
||||
|
||||
Точная схема зависит от вашей инфраструктуры.
|
||||
|
||||
## Траблшутинг
|
||||
|
||||
- “не логинится” → проверьте `npm_host` (http/https), креды, доступность
|
||||
- “сертификат не появился” → проверьте `npm_enabled`, логи скрипта
|
||||
- staging сертификаты: не предназначены для production (браузер не доверяет)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from: Настройке Nginx Manager с SSL)
|
||||
<!-- MIGRATED_FROM_DOCS: Настройке Nginx Manager с SSL -->
|
||||
|
||||
## Подробная инструкция по настройке Nginx Proxy Manager с одним глобальным SSL сертификатом для всех доменов example.com
|
||||
|
||||
### Предпосылки
|
||||
- Установлен и запущен [Nginx Proxy Manager](http://192.0.2.1:81/)
|
||||
- Основной домен: example.com
|
||||
- Хостинг и DNS записи домена находятся на reg.ru
|
||||
- Нужно использовать один SSL сертификат (например, wildcard) для всех поддоменов example.com
|
||||
|
||||
---
|
||||
|
||||
### Шаг 1. Покупка и получение SSL Wildcard сертификата для example.com
|
||||
1. На reg.ru или любом другом удостоверяющем центре (CA) закажите wildcard сертификат на домен вида `*.example.com`.
|
||||
2. Получите файлы сертификата:
|
||||
- Главный сертификат (CRT)
|
||||
- Промежуточные сертификаты (CA Bundle)
|
||||
- Приватный ключ (KEY)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2. Импорт вашего SSL сертификата в Nginx Proxy Manager
|
||||
1. Авторизуйтесь в Nginx Proxy Manager на http://192.0.2.1:81/
|
||||
2. Перейдите в раздел **SSL Certificates** → кнопку **Add SSL Certificate**
|
||||
3. Выберите **Custom** (пользовательский сертификат)
|
||||
4. В поля вставьте:
|
||||
- **Certificate** — основной CRT + CA Bundle (если CA Bundle раздельно, склейте в один файл или вставляйте последовательно)
|
||||
- **Key** — содержимое приватного ключа
|
||||
- Имя сертификата задайте, например, `dfv24_wildcard`
|
||||
5. Сохраните
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3. Настройка прокси-хостов с использованием глобального сертификата
|
||||
|
||||
1. Перейдите в **Proxy Hosts** → **Add Proxy Host**
|
||||
2. Заполните поля:
|
||||
- **Domain Names**: Например, `sub1.example.com` (для первого поддомена)
|
||||
- **Scheme**: http или https, в зависимости от бекенда
|
||||
- **Forward Hostname / IP**: IP или DNS адрес вашего внутреннего сервиса
|
||||
- **Forward Port**: порт сервиса (например, 80 или 443)
|
||||
3. Включите **SSL** → Отметьте **Use a shared SSL certificate** (если такая опция доступна) или выберите ранее импортированный сертификат из списка
|
||||
4. Активируйте: **Block Common Exploits**, **Websockets Support**, выставьте Redirect HTTP to HTTPS, если требуется
|
||||
5. Сохраните прокси-хост
|
||||
|
||||
6. Повторите для всех поддоменов, указывая нужные домены и выбирая тот же wildcard SSL сертификат
|
||||
|
||||
---
|
||||
|
||||
### Шаг 4. Настройка DNS записей на reg.ru
|
||||
|
||||
1. Войдите в панель управления доменом на reg.ru
|
||||
2. Создайте или отредактируйте DNS записи типа A:
|
||||
- `example.com` → IP вашего Nginx Proxy Manager (например, 192.0.2.1)
|
||||
- `*.example.com` → тот же IP или конкретные поддомены, если есть специальные
|
||||
3. Сохраните изменения
|
||||
4. Дождитесь обновления DNS (от нескольких минут до 24 часов)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 5. Тест и проверка работы
|
||||
|
||||
1. В браузере откройте любой из поддоменов `https://sub1.example.com`
|
||||
2. Сертификат должен быть валидным, выданным на wildcard `*.example.com`
|
||||
3. Проверьте работу прокси и корректность подстановки сертификата
|
||||
4. При необходимости проверьте логи Nginx Proxy Manager и исправьте ошибки
|
||||
|
||||
---
|
||||
|
||||
### Дополнительно
|
||||
|
||||
- Если в Nginx Proxy Manager нет GUI опции выбора общего сертификата, можно вручную сконфигурировать конфиги через директорий `/data/nginx/proxy_host` и прописать SSL сертификат для всех хостов.
|
||||
- При обновлении сертификата — повторно импортировать его в Nginx Proxy Manager.
|
||||
- Можно использовать LetsEncrypt для автоматического получения wildcard сертификата с помощью DNS валидации (если поддерживается вашим DNS провайдером).
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
|
||||
Используйте один wildcard сертификат для всех поддоменов, импортируйте его как пользовательский сертификат в Nginx Proxy Manager, при создании прокси-хостов выбирайте его в настройках SSL. Управляйте DNS записями на reg.ru, направляя домен на IP Nginx Proxy Manager.
|
||||
Это позволит юридически использовать единый сертификат для всех сервисов с различными поддоменами под вашим доменом example.com.
|
||||
|
||||
|
||||
+292
-292
@@ -1,292 +1,292 @@
|
||||
# Структура проекта
|
||||
|
||||
Ключевые файлы:
|
||||
|
||||
- `letsencrypt_regru_api.py` — основной Python скрипт (API reg.ru + certbot + NPM)
|
||||
- `letsencrypt_regru.sh` — установщик и менеджер установки
|
||||
- `Makefile` — команды установки/обслуживания/сборки
|
||||
- `config.json.example` — пример конфигурации
|
||||
- `systemd/` — unit файлы для автозапуска/таймера
|
||||
- `wiki/` — актуальная документация (страницы Wiki)
|
||||
|
||||
Скрипты:
|
||||
|
||||
- `letsencrypt_regru_dns.sh` — bash вариант через плагин certbot-dns-regru
|
||||
- `letsencrypt_regru.ps1` — PowerShell версия
|
||||
- `test_certificate.sh` — автономная генерация тестовых сертификатов через OpenSSL
|
||||
|
||||
Документация:
|
||||
|
||||
- `README.md` — основное руководство
|
||||
- `wiki/*` — дополнительные гайды (тестирование, сборка, синхронизация и т.д.)
|
||||
|
||||
## Автоматизация
|
||||
|
||||
- systemd timer обычно запускает `--auto` по расписанию (по умолчанию каждые 12 часов)
|
||||
- после успешного обновления может выполняться reload веб-сервиса
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/PROJECT_STRUCTURE.md)
|
||||
<!-- MIGRATED_FROM_DOCS:PROJECT_STRUCTURE.md -->
|
||||
|
||||
## 📁 Структура проекта configure_nginx_manager
|
||||
|
||||
### Основные скрипты
|
||||
|
||||
#### Python (Рекомендуется)
|
||||
- **letsencrypt_regru_api.py** (1,411 строк)
|
||||
- Полнофункциональный Python скрипт
|
||||
- Прямая работа с API reg.ru
|
||||
- Интеграция с Nginx Proxy Manager
|
||||
- Автоматическая проверка и обновление сертификатов
|
||||
- Генерация тестовых самоподписанных сертификатов
|
||||
- Поддержка wildcard доменов
|
||||
|
||||
#### Bash
|
||||
- **letsencrypt_regru_dns.sh**
|
||||
- Bash скрипт с certbot-dns-regru плагином
|
||||
- Простота использования
|
||||
- Минимальные зависимости
|
||||
|
||||
#### PowerShell
|
||||
- **letsencrypt_regru.ps1**
|
||||
- Windows версия
|
||||
- Аналогична Bash скрипту
|
||||
|
||||
#### Тестирование
|
||||
- **test_certificate.sh**
|
||||
- Быстрое создание тестовых сертификатов через OpenSSL
|
||||
- Автономная работа без Python
|
||||
- Поддержка wildcard доменов
|
||||
|
||||
### Автоматизация
|
||||
|
||||
#### Makefile
|
||||
- **Makefile** (415 строк)
|
||||
- `make install` - Полная установка и настройка
|
||||
- `make uninstall` - Чистое удаление
|
||||
- `make status` - Проверка состояния
|
||||
- `make test-cert` - Создание тестового сертификата
|
||||
- `make obtain` - Получение Let's Encrypt сертификата
|
||||
- `make renew` - Обновление сертификата
|
||||
- `make logs` - Просмотр логов
|
||||
- `make check-config` - Валидация конфигурации
|
||||
|
||||
### Конфигурация
|
||||
|
||||
#### config.json.example
|
||||
Пример конфигурации со всеми параметрами:
|
||||
- Учетные данные reg.ru API
|
||||
- Настройки домена и email
|
||||
- Параметры обновления (renewal_days)
|
||||
- Настройки Nginx Proxy Manager
|
||||
- Пути к директориям и логам
|
||||
|
||||
### Документация
|
||||
|
||||
#### README.md (1,420+ строк)
|
||||
Основная документация:
|
||||
- Введение и возможности
|
||||
- Быстрый старт
|
||||
- Установка через Makefile
|
||||
- Создание тестовых сертификатов
|
||||
- Требования и установка зависимостей
|
||||
- Настройка и использование
|
||||
- Интеграция с NPM
|
||||
- Автоматическая проверка и обновление
|
||||
- Автоматизация через cron/systemd
|
||||
- Устранение неполадок
|
||||
|
||||
#### TESTING_GUIDE.md (370+ строк)
|
||||
Руководство по тестированию:
|
||||
- Зачем нужны тестовые сертификаты
|
||||
- Обход лимитов Let's Encrypt (5 в неделю)
|
||||
- Быстрый старт с тестовыми сертификатами
|
||||
- Сравнение методов создания
|
||||
- Использование в разработке
|
||||
- Автоматизация тестирования
|
||||
- Переход с тестовых на production
|
||||
- Частые вопросы
|
||||
- Примеры для CI/CD и Docker
|
||||
|
||||
#### GITEA_SYNC.md
|
||||
Синхронизация Gitea → GitHub:
|
||||
- 4 метода синхронизации (Git Hooks, GitHub Actions, Gitea Mirror, Double Remote)
|
||||
- Пошаговые инструкции установки
|
||||
- Настройка SSH и токенов
|
||||
- Webhook интеграция
|
||||
- Устранение проблем
|
||||
- Сравнение методов
|
||||
|
||||
#### CHEATSHEET.md
|
||||
Быстрая шпаргалка:
|
||||
- Основные команды
|
||||
- Workflow разработки
|
||||
- Сценарии использования
|
||||
- Частые ошибки и решения
|
||||
- Проверка и отладка
|
||||
|
||||
#### PROJECT_STRUCTURE.md (этот файл)
|
||||
- Описание всех файлов проекта
|
||||
- Краткая характеристика каждого компонента
|
||||
|
||||
#### CHANGELOG.md
|
||||
История изменений:
|
||||
- Версии и обновления
|
||||
- Новые возможности
|
||||
- Исправления
|
||||
- Roadmap
|
||||
|
||||
### Интеграция с Git
|
||||
|
||||
#### .github/workflows/sync-from-gitea.yml
|
||||
GitHub Actions для синхронизации:
|
||||
- Автоматическая проверка каждый час
|
||||
- Webhook триггер от Gitea
|
||||
- Ручной запуск
|
||||
- Merge изменений из Gitea
|
||||
- Push в GitHub
|
||||
|
||||
#### gitea-hooks/
|
||||
Git hooks для Gitea сервера:
|
||||
|
||||
**post-receive**
|
||||
- Автоматический push в GitHub после commit
|
||||
- Мгновенная синхронизация (< 1 секунды)
|
||||
- Логирование операций
|
||||
- Синхронизация тегов
|
||||
- Поддержка SSH и HTTPS
|
||||
|
||||
**README.md**
|
||||
- Инструкции по установке hook
|
||||
- Настройка аутентификации
|
||||
- Устранение проблем
|
||||
|
||||
### Вспомогательные файлы
|
||||
|
||||
#### Markdown документы
|
||||
- **Add Let's Encrypt Certificate для провайдера reg.ru.md**
|
||||
- Первоначальные инструкции
|
||||
|
||||
- **Создание и продление SSL сертификата (md)**
|
||||
- Дополнительная информация о процессе
|
||||
|
||||
### Возможности
|
||||
|
||||
#### ✅ Основные
|
||||
- [x] Создание Let's Encrypt сертификатов через reg.ru DNS API
|
||||
- [x] Wildcard сертификаты (*.domain.com)
|
||||
- [x] Автоматическое обновление сертификатов
|
||||
- [x] DNS-01 валидация
|
||||
- [x] Интеграция с Nginx Proxy Manager
|
||||
- [x] Автоматическая загрузка/обновление в NPM
|
||||
|
||||
#### ✅ Продвинутые
|
||||
- [x] Автоматическая проверка срока действия
|
||||
- [x] Настраиваемый порог обновления (renewal_days)
|
||||
- [x] Systemd service + timer
|
||||
- [x] Cron автоматизация
|
||||
- [x] Подробное логирование
|
||||
- [x] Валидация конфигурации
|
||||
|
||||
#### 🆕 Тестирование
|
||||
- [x] Генерация самоподписанных тестовых сертификатов
|
||||
- [x] Обход лимитов Let's Encrypt (5/неделю)
|
||||
- [x] Мгновенное создание без DNS
|
||||
- [x] Интеграция тестовых сертификатов с NPM
|
||||
- [x] Полная совместимость структуры с Let's Encrypt
|
||||
|
||||
#### 🔄 Синхронизация репозиториев
|
||||
- [x] Автоматическая синхронизация Gitea → GitHub
|
||||
- [x] Git Hooks (мгновенная синхронизация)
|
||||
- [x] GitHub Actions (проверка каждый час)
|
||||
- [x] Webhook интеграция
|
||||
- [x] SSH и HTTPS аутентификация
|
||||
|
||||
### Установка
|
||||
|
||||
#### Быстрая установка
|
||||
```bash
|
||||
sudo make install
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
sudo make test-cert # Для тестирования
|
||||
sudo make obtain # Для production
|
||||
```
|
||||
|
||||
#### Структура после установки
|
||||
```
|
||||
/opt/letsencrypt-regru/
|
||||
├── letsencrypt_regru_api.py
|
||||
|
||||
/etc/letsencrypt/
|
||||
├── regru_config.json
|
||||
└── live/
|
||||
└── example.com/
|
||||
├── privkey.pem
|
||||
├── cert.pem
|
||||
├── fullchain.pem
|
||||
└── chain.pem
|
||||
|
||||
/etc/systemd/system/
|
||||
├── letsencrypt-regru.service
|
||||
└── letsencrypt-regru.timer
|
||||
|
||||
/var/log/letsencrypt/
|
||||
└── letsencrypt_regru.log
|
||||
```
|
||||
|
||||
### Использование
|
||||
|
||||
#### Тестирование (без лимитов)
|
||||
```bash
|
||||
sudo make test-cert # Создать тестовый сертификат
|
||||
sudo make status # Проверить статус
|
||||
```
|
||||
|
||||
#### Production
|
||||
```bash
|
||||
sudo make obtain # Получить Let's Encrypt сертификат
|
||||
sudo make renew # Обновить сертификат
|
||||
sudo make run # Автоматический режим
|
||||
```
|
||||
|
||||
#### Мониторинг
|
||||
```bash
|
||||
sudo make logs # Просмотр логов
|
||||
sudo make status # Статус служб
|
||||
sudo make check-config # Проверка конфигурации
|
||||
```
|
||||
|
||||
### Технологии
|
||||
|
||||
- **Python 3.6+** - Основной язык
|
||||
- **Certbot** - Let's Encrypt клиент
|
||||
- **requests** - HTTP запросы к API
|
||||
- **cryptography** - Генерация тестовых сертификатов
|
||||
- **systemd** - Автоматизация запуска
|
||||
- **cron** - Альтернативная автоматизация
|
||||
- **Make** - Управление установкой
|
||||
- **OpenSSL** - Альтернативная генерация сертификатов
|
||||
|
||||
### Лицензия
|
||||
|
||||
Open Source - свободное использование
|
||||
|
||||
### Автор
|
||||
|
||||
Фофанов Дмитрий @ 2025
|
||||
|
||||
### Поддержка
|
||||
|
||||
См. документацию:
|
||||
- [README.md](README.md) - Основное руководство
|
||||
- [TESTING_GUIDE.md](Testing.md) - Руководство по тестированию
|
||||
|
||||
---
|
||||
|
||||
**Версия**: 2.1
|
||||
**Дата**: 27 октября 2025
|
||||
**Статус**: ✅ Production Ready
|
||||
|
||||
# Структура проекта
|
||||
|
||||
Ключевые файлы:
|
||||
|
||||
- `letsencrypt_regru_api.py` — основной Python скрипт (API reg.ru + certbot + NPM)
|
||||
- `letsencrypt_regru.sh` — установщик и менеджер установки
|
||||
- `Makefile` — команды установки/обслуживания/сборки
|
||||
- `config.json.example` — пример конфигурации
|
||||
- `systemd/` — unit файлы для автозапуска/таймера
|
||||
- `wiki/` — актуальная документация (страницы Wiki)
|
||||
|
||||
Скрипты:
|
||||
|
||||
- `letsencrypt_regru_dns.sh` — bash вариант через плагин certbot-dns-regru
|
||||
- `letsencrypt_regru.ps1` — PowerShell версия
|
||||
- `test_certificate.sh` — автономная генерация тестовых сертификатов через OpenSSL
|
||||
|
||||
Документация:
|
||||
|
||||
- `README.md` — основное руководство
|
||||
- `wiki/*` — дополнительные гайды (тестирование, сборка, синхронизация и т.д.)
|
||||
|
||||
## Автоматизация
|
||||
|
||||
- systemd timer обычно запускает `--auto` по расписанию (по умолчанию каждые 12 часов)
|
||||
- после успешного обновления может выполняться reload веб-сервиса
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Appendix (migrated from docs/PROJECT_STRUCTURE.md)
|
||||
<!-- MIGRATED_FROM_DOCS:PROJECT_STRUCTURE.md -->
|
||||
|
||||
## 📁 Структура проекта configure_nginx_manager
|
||||
|
||||
### Основные скрипты
|
||||
|
||||
#### Python (Рекомендуется)
|
||||
- **letsencrypt_regru_api.py** (1,411 строк)
|
||||
- Полнофункциональный Python скрипт
|
||||
- Прямая работа с API reg.ru
|
||||
- Интеграция с Nginx Proxy Manager
|
||||
- Автоматическая проверка и обновление сертификатов
|
||||
- Генерация тестовых самоподписанных сертификатов
|
||||
- Поддержка wildcard доменов
|
||||
|
||||
#### Bash
|
||||
- **letsencrypt_regru_dns.sh**
|
||||
- Bash скрипт с certbot-dns-regru плагином
|
||||
- Простота использования
|
||||
- Минимальные зависимости
|
||||
|
||||
#### PowerShell
|
||||
- **letsencrypt_regru.ps1**
|
||||
- Windows версия
|
||||
- Аналогична Bash скрипту
|
||||
|
||||
#### Тестирование
|
||||
- **test_certificate.sh**
|
||||
- Быстрое создание тестовых сертификатов через OpenSSL
|
||||
- Автономная работа без Python
|
||||
- Поддержка wildcard доменов
|
||||
|
||||
### Автоматизация
|
||||
|
||||
#### Makefile
|
||||
- **Makefile** (415 строк)
|
||||
- `make install` - Полная установка и настройка
|
||||
- `make uninstall` - Чистое удаление
|
||||
- `make status` - Проверка состояния
|
||||
- `make test-cert` - Создание тестового сертификата
|
||||
- `make obtain` - Получение Let's Encrypt сертификата
|
||||
- `make renew` - Обновление сертификата
|
||||
- `make logs` - Просмотр логов
|
||||
- `make check-config` - Валидация конфигурации
|
||||
|
||||
### Конфигурация
|
||||
|
||||
#### config.json.example
|
||||
Пример конфигурации со всеми параметрами:
|
||||
- Учетные данные reg.ru API
|
||||
- Настройки домена и email
|
||||
- Параметры обновления (renewal_days)
|
||||
- Настройки Nginx Proxy Manager
|
||||
- Пути к директориям и логам
|
||||
|
||||
### Документация
|
||||
|
||||
#### README.md (1,420+ строк)
|
||||
Основная документация:
|
||||
- Введение и возможности
|
||||
- Быстрый старт
|
||||
- Установка через Makefile
|
||||
- Создание тестовых сертификатов
|
||||
- Требования и установка зависимостей
|
||||
- Настройка и использование
|
||||
- Интеграция с NPM
|
||||
- Автоматическая проверка и обновление
|
||||
- Автоматизация через cron/systemd
|
||||
- Устранение неполадок
|
||||
|
||||
#### TESTING_GUIDE.md (370+ строк)
|
||||
Руководство по тестированию:
|
||||
- Зачем нужны тестовые сертификаты
|
||||
- Обход лимитов Let's Encrypt (5 в неделю)
|
||||
- Быстрый старт с тестовыми сертификатами
|
||||
- Сравнение методов создания
|
||||
- Использование в разработке
|
||||
- Автоматизация тестирования
|
||||
- Переход с тестовых на production
|
||||
- Частые вопросы
|
||||
- Примеры для CI/CD и Docker
|
||||
|
||||
#### GITEA_SYNC.md
|
||||
Синхронизация Gitea → GitHub:
|
||||
- 4 метода синхронизации (Git Hooks, GitHub Actions, Gitea Mirror, Double Remote)
|
||||
- Пошаговые инструкции установки
|
||||
- Настройка SSH и токенов
|
||||
- Webhook интеграция
|
||||
- Устранение проблем
|
||||
- Сравнение методов
|
||||
|
||||
#### CHEATSHEET.md
|
||||
Быстрая шпаргалка:
|
||||
- Основные команды
|
||||
- Workflow разработки
|
||||
- Сценарии использования
|
||||
- Частые ошибки и решения
|
||||
- Проверка и отладка
|
||||
|
||||
#### PROJECT_STRUCTURE.md (этот файл)
|
||||
- Описание всех файлов проекта
|
||||
- Краткая характеристика каждого компонента
|
||||
|
||||
#### CHANGELOG.md
|
||||
История изменений:
|
||||
- Версии и обновления
|
||||
- Новые возможности
|
||||
- Исправления
|
||||
- Roadmap
|
||||
|
||||
### Интеграция с Git
|
||||
|
||||
#### .github/workflows/sync-from-gitea.yml
|
||||
GitHub Actions для синхронизации:
|
||||
- Автоматическая проверка каждый час
|
||||
- Webhook триггер от Gitea
|
||||
- Ручной запуск
|
||||
- Merge изменений из Gitea
|
||||
- Push в GitHub
|
||||
|
||||
#### gitea-hooks/
|
||||
Git hooks для Gitea сервера:
|
||||
|
||||
**post-receive**
|
||||
- Автоматический push в GitHub после commit
|
||||
- Мгновенная синхронизация (< 1 секунды)
|
||||
- Логирование операций
|
||||
- Синхронизация тегов
|
||||
- Поддержка SSH и HTTPS
|
||||
|
||||
**README.md**
|
||||
- Инструкции по установке hook
|
||||
- Настройка аутентификации
|
||||
- Устранение проблем
|
||||
|
||||
### Вспомогательные файлы
|
||||
|
||||
#### Markdown документы
|
||||
- **Add Let's Encrypt Certificate для провайдера reg.ru.md**
|
||||
- Первоначальные инструкции
|
||||
|
||||
- **Создание и продление SSL сертификата (md)**
|
||||
- Дополнительная информация о процессе
|
||||
|
||||
### Возможности
|
||||
|
||||
#### ✅ Основные
|
||||
- [x] Создание Let's Encrypt сертификатов через reg.ru DNS API
|
||||
- [x] Wildcard сертификаты (*.domain.com)
|
||||
- [x] Автоматическое обновление сертификатов
|
||||
- [x] DNS-01 валидация
|
||||
- [x] Интеграция с Nginx Proxy Manager
|
||||
- [x] Автоматическая загрузка/обновление в NPM
|
||||
|
||||
#### ✅ Продвинутые
|
||||
- [x] Автоматическая проверка срока действия
|
||||
- [x] Настраиваемый порог обновления (renewal_days)
|
||||
- [x] Systemd service + timer
|
||||
- [x] Cron автоматизация
|
||||
- [x] Подробное логирование
|
||||
- [x] Валидация конфигурации
|
||||
|
||||
#### 🆕 Тестирование
|
||||
- [x] Генерация самоподписанных тестовых сертификатов
|
||||
- [x] Обход лимитов Let's Encrypt (5/неделю)
|
||||
- [x] Мгновенное создание без DNS
|
||||
- [x] Интеграция тестовых сертификатов с NPM
|
||||
- [x] Полная совместимость структуры с Let's Encrypt
|
||||
|
||||
#### 🔄 Синхронизация репозиториев
|
||||
- [x] Автоматическая синхронизация Gitea → GitHub
|
||||
- [x] Git Hooks (мгновенная синхронизация)
|
||||
- [x] GitHub Actions (проверка каждый час)
|
||||
- [x] Webhook интеграция
|
||||
- [x] SSH и HTTPS аутентификация
|
||||
|
||||
### Установка
|
||||
|
||||
#### Быстрая установка
|
||||
```bash
|
||||
sudo make install
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
sudo make test-cert # Для тестирования
|
||||
sudo make obtain # Для production
|
||||
```
|
||||
|
||||
#### Структура после установки
|
||||
```
|
||||
/opt/letsencrypt-regru/
|
||||
├── letsencrypt_regru_api.py
|
||||
|
||||
/etc/letsencrypt/
|
||||
├── regru_config.json
|
||||
└── live/
|
||||
└── example.com/
|
||||
├── privkey.pem
|
||||
├── cert.pem
|
||||
├── fullchain.pem
|
||||
└── chain.pem
|
||||
|
||||
/etc/systemd/system/
|
||||
├── letsencrypt-regru.service
|
||||
└── letsencrypt-regru.timer
|
||||
|
||||
/var/log/letsencrypt/
|
||||
└── letsencrypt_regru.log
|
||||
```
|
||||
|
||||
### Использование
|
||||
|
||||
#### Тестирование (без лимитов)
|
||||
```bash
|
||||
sudo make test-cert # Создать тестовый сертификат
|
||||
sudo make status # Проверить статус
|
||||
```
|
||||
|
||||
#### Production
|
||||
```bash
|
||||
sudo make obtain # Получить Let's Encrypt сертификат
|
||||
sudo make renew # Обновить сертификат
|
||||
sudo make run # Автоматический режим
|
||||
```
|
||||
|
||||
#### Мониторинг
|
||||
```bash
|
||||
sudo make logs # Просмотр логов
|
||||
sudo make status # Статус служб
|
||||
sudo make check-config # Проверка конфигурации
|
||||
```
|
||||
|
||||
### Технологии
|
||||
|
||||
- **Python 3.6+** - Основной язык
|
||||
- **Certbot** - Let's Encrypt клиент
|
||||
- **requests** - HTTP запросы к API
|
||||
- **cryptography** - Генерация тестовых сертификатов
|
||||
- **systemd** - Автоматизация запуска
|
||||
- **cron** - Альтернативная автоматизация
|
||||
- **Make** - Управление установкой
|
||||
- **OpenSSL** - Альтернативная генерация сертификатов
|
||||
|
||||
### Лицензия
|
||||
|
||||
Open Source - свободное использование
|
||||
|
||||
### Автор
|
||||
|
||||
Фофанов Дмитрий @ 2025
|
||||
|
||||
### Поддержка
|
||||
|
||||
См. документацию:
|
||||
- [README.md](README.md) - Основное руководство
|
||||
- [TESTING_GUIDE.md](Testing.md) - Руководство по тестированию
|
||||
|
||||
---
|
||||
|
||||
**Версия**: 2.1
|
||||
**Дата**: 27 октября 2025
|
||||
**Статус**: ✅ Production Ready
|
||||
|
||||
|
||||
+260
-260
@@ -1,57 +1,57 @@
|
||||
# Проблемы API reg.ru (DNS)
|
||||
|
||||
## Ошибка: “Access to API from this IP denied”
|
||||
|
||||
Причина: ваш текущий IP не разрешён в настройках API reg.ru.
|
||||
|
||||
### Диагностика
|
||||
|
||||
- `letsencrypt-regru --test-api`
|
||||
- или `curl -s https://ipinfo.io/ip`
|
||||
|
||||
### Решение (рекомендуется)
|
||||
|
||||
1) Личный кабинет reg.ru
|
||||
2) Настройки → Безопасность → API
|
||||
3) Добавить текущий IP в белый список
|
||||
4) Повторить `--test-api`
|
||||
|
||||
### Альтернатива
|
||||
|
||||
Отключить ограничения по IP (менее безопасно).
|
||||
|
||||
## Ошибка: “Invalid username or password”
|
||||
|
||||
- проверьте `regru_username`/`regru_password` в конфиге
|
||||
- проверьте права доступа к файлу конфига (600)
|
||||
|
||||
## Ошибка: “IP exceeded allowed connection rate”
|
||||
|
||||
API ограничивает частоту запросов.
|
||||
|
||||
Решения:
|
||||
|
||||
- подождать 5–10 минут
|
||||
- не запускать `--test-api` слишком часто
|
||||
- для мониторинга чаще используйте `--check`
|
||||
|
||||
## Таймауты
|
||||
|
||||
- проверьте интернет
|
||||
- проверьте firewall/proxy
|
||||
|
||||
## Логи для диагностики
|
||||
|
||||
- `log_file` из конфигурации
|
||||
- `/var/log/letsencrypt/letsencrypt.log` (certbot)
|
||||
|
||||
## Когда обращаться в поддержку reg.ru
|
||||
|
||||
Приготовьте:
|
||||
|
||||
- ваш IP
|
||||
- точный текст ошибки
|
||||
- фрагмент логов (без паролей)
|
||||
# Проблемы API reg.ru (DNS)
|
||||
|
||||
## Ошибка: “Access to API from this IP denied”
|
||||
|
||||
Причина: ваш текущий IP не разрешён в настройках API reg.ru.
|
||||
|
||||
### Диагностика
|
||||
|
||||
- `letsencrypt-regru --test-api`
|
||||
- или `curl -s https://ipinfo.io/ip`
|
||||
|
||||
### Решение (рекомендуется)
|
||||
|
||||
1) Личный кабинет reg.ru
|
||||
2) Настройки → Безопасность → API
|
||||
3) Добавить текущий IP в белый список
|
||||
4) Повторить `--test-api`
|
||||
|
||||
### Альтернатива
|
||||
|
||||
Отключить ограничения по IP (менее безопасно).
|
||||
|
||||
## Ошибка: “Invalid username or password”
|
||||
|
||||
- проверьте `regru_username`/`regru_password` в конфиге
|
||||
- проверьте права доступа к файлу конфига (600)
|
||||
|
||||
## Ошибка: “IP exceeded allowed connection rate”
|
||||
|
||||
API ограничивает частоту запросов.
|
||||
|
||||
Решения:
|
||||
|
||||
- подождать 5–10 минут
|
||||
- не запускать `--test-api` слишком часто
|
||||
- для мониторинга чаще используйте `--check`
|
||||
|
||||
## Таймауты
|
||||
|
||||
- проверьте интернет
|
||||
- проверьте firewall/proxy
|
||||
|
||||
## Логи для диагностики
|
||||
|
||||
- `log_file` из конфигурации
|
||||
- `/var/log/letsencrypt/letsencrypt.log` (certbot)
|
||||
|
||||
## Когда обращаться в поддержку reg.ru
|
||||
|
||||
Приготовьте:
|
||||
|
||||
- ваш IP
|
||||
- точный текст ошибки
|
||||
- фрагмент логов (без паролей)
|
||||
|
||||
|
||||
---
|
||||
@@ -59,209 +59,209 @@ API ограничивает частоту запросов.
|
||||
## Appendix (migrated from docs/API_TROUBLESHOOTING.md)
|
||||
<!-- MIGRATED_FROM_DOCS:API_TROUBLESHOOTING.md -->
|
||||
|
||||
## 🔧 Решение проблем с API reg.ru
|
||||
|
||||
### ❌ Проблема: "Access to API from this IP denied"
|
||||
|
||||
Эта ошибка возникает, когда API reg.ru заблокирован для вашего IP адреса из соображений безопасности.
|
||||
|
||||
#### 🔍 Диагностика
|
||||
|
||||
Сначала определите ваш текущий IP адрес:
|
||||
|
||||
```bash
|
||||
## Способ 1: Через встроенную функцию скрипта
|
||||
sudo letsencrypt-regru --test-api
|
||||
|
||||
## Способ 2: Через curl
|
||||
curl -s https://ipinfo.io/ip
|
||||
|
||||
## Способ 3: Через веб-сайт
|
||||
## Откройте https://whatismyipaddress.com/
|
||||
```
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
##### Метод 1: Добавить IP в белый список (рекомендуется)
|
||||
|
||||
1. **Войдите в личный кабинет reg.ru**
|
||||
- Откройте https://www.reg.ru/
|
||||
- Войдите в личный кабинет
|
||||
|
||||
2. **Перейдите в настройки API**
|
||||
- Меню → "Настройки"
|
||||
- Раздел "Безопасность"
|
||||
- Подраздел "API"
|
||||
|
||||
3. **Настройте доступ по IP**
|
||||
- Найдите раздел "Ограничения по IP"
|
||||
- Нажмите "Добавить IP адрес"
|
||||
- Введите ваш текущий IP адрес
|
||||
- Сохраните настройки
|
||||
|
||||
4. **Проверьте настройки**
|
||||
```bash
|
||||
sudo letsencrypt-regru --test-api
|
||||
```
|
||||
|
||||
##### Метод 2: Отключить ограничения по IP (менее безопасно)
|
||||
|
||||
⚠️ **ВНИМАНИЕ**: Это снижает безопасность вашего аккаунта!
|
||||
|
||||
1. В настройках API reg.ru найдите "Ограничения по IP"
|
||||
2. Отключите опцию "Разрешить доступ только с указанных IP"
|
||||
3. Сохраните настройки
|
||||
|
||||
#### 🔒 Рекомендации по безопасности
|
||||
|
||||
1. **Используйте статический IP**
|
||||
- Если у вас динамический IP, рассмотрите покупку статического
|
||||
- Или регулярно обновляйте список разрешенных IP
|
||||
|
||||
2. **Ограничьте доступ к API**
|
||||
- Добавляйте только необходимые IP адреса
|
||||
- Регулярно проверяйте и очищайте список
|
||||
|
||||
3. **Используйте сильные пароли**
|
||||
- Сложный пароль для аккаунта reg.ru
|
||||
- Двухфакторная аутентификация если доступна
|
||||
|
||||
### ❌ Проблема: "Invalid username or password"
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Проверьте учетные данные**
|
||||
```bash
|
||||
sudo nano /etc/letsencrypt-regru/config.json
|
||||
```
|
||||
|
||||
Убедитесь что указаны правильные:
|
||||
- `regru_username` - логин от reg.ru
|
||||
- `regru_password` - пароль от reg.ru
|
||||
|
||||
2. **Проверьте права на файл**
|
||||
```bash
|
||||
sudo chmod 600 /etc/letsencrypt-regru/config.json
|
||||
sudo chown root:root /etc/letsencrypt-regru/config.json
|
||||
```
|
||||
|
||||
3. **Протестируйте подключение**
|
||||
```bash
|
||||
sudo letsencrypt-regru --test-api
|
||||
```
|
||||
|
||||
### ❌ Проблема: "IP exceeded allowed connection rate"
|
||||
|
||||
#### Причина
|
||||
API reg.ru ограничивает частоту запросов с одного IP (обычно 10-20 запросов в минуту).
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Подождите 5-10 минут**
|
||||
```bash
|
||||
# Подождите перед следующей попыткой
|
||||
sleep 600 # 10 минут
|
||||
sudo letsencrypt-regru --obtain
|
||||
```
|
||||
|
||||
2. **Настройте автоматизацию правильно**
|
||||
```bash
|
||||
# Проверка сертификатов 1 раз в день
|
||||
sudo systemctl enable letsencrypt-regru.timer
|
||||
sudo systemctl start letsencrypt-regru.timer
|
||||
|
||||
# Проверить расписание
|
||||
sudo systemctl cat letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
3. **Рекомендации по частоте запросов**
|
||||
- ✅ Автоматическая проверка: **1 раз в день**
|
||||
- ✅ Ручная проверка: **не чаще 1 раза в час**
|
||||
- ❌ Избегайте частых тестов `--test-api`
|
||||
- ❌ Не создавайте cron с частым запуском
|
||||
|
||||
4. **Используйте --check вместо --obtain**
|
||||
```bash
|
||||
# Проверка без создания сертификата
|
||||
sudo letsencrypt-regru --check
|
||||
```
|
||||
|
||||
### ❌ Проблема: Таймаут подключения
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Проверьте интернет соединение**
|
||||
```bash
|
||||
ping -c 4 api.reg.ru
|
||||
curl -I https://api.reg.ru/api/regru2
|
||||
```
|
||||
|
||||
2. **Проверьте брандмауэр**
|
||||
```bash
|
||||
# Временно отключите firewall для теста
|
||||
sudo ufw status
|
||||
sudo iptables -L
|
||||
```
|
||||
|
||||
3. **Проверьте прокси настройки**
|
||||
- Убедитесь что переменные окружения `HTTP_PROXY`, `HTTPS_PROXY` не мешают
|
||||
|
||||
### 🧪 Тестирование API
|
||||
|
||||
Всегда тестируйте API перед использованием:
|
||||
|
||||
```bash
|
||||
## Полный тест API
|
||||
sudo letsencrypt-regru --test-api
|
||||
|
||||
## Тест с подробным выводом
|
||||
sudo letsencrypt-regru --test-api -v
|
||||
|
||||
## Проверка конфигурации
|
||||
sudo letsencrypt-regru --check
|
||||
```
|
||||
|
||||
### 📞 Получение помощи
|
||||
|
||||
#### Техподдержка reg.ru
|
||||
|
||||
- **Email**: support@reg.ru
|
||||
- **Телефон**: 8 (495) 580-11-11
|
||||
- **Онлайн чат**: на сайте reg.ru
|
||||
|
||||
#### Документация
|
||||
|
||||
- **API reg.ru**: https://www.reg.ru/support/api
|
||||
- **Примеры использования**: https://www.reg.ru/support/api/examples
|
||||
- **FAQ по API**: https://www.reg.ru/support/api/faq
|
||||
|
||||
#### Логи для диагностики
|
||||
|
||||
Всегда включайте логи при обращении в поддержку:
|
||||
|
||||
```bash
|
||||
## Включить подробные логи
|
||||
sudo letsencrypt-regru --test-api -v
|
||||
|
||||
## Посмотреть последние логи
|
||||
sudo tail -n 50 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Логи certbot
|
||||
sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log
|
||||
```
|
||||
|
||||
### 🔄 Альтернативные DNS провайдеры
|
||||
|
||||
Если проблемы с reg.ru API критичны, рассмотрите альтернативы:
|
||||
|
||||
1. **Cloudflare** - отличный API, бесплатный DNS
|
||||
2. **Route53** (AWS) - мощный, но платный
|
||||
3. **DigitalOcean DNS** - простой и надежный
|
||||
4. **Google Cloud DNS** - интеграция с GCP
|
||||
|
||||
Для них потребуется модификация скрипта или использование других плагинов certbot.
|
||||
|
||||
---
|
||||
|
||||
**Дата обновления**: 29.10.2025
|
||||
**Версия документа**: 1.0
|
||||
## 🔧 Решение проблем с API reg.ru
|
||||
|
||||
### ❌ Проблема: "Access to API from this IP denied"
|
||||
|
||||
Эта ошибка возникает, когда API reg.ru заблокирован для вашего IP адреса из соображений безопасности.
|
||||
|
||||
#### 🔍 Диагностика
|
||||
|
||||
Сначала определите ваш текущий IP адрес:
|
||||
|
||||
```bash
|
||||
## Способ 1: Через встроенную функцию скрипта
|
||||
sudo letsencrypt-regru --test-api
|
||||
|
||||
## Способ 2: Через curl
|
||||
curl -s https://ipinfo.io/ip
|
||||
|
||||
## Способ 3: Через веб-сайт
|
||||
## Откройте https://whatismyipaddress.com/
|
||||
```
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
##### Метод 1: Добавить IP в белый список (рекомендуется)
|
||||
|
||||
1. **Войдите в личный кабинет reg.ru**
|
||||
- Откройте https://www.reg.ru/
|
||||
- Войдите в личный кабинет
|
||||
|
||||
2. **Перейдите в настройки API**
|
||||
- Меню → "Настройки"
|
||||
- Раздел "Безопасность"
|
||||
- Подраздел "API"
|
||||
|
||||
3. **Настройте доступ по IP**
|
||||
- Найдите раздел "Ограничения по IP"
|
||||
- Нажмите "Добавить IP адрес"
|
||||
- Введите ваш текущий IP адрес
|
||||
- Сохраните настройки
|
||||
|
||||
4. **Проверьте настройки**
|
||||
```bash
|
||||
sudo letsencrypt-regru --test-api
|
||||
```
|
||||
|
||||
##### Метод 2: Отключить ограничения по IP (менее безопасно)
|
||||
|
||||
⚠️ **ВНИМАНИЕ**: Это снижает безопасность вашего аккаунта!
|
||||
|
||||
1. В настройках API reg.ru найдите "Ограничения по IP"
|
||||
2. Отключите опцию "Разрешить доступ только с указанных IP"
|
||||
3. Сохраните настройки
|
||||
|
||||
#### 🔒 Рекомендации по безопасности
|
||||
|
||||
1. **Используйте статический IP**
|
||||
- Если у вас динамический IP, рассмотрите покупку статического
|
||||
- Или регулярно обновляйте список разрешенных IP
|
||||
|
||||
2. **Ограничьте доступ к API**
|
||||
- Добавляйте только необходимые IP адреса
|
||||
- Регулярно проверяйте и очищайте список
|
||||
|
||||
3. **Используйте сильные пароли**
|
||||
- Сложный пароль для аккаунта reg.ru
|
||||
- Двухфакторная аутентификация если доступна
|
||||
|
||||
### ❌ Проблема: "Invalid username or password"
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Проверьте учетные данные**
|
||||
```bash
|
||||
sudo nano /etc/letsencrypt-regru/config.json
|
||||
```
|
||||
|
||||
Убедитесь что указаны правильные:
|
||||
- `regru_username` - логин от reg.ru
|
||||
- `regru_password` - пароль от reg.ru
|
||||
|
||||
2. **Проверьте права на файл**
|
||||
```bash
|
||||
sudo chmod 600 /etc/letsencrypt-regru/config.json
|
||||
sudo chown root:root /etc/letsencrypt-regru/config.json
|
||||
```
|
||||
|
||||
3. **Протестируйте подключение**
|
||||
```bash
|
||||
sudo letsencrypt-regru --test-api
|
||||
```
|
||||
|
||||
### ❌ Проблема: "IP exceeded allowed connection rate"
|
||||
|
||||
#### Причина
|
||||
API reg.ru ограничивает частоту запросов с одного IP (обычно 10-20 запросов в минуту).
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Подождите 5-10 минут**
|
||||
```bash
|
||||
# Подождите перед следующей попыткой
|
||||
sleep 600 # 10 минут
|
||||
sudo letsencrypt-regru --obtain
|
||||
```
|
||||
|
||||
2. **Настройте автоматизацию правильно**
|
||||
```bash
|
||||
# Проверка сертификатов 1 раз в день
|
||||
sudo systemctl enable letsencrypt-regru.timer
|
||||
sudo systemctl start letsencrypt-regru.timer
|
||||
|
||||
# Проверить расписание
|
||||
sudo systemctl cat letsencrypt-regru.timer
|
||||
```
|
||||
|
||||
3. **Рекомендации по частоте запросов**
|
||||
- ✅ Автоматическая проверка: **1 раз в день**
|
||||
- ✅ Ручная проверка: **не чаще 1 раза в час**
|
||||
- ❌ Избегайте частых тестов `--test-api`
|
||||
- ❌ Не создавайте cron с частым запуском
|
||||
|
||||
4. **Используйте --check вместо --obtain**
|
||||
```bash
|
||||
# Проверка без создания сертификата
|
||||
sudo letsencrypt-regru --check
|
||||
```
|
||||
|
||||
### ❌ Проблема: Таймаут подключения
|
||||
|
||||
#### ✅ Решение
|
||||
|
||||
1. **Проверьте интернет соединение**
|
||||
```bash
|
||||
ping -c 4 api.reg.ru
|
||||
curl -I https://api.reg.ru/api/regru2
|
||||
```
|
||||
|
||||
2. **Проверьте брандмауэр**
|
||||
```bash
|
||||
# Временно отключите firewall для теста
|
||||
sudo ufw status
|
||||
sudo iptables -L
|
||||
```
|
||||
|
||||
3. **Проверьте прокси настройки**
|
||||
- Убедитесь что переменные окружения `HTTP_PROXY`, `HTTPS_PROXY` не мешают
|
||||
|
||||
### 🧪 Тестирование API
|
||||
|
||||
Всегда тестируйте API перед использованием:
|
||||
|
||||
```bash
|
||||
## Полный тест API
|
||||
sudo letsencrypt-regru --test-api
|
||||
|
||||
## Тест с подробным выводом
|
||||
sudo letsencrypt-regru --test-api -v
|
||||
|
||||
## Проверка конфигурации
|
||||
sudo letsencrypt-regru --check
|
||||
```
|
||||
|
||||
### 📞 Получение помощи
|
||||
|
||||
#### Техподдержка reg.ru
|
||||
|
||||
- **Email**: support@reg.ru
|
||||
- **Телефон**: 8 (495) 580-11-11
|
||||
- **Онлайн чат**: на сайте reg.ru
|
||||
|
||||
#### Документация
|
||||
|
||||
- **API reg.ru**: https://www.reg.ru/support/api
|
||||
- **Примеры использования**: https://www.reg.ru/support/api/examples
|
||||
- **FAQ по API**: https://www.reg.ru/support/api/faq
|
||||
|
||||
#### Логи для диагностики
|
||||
|
||||
Всегда включайте логи при обращении в поддержку:
|
||||
|
||||
```bash
|
||||
## Включить подробные логи
|
||||
sudo letsencrypt-regru --test-api -v
|
||||
|
||||
## Посмотреть последние логи
|
||||
sudo tail -n 50 /var/log/letsencrypt-regru/letsencrypt_regru.log
|
||||
|
||||
## Логи certbot
|
||||
sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log
|
||||
```
|
||||
|
||||
### 🔄 Альтернативные DNS провайдеры
|
||||
|
||||
Если проблемы с reg.ru API критичны, рассмотрите альтернативы:
|
||||
|
||||
1. **Cloudflare** - отличный API, бесплатный DNS
|
||||
2. **Route53** (AWS) - мощный, но платный
|
||||
3. **DigitalOcean DNS** - простой и надежный
|
||||
4. **Google Cloud DNS** - интеграция с GCP
|
||||
|
||||
Для них потребуется модификация скрипта или использование других плагинов certbot.
|
||||
|
||||
---
|
||||
|
||||
**Дата обновления**: 29.10.2025
|
||||
**Версия документа**: 1.0
|
||||
|
||||
+436
-436
@@ -1,56 +1,56 @@
|
||||
# Тестирование
|
||||
|
||||
Главная цель тестовых режимов — не упереться в лимиты Let’s Encrypt и быстро проверять интеграции.
|
||||
|
||||
## Лимиты Let’s Encrypt
|
||||
|
||||
- production: обычно 5 сертификатов/неделю на домен
|
||||
- при частых ошибках можно быстро исчерпать лимит
|
||||
|
||||
## Варианты тестирования
|
||||
|
||||
### 1) Самоподписанный сертификат (рекомендуется для разработки)
|
||||
|
||||
- `letsencrypt-regru --test-cert`
|
||||
|
||||
Плюсы:
|
||||
|
||||
- мгновенно (1–2 секунды)
|
||||
- без интернета
|
||||
- без DNS
|
||||
- структура файлов совпадает с Let’s Encrypt (`cert.pem`, `fullchain.pem`, …)
|
||||
|
||||
Минусы:
|
||||
|
||||
- браузер не доверяет сертификату
|
||||
|
||||
### 2) Let’s Encrypt staging
|
||||
|
||||
- `letsencrypt-regru --staging`
|
||||
|
||||
Плюсы:
|
||||
|
||||
- полностью реальный процесс ACME
|
||||
- нет лимитов
|
||||
- проверяет DNS хуки и certbot
|
||||
|
||||
Минусы:
|
||||
|
||||
- staging сертификаты не доверяются браузером
|
||||
|
||||
### 3) Диагностика API и DNS
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
Рекомендуется прогонять перед production получением.
|
||||
|
||||
## Переход тест → production
|
||||
|
||||
1) убедиться что всё работает на `--staging` или `--test-cert`
|
||||
2) затем выполнить `--obtain`
|
||||
|
||||
Если ранее создавался тестовый сертификат и вы хотите «чисто» перейти на production, иногда удобно удалить старую папку сертификата для домена в `cert_dir/<domain>/` (аккуратно).
|
||||
# Тестирование
|
||||
|
||||
Главная цель тестовых режимов — не упереться в лимиты Let’s Encrypt и быстро проверять интеграции.
|
||||
|
||||
## Лимиты Let’s Encrypt
|
||||
|
||||
- production: обычно 5 сертификатов/неделю на домен
|
||||
- при частых ошибках можно быстро исчерпать лимит
|
||||
|
||||
## Варианты тестирования
|
||||
|
||||
### 1) Самоподписанный сертификат (рекомендуется для разработки)
|
||||
|
||||
- `letsencrypt-regru --test-cert`
|
||||
|
||||
Плюсы:
|
||||
|
||||
- мгновенно (1–2 секунды)
|
||||
- без интернета
|
||||
- без DNS
|
||||
- структура файлов совпадает с Let’s Encrypt (`cert.pem`, `fullchain.pem`, …)
|
||||
|
||||
Минусы:
|
||||
|
||||
- браузер не доверяет сертификату
|
||||
|
||||
### 2) Let’s Encrypt staging
|
||||
|
||||
- `letsencrypt-regru --staging`
|
||||
|
||||
Плюсы:
|
||||
|
||||
- полностью реальный процесс ACME
|
||||
- нет лимитов
|
||||
- проверяет DNS хуки и certbot
|
||||
|
||||
Минусы:
|
||||
|
||||
- staging сертификаты не доверяются браузером
|
||||
|
||||
### 3) Диагностика API и DNS
|
||||
|
||||
- `letsencrypt-regru --test-api -v`
|
||||
- `letsencrypt-regru --test-dns -v`
|
||||
|
||||
Рекомендуется прогонять перед production получением.
|
||||
|
||||
## Переход тест → production
|
||||
|
||||
1) убедиться что всё работает на `--staging` или `--test-cert`
|
||||
2) затем выполнить `--obtain`
|
||||
|
||||
Если ранее создавался тестовый сертификат и вы хотите «чисто» перейти на production, иногда удобно удалить старую папку сертификата для домена в `cert_dir/<domain>/` (аккуратно).
|
||||
|
||||
|
||||
---
|
||||
@@ -58,386 +58,386 @@
|
||||
## Appendix (migrated from docs/TESTING_GUIDE.md)
|
||||
<!-- MIGRATED_FROM_DOCS:TESTING_GUIDE.md -->
|
||||
|
||||
## 🧪 Руководство по тестированию SSL сертификатов
|
||||
|
||||
### Зачем нужны тестовые сертификаты?
|
||||
|
||||
Let's Encrypt имеет **строгие ограничения**:
|
||||
- ⚠️ Максимум **5 сертификатов в неделю** на один домен
|
||||
- ⚠️ Максимум **50 сертификатов в неделю** на аккаунт
|
||||
- ⚠️ **Бан на 1 неделю** при превышении лимита
|
||||
|
||||
**Решение**: Используйте самоподписанные тестовые сертификаты для разработки!
|
||||
|
||||
---
|
||||
|
||||
### Быстрый старт
|
||||
|
||||
#### Вариант 1: Через Makefile (рекомендуется)
|
||||
|
||||
```bash
|
||||
## После установки скрипта (make install)
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
**Результат**: Создан сертификат в `/etc/letsencrypt/live/your-domain/`
|
||||
|
||||
#### Вариант 2: Через Python скрипт
|
||||
|
||||
```bash
|
||||
sudo python3 letsencrypt_regru_api.py \
|
||||
--config /etc/letsencrypt/regru_config.json \
|
||||
--test-cert -v
|
||||
```
|
||||
|
||||
#### Вариант 3: Через Bash скрипт (автономный)
|
||||
|
||||
```bash
|
||||
## Простой домен
|
||||
sudo ./test_certificate.sh example.com no
|
||||
|
||||
## С wildcard
|
||||
sudo ./test_certificate.sh example.com yes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Сравнение методов
|
||||
|
||||
| Метод | Скорость | Требования | NPM интеграция | Лимиты |
|
||||
|-------|----------|------------|----------------|--------|
|
||||
| **Let's Encrypt** | 2-5 минут | Internet, DNS | ✅ Да | ⚠️ 5/неделю |
|
||||
| **Тестовый (Python)** | 1-2 секунды | Только Python | ✅ Да | ✅ Нет |
|
||||
| **Тестовый (Bash)** | 1-2 секунды | Только OpenSSL | ❌ Ручная | ✅ Нет |
|
||||
|
||||
---
|
||||
|
||||
### Детальная инструкция
|
||||
|
||||
#### 1. Подготовка конфигурации
|
||||
|
||||
```bash
|
||||
## Создать конфигурацию
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "test.example.com",
|
||||
"wildcard": true,
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"npm_enabled": true,
|
||||
"npm_host": "https://npm.example.com",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "your_password"
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Создание тестового сертификата
|
||||
|
||||
```bash
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
#### 3. Проверка созданных файлов
|
||||
|
||||
```bash
|
||||
ls -la /etc/letsencrypt/live/test.example.com/
|
||||
## Должны быть:
|
||||
## - privkey.pem (приватный ключ)
|
||||
## - cert.pem (сертификат)
|
||||
## - fullchain.pem (полная цепочка)
|
||||
## - chain.pem (CA цепочка)
|
||||
```
|
||||
|
||||
#### 4. Просмотр информации о сертификате
|
||||
|
||||
```bash
|
||||
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -text -noout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Использование в Nginx
|
||||
|
||||
#### Прямое использование
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name test.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem;
|
||||
|
||||
# ... остальная конфигурация
|
||||
}
|
||||
```
|
||||
|
||||
#### Через Nginx Proxy Manager
|
||||
|
||||
Если `npm_enabled: true` в конфигурации, сертификат автоматически загрузится в NPM.
|
||||
|
||||
**Проверка в NPM:**
|
||||
1. Откройте веб-интерфейс NPM
|
||||
2. Перейдите в **SSL Certificates**
|
||||
3. Найдите ваш домен в списке
|
||||
4. ⚠️ Будет помечен как "Custom" (не Let's Encrypt)
|
||||
|
||||
---
|
||||
|
||||
### Автоматизация тестирования
|
||||
|
||||
#### Скрипт для CI/CD
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
## test_ssl_integration.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧪 Тестирование SSL интеграции..."
|
||||
|
||||
## 1. Создать тестовый сертификат
|
||||
sudo python3 letsencrypt_regru_api.py \
|
||||
--config test_config.json \
|
||||
--test-cert
|
||||
|
||||
## 2. Проверить файлы
|
||||
if [ ! -f "/etc/letsencrypt/live/test.example.com/fullchain.pem" ]; then
|
||||
echo "❌ Сертификат не создан"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## 3. Проверить валидность
|
||||
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -noout -checkend 0
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Сертификат валиден"
|
||||
else
|
||||
echo "❌ Сертификат невалиден"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## 4. Проверить загрузку в NPM (опционально)
|
||||
## ... ваша проверка через API NPM
|
||||
|
||||
echo "✅ Все тесты пройдены"
|
||||
```
|
||||
|
||||
#### Makefile для тестирования
|
||||
|
||||
```makefile
|
||||
.PHONY: test-ssl test-npm test-all
|
||||
|
||||
test-ssl:
|
||||
@echo "Создание тестового сертификата..."
|
||||
sudo make test-cert
|
||||
@echo "Проверка файлов..."
|
||||
test -f /etc/letsencrypt/live/$(DOMAIN)/fullchain.pem
|
||||
@echo "✅ SSL тест пройден"
|
||||
|
||||
test-npm:
|
||||
@echo "Проверка интеграции с NPM..."
|
||||
# Ваши проверки API NPM
|
||||
@echo "✅ NPM тест пройден"
|
||||
|
||||
test-all: test-ssl test-npm
|
||||
@echo "✅ Все тесты пройдены"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Переход на production
|
||||
|
||||
#### Шаг 1: Тестирование
|
||||
|
||||
```bash
|
||||
## 1. Создать тестовый сертификат
|
||||
sudo make test-cert
|
||||
|
||||
## 2. Проверить работу с NPM
|
||||
## Открыть https://your-domain и проверить
|
||||
|
||||
## 3. Убедиться что все работает
|
||||
```
|
||||
|
||||
#### Шаг 2: Переключение на Let's Encrypt
|
||||
|
||||
```bash
|
||||
## 1. Удалить тестовый сертификат
|
||||
sudo rm -rf /etc/letsencrypt/live/your-domain/
|
||||
|
||||
## 2. Получить настоящий сертификат
|
||||
sudo make obtain
|
||||
|
||||
## 3. Проверить обновление в NPM
|
||||
sudo make status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Частые вопросы
|
||||
|
||||
#### Q: Почему браузер показывает предупреждение?
|
||||
|
||||
**A:** Самоподписанные сертификаты не доверяются браузерами. Это нормально для тестирования.
|
||||
|
||||
Чтобы избежать предупреждения в браузере (только для локального тестирования):
|
||||
1. Chrome: `chrome://flags/#allow-insecure-localhost`
|
||||
2. Firefox: Нажмите "Advanced" → "Accept the Risk"
|
||||
|
||||
#### Q: Можно ли использовать для production?
|
||||
|
||||
**A:** ❌ **НЕТ!** Тестовые сертификаты только для разработки и тестирования.
|
||||
|
||||
#### Q: Как часто можно создавать тестовые сертификаты?
|
||||
|
||||
**A:** ✅ Неограниченно! Нет никаких лимитов.
|
||||
|
||||
#### Q: Загружаются ли в NPM автоматически?
|
||||
|
||||
**A:** ✅ Да, если `npm_enabled: true` в конфигурации.
|
||||
|
||||
#### Q: Работают ли с wildcard доменами?
|
||||
|
||||
**A:** ✅ Да! Просто установите `"wildcard": true` в конфигурации.
|
||||
|
||||
#### Q: Как проверить срок действия?
|
||||
|
||||
```bash
|
||||
openssl x509 -in /etc/letsencrypt/live/your-domain/cert.pem -noout -dates
|
||||
```
|
||||
|
||||
#### Q: Как изменить срок действия?
|
||||
|
||||
Отредактируйте `validity_days` в функции `generate_self_signed_certificate()`:
|
||||
|
||||
```python
|
||||
validity_days: int = 365 # Изменить на нужное количество дней
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Устранение проблем
|
||||
|
||||
#### Ошибка: Permission denied
|
||||
|
||||
```bash
|
||||
## Запускайте с sudo
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
#### Ошибка: Module 'cryptography' not found
|
||||
|
||||
```bash
|
||||
## Установите зависимости
|
||||
sudo pip3 install cryptography
|
||||
```
|
||||
|
||||
#### NPM не показывает сертификат
|
||||
|
||||
1. Проверьте настройки NPM в конфигурации
|
||||
2. Проверьте логи: `sudo make logs`
|
||||
3. Попробуйте загрузить вручную через веб-интерфейс NPM
|
||||
|
||||
#### Сертификат не создается
|
||||
|
||||
```bash
|
||||
## Проверьте права
|
||||
ls -la /etc/letsencrypt/live/
|
||||
|
||||
## Создайте директорию вручную
|
||||
sudo mkdir -p /etc/letsencrypt/live/
|
||||
|
||||
## Проверьте конфигурацию
|
||||
sudo make check-config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Примеры использования
|
||||
|
||||
#### Разработка с Docker
|
||||
|
||||
```dockerfile
|
||||
FROM nginx:alpine
|
||||
|
||||
## Копировать тестовый сертификат
|
||||
COPY test-certs/ /etc/nginx/ssl/
|
||||
|
||||
## Конфигурация nginx
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
EXPOSE 443
|
||||
```
|
||||
|
||||
#### Локальное тестирование
|
||||
|
||||
```bash
|
||||
## Создать сертификат для localhost
|
||||
sudo python3 letsencrypt_regru_api.py --test-cert
|
||||
|
||||
## Добавить в /etc/hosts
|
||||
echo "127.0.0.1 test.example.com" | sudo tee -a /etc/hosts
|
||||
|
||||
## Запустить nginx
|
||||
sudo nginx -t && sudo nginx -s reload
|
||||
|
||||
## Открыть в браузере
|
||||
open https://test.example.com
|
||||
```
|
||||
|
||||
#### Автоматическое тестирование перед deployment
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
## pre-deploy.sh
|
||||
|
||||
## Тестовая проверка SSL
|
||||
sudo make test-cert
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Тестовый сертификат создан успешно"
|
||||
echo "✅ Готово к созданию production сертификата"
|
||||
sudo make obtain
|
||||
else
|
||||
echo "❌ Ошибка при создании тестового сертификата"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Дополнительные ресурсы
|
||||
|
||||
- 📘 [Let's Encrypt Rate Limits](https://letsencrypt.org/docs/rate-limits/)
|
||||
- 📘 [OpenSSL Documentation](https://www.openssl.org/docs/)
|
||||
- 📘 [Nginx Proxy Manager Docs](https://nginxproxymanager.com/guide/)
|
||||
|
||||
---
|
||||
|
||||
### Итоговая шпаргалка
|
||||
|
||||
```bash
|
||||
## Установка
|
||||
sudo make install
|
||||
|
||||
## Конфигурация
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Создать тестовый сертификат
|
||||
sudo make test-cert
|
||||
|
||||
## Проверить
|
||||
sudo make check-config
|
||||
sudo make status
|
||||
|
||||
## Переход на production
|
||||
sudo rm -rf /etc/letsencrypt/live/your-domain/
|
||||
sudo make obtain
|
||||
|
||||
## Автоматическое обновление
|
||||
sudo make run
|
||||
```
|
||||
|
||||
**Готово!** 🎉 Теперь вы можете тестировать SSL сертификаты без ограничений!
|
||||
|
||||
## 🧪 Руководство по тестированию SSL сертификатов
|
||||
|
||||
### Зачем нужны тестовые сертификаты?
|
||||
|
||||
Let's Encrypt имеет **строгие ограничения**:
|
||||
- ⚠️ Максимум **5 сертификатов в неделю** на один домен
|
||||
- ⚠️ Максимум **50 сертификатов в неделю** на аккаунт
|
||||
- ⚠️ **Бан на 1 неделю** при превышении лимита
|
||||
|
||||
**Решение**: Используйте самоподписанные тестовые сертификаты для разработки!
|
||||
|
||||
---
|
||||
|
||||
### Быстрый старт
|
||||
|
||||
#### Вариант 1: Через Makefile (рекомендуется)
|
||||
|
||||
```bash
|
||||
## После установки скрипта (make install)
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
**Результат**: Создан сертификат в `/etc/letsencrypt/live/your-domain/`
|
||||
|
||||
#### Вариант 2: Через Python скрипт
|
||||
|
||||
```bash
|
||||
sudo python3 letsencrypt_regru_api.py \
|
||||
--config /etc/letsencrypt/regru_config.json \
|
||||
--test-cert -v
|
||||
```
|
||||
|
||||
#### Вариант 3: Через Bash скрипт (автономный)
|
||||
|
||||
```bash
|
||||
## Простой домен
|
||||
sudo ./test_certificate.sh example.com no
|
||||
|
||||
## С wildcard
|
||||
sudo ./test_certificate.sh example.com yes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Сравнение методов
|
||||
|
||||
| Метод | Скорость | Требования | NPM интеграция | Лимиты |
|
||||
|-------|----------|------------|----------------|--------|
|
||||
| **Let's Encrypt** | 2-5 минут | Internet, DNS | ✅ Да | ⚠️ 5/неделю |
|
||||
| **Тестовый (Python)** | 1-2 секунды | Только Python | ✅ Да | ✅ Нет |
|
||||
| **Тестовый (Bash)** | 1-2 секунды | Только OpenSSL | ❌ Ручная | ✅ Нет |
|
||||
|
||||
---
|
||||
|
||||
### Детальная инструкция
|
||||
|
||||
#### 1. Подготовка конфигурации
|
||||
|
||||
```bash
|
||||
## Создать конфигурацию
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "test.example.com",
|
||||
"wildcard": true,
|
||||
"cert_dir": "/etc/letsencrypt/live",
|
||||
"npm_enabled": true,
|
||||
"npm_host": "https://npm.example.com",
|
||||
"npm_email": "admin@example.com",
|
||||
"npm_password": "your_password"
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Создание тестового сертификата
|
||||
|
||||
```bash
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
#### 3. Проверка созданных файлов
|
||||
|
||||
```bash
|
||||
ls -la /etc/letsencrypt/live/test.example.com/
|
||||
## Должны быть:
|
||||
## - privkey.pem (приватный ключ)
|
||||
## - cert.pem (сертификат)
|
||||
## - fullchain.pem (полная цепочка)
|
||||
## - chain.pem (CA цепочка)
|
||||
```
|
||||
|
||||
#### 4. Просмотр информации о сертификате
|
||||
|
||||
```bash
|
||||
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -text -noout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Использование в Nginx
|
||||
|
||||
#### Прямое использование
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name test.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem;
|
||||
|
||||
# ... остальная конфигурация
|
||||
}
|
||||
```
|
||||
|
||||
#### Через Nginx Proxy Manager
|
||||
|
||||
Если `npm_enabled: true` в конфигурации, сертификат автоматически загрузится в NPM.
|
||||
|
||||
**Проверка в NPM:**
|
||||
1. Откройте веб-интерфейс NPM
|
||||
2. Перейдите в **SSL Certificates**
|
||||
3. Найдите ваш домен в списке
|
||||
4. ⚠️ Будет помечен как "Custom" (не Let's Encrypt)
|
||||
|
||||
---
|
||||
|
||||
### Автоматизация тестирования
|
||||
|
||||
#### Скрипт для CI/CD
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
## test_ssl_integration.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧪 Тестирование SSL интеграции..."
|
||||
|
||||
## 1. Создать тестовый сертификат
|
||||
sudo python3 letsencrypt_regru_api.py \
|
||||
--config test_config.json \
|
||||
--test-cert
|
||||
|
||||
## 2. Проверить файлы
|
||||
if [ ! -f "/etc/letsencrypt/live/test.example.com/fullchain.pem" ]; then
|
||||
echo "❌ Сертификат не создан"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## 3. Проверить валидность
|
||||
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -noout -checkend 0
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Сертификат валиден"
|
||||
else
|
||||
echo "❌ Сертификат невалиден"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## 4. Проверить загрузку в NPM (опционально)
|
||||
## ... ваша проверка через API NPM
|
||||
|
||||
echo "✅ Все тесты пройдены"
|
||||
```
|
||||
|
||||
#### Makefile для тестирования
|
||||
|
||||
```makefile
|
||||
.PHONY: test-ssl test-npm test-all
|
||||
|
||||
test-ssl:
|
||||
@echo "Создание тестового сертификата..."
|
||||
sudo make test-cert
|
||||
@echo "Проверка файлов..."
|
||||
test -f /etc/letsencrypt/live/$(DOMAIN)/fullchain.pem
|
||||
@echo "✅ SSL тест пройден"
|
||||
|
||||
test-npm:
|
||||
@echo "Проверка интеграции с NPM..."
|
||||
# Ваши проверки API NPM
|
||||
@echo "✅ NPM тест пройден"
|
||||
|
||||
test-all: test-ssl test-npm
|
||||
@echo "✅ Все тесты пройдены"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Переход на production
|
||||
|
||||
#### Шаг 1: Тестирование
|
||||
|
||||
```bash
|
||||
## 1. Создать тестовый сертификат
|
||||
sudo make test-cert
|
||||
|
||||
## 2. Проверить работу с NPM
|
||||
## Открыть https://your-domain и проверить
|
||||
|
||||
## 3. Убедиться что все работает
|
||||
```
|
||||
|
||||
#### Шаг 2: Переключение на Let's Encrypt
|
||||
|
||||
```bash
|
||||
## 1. Удалить тестовый сертификат
|
||||
sudo rm -rf /etc/letsencrypt/live/your-domain/
|
||||
|
||||
## 2. Получить настоящий сертификат
|
||||
sudo make obtain
|
||||
|
||||
## 3. Проверить обновление в NPM
|
||||
sudo make status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Частые вопросы
|
||||
|
||||
#### Q: Почему браузер показывает предупреждение?
|
||||
|
||||
**A:** Самоподписанные сертификаты не доверяются браузерами. Это нормально для тестирования.
|
||||
|
||||
Чтобы избежать предупреждения в браузере (только для локального тестирования):
|
||||
1. Chrome: `chrome://flags/#allow-insecure-localhost`
|
||||
2. Firefox: Нажмите "Advanced" → "Accept the Risk"
|
||||
|
||||
#### Q: Можно ли использовать для production?
|
||||
|
||||
**A:** ❌ **НЕТ!** Тестовые сертификаты только для разработки и тестирования.
|
||||
|
||||
#### Q: Как часто можно создавать тестовые сертификаты?
|
||||
|
||||
**A:** ✅ Неограниченно! Нет никаких лимитов.
|
||||
|
||||
#### Q: Загружаются ли в NPM автоматически?
|
||||
|
||||
**A:** ✅ Да, если `npm_enabled: true` в конфигурации.
|
||||
|
||||
#### Q: Работают ли с wildcard доменами?
|
||||
|
||||
**A:** ✅ Да! Просто установите `"wildcard": true` в конфигурации.
|
||||
|
||||
#### Q: Как проверить срок действия?
|
||||
|
||||
```bash
|
||||
openssl x509 -in /etc/letsencrypt/live/your-domain/cert.pem -noout -dates
|
||||
```
|
||||
|
||||
#### Q: Как изменить срок действия?
|
||||
|
||||
Отредактируйте `validity_days` в функции `generate_self_signed_certificate()`:
|
||||
|
||||
```python
|
||||
validity_days: int = 365 # Изменить на нужное количество дней
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Устранение проблем
|
||||
|
||||
#### Ошибка: Permission denied
|
||||
|
||||
```bash
|
||||
## Запускайте с sudo
|
||||
sudo make test-cert
|
||||
```
|
||||
|
||||
#### Ошибка: Module 'cryptography' not found
|
||||
|
||||
```bash
|
||||
## Установите зависимости
|
||||
sudo pip3 install cryptography
|
||||
```
|
||||
|
||||
#### NPM не показывает сертификат
|
||||
|
||||
1. Проверьте настройки NPM в конфигурации
|
||||
2. Проверьте логи: `sudo make logs`
|
||||
3. Попробуйте загрузить вручную через веб-интерфейс NPM
|
||||
|
||||
#### Сертификат не создается
|
||||
|
||||
```bash
|
||||
## Проверьте права
|
||||
ls -la /etc/letsencrypt/live/
|
||||
|
||||
## Создайте директорию вручную
|
||||
sudo mkdir -p /etc/letsencrypt/live/
|
||||
|
||||
## Проверьте конфигурацию
|
||||
sudo make check-config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Примеры использования
|
||||
|
||||
#### Разработка с Docker
|
||||
|
||||
```dockerfile
|
||||
FROM nginx:alpine
|
||||
|
||||
## Копировать тестовый сертификат
|
||||
COPY test-certs/ /etc/nginx/ssl/
|
||||
|
||||
## Конфигурация nginx
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
EXPOSE 443
|
||||
```
|
||||
|
||||
#### Локальное тестирование
|
||||
|
||||
```bash
|
||||
## Создать сертификат для localhost
|
||||
sudo python3 letsencrypt_regru_api.py --test-cert
|
||||
|
||||
## Добавить в /etc/hosts
|
||||
echo "127.0.0.1 test.example.com" | sudo tee -a /etc/hosts
|
||||
|
||||
## Запустить nginx
|
||||
sudo nginx -t && sudo nginx -s reload
|
||||
|
||||
## Открыть в браузере
|
||||
open https://test.example.com
|
||||
```
|
||||
|
||||
#### Автоматическое тестирование перед deployment
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
## pre-deploy.sh
|
||||
|
||||
## Тестовая проверка SSL
|
||||
sudo make test-cert
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Тестовый сертификат создан успешно"
|
||||
echo "✅ Готово к созданию production сертификата"
|
||||
sudo make obtain
|
||||
else
|
||||
echo "❌ Ошибка при создании тестового сертификата"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Дополнительные ресурсы
|
||||
|
||||
- 📘 [Let's Encrypt Rate Limits](https://letsencrypt.org/docs/rate-limits/)
|
||||
- 📘 [OpenSSL Documentation](https://www.openssl.org/docs/)
|
||||
- 📘 [Nginx Proxy Manager Docs](https://nginxproxymanager.com/guide/)
|
||||
|
||||
---
|
||||
|
||||
### Итоговая шпаргалка
|
||||
|
||||
```bash
|
||||
## Установка
|
||||
sudo make install
|
||||
|
||||
## Конфигурация
|
||||
sudo nano /etc/letsencrypt/regru_config.json
|
||||
|
||||
## Создать тестовый сертификат
|
||||
sudo make test-cert
|
||||
|
||||
## Проверить
|
||||
sudo make check-config
|
||||
sudo make status
|
||||
|
||||
## Переход на production
|
||||
sudo rm -rf /etc/letsencrypt/live/your-domain/
|
||||
sudo make obtain
|
||||
|
||||
## Автоматическое обновление
|
||||
sudo make run
|
||||
```
|
||||
|
||||
**Готово!** 🎉 Теперь вы можете тестировать SSL сертификаты без ограничений!
|
||||
|
||||
|
||||
+15
-15
@@ -1,15 +1,15 @@
|
||||
# Навигация
|
||||
|
||||
- [Home](Home.md)
|
||||
- [Установка](Installation.md)
|
||||
- [Конфигурация](Configuration.md)
|
||||
- [Команды](Commands.md)
|
||||
- [Алгоритм получения/продления](LetsEncrypt_Workflow.md)
|
||||
- [Интеграция с NPM](Nginx_Proxy_Manager.md)
|
||||
- [Тестирование](Testing.md)
|
||||
- [Проблемы API reg.ru](RegRu_API_Troubleshooting.md)
|
||||
- [Сборка и релизы](Build_and_Release.md)
|
||||
- [Deploy и Secrets](Deploy_Actions_Secrets.md)
|
||||
- [Структура проекта](Project_Structure.md)
|
||||
- [Синхронизация Gitea → GitHub](Gitea_Sync.md)
|
||||
- [Changelog](Changelog.md)
|
||||
# Навигация
|
||||
|
||||
- [Home](Home.md)
|
||||
- [Установка](Installation.md)
|
||||
- [Конфигурация](Configuration.md)
|
||||
- [Команды](Commands.md)
|
||||
- [Алгоритм получения/продления](LetsEncrypt_Workflow.md)
|
||||
- [Интеграция с NPM](Nginx_Proxy_Manager.md)
|
||||
- [Тестирование](Testing.md)
|
||||
- [Проблемы API reg.ru](RegRu_API_Troubleshooting.md)
|
||||
- [Сборка и релизы](Build_and_Release.md)
|
||||
- [Deploy и Secrets](Deploy_Actions_Secrets.md)
|
||||
- [Структура проекта](Project_Structure.md)
|
||||
- [Синхронизация Gitea → GitHub](Gitea_Sync.md)
|
||||
- [Changelog](Changelog.md)
|
||||
|
||||
Reference in New Issue
Block a user