Skip to content

[fix] Updated auto-install script prompt for SSL certificate #556#564

Merged
nemesifier merged 1 commit intomasterfrom
issues/556-ssl-certificate
Feb 17, 2026
Merged

[fix] Updated auto-install script prompt for SSL certificate #556#564
nemesifier merged 1 commit intomasterfrom
issues/556-ssl-certificate

Conversation

@pandafy
Copy link
Member

@pandafy pandafy commented Feb 17, 2026

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Fixes #556

Description of Changes

Removed CERT_ADMIN_EMAIL setting as Let's Encrypt no long sends expiration email to the user.

@pandafy pandafy self-assigned this Feb 17, 2026
@pandafy pandafy moved this from To do (general) to Needs review in OpenWISP Contributor's Board Feb 17, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

No actionable comments were generated in the recent review. 🎉

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59d689c and 89df106.

📒 Files selected for processing (5)
  • .env
  • deploy/auto-install.sh
  • docs/user/settings.rst
  • images/common/utils.sh
  • images/openwisp_nginx/Dockerfile
💤 Files with no reviewable changes (3)
  • .env
  • images/openwisp_nginx/Dockerfile
  • docs/user/settings.rst
🚧 Files skipped from review as they are similar to previous changes (1)
  • deploy/auto-install.sh
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: In certbot 3.3.0+ (released March 2025), the `--register-unsafely-without-email` flag is no longer required when using `--noninteractive --agree-tos` without providing an email address. Account registration will proceed without an email by default.
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/utils.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🔇 Additional comments (1)
images/common/utils.sh (1)

31-42: LGTM!

The removal of --email ${CERT_ADMIN_EMAIL} from both certbot invocations is correct. Based on learnings, certbot 3.3.0+ (released March 2025) no longer requires --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email address—account registration proceeds without an email by default.

The existing certificate checks (privkey.pem existence) and other command options remain intact, preserving idempotency.


Walkthrough

This pull request removes the CERT_ADMIN_EMAIL variable from the OpenWISP installation and configuration process, addressing the obsolescence of Let's Encrypt renewal emails. The auto-install script replaces the email prompt with a yes/no question for Let's Encrypt usage. The corresponding environment variable is removed from configuration files, certbot commands are updated to exclude the email parameter, and related documentation is deleted. Self-signed certificate flow remains unchanged when users decline Let's Encrypt.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant InstallScript as "auto-install.sh"
  participant Certbot
  participant SystemFiles as "nginx/certs/files"

  User->>InstallScript: Run installer / answer prompt "Use Let's Encrypt SSL? (y/N)"
  InstallScript->>InstallScript: Interpret response -> set SSL_CERT_MODE (Yes or SelfSigned)
  alt User answered yes
    InstallScript->>Certbot: Invoke certbot certonly --standalone --noninteractive --agree-tos --rsa-key-size ... --domain example.com
    Certbot-->>InstallScript: Return cert files (privkey.pem/fullchain.pem)
    InstallScript->>SystemFiles: Write certs to expected paths
  else User answered no
    InstallScript->>SystemFiles: Generate self-signed certs (openssl or existing logic)
  end
  InstallScript->>SystemFiles: Update config / ENV (remove CERT_ADMIN_EMAIL usage)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • nemesifier
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: updating the auto-install script prompt for SSL certificates and references issue #556.
Description check ✅ Passed The description covers required sections and explains the rationale for the change with a reference to issue #556, though test cases were not updated.
Linked Issues check ✅ Passed The pull request successfully implements all coding requirements from issue #556: changed the prompt from email to yes/no, removed CERT_ADMIN_EMAIL from all relevant files, and updated documentation.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #556's objectives: removing CERT_ADMIN_EMAIL and updating the SSL prompt across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issues/556-ssl-certificate

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot added the bug Something isn't working label Feb 17, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
deploy/auto-install.sh (1)

120-121: Validate yes/no input to avoid accidental SelfSigned selection.

Any non-yes/y value currently flips to SelfSigned, which can happen on typos or empty input. Consider an explicit yes/no loop and then set SSL_CERT_MODE from that result.

