changeset 2036:2740f8a9ba3a acme-tiny tip

First test prototype (also convert spaces to tabs and remove *.orig files)
author Violet7
date Wed, 05 Nov 2025 21:49:39 -0800
parents 00bbfef1a86b
children
files backup/start.sh.orig backup/stop.sh.orig host/startup/nginx/nginx.acme_setup.conf.luan src/luan/host/https.luan
diffstat 4 files changed, 120 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
diff -r 00bbfef1a86b -r 2740f8a9ba3a backup/start.sh.orig
--- a/backup/start.sh.orig	Wed Nov 05 11:20:47 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#!/bin/bash -e
-
-ROOTPWD=$(pwd);
-logsdir=${ROOTPWD}"/logs";
-servelog=${logsdir}"/server.log";
-
-mkdir -p "$logsdir"
-
-if [ "$1" == "launchd" ]; then
-    ${ROOTPWD}/luan.sh server.luan $* &2>${servelog}
-else
-    ${ROOTPWD}/luan.sh server.luan $* &2>${servelog}&
-fi;
diff -r 00bbfef1a86b -r 2740f8a9ba3a backup/stop.sh.orig
--- a/backup/stop.sh.orig	Wed Nov 05 11:20:47 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-LUAN_PIDS=$(ps ax | awk '/[s]erver.luan/ {print $1}')
-
-if [ -n "$LUAN_PIDS" ]; then
-    echo "Killing luan processes: $LUAN_PIDS"
-    kill -TERM $LUAN_PIDS
-else
-    echo "Info: No luan processes found, continuing."
-fi
-
-exit 0
diff -r 00bbfef1a86b -r 2740f8a9ba3a host/startup/nginx/nginx.acme_setup.conf.luan
--- a/host/startup/nginx/nginx.acme_setup.conf.luan	Wed Nov 05 11:20:47 2025 -0700
+++ b/host/startup/nginx/nginx.acme_setup.conf.luan	Wed Nov 05 21:49:39 2025 -0800
@@ -1,24 +1,24 @@
 local rootDir, domain = ...
 
 %>
-  # This config exists to serve up acme challenges on
-  # .well-known for initial domain verification by letsencrypt.
-  # see set_https in luan/src/luan/host/https.luan for more.
-  server {
-    server_name <%=domain%>;
-    listen 80;
-    listen [::]:80;
+	# This config exists to serve up acme challenges on
+	# .well-known for initial domain verification by letsencrypt.
+	# see set_https in luan/src/luan/host/https.luan for more.
+	server {
+		server_name <%=domain%>;
+		listen 80;
+		listen [::]:80;
 
-    error_log <%=rootDir%>/error.log;
-    access_log <%=rootDir%>/access.log;
+		error_log <%=rootDir%>/error.log;
+		access_log <%=rootDir%>/access.log;
 
-    root <%=rootDir%>;
-    index index.html;
+		root <%=rootDir%>;
+		index index.html;
 
-    location / {
-        try_files $uri $uri/ =404;
-    }
-  }
+		location / {
+				try_files $uri $uri/ =404;
+		}
+	}
 
 <%
 
diff -r 00bbfef1a86b -r 2740f8a9ba3a src/luan/host/https.luan
--- a/src/luan/host/https.luan	Wed Nov 05 11:20:47 2025 -0700
+++ b/src/luan/host/https.luan	Wed Nov 05 21:49:39 2025 -0800
@@ -22,136 +22,141 @@
 		return
 	end
 	local domain = Http.domain
-	local dir = uri("site:").parent()
-	local nginx_file = dir.child("nginx.ssl.conf")
-	local key_file = dir.child(domain..".key")
-  local key_file_str = key_file.canonical().to_string()
-  local csr_file = dir.child(domain..".csr")
-  local csr_file_str = csr_file.canonical().to_string()
-	local local_cer_file = dir.child("fullchain.cer")
-  local local_cer_file_str = local_cer_file.canonical().to_string()
-	local local_ca_file = dir.child("ca.cer")
-	local top_dir = uri("file:.").canonical().to_string()
+	local site_dir = uri("site:").parent()
+	local nginx_file = site_dir.child("nginx.ssl.conf")
+	local key_file = site_dir.child(domain..".key")
+	local key_file_str = key_file.canonical().to_string()
+	local csr_file = site_dir.child(domain..".csr")
+	local csr_file_str = csr_file.canonical().to_string()
+	local local_cer_file = site_dir.child("fullchain.cer")
+	local local_cer_file_str = local_cer_file.canonical().to_string()
+	local local_ca_file = site_dir.child("ca.cer")
+	-- luan/host
+	local luanhost_dir = uri("file:.").canonical().to_string()
 	local changed = false
