mirror of
https://github.com/chatmail/relay.git
synced 2026-05-20 04:48:06 +00:00
fix: resolve issue on deployment
This commit is contained in:
@@ -63,7 +63,7 @@ class AcmetoolDeployer(Deployer):
|
|||||||
|
|
||||||
server.shell(
|
server.shell(
|
||||||
name=f"Remove old acmetool desired files for {self.domains[0]}",
|
name=f"Remove old acmetool desired files for {self.domains[0]}",
|
||||||
commands=[f"rm -f /var/lib/acme/desired/{self.domains[0]}-*"],
|
commands=[f"rm -f /var/lib/acme/desired/'{self.domains[0]}'-*"],
|
||||||
)
|
)
|
||||||
files.template(
|
files.template(
|
||||||
src=importlib.resources.files(__package__).joinpath("desired.yaml.j2"),
|
src=importlib.resources.files(__package__).joinpath("desired.yaml.j2"),
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
|
|||||||
key=key,
|
key=key,
|
||||||
value=65535,
|
value=65535,
|
||||||
persist=True,
|
persist=True,
|
||||||
|
_ignore_errors=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
timezone_env = files.line(
|
timezone_env = files.line(
|
||||||
|
|||||||
42
doc/tool/lxc_test_en.md
Normal file
42
doc/tool/lxc_test_en.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Testing with LXC
|
||||||
|
|
||||||
|
To test the relay setup in a local LXC container (tested on Arch Linux host):
|
||||||
|
|
||||||
|
### 1. Host Preparation
|
||||||
|
Install the necessary packages:
|
||||||
|
```bash
|
||||||
|
sudo pacman -S lxc arch-install-scripts dnsmasq
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Network Configuration
|
||||||
|
If your host system has IPv6 disabled, you must disable it for LXC as well to avoid service failures:
|
||||||
|
Edit `/etc/default/lxc-net` and ensure these lines exist:
|
||||||
|
```bash
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
LXC_IPV6_ENABLE="false"
|
||||||
|
LXC_IPV6_NAT="false"
|
||||||
|
```
|
||||||
|
*Note: If port 53 is occupied (e.g., by dnscrypt-proxy), you may need to configure your DNS service to listen only on `127.0.0.1` so LXC's dnsmasq can bind to the bridge.*
|
||||||
|
|
||||||
|
Restart the network:
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable --now lxc-net.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Create and Prepare Container
|
||||||
|
Create a Debian 12 (bookworm) container:
|
||||||
|
```bash
|
||||||
|
sudo lxc-create -n test -t download -- -d debian -r bookworm -a amd64
|
||||||
|
sudo lxc-start -n test
|
||||||
|
```
|
||||||
|
|
||||||
|
Sync your local repository to the container:
|
||||||
|
```bash
|
||||||
|
sudo rsync -av --exclude=.git ./ /var/lib/lxc/test/rootfs/relay-ir/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Run Deployment
|
||||||
|
Attach to the container and run the deployment locally:
|
||||||
|
```bash
|
||||||
|
sudo lxc-attach -n test -- bash -c "cd /relay-ir && ./scripts/initenv.sh && ./scripts/cmdeploy run --ssh-host @local --skip-dns-check"
|
||||||
|
```
|
||||||
42
doc/tool/lxc_test_fa.md
Normal file
42
doc/tool/lxc_test_fa.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# تست با LXC
|
||||||
|
|
||||||
|
برای تست تنظیمات رله در یک کانتینر محلی LXC (تست شده روی میزبان آرچ لینوکس):
|
||||||
|
|
||||||
|
### ۱. آمادهسازی میزبان
|
||||||
|
بستههای مورد نیاز را نصب کنید:
|
||||||
|
```bash
|
||||||
|
sudo pacman -S lxc arch-install-scripts dnsmasq
|
||||||
|
```
|
||||||
|
|
||||||
|
### ۲. پیکربندی شبکه
|
||||||
|
اگر IPv6 در سیستم میزبان شما غیرفعال است، باید آن را برای LXC نیز غیرفعال کنید تا از بروز خطا جلوگیری شود:
|
||||||
|
فایل `/etc/default/lxc-net` را ویرایش کرده و مطمین شوید این خطوط وجود دارند:
|
||||||
|
```bash
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
LXC_IPV6_ENABLE="false"
|
||||||
|
LXC_IPV6_NAT="false"
|
||||||
|
```
|
||||||
|
*نکته: اگر پورت ۵۳ اشغال است (مثلاً توسط dnscrypt-proxy)، ممکن است لازم باشد سرویس DNS خود را طوری تنظیم کنید که فقط روی `127.0.0.1` گوش دهد تا dnsmasq مربوط به LXC بتواند به بریج متصل شود.*
|
||||||
|
|
||||||
|
شبکه را راهاندازی کنید:
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable --now lxc-net.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### ۳. ساخت و آمادهسازی کانتینر
|
||||||
|
یک کانتینر دبیان ۱۲ (bookworm) بسازید:
|
||||||
|
```bash
|
||||||
|
sudo lxc-create -n test -t download -- -d debian -r bookworm -a amd64
|
||||||
|
sudo lxc-start -n test
|
||||||
|
```
|
||||||
|
|
||||||
|
کد محلی خود را به کانتینر منتقل کنید:
|
||||||
|
```bash
|
||||||
|
sudo rsync -av --exclude=.git ./ /var/lib/lxc/test/rootfs/relay-ir/
|
||||||
|
```
|
||||||
|
|
||||||
|
### ۴. اجرای استقرار (Deployment)
|
||||||
|
به کانتینر متصل شده و استقرار را به صورت محلی اجرا کنید:
|
||||||
|
```bash
|
||||||
|
sudo lxc-attach -n test -- bash -c "cd /relay-ir && ./scripts/initenv.sh && ./scripts/cmdeploy run --ssh-host @local --skip-dns-check"
|
||||||
|
```
|
||||||
8
init.sh
8
init.sh
@@ -38,8 +38,12 @@ echo "--- Initializing environment ---"
|
|||||||
./scripts/initenv.sh
|
./scripts/initenv.sh
|
||||||
|
|
||||||
# 4. Ask for domain and email
|
# 4. Ask for domain and email
|
||||||
read -p "Enter your mail domain (e.g. example.com): " MAIL_DOMAIN
|
if [ -z "$MAIL_DOMAIN" ]; then
|
||||||
read -p "Enter your email for ACME/Let's Encrypt: " ACME_EMAIL
|
read -p "Enter your mail domain (e.g. example.com): " MAIL_DOMAIN < /dev/tty
|
||||||
|
fi
|
||||||
|
if [ -z "$ACME_EMAIL" ]; then
|
||||||
|
read -p "Enter your email for ACME/Let's Encrypt: " ACME_EMAIL < /dev/tty
|
||||||
|
fi
|
||||||
|
|
||||||
# 5. Initialize configuration
|
# 5. Initialize configuration
|
||||||
echo "--- Initializing chatmail configuration ---"
|
echo "--- Initializing chatmail configuration ---"
|
||||||
|
|||||||
97
test/lxc_runner.py
Normal file
97
test/lxc_runner.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
# This script automates LXC container creation and relay deployment testing.
|
||||||
|
# It cleans up old containers, creates a new one, and runs the deployment.
|
||||||
|
|
||||||
|
CONTAINER_PREFIX = "testrelay"
|
||||||
|
CONTAINER_NAME = f"{CONTAINER_PREFIX}-auto"
|
||||||
|
RELAY_SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
def run_cmd(cmd, check=True, shell=True):
|
||||||
|
print(f"Executing: {cmd}")
|
||||||
|
try:
|
||||||
|
result = subprocess.run(cmd, shell=shell, check=check, capture_output=True, text=True)
|
||||||
|
return result.stdout.strip()
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error executing command: {e}")
|
||||||
|
print(f"Stdout: {e.stdout}")
|
||||||
|
print(f"Stderr: {e.stderr}")
|
||||||
|
if check:
|
||||||
|
sys.exit(1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def cleanup():
|
||||||
|
print("--- Cleaning up old containers ---")
|
||||||
|
containers = run_cmd("sudo lxc-ls -1").splitlines()
|
||||||
|
for c in containers:
|
||||||
|
if c.startswith(CONTAINER_PREFIX):
|
||||||
|
print(f"Destroying container: {c}")
|
||||||
|
run_cmd(f"sudo lxc-destroy -n {c} -f", check=False)
|
||||||
|
|
||||||
|
def create_container():
|
||||||
|
print(f"--- Creating container: {CONTAINER_NAME} ---")
|
||||||
|
run_cmd(f"sudo lxc-create -n {CONTAINER_NAME} -t download -- -d debian -r bookworm -a amd64")
|
||||||
|
|
||||||
|
def run_in_container(name, command):
|
||||||
|
return run_cmd(f'sudo lxc-attach -n {name} -- bash -c "{command}"')
|
||||||
|
|
||||||
|
def prepare_container():
|
||||||
|
print("--- Preparing container ---")
|
||||||
|
run_cmd(f"sudo lxc-start -n {CONTAINER_NAME}")
|
||||||
|
|
||||||
|
# Wait for IP
|
||||||
|
print("Waiting for container IP...")
|
||||||
|
for _ in range(30):
|
||||||
|
ip = run_cmd(f"sudo lxc-info -n {CONTAINER_NAME} -i").split()
|
||||||
|
if ip and len(ip) > 1:
|
||||||
|
print(f"Container IP: {ip[1]}")
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
print("Failed to get container IP.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Disable systemd-resolved to free port 53
|
||||||
|
run_in_container(CONTAINER_NAME, "systemctl disable --now systemd-resolved || true")
|
||||||
|
run_in_container(CONTAINER_NAME, "echo 'nameserver 8.8.8.8' > /etc/resolv.conf")
|
||||||
|
|
||||||
|
# Sync code
|
||||||
|
print("Syncing code to container...")
|
||||||
|
target_path = f"/var/lib/lxc/{CONTAINER_NAME}/rootfs/relay-ir"
|
||||||
|
run_cmd(f"sudo mkdir -p {target_path}")
|
||||||
|
run_cmd(f"sudo rsync -av --exclude=.git --exclude='*.log' --exclude='test' {RELAY_SRC}/ {target_path}/")
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
print("Installing dependencies inside container...")
|
||||||
|
run_in_container(CONTAINER_NAME, "apt-get update && apt-get install -y curl sudo python3-dev gcc")
|
||||||
|
run_in_container(CONTAINER_NAME, "apt-get remove --purge -y exim4*")
|
||||||
|
run_in_container(CONTAINER_NAME, "curl -LsSf https://astral.sh/uv/install.sh | sh")
|
||||||
|
|
||||||
|
def perform_deployment():
|
||||||
|
print("--- Running deployment test ---")
|
||||||
|
# Using the PATH where uv is installed
|
||||||
|
path_env = "export PATH='/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'"
|
||||||
|
deploy_cmd = f"cd /relay-ir && {path_env} && ./scripts/initenv.sh && ./scripts/cmdeploy run --ssh-host @local --skip-dns-check"
|
||||||
|
|
||||||
|
try:
|
||||||
|
output = run_in_container(CONTAINER_NAME, deploy_cmd)
|
||||||
|
print("Deployment Output Summary:")
|
||||||
|
print(output[-1000:] if output else "No output") # Show last bit of output
|
||||||
|
print("\nSUCCESS: Deployment completed.")
|
||||||
|
except Exception:
|
||||||
|
print("\nFAILURE: Deployment failed.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if os.geteuid() != 0:
|
||||||
|
print("This script must be run as root/sudo.")
|
||||||
|
# We don't exit here because the inner run_cmd uses sudo, but it's better to be root.
|
||||||
|
|
||||||
|
cleanup()
|
||||||
|
create_container()
|
||||||
|
prepare_container()
|
||||||
|
perform_deployment()
|
||||||
Reference in New Issue
Block a user