changeset 2076:385ab09fb2ca ssltesting

initial draft
author Violet7
date Tue, 09 Dec 2025 16:37:56 -0800
parents db677318ce63
children 6016342e54ea
files host/renewSsl.sh host/startup/nginx/nginx.acme_setup.conf.luan src/luan/host/https.luan
diffstat 3 files changed, 76 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/host/renewSsl.sh	Mon Dec 08 11:26:31 2025 -0700
+++ b/host/renewSsl.sh	Tue Dec 09 16:37:56 2025 -0800
@@ -1,13 +1,21 @@
 #!/bin/bash
 set -e
 
-# for now - fschmidt
-echo 'totally fucked up'
-exit 1
-
-cd "$1" || exit 1
+if [ -n "$1" ]; then
+  cd "$1" || echo "no first argument passed, staying in cwd"
+fi
 
 ROOTPWD=$(pwd)
+# this awkward method is used for portability
+ROOTPWDOWNER=$(ls -ld $ROOTPWD | awk '{printf "%s", $3}')
+
+# change to owner of host/ if running as root
+# prevents nginx being unable to read files owned by root
+if [ "$(id -u)" -eq 0 ]; then
+  echo "switching to $ROOTPWDOWNER in order to preserve permissions"
+  exec sudo -u $ROOTPWDOWNER "$0" "$@"
+fi
+
 KEYFILE="$ROOTPWD/local/tiny_account.key"
 for SITEROOT in "$ROOTPWD"/sites/*; do
   {
@@ -34,7 +42,16 @@
       --account-key "$KEYFILE" \
       --csr "$CSRFILE" \
       --acme-dir "$CHALLENGEDIR" \
-      > "$TMPOUT"
+      >"$TMPOUT"
+
+    wc -c <$TMPOUT
+
+    # If TMPOUT is empty, something failed.
+    if [ ! -s "$TMPOUT" ]; then
+      echo "Error: $TMPOUT is empty - please see previous output for details.\nContinuing to next domain..."
+      rm -f "$TMPOUT"
+      continue
+    fi
 
     # check if exists
     if [ -f "$FULLCHAIN" ]; then
--- a/host/startup/nginx/nginx.acme_setup.conf.luan	Mon Dec 08 11:26:31 2025 -0700
+++ b/host/startup/nginx/nginx.acme_setup.conf.luan	Tue Dec 09 16:37:56 2025 -0800
@@ -12,12 +12,13 @@
 		error_log <%=rootDir%>/error.log;
 		access_log <%=rootDir%>/access.log;
 
-		root <%=rootDir%>;
-		index index.html;
-
-		location / {
+		location /.well-known/acme-challenge/ {
+        root <%=rootDir%>;
 				try_files $uri $uri/ =404;
 		}
+
+    include nginx.default.conf;
+
 	}
 
 <%
--- a/src/luan/host/https.luan	Mon Dec 08 11:26:31 2025 -0700
+++ b/src/luan/host/https.luan	Tue Dec 09 16:37:56 2025 -0800
@@ -21,10 +21,17 @@
 
 local function do_set_https(is_https,domain,site_dir,luanhost_dir,dry_run)
 	local nginx_file = site_dir.child("nginx.ssl.conf")
-	local key_file = site_dir.child(domain..".key")
-	local csr_file = site_dir.child(domain..".csr")
+
+  -- for storing csr and key, but not fullchain
+  -- TODO: store fullchain in here,
+  -- not done yet for backwards compatibility
+  local ssl_files_dir = site_dir.child("ssl/")
+  ssl_files_dir.mkdir()
+
+  local key_file = ssl_files_dir.child(domain..".key")
+	local csr_file = ssl_files_dir.child(domain..".csr")
+  local tmp_cert_out = ssl_files_dir.child(domain..".crt.tmp")
 	local local_cer_file = site_dir.child("fullchain.cer")
-	local local_ca_file = site_dir.child("ca.cer")
 	-- luan/host
 	local luanhost_file = "file:"..luanhost_dir.to_string().."/"
 	local luanhost_dir_str = luanhost_dir.canonical().to_string()
@@ -59,29 +66,26 @@
 					-- Clean out old temp files
 					temp_dir.delete()
 
-					-- create all needed dirs at once by using
-					-- mkdir -p on the deepest nested dir (acme-challenge)
-					local webroot = temp_dir.to_string().."/webroot"
-					local acme_challenges = webroot.."/.well-known/acme-challenge"
-					uri("file:"..acme_challenges).mkdir()
+          -- CHANGEME
+          dry_run = true
 
-					-- Create the nginx config from the template
-					-- The *output* file, where the generated config is stored
-					local acme_nginx_file = temp_dir.child("nginx.acme_setup.conf")
+          -- make the challenge dir. note that this is
+          -- directly under sites/DOMAIN, and *not* under
+          -- sites/DOMAIN/site.
+          local wellknown = site_dir.child(".well-known/")
+          wellknown.mkdir()
+          local acme_challenges = wellknown.child("acme-challenge/")
+          acme_challenges.mkdir()
+
+          -- generate and write the conf
+          -- TODO: maybe store this in the ssl files dir?
 					local conf = load_file(luanhost_file.."startup/nginx/nginx.acme_setup.conf.luan")
-					local acme_nginx = ` conf(webroot,domain) `
-					acme_nginx_file.write(acme_nginx)
+					local acme_nginx = ` conf(site_dir_str,domain) `
+          local outfile = site_dir.child("nginx.acme_setup.conf")
+          outfile.write(acme_nginx)
 
-					-- Create an index.html to search for in the logs
-					-- to verify everything is working
-					local index_file = webroot.."/index.html"
-					local cmd = "echo 'if you are seeing this, ssl setup has failed. please check the logs.' > "..index_file
-					local s = uri("bash:"..cmd).read_text()
-
-					-- The config in ./local/nginx.conf has a directive to
-					-- glob include confs in /tmp/acme_setup/*/nginx.acme_setup.conf
-					-- so we just need to reload it so it can find the one we just made
-					local cmd = [[
+          -- reload nginx
+          local cmd = [[
 						sudo $(which nginx) -t -c "]]..luanhost_dir_str..[[/local/nginx.conf" && \ 
 						sudo $(which nginx) -s reload -c "]]..luanhost_dir_str..[[/local/nginx.conf";
 					]]
@@ -95,28 +99,44 @@
 					local s = uri("bash:"..cmd).read_text()
 					logger.info("create domain key\n"..s)
 
-					-- create the cert, signed with the key we just made
+					-- create the certificate signing request (CSR), signed with the key we just made
 					local csr_file_str = csr_file.canonical().to_string()
 					local cmd = 'openssl req -new -sha256 -key '..key_file_str..' -subj "/CN='..domain..'" > '..csr_file_str
 					local s = uri("bash:"..cmd).read_text()
-					logger.info("create cert\n"..s)
+					logger.info("create csr\n"..s)
 
-					-- Finally, get our cert signed by letsencrypt.
+					-- Finally, get our cert from letsencrypt.
 					local cmd = [[
 						]]..luanhost_dir_str..[[/acme_tiny --account-key ]]..luanhost_dir_str..[[/local/tiny_account.key \
 						--csr ]]..csr_file_str..[[ \
 						--acme-dir ]]..acme_challenges..[[ \
 					]]
+
+          -- TODO: this often doesn't work and I don't know if it's
+          -- because of this code or because of letsencrypt.
+          -- fix if broken.
 					if dry_run then
 						local dry_run_dir_url = "https://acme-staging-v02.api.letsencrypt.org/directory"
 						cmd = cmd.." --directory-url "..dry_run_dir_url
 					end
-					local local_cer_file_str = local_cer_file.canonical().to_string()
-					cmd = cmd.."> "..local_cer_file_str
+					cmd = cmd.." > "..tmp_cert_out.canonical().to_string()
 
 					local s = uri("bash:"..cmd).read_text()
 					logger.info("get cert signed by letsencrypt\n"..s)
 
+          if tmp_cert_out.length() == 0 then
+            -- TODO: this should fail non-gracefully,
+            -- all failures here are almost certainly bugs.
+            logger.error("FAILED getting cert from letsencrypt.\nSee previous output.\nNot writing to fullchain.cer")
+          else
+            local tmp_out_str = tmp_cert_out.canonical().to_string()
+            local local_cer_file_str = local_cer_file.canonical().to_string()
+
+            local cmd = "mv "..tmp_out_str.." "..local_cer_file_str
+            local s = uri("bash:"..cmd).read_text()
+            logger.info("move temp output to fullchain.cer\n"..s)
+          end
+
 				catch e
 					logger.error("Error setting up ACME: "..e)
 				finally
@@ -143,7 +163,6 @@
 			changed = true
 			nginx_file.delete()
 			local_cer_file.delete()
-			local_ca_file.delete()
 			local ptn = domain.."."
 			for _, file in ipairs(site_dir.children()) do
 				if starts_with(file.name(),ptn) then