-  -- use for testing, so as to not hit rate limits
-  -- on the real letsencrypt servers
-  local dry_run = true
+	-- use for testing, so as to not hit rate limits
+	-- on the real letsencrypt servers
+	local dry_run = true
+	local dry_run_dir_url = "https://acme-staging-v02.api.letsencrypt.org/directory"
 
 	if is_https then  -- https
 		if not key_file.exists() then
 			local is_local = ip(domain) == "127.0.0.1"
 			logger.info("is_local "..is_local)
 
-      -- Use openssl directly to make a self-signed cert,
-      -- no external cert authority involved
+			-- Use openssl directly to make a self-signed cert,
+			-- no external cert authority involved
 			if is_local then
-        -- set up a temporary barebones nginx conf
-        -- to serve acme challenges on the domain
+				local cmd = [[
+							./local_https.sh "]]..domain..[["
+						]]
+				local s = uri("bash:"..cmd).read_text()
+				logger.info("issue local certificate")
+			else
+				-- set up a temporary barebones nginx conf
+				-- to serve acme challenges on the domain
 
-        local temp_dir_string = "/tmp/acme_setup/"..domain
+				local temp_dir_string = "/tmp/acme_setup/"..domain
 
-        -- recursion guard, must have this to prevent
-        -- the http request from invoking this code
-        -- and causing an infinite recursion.
-        local guard_file = temp_dir_string.."/recursionguard.lock"
-        local guard_uri = uri("file:"..guard_file)
-        if guard_uri.exists() then
-            logger.info("set_https already running for "..domain..", skipping")
-            return
-        end
+				-- recursion guard, must have this to prevent
+				-- the http request from invoking this code
+				-- and causing an infinite recursion.
+				local cmd = "mkdir -p /tmp/acme_setup_locks/"
+				local s = uri("bash:"..cmd).read_text()
+				local guard_file = "/tmp/acme_setup_locks/"..domain..".lock"
+				local guard_uri = uri("file:"..guard_file)
+				if guard_uri.exists() then
+						logger.info("set_https already running for "..domain..", skipping")
+						return
+				end
 
-        -- Clean out old temp files
-        local cmd = "rm -rf "..temp_dir_string
+				-- Clean out old temp files
+				local cmd = "rm -rf "..temp_dir_string
 				local s = uri("bash:"..cmd).read_text()
 
-        -- create all the dirs needed
-        local webroot = temp_dir_string.."/webroot"
-        local acme_challenges = webroot.."/.well-known/acme-challenge"
-        local cmd = "mkdir -p "..acme_challenges
+				-- create all needed dirs at once by using
+				-- mkdir -p on the deepest nested dir (acme-challenge)
+				local webroot = temp_dir_string.."/webroot"
+				local acme_challenges = webroot.."/.well-known/acme-challenge"
+				local cmd = "mkdir -p "..acme_challenges
 				local s = uri("bash:"..cmd).read_text()
 
-        guard_uri.write("this is a recursion guard, see https.luan")
+				guard_uri.write("this is a recursion guard, see https.luan")
 
 
-        -- Create the nginx config from the template
-        local temp_dir = uri("file:"..temp_dir_string)
-        -- The *output* file, where the generated config is stored
-        local acme_nginx_file = temp_dir.child("nginx.acme_setup.conf")
-        local conf = load_file "file:startup/nginx/nginx.acme_setup.conf.luan"
+				-- Create the nginx config from the template
+				local temp_dir = uri("file:"..temp_dir_string)
+				-- The *output* file, where the generated config is stored
+				local acme_nginx_file = temp_dir.child("nginx.acme_setup.conf")
+				local conf = load_file "file:startup/nginx/nginx.acme_setup.conf.luan"
 				local acme_nginx = ` conf(webroot,domain) `
 				acme_nginx_file.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 'hi, testing' > "..index_file
-        local s = uri("bash:"..cmd).read_text()
+				-- Create an index.html to search for in the logs
+				-- to verify everything is working
+				local index_file = webroot.."/index.html"
+				local cmd = "echo 'hi, testing' > "..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 = [[
-          sudo $(which nginx) -t -c "]]..top_dir..[[/local/nginx.conf" && sudo $(which nginx) -s reload;
-        ]]
-        local s = uri("bash:"..cmd).read_text()
-        logger.info("reload_nginx "..s)
+				-- 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 = [[
+					sudo $(which nginx) -t -c "]]..luanhost_dir..[[/local/nginx.conf" && sudo $(which nginx) -s reload;
+				]]
+				local s = uri("bash:"..cmd).read_text()
+				logger.info("reload_nginx "..s)
 
-        -- We've set up nginx to serve from our temp root, now we need to
-        -- create a *domain key*, which we then use to sign our cert.
-        local cmd = "openssl genrsa 4096 > "..key_file_str
-        local s = uri("bash:"..cmd).read_text()
-        logger.info("create domain key"..s)
+				-- We've set up nginx to serve from our temp root, now we need to
+				-- create a *domain key*, which we then use to sign our cert.
+				local cmd = "openssl genrsa 4096 > "..key_file_str
+				local s = uri("bash:"..cmd).read_text()
+				logger.info("create domain key\n"..s)
 