♻️ Suggested change
-		# SSL Configuration
-		echo -ne ${GRN}"(5/5) Use Let's Encrypt to generate SSL certificate (yes/no): "${NON}
-		read use_letsencrypt
+		# SSL Configuration
+		while :; do
+			echo -ne ${GRN}"(5/5) Use Let's Encrypt to generate SSL certificate (yes/no): "${NON}
+			read use_letsencrypt
+			case "${use_letsencrypt,,}" in
+				yes|y) ssl_cert_mode="Yes"; break ;;
+				no|n)  ssl_cert_mode="SelfSigned"; break ;;
+				*) echo -e ${YLW}"Please answer yes or no."${NON} ;;
+			esac
+		done
@@
-		if [[ "${use_letsencrypt,,}" == "yes" || "${use_letsencrypt,,}" == "y" ]]; then
-			set_env "SSL_CERT_MODE" "Yes"
-		else
-			set_env "SSL_CERT_MODE" "SelfSigned"
-		fi
+		set_env "SSL_CERT_MODE" "$ssl_cert_mode"

Also applies to: 164-167

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy/auto-install.sh` around lines 120 - 121, The prompt currently reads
into use_letsencrypt and treats any non-yes as SelfSigned; change this to an
explicit validation loop that repeatedly prompts (using the same echo prompt
text) until the user enters a clear yes or no (accept case-insensitive "y"/"yes"
and "n"/"no"), then set SSL_CERT_MODE to "Let's Encrypt" (or "letsencrypt") on
yes and "SelfSigned" on no; apply the same validated-loop logic to the other
prompt block that also reads user input (the second read block around the other
SSL prompt). Use the existing variable names (use_letsencrypt and SSL_CERT_MODE)
so the rest of the script continues to work.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d3db88 and 59d689c.

📒 Files selected for processing (5)
  • .env
  • deploy/auto-install.sh
  • docs/user/settings.rst
  • images/common/utils.sh
  • images/openwisp_nginx/Dockerfile
💤 Files with no reviewable changes (3)
  • .env
  • images/openwisp_nginx/Dockerfile
  • docs/user/settings.rst
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@images/common/utils.sh`:
- Around line 33-40: The certbot invocations in the create_prod_certs function
can fail on a fresh LetsEncrypt volume because Certbot requires either --email
or --register-unsafely-without-email when using --noninteractive --agree-tos;
update both certbot certonly calls (the ones using ${DASHBOARD_DOMAIN} and
${API_DOMAIN}) to include --register-unsafely-without-email so account
registration succeeds without an email during initial deployment.

---

Nitpick comments:
In `@deploy/auto-install.sh`:
- Around line 120-121: The prompt currently reads into use_letsencrypt and
treats any non-yes as SelfSigned; change this to an explicit validation loop
that repeatedly prompts (using the same echo prompt text) until the user enters
a clear yes or no (accept case-insensitive "y"/"yes" and "n"/"no"), then set
SSL_CERT_MODE to "Let's Encrypt" (or "letsencrypt") on yes and "SelfSigned" on
no; apply the same validated-loop logic to the other prompt block that also
reads user input (the second read block around the other SSL prompt). Use the
existing variable names (use_letsencrypt and SSL_CERT_MODE) so the rest of the
script continues to work.

Comment on lines 33 to +40
certbot certonly --standalone --noninteractive --agree-tos \
--rsa-key-size 4096 \
--domain ${DASHBOARD_DOMAIN} \
--email ${CERT_ADMIN_EMAIL}
--domain ${DASHBOARD_DOMAIN}
fi
if [ ! -f /etc/letsencrypt/live/${API_DOMAIN}/privkey.pem ]; then
certbot certonly --standalone --noninteractive --agree-tos \
--rsa-key-size 4096 \
--domain ${API_DOMAIN} \
--email ${CERT_ADMIN_EMAIL}
--domain ${API_DOMAIN}
Copy link

@coderabbitai coderabbitai bot Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find Dockerfile or image configuration files
find . -name "Dockerfile*" -o -name "docker-compose*" | head -20

Repository: openwisp/docker-openwisp

Length of output: 415


🏁 Script executed:

# Look for any image build configuration in the images directory
find images -type f -name "Dockerfile*" -o -name "*.sh" | grep -E "(Dockerfile|^Dockerfile)" | head -20

Repository: openwisp/docker-openwisp

Length of output: 376


🏁 Script executed:

# Search for how certbot is installed in the codebase
rg "certbot" --type dockerfile --type shell -B 2 -A 2 | head -100

Repository: openwisp/docker-openwisp

