Merge pull request #2676 from ToledoEM/nginx_wp

NGINX webserver and Proxy Manager
This commit is contained in:
Alexandre
2026-05-10 04:04:10 +02:00
committed by GitHub
10 changed files with 413 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
# Changelog
## Unreleased
- Fix Codacy style warnings: add blank lines around lists in README
## 2.14.0
- Initial release wrapping jc21/nginx-proxy-manager:latest
- NPM Admin UI on port 81; HTTP on port 80; HTTPS on port 443
- Configurable static file server via NPM's default_host nginx config
- Supports /share, /media, /config paths; warns for /mnt; blocks dangerous system paths
- NPM state persisted via Docker volume (managed by HA Supervisor)
- Supports amd64 and aarch64

View File

@@ -0,0 +1,23 @@
ARG BUILD_FROM=jc21/nginx-proxy-manager:latest
FROM ${BUILD_FROM}
# NPM is Debian-based; install jq for options parsing + stub with-contenv if absent
# hadolint ignore=DL3008
RUN apt-get update \
&& apt-get install -y --no-install-recommends jq \
&& rm -rf /var/lib/apt/lists/* \
&& if ! command -v with-contenv >/dev/null 2>&1; then \
printf '#!/usr/bin/env bash\nexec "$@"\n' > /usr/bin/with-contenv \
&& chmod +x /usr/bin/with-contenv; \
fi
COPY run.sh /npm-addon-init.sh
RUN chmod +x /npm-addon-init.sh
ARG BUILD_VERSION
LABEL \
io.hass.version="${BUILD_VERSION}" \
io.hass.type="addon" \
io.hass.arch="aarch64|amd64"
ENTRYPOINT ["/npm-addon-init.sh"]

View File

@@ -0,0 +1,85 @@
# Nginx Proxy Manager + Static Web Server
[Nginx Proxy Manager](https://nginxproxymanager.com/) with a configurable static file server for Home Assistant. Manage reverse proxies and SSL certificates via the web UI (port 81) while serving static files from your HA storage (port 80).
## Why This Add-on?
Home Assistant's built-in folder server has limitations:
- Can only serve from a single folder at a time
- No reverse proxy capabilities
- No SSL/HTTPS support
- Limited HTTP headers and caching control
- No support for URL rewriting or advanced routing
This add-on combines a full reverse proxy with a proper static file server, allowing you to host multiple sites, manage SSL certificates, and proxy traffic to other services from a single interface.
[![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons)
## Features
- Reverse proxy manager (web UI on port 81)
- Static file server (port 80)
- HTTPS support (port 443)
- Persistent configuration and SSL certificates
- Works on amd64 and aarch64
## Installation
1. Add this repository to Home Assistant via Settings → Add-ons → Add-on Store → ⋮ → Manage repositories (or use the button above).
2. Install Nginx Proxy Manager + Static Web Server.
3. Configure options (defaults work for first run).
4. Start the add-on.
5. Open `http://<HA_IP>:81` to access the admin UI.
## Configuration
| Option | Default | Description |
|--------|---------|-------------|
| `static_site_enabled` | `true` | Enable or disable the static file server on port 80 |
| `static_site_root` | `/share/www` | Path to serve static files from |
| `static_site_prefix` | `/` | URL prefix for the static site (e.g., `/www` for `http://host/www`) |
| `log_level` | `info` | Logging verbosity: `info`, `debug`, `warn`, or `error` |
## Default Credentials
First login (port 81):
- Email: `admin@example.com`
- Password: `changeme`
Change these on first login.
## Path Validation
Paths are validated at startup for safe access:
- `/share`, `/media`, `/config` fully supported (HA maps these automatically)
- `/mnt` allowed but not mapped by HA. Create a symlink under `/share` or `/media` if files are inaccessible.
- `/`, `/etc`, `/bin`, `/lib`, `/proc`, `/sys` blocked (will prevent startup)
## Examples
**Reverse proxy:**
1. Open the admin UI at `http://<HA_IP>:81`
2. Add a proxy host pointing to another service
3. Configure SSL via Let's Encrypt (optional)
**Static website:**
1. Place files in `/share/www` (or your configured `static_site_root`)
2. Access at `http://<HA_IP>:80/` (or your configured `static_site_prefix`)
You can run both simultaneously on the same ports.
## Notes
- Wraps `jc21/nginx-proxy-manager` upstream image
- State persists in `/data` (managed by HA Supervisor)
- Custom AppArmor profile restricts system access
- Edit NPM's database directly via SSH if needed
## Issues
For problems with this add-on (not the upstream NPM software), open an issue and tag @ToledoEM.

View File

@@ -0,0 +1,104 @@
#include <tunables/global>
profile nginx-proxy-manager flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/openssl>
# Core capabilities
capability chown,
capability dac_override,
capability net_bind_service,
capability setfcap,
capability setgid,
capability setuid,
capability sys_chroot,
capability kill,
# Process and memory management
capability sys_resource,
# Deny dangerous capabilities
deny capability dac_read_search,
deny capability linux_immutable,
deny capability mac_admin,
deny capability mac_override,
deny capability sys_admin,
deny capability sys_boot,
deny capability sys_module,
deny capability sys_rawio,
deny capability syslog,
# Network
network inet stream,
network inet dgram,
network inet6 stream,
network inet6 dgram,
network unix stream,
network unix dgram,
# /data - addon config (read/write)
/data/ r,
/data/** rwk,
# /share - Home Assistant storage (read/write)
/share/ r,
/share/** rwk,
# /media - Home Assistant media (read/write)
/media/ r,
/media/** rwk,
# /config - Home Assistant config (read/write)
/config/ r,
/config/** rwk,
# /addon_configs - addon instance config
/addon_configs/ r,
/addon_configs/** rwk,
# /etc/letsencrypt - SSL certs
/etc/letsencrypt/ r,
/etc/letsencrypt/** rwk,
# /proc and /sys
@{PROC}/ r,
@{PROC}/** rw,
@{sys}/ r,
@{sys}/** rw,
# Temporary files
/tmp/ r,
/tmp/** rwk,
/var/tmp/ r,
/var/tmp/** rwk,
# Basic system access
/bin/bash ix,
/bin/sh ix,
/bin/ls ix,
/bin/cat ix,
/bin/sed ix,
/usr/bin/jq ix,
# Nginx binary and libraries
/usr/sbin/nginx ix,
/usr/local/sbin/nginx ix,
/usr/lib/** rm,
/lib/** rm,
/usr/local/lib/** rm,
# Allow reading app-specific configs (read-only)
/etc/nginx/ r,
/etc/nginx/** r,
/var/log/ r,
/var/log/** w,
# Deny sensitive system areas
deny /root/** rwkl,
deny /home/** rwkl,
deny /proc/sysrq-trigger rwkl,
deny /sys/firmware/** rwkl,
deny /sys/kernel/security/** rwkl,
deny /sys/kernel/debug/** rwkl,
}

View File

@@ -0,0 +1,4 @@
---
build_from:
aarch64: jc21/nginx-proxy-manager:latest
amd64: jc21/nginx-proxy-manager:latest

View File

@@ -0,0 +1,40 @@
name: "Nginx Proxy Manager + Static Web Server"
slug: nginx_webserver_proxy
description: "Nginx Proxy Manager with a built-in configurable static file server. Manage reverse proxies via NPM UI on port 81 while serving files from HA storage on port 80."
version: "2.14.0"
url: "https://github.com/alexbelgium/hassio-addons/tree/master/nginx_webserver_proxy"
arch:
- amd64
- aarch64
startup: services
init: false
ports:
80/tcp: 80
81/tcp: 81
443/tcp: 443
ports_description:
80/tcp: "HTTP (static site + NPM proxy hosts)"
81/tcp: "NPM Admin Web UI"
443/tcp: "HTTPS (NPM proxy hosts)"
webui: "http://[HOST]:[PORT:81]"
map:
- addon_config:rw
- share:rw
- media:rw
options:
static_site_enabled: true
static_site_root: "/share/www"
static_site_prefix: "/"
log_level: "info"
schema:
static_site_enabled: bool
static_site_root: str
static_site_prefix: str
log_level: list(info|debug|warn|error)
image: "ghcr.io/alexbelgium/nginx_webserver_proxy-{arch}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

118
nginx_webserver_proxy/run.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/with-contenv bash
# shellcheck shell=bash
set -Eeuo pipefail
# HA Supervisor places options.json at /data/options.json.
# NPM also uses /data for its database and generated configs.
# The /data Docker VOLUME is persisted automatically by HA Supervisor between restarts.
OPTIONS_JSON="/data/options.json"
log() { echo "[nginx-proxy-manager-addon] $*"; }
warn() { echo "[nginx-proxy-manager-addon] WARN: $*" >&2; }
die() {
echo "[nginx-proxy-manager-addon] ERROR: $*" >&2
exit 1
}
read_opt() {
jq -er --arg k "$1" '.[$k]' "$OPTIONS_JSON" 2> /dev/null || true
}
# ---------------------------------------------------------------------------
# Step 1: Read add-on options
# ---------------------------------------------------------------------------
[[ -f "$OPTIONS_JSON" ]] || die "Missing options file at ${OPTIONS_JSON}"
STATIC_ENABLED="$(read_opt static_site_enabled)"
STATIC_ENABLED="${STATIC_ENABLED:-true}"
STATIC_ROOT_RAW="$(read_opt static_site_root)"
STATIC_ROOT_RAW="${STATIC_ROOT_RAW:-/share/www}"
STATIC_PREFIX="$(read_opt static_site_prefix)"
STATIC_PREFIX="${STATIC_PREFIX:-/}"
LOG_LEVEL="$(read_opt log_level)"
LOG_LEVEL="${LOG_LEVEL:-info}"
# ---------------------------------------------------------------------------
# Step 2: Validate static_site_root
# ---------------------------------------------------------------------------
normalize_path() {
if command -v realpath > /dev/null 2>&1; then
realpath -m -- "$1"
else
local p="${1%/}"
[[ "$p" == /* ]] || p="/$p"
printf '%s\n' "$p"
fi
}
STATIC_ROOT="$(normalize_path "$STATIC_ROOT_RAW")"
case "$STATIC_ROOT" in
/ | /etc | /etc/* | /bin | /bin/* | /sbin | /sbin/* | /lib | /lib/* | /proc | /proc/* | /sys | /sys/*)
die "static_site_root '${STATIC_ROOT}' is a dangerous system path. Use /share, /media, /config, or /mnt."
;;
esac
case "$STATIC_ROOT" in
/share | /share/* | /media | /media/* | /config | /config/*)
log "static_site_root: ${STATIC_ROOT}"
;;
/mnt | /mnt/*)
warn "static_site_root '${STATIC_ROOT}' is under /mnt — HA cannot map /mnt."
warn "If files are inaccessible, create a symlink under /share or /media pointing to your /mnt path."
;;
*)
warn "static_site_root '${STATIC_ROOT}' is outside standard HA-mapped paths — may not be accessible."
;;
esac
[[ "$STATIC_PREFIX" == /* ]] || die "static_site_prefix must start with '/'. Got: '${STATIC_PREFIX}'"
# ---------------------------------------------------------------------------
# Step 3: Write static-site server block into NPM's default_host dir
# NPM includes /data/nginx/default_host/*.conf for the port 80 default server.
# Writing here replaces NPM's "Congratulations" page with our static file server.
# ---------------------------------------------------------------------------
DEFAULT_HOST_DIR="/data/nginx/default_host"
mkdir -p "$DEFAULT_HOST_DIR"
STATIC_CONF="${DEFAULT_HOST_DIR}/static_site.conf"
if [[ "$STATIC_ENABLED" == "true" ]]; then
mkdir -p "$STATIC_ROOT" 2> /dev/null \
|| warn "Could not create '${STATIC_ROOT}' (may not be mounted yet)"
cat > "$STATIC_CONF" << NGINX_EOF
# Managed by nginx_webserver_proxy add-on — regenerated on every container start.
# Edit options in the HA add-on configuration UI, not here.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location ${STATIC_PREFIX} {
alias ${STATIC_ROOT}/;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
try_files \$uri \$uri/ =404;
access_log /proc/1/fd/1;
error_log /proc/1/fd/1 warn;
}
}
NGINX_EOF
log "Static site config written → ${STATIC_CONF}"
else
printf '# Static site disabled by add-on options\n' > "$STATIC_CONF"
log "Static site disabled"
fi
# ---------------------------------------------------------------------------
# Step 4: Hand off to NPM's own s6-overlay boot
# ---------------------------------------------------------------------------
log "static_site_root=${STATIC_ROOT} prefix=${STATIC_PREFIX} log_level=${LOG_LEVEL}"
# NPM's prepare service requires /etc/letsencrypt to exist.
# HA Supervisor maps the ssl volume there automatically; for other environments create it.
mkdir -p /etc/letsencrypt
log "Handing off to NPM: exec /init"
exec /init

View File

@@ -0,0 +1,25 @@
configuration:
static_site_enabled:
name: Enable static file server
description: Serve files from static_site_root on port 80. NPM proxy functionality is always active regardless of this setting.
static_site_root:
name: Static site root path
description: >
Absolute path to the directory to serve as the static site.
/share, /media, and /config are fully mapped by HA.
/mnt is allowed with a warning — if files are inaccessible, create a symlink under /share or /media pointing to your /mnt path.
Dangerous system paths (/, /etc, /bin, /lib, /proc, /sys) are blocked and will prevent startup.
static_site_prefix:
name: URL prefix
description: >
The URL path at which static files are served on port 80.
Default "/" serves files at the root. Use a sub-path like "/files/" to restrict
static serving to that location, leaving other paths available for NPM proxy hosts.
log_level:
name: Log level
description: Controls the verbosity of add-on logging.
network:
80/tcp: HTTP — static file server and NPM proxy hosts
81/tcp: NPM Admin Web UI
443/tcp: HTTPS — NPM proxy hosts