-        -- create the cert, signed with the key we just made
-        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 domain key"..s)
+				-- create the cert, signed with the key we just made
+				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)
 
-        -- Finally, get our cert signed by letsencrypt.
-        local cmd = [[
-        python acme_tiny.py --account-key ./local/tiny_account.key \
-        --csr ]]..csr_file_str..[[ \
-        --acme-dir ]]..acme_challenges..[[ \
-        > ./local/]]..domain..[[_signed_chain.crt
-        ]]
-        local s = uri("bash:"..cmd).read_text()
-        logger.info("create domain key"..s)
+				-- Finally, get our cert signed by letsencrypt.
+				local cmd = [[
+					python acme_tiny.py --account-key ./local/tiny_account.key \
+					--csr ]]..csr_file_str..[[ \
+					--acme-dir ]]..acme_challenges..[[ \
+				]]
+				if dry_run then
+					cmd = cmd.." --directory-url "..dry_run_dir_url
+				end
+				cmd = cmd.."> "..local_cer_file_str
 
-
-
-        -- testing if there is an http server on the domain
-        -- that is serving files
-				local cmd = "./testhttp.sh "..domain
 				local s = uri("bash:"..cmd).read_text()
-				logger.info("test if http up")
-        -- The above http request is the only thing that causes a recursion
-        -- so it is safe to delete the guard here.
-        guard_uri.delete()
+				logger.info("get cert signed by letsencrypt\n"..s)
+
+				-- The above http requests made by acme_tiny are the only thing
+				-- that could cause a recursion so it is safe to delete the guard here.
+				guard_uri.delete()
 
-				local cmd = [[
-          ./local_https.sh "]]..domain..[["
-        ]]
-				local s = uri("bash:"..cmd).read_text()
-				logger.info("issue local certificate")
-			else
-        -- 1. Generate certificate
-        -- 2. Put it in the 
-          local cmd = [[
-            ./acme.sh --debug --issue -d "]]..domain..[[" --stateless --server letsencrypt \
-              --config-home "]]..top_dir..[[/local/letsencrypt/config" \
-              --key-file "]]..key_file.canonical().to_string()..[[" \
-              --ca-file "]]..local_ca_file.canonical().to_string()..[[" \
-              --fullchain-file "]]..local_cer_file.canonical().to_string()..[[" ;
-          ]]
-          local s = uri("bash:"..cmd).read_text()
+				-- We now have our certificate!
+				-- Now we just need to generate the nginx config
+				-- that uses it, place it in luan/host/sites/*/nginx.ssl.conf
+				-- and tell luan-host to reload nginx.
+
+				-- local cmd = [[
+				--     ./acme.sh --debug --issue -d "]]..domain..[[" --stateless --server letsencrypt \
+				--       --config-home "]]..luanhost_dir..[[/local/letsencrypt/config" \
+				--       --key-file "]]..key_file.canonical().to_string()..[[" \
+				--       --ca-file "]]..local_ca_file.canonical().to_string()..[[" \
+				--       --fullchain-file "]]..local_cer_file.canonical().to_string()..[[" ;
+				--   ]]
+				--   local s = uri("bash:"..cmd).read_text()
 				logger.info("issue certificate "..s)
 			end
 			if key_file.exists() and local_cer_file.exists() then
 				changed = true
-        -- the nginx config only requires 2 files:
-        -- fullchain.cer and DOMAIN.key
+				-- the nginx config only requires 2 files:
+				-- fullchain.cer and DOMAIN.key
 				local conf = load_file "file:startup/nginx/nginx.ssl.conf.luan"
-				local nginx = ` conf(top_dir,domain) `
+				local nginx = ` conf(luanhost_dir,domain) `
 				nginx_file.write(nginx)
 			end
 		end
@@ -162,7 +167,7 @@
 			local_cer_file.delete()
 			local_ca_file.delete()
 			local ptn = domain.."."
-			for _, file in ipairs(dir.children()) do
+			for _, file in ipairs(site_dir.children()) do
 				if starts_with(file.name(),ptn) then
 					file.delete()
 				end
@@ -171,7 +176,7 @@
 	end
 	if changed then
 		local cmd = [[
-sudo $(which nginx) -t -c "]]..top_dir..[[/local/nginx.conf" && sudo $(which nginx) -s reload;
+sudo $(which nginx) -t -c "]]..luanhost_dir..[[/local/nginx.conf" && sudo $(which nginx) -s reload;
 ]]
 		local s = uri("bash:"..cmd).read_text()
 		logger.info("reload_nginx "..s)