Length of output: 102


🏁 Script executed:

# Find the images/common directory and utils.sh
find images -name "utils.sh" -o -name "common" -type d

Repository: openwisp/docker-openwisp

Length of output: 104


🏁 Script executed:

# Search for certbot in shell files
rg "certbot" --type shell -B 2 -A 2 | head -150

Repository: openwisp/docker-openwisp

Length of output: 97


🏁 Script executed:

# Check the base Dockerfile which likely installs certbot
cat images/openwisp_base/Dockerfile | head -100

Repository: openwisp/docker-openwisp

Length of output: 4177


🏁 Script executed:

# Read the utils.sh file to see full context
cat -n images/common/utils.sh | head -80

Repository: openwisp/docker-openwisp

Length of output: 3136


🏁 Script executed:

# Search for certbot installation in all Dockerfiles
rg "certbot" . --no-heading -B 3 -A 3

Repository: openwisp/docker-openwisp

Length of output: 2270


🌐 Web query:

Alpine Linux certbot version requirements --noninteractive --email

💡 Result:

On Alpine Linux, there isn’t a special Alpine-specific minimum version for these flags—--noninteractive/--non-interactive and --email are long-standing Certbot CLI options and are present in current Alpine packages (e.g., Alpine v3.22 ships certbot 4.0.0 in community). [1]

What matters is Certbot’s non-interactive requirements:

  • If you run with --noninteractive (aka --non-interactive), you must also provide the inputs Certbot would otherwise prompt for—most commonly:
    • --agree-tos
    • either --email you@example.com or --register-unsafely-without-email (not recommended) [2][3]

Example (typical webroot issuance):

certbot certonly --noninteractive --agree-tos --email you@example.com \
  --webroot -w /var/www/html -d example.com

To confirm what your Alpine image actually has installed:

certbot --version
apk info -v certbot

Sources: [1] [2] [3]


🌐 Web query:

certbot documentation --noninteractive flag email requirement

💡 Result:

With Certbot, -n/--noninteractive means Certbot will not prompt you, so any info it would normally ask for must already be available.

  • If no ACME account is registered yet on that machine, Certbot will refuse to proceed non-interactively unless you provide:
    • --agree-tos and
    • either -m/--email you@example.com or --register-unsafely-without-email (discouraged) [1][2].
  • If an ACME account already exists locally, Certbot will reuse it and typically won’t require --email on subsequent runs (because the account already has contact info) [3].

You can also pre-create/update the account explicitly (so later --noninteractive runs don’t need to prompt) using the registration options (-m/--email, --update-registration, etc.) [1][2].

Sources:
[1] Certbot manpage / CLI options (--email, --register-unsafely-without-email) https://eff-certbot.readthedocs.io/en/zoraconpatch-readthedocs-reqtxt/man/certbot.html
[2] Certbot User Guide (same registration options) https://dokk.org/documentation/certbot/v0.22.1/using/
[3] Let’s Encrypt Community Support explanation of account reuse in noninteractive mode https://community.letsencrypt.org/t/further-automating-certification-creation-command/52873


🏁 Script executed:

# Check if there's any account pre-setup or email configuration
rg "register-unsafely|--email|certbot register|ACME_EMAIL|CERTBOT_EMAIL" images/ docs/ --no-heading -B 2 -A 2

Repository: openwisp/docker-openwisp

Length of output: 50


🏁 Script executed:

# Check docker-compose.yml for environment variables related to certbot/email
cat docker-compose.yml

Repository: openwisp/docker-openwisp

Length of output: 5705


Add --register-unsafely-without-email to certbot commands in create_prod_certs function.

Certbot with --noninteractive --agree-tos requires either --email or --register-unsafely-without-email when registering a new ACME account. On initial deployment with a fresh /etc/letsencrypt volume, the current commands will fail and block TLS certificate generation. Add the flag to both certbot certonly invocations:

Suggested fix
-		certbot certonly --standalone --noninteractive --agree-tos \
+		certbot certonly --standalone --noninteractive --agree-tos \
+			--register-unsafely-without-email \
 			--rsa-key-size 4096 \
 			--domain ${DASHBOARD_DOMAIN}
@@
-		certbot certonly --standalone --noninteractive --agree-tos \
+		certbot certonly --standalone --noninteractive --agree-tos \
+			--register-unsafely-without-email \
 			--rsa-key-size 4096 \
 			--domain ${API_DOMAIN}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
