chore: sync ISO build configs with live server state

- Add nginx snippets (PWA, HTTPS app proxies) to image-recipe/configs/
- Update build script Dockerfile to install openssl, generate self-signed
  SSL cert, copy nginx snippets, and create Cloud dummy directories
- Ensures fresh ISO installs have working HTTPS, PWA installability,
  and pre-created Cloud storage folders

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian 2026-03-05 08:34:53 +00:00
parent 0bc7251e22
commit 1b2021cece
4 changed files with 222 additions and 3 deletions

View File

@ -113,7 +113,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy
- **Change**: Add security flags to default container `run_args`: `--read-only` (with tmpfs for /tmp), `--cap-drop=ALL`, `--security-opt=no-new-privileges:true`. Create per-app capability mapping for apps that need specific caps.
- **Verify**: Install an app, `podman inspect` shows security constraints
### Task 20: ISO build script sync
### Task 20: ISO build script sync [DONE]
- **Files**: `image-recipe/configs/nginx-archipelago.conf`, `image-recipe/configs/archipelago.service`
- **Change**: Ensure all recent nginx changes (new app proxies, AIUI proxies) are in the image-recipe config. Verify systemd service is current. Check that the auto-installer includes dummy content files for Cloud sections.
- **Verify**: Configs match live server state

View File

@ -134,7 +134,7 @@ FROM debian:bookworm
ENV DEBIAN_FRONTEND=noninteractive
# Install all packages we need including nginx and podman
# Install all packages we need including nginx, podman, and openssl (for self-signed certs)
RUN apt-get update && apt-get install -y \
linux-image-amd64 \
grub-efi-amd64 \
@ -153,6 +153,7 @@ RUN apt-get update && apt-get install -y \
htop \
vim-tiny \
ca-certificates \
openssl \
locales \
console-setup \
keyboard-configuration \
@ -180,6 +181,17 @@ RUN rm -f /etc/nginx/sites-enabled/default
COPY nginx-archipelago.conf /etc/nginx/sites-available/archipelago
RUN ln -sf /etc/nginx/sites-available/archipelago /etc/nginx/sites-enabled/archipelago
# Install nginx snippets (PWA config, HTTPS app proxies)
COPY snippets/ /etc/nginx/snippets/
# Generate self-signed SSL certificate for HTTPS (PWA install requires secure context)
RUN mkdir -p /etc/archipelago/ssl && \
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/archipelago/ssl/archipelago.key \
-out /etc/archipelago/ssl/archipelago.crt \
-subj "/C=XX/ST=Bitcoin/L=Node/O=Archipelago/CN=archipelago" && \
chmod 600 /etc/archipelago/ssl/archipelago.key
# Create archipelago systemd service
COPY archipelago.service /etc/systemd/system/archipelago.service
@ -189,10 +201,11 @@ RUN systemctl enable NetworkManager || true && \
systemctl enable nginx || true && \
systemctl enable archipelago || true
# Create directories
# Create directories (including Cloud storage for FileBrowser)
RUN mkdir -p /var/lib/archipelago/{data,config,containers} && \
mkdir -p /etc/archipelago && \
mkdir -p /opt/archipelago/{bin,scripts,web-ui} && \
mkdir -p /var/lib/archipelago/data/cloud/{Documents,Photos,Music,Videos,Downloads} && \
chown -R archipelago:archipelago /var/lib/archipelago /opt/archipelago
# Clean up
@ -200,6 +213,16 @@ RUN apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
DOCKERFILE
# Copy nginx snippets for HTTPS (PWA, app proxies)
if [ -d "$SCRIPT_DIR/configs/snippets" ]; then
mkdir -p "$WORK_DIR/snippets"
cp "$SCRIPT_DIR/configs/snippets/"*.conf "$WORK_DIR/snippets/" 2>/dev/null || true
echo " Using nginx snippets from configs/snippets/"
else
mkdir -p "$WORK_DIR/snippets"
echo " ⚠ No nginx snippets found, HTTPS features may not work"
fi
# Use nginx config from configs/ (includes app proxies for Nextcloud, Vaultwarden, Immich, Penpot)
if [ -f "$SCRIPT_DIR/configs/nginx-archipelago.conf" ]; then
cp "$SCRIPT_DIR/configs/nginx-archipelago.conf" "$WORK_DIR/nginx-archipelago.conf"

View File

@ -0,0 +1,180 @@
# App proxies for HTTPS - avoids mixed content when embedding apps from HTTPS page
# Complete list for all apps that may be launched from the UI
location /app/grafana/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/uptime-kuma/ {
proxy_pass http://127.0.0.1:3001/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/searxng/ {
proxy_pass http://127.0.0.1:8888/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/portainer/ {
proxy_pass http://127.0.0.1:9000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/filebrowser/ {
client_max_body_size 10G;
proxy_pass http://127.0.0.1:8083/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_request_buffering off;
}
location /app/endurain/ {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/lnd/ {
proxy_pass http://127.0.0.1:8081/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /app/onlyoffice/ {
proxy_pass http://127.0.0.1:9980/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/jellyfin/ {
proxy_pass http://127.0.0.1:8096/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/photoprism/ {
proxy_pass http://127.0.0.1:2342/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/mempool/ {
proxy_pass http://127.0.0.1:4080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /app/fedimint/ {
proxy_pass http://127.0.0.1:8175/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /app/tailscale/ {
proxy_pass http://127.0.0.1:8240/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/ollama/ {
proxy_pass http://127.0.0.1:11434/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/bitcoin-ui/ {
proxy_pass http://127.0.0.1:8334/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/electrs/ {
proxy_pass http://127.0.0.1:50002/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}
location /app/nginx-proxy-manager/ {
proxy_pass http://127.0.0.1:81/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
}

View File

@ -0,0 +1,16 @@
# PWA installability - required for Install (not just Add to Home Screen) on Android
# Manifest MUST be served with application/manifest+json - Chrome rejects otherwise
location = /manifest.webmanifest {
default_type application/manifest+json;
add_header Cache-Control "public, max-age=0, must-revalidate";
}
# Service worker - no cache so updates apply
location ~ ^/(sw\.js|workbox-.*\.js|registerSW\.js)$ {
add_header Content-Type application/javascript;
add_header Service-Worker-Allowed /;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# index.html - avoid aggressive cache for PWA updates
location = /index.html {
add_header Cache-Control "public, max-age=0, must-revalidate";
}