mirror of
https://github.com/chatmail/relay.git
synced 2026-05-11 16:34:39 +00:00
fix: change config to work also on debian 11
This commit is contained in:
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.11
|
||||
@@ -108,6 +108,13 @@ class AcmetoolDeployer(Deployer):
|
||||
self.need_restart_reconcile_timer = reconcile_timer_file.changed
|
||||
|
||||
def activate(self):
|
||||
systemd.service(
|
||||
name="Stop nginx to free port 80 for acmetool",
|
||||
service="nginx.service",
|
||||
running=False,
|
||||
enabled=True,
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name="Setup acmetool-redirector service",
|
||||
service="acmetool-redirector.service",
|
||||
@@ -135,6 +142,15 @@ class AcmetoolDeployer(Deployer):
|
||||
)
|
||||
self.need_restart_reconcile_timer = False
|
||||
|
||||
# Add the first domain to /etc/hosts to help acmetool's self-test
|
||||
# bypass external firewalls or split-brain DNS issues.
|
||||
server.shell(
|
||||
name=f"Add {self.domains[0]} to /etc/hosts for self-test",
|
||||
commands=[
|
||||
f"grep -q ' {self.domains[0]}$' /etc/hosts || echo '127.0.0.1 {self.domains[0]}' >> /etc/hosts"
|
||||
],
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name=f"Reconcile certificates for: {', '.join(self.domains)}",
|
||||
commands=["acmetool --batch --xlog.severity=debug reconcile"],
|
||||
|
||||
@@ -80,14 +80,22 @@ def _install_remote_venv_with_chatmaild() -> None:
|
||||
remote_dist_file = f"{remote_base_dir}/dist/{dist_file.name}"
|
||||
remote_venv_dir = f"{remote_base_dir}/venv"
|
||||
root_owned = dict(user="root", group="root", mode="644")
|
||||
root_owned_dir = dict(user="root", group="root", mode="755")
|
||||
uv_prefix = "UV_PYTHON_INSTALL_DIR=/usr/local/share/uv/python"
|
||||
|
||||
server.shell(
|
||||
name="Install uv",
|
||||
name="Install uv globally if not present",
|
||||
commands=[
|
||||
"curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_NO_MODIFY_PATH=1 sh",
|
||||
"command -v uv >/dev/null 2>&1 || (curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_NO_MODIFY_PATH=1 sudo sh -s -- --install-dir /usr/local/bin)",
|
||||
],
|
||||
)
|
||||
|
||||
files.directory(
|
||||
name="Ensure shared uv python directory exists",
|
||||
path="/usr/local/share/uv/python",
|
||||
**root_owned_dir,
|
||||
)
|
||||
|
||||
files.put(
|
||||
name="Upload chatmaild source package",
|
||||
src=dist_file.open("rb"),
|
||||
@@ -95,10 +103,30 @@ def _install_remote_venv_with_chatmaild() -> None:
|
||||
create_remote_dir=True,
|
||||
**root_owned,
|
||||
)
|
||||
# Ensure parent directory is accessible
|
||||
files.directory(
|
||||
name=f"Ensure {remote_base_dir} is accessible",
|
||||
path=remote_base_dir,
|
||||
**root_owned_dir,
|
||||
)
|
||||
files.directory(
|
||||
name=f"Ensure {remote_base_dir}/dist is accessible",
|
||||
path=f"{remote_base_dir}/dist",
|
||||
**root_owned_dir,
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name=f"chatmaild virtualenv {remote_venv_dir}",
|
||||
commands=[f"/root/.local/bin/uv venv {remote_venv_dir} --allow-existing"],
|
||||
commands=[f"{uv_prefix} uv venv {remote_venv_dir} --python 3.11 --allow-existing"],
|
||||
)
|
||||
|
||||
# Ensure venv and managed pythons are accessible by other users (like www-data)
|
||||
server.shell(
|
||||
name="Make venv and managed pythons accessible",
|
||||
commands=[
|
||||
f"chmod -R a+rX {remote_venv_dir}",
|
||||
"chmod -R a+rX /usr/local/share/uv/python || true",
|
||||
],
|
||||
)
|
||||
|
||||
apt.packages(
|
||||
@@ -109,7 +137,7 @@ def _install_remote_venv_with_chatmaild() -> None:
|
||||
server.shell(
|
||||
name=f"forced uv-pip-install {dist_file.name}",
|
||||
commands=[
|
||||
f"/root/.local/bin/uv pip install --python {remote_venv_dir}/bin/python --force-reinstall {remote_dist_file}"
|
||||
f"{uv_prefix} uv pip install --python {remote_venv_dir}/bin/python --force-reinstall {remote_dist_file}"
|
||||
],
|
||||
)
|
||||
|
||||
@@ -448,6 +476,10 @@ class ChatmailDeployer(Deployer):
|
||||
self.mail_domain = mail_domain
|
||||
|
||||
def install(self):
|
||||
server.shell(
|
||||
name="Fix broken packages",
|
||||
commands=["apt-get install -f -y"],
|
||||
)
|
||||
apt.update(name="apt update", cache_time=24 * 3600)
|
||||
apt.upgrade(name="upgrade apt packages", auto_remove=True)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from chatmaild.config import Config
|
||||
from pyinfra import host
|
||||
from pyinfra.facts.server import Arch, Sysctl
|
||||
from pyinfra.facts.server import Arch, LinuxDistribution, Sysctl
|
||||
from pyinfra.facts.systemd import SystemdEnabled
|
||||
from pyinfra.operations import apt, files, server, systemd
|
||||
|
||||
@@ -50,6 +50,33 @@ class DovecotDeployer(Deployer):
|
||||
|
||||
|
||||
def _install_dovecot_package(package: str, arch: str):
|
||||
distro = host.get_fact(LinuxDistribution)
|
||||
is_old_debian = False
|
||||
if distro:
|
||||
distro_id = str(distro.get("id", "")).lower()
|
||||
distro_name = str(distro.get("name", "")).lower()
|
||||
major_version = str(distro.get("major_version", "0"))
|
||||
|
||||
if "debian" in distro_id or "debian" in distro_name:
|
||||
try:
|
||||
# Handle cases where major_version might be '11.13'
|
||||
m_ver = major_version.split(".")[0]
|
||||
if m_ver.isdigit() and 0 < int(m_ver) < 12:
|
||||
is_old_debian = True
|
||||
except (ValueError, TypeError, IndexError):
|
||||
pass
|
||||
# Fallback for systems where major_version might not be parsed correctly but name contains 'bullseye'
|
||||
if "bullseye" in distro_name or "buster" in distro_name:
|
||||
is_old_debian = True
|
||||
|
||||
if is_old_debian:
|
||||
apt.packages(
|
||||
name=f"Install system dovecot-{package}",
|
||||
packages=[f"dovecot-{package}"],
|
||||
update=True,
|
||||
)
|
||||
return
|
||||
|
||||
arch = "amd64" if arch == "x86_64" else arch
|
||||
arch = "arm64" if arch == "aarch64" else arch
|
||||
url = f"https://download.delta.chat/dovecot/dovecot-{package}_2.3.21%2Bdfsg1-3_{arch}.deb"
|
||||
@@ -80,7 +107,18 @@ def _install_dovecot_package(package: str, arch: str):
|
||||
cache_time=60 * 60 * 24 * 365 * 10, # never redownload the package
|
||||
)
|
||||
|
||||
apt.deb(name=f"Install dovecot-{package}", src=deb_filename)
|
||||
# Use a shell command to try installing the custom .deb and fallback if it fails.
|
||||
# This prevents the whole deployment from failing if custom dovecot is not compatible.
|
||||
server.shell(
|
||||
name=f"Install dovecot-{package} (custom or system fallback)",
|
||||
commands=[
|
||||
f"if ! dpkg -i {deb_filename}; then "
|
||||
f"echo 'HEY: dovecot the custom is not installed, we install your os main one' >&2; "
|
||||
f"DEBIAN_FRONTEND=noninteractive apt-get install -f -y; "
|
||||
f"DEBIAN_FRONTEND=noninteractive apt-get install -y dovecot-{package}; "
|
||||
f"fi"
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
|
||||
|
||||
@@ -229,7 +229,7 @@ ssl = required
|
||||
ssl_cert = </var/lib/acme/live/{{ config.mail_domain }}/fullchain
|
||||
ssl_key = </var/lib/acme/live/{{ config.mail_domain }}/privkey
|
||||
ssl_dh = </usr/share/dovecot/dh.pem
|
||||
ssl_min_protocol = TLSv1.3
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_prefer_server_ciphers = yes
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from chatmaild.config import Config
|
||||
from pyinfra.operations import apt, files, systemd
|
||||
from pyinfra.operations import apt, files, server, systemd
|
||||
|
||||
from cmdeploy.basedeploy import (
|
||||
Deployer,
|
||||
@@ -43,6 +43,13 @@ class NginxDeployer(Deployer):
|
||||
name="Install nginx",
|
||||
packages=["nginx", "libnginx-mod-stream"],
|
||||
)
|
||||
server.shell(
|
||||
name="Remove default nginx configuration",
|
||||
commands=[
|
||||
"rm -f /etc/nginx/sites-enabled/default",
|
||||
"rm -f /etc/nginx/conf.d/default.conf",
|
||||
],
|
||||
)
|
||||
|
||||
files.file("/usr/sbin/policy-rc.d", present=False)
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ smtp_tls_security_level=verify
|
||||
smtp_tls_servername = hostname
|
||||
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
|
||||
smtp_tls_policy_maps = inline:{nauta.cu=may}
|
||||
smtp_tls_protocols = >=TLSv1.2
|
||||
smtp_tls_mandatory_protocols = >=TLSv1.2
|
||||
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
|
||||
# Disable anonymous cipher suites
|
||||
# and known insecure algorithms.
|
||||
|
||||
@@ -10,17 +10,15 @@
|
||||
# (yes) (yes) (no) (never) (100)
|
||||
# ==========================================================================
|
||||
{% if debug == true %}
|
||||
smtp inet n - y - - smtpd -v
|
||||
{%- else %}
|
||||
smtp inet n - y - - smtpd
|
||||
smtp inet n - n - - smtpd
|
||||
{%- endif %}
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_tls_mandatory_protocols=>=TLSv1.2
|
||||
-o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1
|
||||
-o smtpd_proxy_filter=127.0.0.1:{{ config.filtermail_smtp_port_incoming }}
|
||||
submission inet n - y - 5000 smtpd
|
||||
submission inet n - n - 5000 smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_tls_mandatory_protocols=>=TLSv1.3
|
||||
-o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_sasl_type=dovecot
|
||||
-o smtpd_sasl_path=private/auth
|
||||
@@ -33,11 +31,11 @@ submission inet n - y - 5000 smtpd
|
||||
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
||||
-o smtpd_client_connection_count_limit=1000
|
||||
-o smtpd_proxy_filter=127.0.0.1:{{ config.filtermail_smtp_port }}
|
||||
smtps inet n - y - 5000 smtpd
|
||||
smtps inet n - n - 5000 smtpd
|
||||
-o syslog_name=postfix/smtps
|
||||
-o smtpd_tls_wrappermode=yes
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_tls_mandatory_protocols=>=TLSv1.3
|
||||
-o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_sasl_type=dovecot
|
||||
-o smtpd_sasl_path=private/auth
|
||||
|
||||
7
init.sh
7
init.sh
@@ -8,7 +8,7 @@ sudo apt install -y git curl wget python3-dev gcc python3 nano sed
|
||||
|
||||
# 1.1 Install uv
|
||||
export PATH="$HOME/.local/bin:/root/.local/bin:$PATH"
|
||||
if ! command -v uv &> /dev/null; then
|
||||
if ! command -v uv > /dev/null 2>&1; then
|
||||
if [ -f "/root/.local/bin/uv" ]; then
|
||||
export PATH="/root/.local/bin:$PATH"
|
||||
elif [ -f "$HOME/.local/bin/uv" ]; then
|
||||
@@ -16,7 +16,7 @@ if ! command -v uv &> /dev/null; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v uv &> /dev/null; then
|
||||
if ! command -v uv > /dev/null 2>&1; then
|
||||
echo "--- Installing uv ---"
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
# Ensure uv is in PATH for the current script
|
||||
@@ -43,7 +43,8 @@ read -p "Enter your email for ACME/Let's Encrypt: " ACME_EMAIL
|
||||
|
||||
# 5. Initialize configuration
|
||||
echo "--- Initializing chatmail configuration ---"
|
||||
./scripts/cmdeploy init "$MAIL_DOMAIN"
|
||||
./scripts/cmdeploy init "$MAIL_DOMAIN" || true
|
||||
|
||||
|
||||
# 6. Modify chatmail.ini with specific requirements
|
||||
echo "--- Customizing chatmail.ini ---"
|
||||
|
||||
29
pyproject.toml
Normal file
29
pyproject.toml
Normal file
@@ -0,0 +1,29 @@
|
||||
[project]
|
||||
name = "relay-ir"
|
||||
version = "0.1.0"
|
||||
description = "Chatmail relay workspace"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"chatmaild",
|
||||
"cmdeploy",
|
||||
"sphinx",
|
||||
"sphinxcontrib-mermaid",
|
||||
"sphinx-autobuild",
|
||||
"furo",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
managed = true
|
||||
package = false
|
||||
|
||||
[tool.uv.workspace]
|
||||
members = ["chatmaild", "cmdeploy"]
|
||||
|
||||
[tool.uv.sources]
|
||||
chatmaild = { workspace = true }
|
||||
cmdeploy = { workspace = true }
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=61"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
@@ -21,7 +21,7 @@ fi
|
||||
# Ensure uv is in PATH
|
||||
export PATH="$HOME/.local/bin:/root/.local/bin:$PATH"
|
||||
|
||||
if ! command -v uv &> /dev/null; then
|
||||
if ! command -v uv > /dev/null 2>&1; then
|
||||
if [ -f "/root/.local/bin/uv" ]; then
|
||||
export PATH="/root/.local/bin:$PATH"
|
||||
elif [ -f "$HOME/.local/bin/uv" ]; then
|
||||
@@ -29,13 +29,9 @@ if ! command -v uv &> /dev/null; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v uv &> /dev/null; then
|
||||
if ! command -v uv > /dev/null 2>&1; then
|
||||
echo "uv not found. Please install it first or run init.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
uv venv venv
|
||||
|
||||
uv pip install -e chatmaild
|
||||
uv pip install -e cmdeploy
|
||||
uv pip install sphinx sphinxcontrib-mermaid sphinx-autobuild furo # for building the docs
|
||||
uv sync --python 3.11
|
||||
|
||||
Reference in New Issue
Block a user