add nginx and cert subcommands to service.sh
This commit is contained in:
+1
-1
@@ -92,7 +92,7 @@ parses it to determine the action:
|
||||
|
||||
- `deploy-<app>` — deploy a specific app
|
||||
- `deploy-nginx` — deploy nginx (fails if certs are missing)
|
||||
- `cert-<domain>` — issue a cert only (via `certbot --webroot`, zero downtime)
|
||||
- `cert-<domain>` — issue a cert only (via `certbot --webroot`, zero downtime; subdomains like `garage.hantim.net` skip the `www.` variant)
|
||||
- `provision` — run `configure.sh`
|
||||
|
||||
## SSL certificate handling
|
||||
|
||||
@@ -9,7 +9,7 @@ for technical deep-dives, USECASES.md for expected behaviors.
|
||||
- `scripts/configure.sh` -- Idempotent server config (firewall, certbot, start services; CI-safe)
|
||||
- `scripts/deploy.sh` -- SSH-triggered deploy + cert issuance + provision (deploy-*, cert-*, provision commands)
|
||||
- `tools/app.sh` -- App provisioning by subcommand (dns, repo, files, cert, garage, build, verify, all)
|
||||
- `tools/service.sh` -- Manage Docker services by subcommand (dns, files, all)
|
||||
- `tools/service.sh` -- Manage Docker services by subcommand (dns, files, nginx, cert, all)
|
||||
- `tools/remove-app.sh` -- Remove a static site (local files + Gitea repo)
|
||||
- `docker/nginx/conf.d/` -- Per-app nginx server blocks
|
||||
- `docker/<domain>/compose.yml` -- Per-app compose files
|
||||
|
||||
@@ -29,7 +29,7 @@ scripts/
|
||||
deploy.sh # Deploy + provision (called via SSH)
|
||||
tools/
|
||||
app.sh # Add a new static site (run from dev machine)
|
||||
service.sh # Manage Docker services by subcommand (dns, files, all)
|
||||
service.sh # Manage Docker services by subcommand (dns, files, nginx, cert, all)
|
||||
remove-app.sh # Remove a static site (run from dev machine)
|
||||
docker/
|
||||
nginx/ # Reverse proxy (nginx:alpine) + SSL config
|
||||
|
||||
+14
-1
@@ -89,7 +89,20 @@ for stateless static sites.
|
||||
- Existing certs skipped
|
||||
- Services restarted
|
||||
|
||||
## 8. Upload media files
|
||||
## 8. Add a new Docker service
|
||||
|
||||
**Trigger:** `./tools/service.sh all <name> <port>` from dev machine.
|
||||
|
||||
**Prerequisites:** `bws`/`jq`/`dig` installed.
|
||||
|
||||
**Expected outcome:**
|
||||
- DNS A record created for `<name>.hantim.net`
|
||||
- Compose file and deploy workflow scaffolded
|
||||
- Nginx conf created proxying `<name>.hantim.net` to port `<port>`
|
||||
- SSL cert issued for `<name>.hantim.net` (no www variant)
|
||||
- Service ready for customization (edit compose.yml image, add `.env.keys` if needed)
|
||||
|
||||
## 9. Upload media files
|
||||
|
||||
**Trigger:** `aws s3 cp` or `aws s3 sync` to `s3://example.com/`.
|
||||
|
||||
|
||||
+11
-2
@@ -6,12 +6,21 @@ CMD="${SSH_ORIGINAL_COMMAND:-${1:-}}"
|
||||
if [[ "$CMD" =~ ^cert-[a-zA-Z0-9._-]+$ ]]; then
|
||||
APP="${CMD#cert-}"
|
||||
|
||||
# Subdomains (e.g., garage.hantim.net) don't have www variants
|
||||
if [[ "$APP" == *.*.* ]]; then
|
||||
CERT_DOMAINS="-d $APP"
|
||||
SERVER_NAMES="$APP"
|
||||
else
|
||||
CERT_DOMAINS="-d $APP -d www.$APP"
|
||||
SERVER_NAMES="$APP www.$APP"
|
||||
fi
|
||||
|
||||
# Write temporary HTTP-only config so nginx can serve ACME challenges
|
||||
cat > "/opt/hantim/docker/nginx/conf.d/$APP.conf" <<NGINXCONF
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $APP www.$APP;
|
||||
server_name $SERVER_NAMES;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
@@ -27,7 +36,7 @@ NGINXCONF
|
||||
docker exec nginx nginx -t && docker exec nginx nginx -s reload
|
||||
certbot certonly --webroot -w /opt/hantim/docker/nginx/certbot/www \
|
||||
--non-interactive --agree-tos -m timothykim@fastmail.fm \
|
||||
--cert-name "$APP" -d "$APP" -d "www.$APP"
|
||||
--cert-name "$APP" $CERT_DOMAINS
|
||||
git -C /opt/hantim restore "docker/nginx/conf.d/$APP.conf" 2>/dev/null || rm -f "/opt/hantim/docker/nginx/conf.d/$APP.conf"
|
||||
trap - EXIT
|
||||
docker exec nginx nginx -t && docker exec nginx nginx -s reload
|
||||
|
||||
+110
-7
@@ -5,16 +5,20 @@ usage() {
|
||||
echo "Usage: ./tools/service.sh <command> <name>"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " dns <name> Create A record for <name>.hantim.net"
|
||||
echo " files <name> Create compose.yml and deploy workflow"
|
||||
echo " all <name> Run dns + files"
|
||||
echo " dns <name> Create A record for <name>.hantim.net"
|
||||
echo " files <name> Create compose.yml and deploy workflow"
|
||||
echo " nginx <name> <port> Create nginx conf for <name>.hantim.net"
|
||||
echo " cert <name> Issue SSL certificate for <name>.hantim.net"
|
||||
echo " all <name> <port> Run dns + files + nginx + cert"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " ./tools/service.sh files garage"
|
||||
echo " ./tools/service.sh dns garage # garage.hantim.net -> server IP"
|
||||
echo " ./tools/service.sh all garage"
|
||||
echo " ./tools/service.sh dns garage # garage.hantim.net -> server IP"
|
||||
echo " ./tools/service.sh nginx garage 3903 # create nginx conf"
|
||||
echo " ./tools/service.sh cert garage # issue SSL cert"
|
||||
echo " ./tools/service.sh all garage 3903"
|
||||
echo ""
|
||||
echo "Requires: bws, jq, dig (for dns)"
|
||||
echo "Requires: bws, jq, dig (for dns/cert)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -80,6 +84,25 @@ require_dig() {
|
||||
fi
|
||||
}
|
||||
|
||||
resolve_server_ip() {
|
||||
require_dig
|
||||
SERVER_IP=$(dig +short hantim.net | head -1)
|
||||
if [ -z "$SERVER_IP" ]; then
|
||||
echo "Error: Could not resolve hantim.net to get server IP."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
setup_deploy_key() {
|
||||
require_bws
|
||||
echo "==> Fetching deploy key..."
|
||||
DEPLOY_KEY=$(bws_get "hantim-deploy-ssh-private-key")
|
||||
DEPLOY_KEY_FILE=$(mktemp)
|
||||
echo "$DEPLOY_KEY" > "$DEPLOY_KEY_FILE"
|
||||
chmod 600 "$DEPLOY_KEY_FILE"
|
||||
trap "rm -f $DEPLOY_KEY_FILE" EXIT
|
||||
}
|
||||
|
||||
validate_name() {
|
||||
local name="$1"
|
||||
if [ -z "$name" ]; then
|
||||
@@ -228,11 +251,73 @@ OUTER
|
||||
echo " configure.sh will generate the .env file on the server automatically."
|
||||
}
|
||||
|
||||
cmd_nginx() {
|
||||
local name="$1"
|
||||
local port="$2"
|
||||
local fqdn="$name.hantim.net"
|
||||
|
||||
if [ -e "$REPO_ROOT/docker/nginx/conf.d/$fqdn.conf" ]; then
|
||||
echo " docker/nginx/conf.d/$fqdn.conf already exists, skipping."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "==> Creating docker/nginx/conf.d/$fqdn.conf..."
|
||||
cat > "$REPO_ROOT/docker/nginx/conf.d/$fqdn.conf" <<NGINX
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name $fqdn;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$fqdn\$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
http2 on;
|
||||
server_name $fqdn;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/$fqdn/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/$fqdn/privkey.pem;
|
||||
|
||||
include /etc/nginx/conf.d/security-headers.inc;
|
||||
|
||||
location / {
|
||||
proxy_pass http://$name:$port;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
NGINX
|
||||
}
|
||||
|
||||
cmd_cert() {
|
||||
local name="$1"
|
||||
local fqdn="$name.hantim.net"
|
||||
|
||||
resolve_server_ip
|
||||
setup_deploy_key
|
||||
|
||||
echo "==> Issuing SSL certificate for $fqdn via deploy user..."
|
||||
ssh -o StrictHostKeyChecking=accept-new -i "$DEPLOY_KEY_FILE" deploy@"$SERVER_IP" "cert-$fqdn"
|
||||
echo " Certificate issued."
|
||||
}
|
||||
|
||||
cmd_all() {
|
||||
local name="$1"
|
||||
local port="$2"
|
||||
|
||||
cmd_dns "$name"
|
||||
cmd_files "$name"
|
||||
cmd_nginx "$name" "$port"
|
||||
cmd_cert "$name"
|
||||
}
|
||||
|
||||
# --- Dispatch ---
|
||||
@@ -246,9 +331,27 @@ case "$COMMAND" in
|
||||
validate_name "${2:-}"
|
||||
cmd_files "${2:-}"
|
||||
;;
|
||||
nginx)
|
||||
validate_name "${2:-}"
|
||||
if [ -z "${3:-}" ]; then
|
||||
echo "Error: port is required for nginx command."
|
||||
echo " Usage: ./tools/service.sh nginx <name> <port>"
|
||||
exit 1
|
||||
fi
|
||||
cmd_nginx "${2:-}" "${3:-}"
|
||||
;;
|
||||
cert)
|
||||
validate_name "${2:-}"
|
||||
cmd_cert "${2:-}"
|
||||
;;
|
||||
all)
|
||||
validate_name "${2:-}"
|
||||
cmd_all "${2:-}"
|
||||
if [ -z "${3:-}" ]; then
|
||||
echo "Error: port is required for all command."
|
||||
echo " Usage: ./tools/service.sh all <name> <port>"
|
||||
exit 1
|
||||
fi
|
||||
cmd_all "${2:-}" "${3:-}"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $COMMAND"
|
||||
|
||||
Reference in New Issue
Block a user