Skip to content

Commit ab04e8c

Browse files
committed
fix: multiple certbot instances
1 parent 391eece commit ab04e8c

File tree

3 files changed

+41
-56
lines changed

3 files changed

+41
-56
lines changed

custom-domain/dstack-ingress/Dockerfile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ RUN set -e; \
1818
done && \
1919
apt-get update && \
2020
apt-get install -y --no-install-recommends \
21-
certbot \
2221
openssl \
2322
bash \
2423
python3-pip \
@@ -32,6 +31,17 @@ RUN set -e; \
3231

3332
RUN mkdir -p /etc/letsencrypt /var/www/certbot /usr/share/nginx/html
3433

34+
# Set up Python virtual environment and install certbot
35+
RUN set -e; \
36+
python3 -m venv --system-site-packages /opt/app-venv && \
37+
. /opt/app-venv/bin/activate && \
38+
pip install --upgrade pip && \
39+
pip install certbot requests && \
40+
# Create symlinks for system-wide access
41+
ln -sf /opt/app-venv/bin/certbot /usr/local/bin/certbot && \
42+
# Ensure the virtual environment is always activated for scripts
43+
echo 'source /opt/app-venv/bin/activate' > /etc/profile.d/app-venv.sh
44+
3545
COPY ./scripts /scripts/
3646
RUN chmod +x /scripts/*.sh /scripts/*.py
3747
ENV PATH="/scripts:$PATH"

custom-domain/dstack-ingress/scripts/certman.py

Lines changed: 24 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ def install_plugin(self) -> bool:
9090
import pkg_resources
9191
print(f"Installed to Python: {sys.executable}")
9292

93-
# Show certbot location
94-
certbot_exec = self._get_certbot_executable()
95-
print(f"Using certbot: {certbot_exec}")
93+
# Show certbot command
94+
certbot_cmd = self._get_certbot_command()
95+
print(f"Using certbot: {' '.join(certbot_cmd)}")
9696

9797
try:
9898
dist = pkg_resources.get_distribution("certbot-dns-namecheap")
@@ -109,8 +109,8 @@ def install_plugin(self) -> bool:
109109
print(f"Plugin {self.provider.CERTBOT_PLUGIN} successfully imported")
110110

111111
# Test if plugin is recognized by certbot
112-
certbot_exec = self._get_certbot_executable()
113-
test_cmd = [certbot_exec, "plugins"]
112+
certbot_cmd = self._get_certbot_command()
113+
test_cmd = certbot_cmd + ["plugins"]
114114
test_result = subprocess.run(test_cmd, capture_output=True, text=True, timeout=10)
115115

116116
if test_result.returncode == 0 and "dns-namecheap" in test_result.stdout:
@@ -135,7 +135,7 @@ def install_plugin(self) -> bool:
135135

136136
if force_result.returncode == 0:
137137
# Test again after reinstall
138-
retest_cmd = [certbot_exec, "plugins"]
138+
retest_cmd = certbot_cmd + ["plugins"]
139139
retest_result = subprocess.run(retest_cmd, capture_output=True, text=True, timeout=10)
140140
if retest_result.returncode == 0 and "dns-namecheap" in retest_result.stdout:
141141
print(f"✓ Plugin registration fixed after reinstall")
@@ -159,25 +159,16 @@ def install_plugin(self) -> bool:
159159
def _ensure_certbot_in_env(self) -> None:
160160
"""Ensure certbot is installed in the current Python environment."""
161161
import sys
162-
import shutil
163-
164-
# Check if certbot is available in current environment
165-
python_dir = os.path.dirname(sys.executable)
166-
potential_certbot = os.path.join(python_dir, "certbot")
167-
168-
if os.path.exists(potential_certbot):
169-
print(f"Certbot already available in current environment: {potential_certbot}")
170-
return
171162

172163
# Try to import certbot to check if it's installed
173164
try:
174165
import certbot
175-
print(f"Certbot module available in current environment")
166+
print(f"Certbot module available in current environment")
176167
return
177168
except ImportError:
178-
pass
169+
print(f"Certbot module not found, installing...")
179170

180-
print(f"Installing certbot in current environment...")
171+
# Install certbot if not available
181172
try:
182173
install_cmd = [sys.executable, "-m", "pip", "install", "certbot"]
183174
print(f"Running: {' '.join(install_cmd)}")
@@ -187,33 +178,21 @@ def _ensure_certbot_in_env(self) -> None:
187178
print(f"✓ Certbot installed successfully in current environment")
188179
else:
189180
print(f"Failed to install certbot: {result.stderr}")
190-
# Continue anyway - system certbot might still work
181+
# Continue anyway - may still work
191182
except Exception as e:
192183
print(f"Error installing certbot: {e}")
193-
# Continue anyway - system certbot might still work
184+
# Continue anyway - may still work
194185

195-
def _get_certbot_executable(self) -> str:
196-
"""Get the correct certbot executable path that matches the Python environment."""
186+
def _get_certbot_command(self) -> List[str]:
187+
"""Get the correct certbot command that uses the same Python environment."""
197188
import sys
198-
import shutil
199-
200-
# Try to find certbot in the same environment as the current Python
201-
python_dir = os.path.dirname(sys.executable)
202-
potential_certbot = os.path.join(python_dir, "certbot")
203-
204-
if os.path.exists(potential_certbot):
205-
print(f"Found certbot in same environment: {potential_certbot}")
206-
return potential_certbot
207-
208-
# Try which certbot
209-
certbot_path = shutil.which("certbot")
210-
if certbot_path:
211-
print(f"Found certbot via which: {certbot_path}")
212-
return certbot_path
213189

214-
# Fall back to system certbot
215-
print(f"Falling back to system certbot command")
216-
return "certbot"
190+
# Always use Python module execution to ensure same environment
191+
# This guarantees that certbot runs in the same Python environment
192+
# where we installed the plugins
193+
cmd = [sys.executable, "-m", "certbot"]
194+
print(f"Using certbot via Python module: {' '.join(cmd)}")
195+
return cmd
217196

218197
def _debug_plugin_registration(self) -> None:
219198
"""Debug why plugin is not being registered by certbot."""
@@ -222,8 +201,8 @@ def _debug_plugin_registration(self) -> None:
222201
print("=== Plugin Registration Debug ===")
223202

224203
# Show which certbot we're using
225-
certbot_exec = self._get_certbot_executable()
226-
print(f"Using certbot: {certbot_exec}")
204+
certbot_cmd = self._get_certbot_command()
205+
print(f"Using certbot: {' '.join(certbot_cmd)}")
227206

228207
# Check entry points
229208
try:
@@ -292,9 +271,9 @@ def _build_certbot_command(self, action: str, domain: str, email: str) -> List[s
292271
if not plugin:
293272
raise ValueError(f"No certbot plugin configured for {self.provider_type}")
294273

295-
# Use the same certbot executable as the Python environment
296-
certbot_exec = self._get_certbot_executable()
297-
base_cmd = [certbot_exec, action, "-a", plugin, "--non-interactive", "-v"]
274+
# Use Python module execution to ensure same environment
275+
certbot_cmd = self._get_certbot_command()
276+
base_cmd = certbot_cmd + [action, "-a", plugin, "--non-interactive", "-v"]
298277

299278
# Add credentials file if configured
300279
if self.provider.CERTBOT_CREDENTIALS_FILE:

custom-domain/dstack-ingress/scripts/entrypoint.sh

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@ set -e
55
PORT=${PORT:-443}
66
TXT_PREFIX=${TXT_PREFIX:-"_tapp-address"}
77

8-
echo "Setting up Python environment"
8+
echo "Setting up certbot environment"
99

10-
setup_py_env() {
11-
if [ ! -d "/opt/app-venv" ]; then
12-
python3 -m venv --system-site-packages /opt/app-venv
13-
fi
10+
setup_certbot_env() {
11+
# Activate the pre-built virtual environment
1412
source /opt/app-venv/bin/activate
1513

16-
pip install requests
17-
1814
# Use the unified certbot manager to install plugins and setup credentials
19-
echo "Setting up certbot environment"
15+
echo "Installing DNS plugins and setting up credentials"
2016
certman.py setup
2117
if [ $? -ne 0 ]; then
2218
echo "Error: Failed to setup certbot environment"
@@ -156,8 +152,8 @@ bootstrap() {
156152

157153
# Credentials are now handled by certman.py setup
158154

159-
# Setup Python environment and install dependencies first
160-
setup_py_env
155+
# Setup certbot environment (venv is already created in Dockerfile)
156+
setup_certbot_env
161157

162158
# Check if it's the first time the container is started
163159
if [ ! -f "/.bootstrapped" ]; then

0 commit comments

Comments
 (0)