certbot certonly --standalone --noninteractive --agree-tos \
--rsa-key-size 4096 \
--domain ${DASHBOARD_DOMAIN} \
--email ${CERT_ADMIN_EMAIL}
--domain ${DASHBOARD_DOMAIN}
fi
if [ ! -f /etc/letsencrypt/live/${API_DOMAIN}/privkey.pem ]; then
certbot certonly --standalone --noninteractive --agree-tos \
--rsa-key-size 4096 \
--domain ${API_DOMAIN} \
--email ${CERT_ADMIN_EMAIL}
--domain ${API_DOMAIN}
certbot certonly --standalone --noninteractive --agree-tos \
--register-unsafely-without-email \
--rsa-key-size 4096 \
--domain ${DASHBOARD_DOMAIN}
fi
if [ ! -f /etc/letsencrypt/live/${API_DOMAIN}/privkey.pem ]; then
certbot certonly --standalone --noninteractive --agree-tos \
--register-unsafely-without-email \
--rsa-key-size 4096 \
--domain ${API_DOMAIN}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@images/common/utils.sh` around lines 33 - 40, The certbot invocations in the
create_prod_certs function can fail on a fresh LetsEncrypt volume because
Certbot requires either --email or --register-unsafely-without-email when using
--noninteractive --agree-tos; update both certbot certonly calls (the ones using
${DASHBOARD_DOMAIN} and ${API_DOMAIN}) to include
--register-unsafely-without-email so account registration succeeds without an
email during initial deployment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since certbot 3.3, the register-unsafely-without-email is no longer required.

https://github.com/certbot/certbot/blob/ff281d48a8db6052d2ae7426553bcd1609ca410f/certbot/CHANGELOG.md?plain=1#L291

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check which version of certbot is installed in the Docker images
rg "certbot" images/ --type dockerfile -B 2 -A 2

# Check for certbot installation in Dockerfiles
cat images/openwisp_nginx/Dockerfile | grep -i certbot -A 5 -B 5

Length of output: 302


🌐 Web query:

certbot 3.3 changelog email requirement removal

💡 Result:

Certbot 3.3.0 (released March 11, 2025) changed account registration so an email address is no longer effectively required:

  • Non-interactive mode: you no longer need --register-unsafely-without-email to register without an email. [1]
  • Interactive mode: at the email prompt, pressing Enter will register without an email. [1]

Context: Let’s Encrypt also announced it would end certificate expiration notification emails on June 4, 2025, reducing the value of supplying an email for reminders. [2]

Sources: [1] Certbot 3.3.0 release notes/changelog, Let’s Encrypt Community Support; [2] Let’s Encrypt blog announcement.


@pandafy Thank you for the correction! You're absolutely right. The web search confirms that certbot 3.3.0 (released March 11, 2025) removed the requirement for --register-unsafely-without-email in non-interactive mode, and pressing Enter at the email prompt now registers without an email.

Since the Alpine image installs certbot via apk add certbot without version pinning, and we're currently in February 2026, the installed version would be 3.3+. Your implementation is correct as-is—the certbot commands will work fine without the email parameter or the unsafe registration flag.

I apologize for the incorrect review comment!


✏️ Learnings added
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: In certbot 3.3.0+ (released March 2025), the `--register-unsafely-without-email` flag is no longer required when using `--noninteractive --agree-tos` without providing an email address. Account registration will proceed without an email by default.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@github-project-automation github-project-automation bot moved this from Needs review to In progress in OpenWISP Contributor's Board Feb 17, 2026
Removed CERT_ADMIN_EMAIL setting as Let's Encrypt no long sends
expiration email to the user.

Fixes #556
@pandafy pandafy force-pushed the issues/556-ssl-certificate branch from 59d689c to 89df106 Compare February 17, 2026 13:58
@nemesifier nemesifier merged commit 8f378f3 into master Feb 17, 2026
5 checks passed
@nemesifier nemesifier deleted the issues/556-ssl-certificate branch February 17, 2026 16:39
@github-project-automation github-project-automation bot moved this from In progress to Done in OpenWISP Contributor's Board Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Development

Successfully merging this pull request may close these issues.

[bug] Update auto-install script to prompt yes/no for Let's Encrypt instead of email

2 participants