Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 13 additions & 18 deletions docker_ignis/ignis.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ARG BASE_IMG="node"
FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG}

LABEL maintainer="postmaster@labnow.ai"
LABEL com.thiefling.ignis.obsidian-version="1.12.7"
# LABEL com.thiefling.ignis.obsidian-version="1.12.7"

ENV NODE_ENV=production
ENV PORT=8080
Expand All @@ -15,29 +15,24 @@ ENV OBSIDIAN_ASSETS_PATH=/app/obsidian-app
ENV PUID=1000
ENV PGID=1000

# Install runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl gosu \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy utility scripts
COPY work /opt/ignis/

# Clone and build ignis from source
RUN set -eux \
&& chmod +x /opt/ignis/*.sh \
&& git clone --depth 1 --branch main https://github.com/Nystik-gh/ignis.git . \
&& mv /opt/ignis/start-ignis.sh /app/

# Install build-time dependencies explicitly: NODE_ENV=production would otherwise omit esbuild.
RUN set -eux \
&& npm install --include=dev --prefer-offline --no-audit --fetch-retries=5 \
&& npm run build \
&& chmod +x /app/apps/ignis-server/scripts/entrypoint.sh \
&& ln -sf /app/start-ignis.sh /usr/local/bin/ignis-server \
&& npm cache clean --force
&& apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gosu \
## Clone and build ignis from source
&& chmod +x /opt/ignis/*.sh \
&& git clone --depth 1 --branch main https://github.com/Nystik-gh/ignis.git . \
&& mv /opt/ignis/start-ignis.sh /app/ \
## Install build-time dependencies explicitly: NODE_ENV=production would otherwise omit esbuild.
&& npm install --include=dev --prefer-offline --no-audit --fetch-retries=5 \
&& npm run build \
&& chmod +x /app/apps/ignis-server/scripts/entrypoint.sh \
&& ln -sf /app/start-ignis.sh /usr/local/bin/ignis-server \
&& npm cache clean --force \
&& source /opt/utils/script-utils.sh && install__clean

# Data volumes
VOLUME ["/vaults", "/app/obsidian-app", "/app/data"]
Expand Down
81 changes: 50 additions & 31 deletions docker_openresty/README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,94 @@
# OpenResty with Lua & acme.sh

`openresty` is a full-fledged web platform that integrates the standard Nginx core, LuaJIT, and acme.sh SSL certificate management tools.
`openresty` integrates the Nginx core, LuaJIT, and acme.sh SSL certificate management into a single web platform.

---

## 1. Port Configuration
## 1. Ports

- **`80` (HTTP)**: Serves standard HTTP proxy requests, acme-challenge routing, and redirect logic.
- **`443` (HTTPS)**: Serves SSL-terminated connections (configured inside custom proxy templates).
- **`80` (HTTP)**HTTP proxying, ACME HTTP-01 challenges, and redirects.
- **`443` (HTTPS)** SSL-terminated connections.

---

## 2. Data Persistence (Volumes)
## 2. Template Pipeline

To store custom configuration templates and SSL certificates, mount the following directories:
Nginx configuration is generated at container start from profile-selected templates.

- **`/var/log/nginx`**: Directory for access and error log outputs.
- **`/var/cache/nginx`**: Proxy cache directories.
- **`/etc/nginx/templates/`**: Directory containing `.template` files for environment variables substitutions.
- **`/etc/nginx/ssl`**: Stores certificates and private keys generated by acme.sh.
- **`/root/.acme.sh`**: Houses acme.sh configs, renewal certificates, and API secrets.
1. `PROFILE_NGINX` (optional) selects a list file at `/etc/nginx/profiles/<profile>.list`.
2. Each non-comment line names a flat template filename from `/etc/nginx/templates.repo/`:
- `*.conf.template` → HTTP output (`/etc/nginx/conf.d/`)
- `*.conf.stream-template` → stream output (`/etc/nginx/stream-conf.d/`)
3. `20-prepare-template-files.sh` copies the listed templates into the internal `/etc/nginx/templates/` staging directory (tmpfs, cleared each start).
4. `21-envsubst-on-templates.sh` renders them via `envsubst` into the output directories.

Template variables (e.g. `SERVER_DOMAIN_NAME`, `SERVER_HOME_REDIRECT`) are supplied via `env_file`. Blank lines and `#` comments are ignored. When `PROFILE_NGINX` is unset, or the profile/source directories are empty, preparation is skipped and nginx starts with its default configuration.

---

## 3. Resolver

Set `NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1` to write `resolver ... valid=10s ipv6=off;` into `/etc/nginx/conf.d/include/resolvers.conf`, populated from the container's DNS servers (fallback: Docker's embedded `127.0.0.11`).

---

## 4. Volumes

- **`/var/log/nginx`** — access/error logs.
- **`/var/cache/nginx`** — persistent proxy cache and client-body temp files; keep on disk, do not mount as tmpfs.
- **`/etc/nginx/ssl`** — acme.sh certificates and private keys.
- **`/root/.acme.sh`** — acme.sh config, renewals, and API credentials.
- **`/etc/nginx/profiles/`** — profile list files (`*.list`); may be empty.
- **`/etc/nginx/templates.repo/`** — template sources; may be empty.

`/etc/nginx/templates/` is an internal tmpfs staging directory, not a user-facing mount.

---

## 3. How to apply for certificates using ACME.sh
## 5. ACME Certificates

Log into the running container to inspect existing certificates:

Log into the running container to view existing certificates:
```bash
docker exec -it svc-proxy-openresty bash
docker exec -it svc-openresty bash
cd /etc/nginx/ssl && ls -alh
```

Choose your validation method:

### Method A: HTTP-01 Validation
Requires public endpoint accessibility and nginx challenge configuration files.

Requires public endpoint accessibility and nginx challenge configuration.

```bash
# Set your DOMAINS environment variable
DOMAINS='a1.example.com a2.example.com a3.example.com'

# Or if you already have certs in this folder, run the command below to get a list of DOMAINS
# or, if certificates already exist:
# DOMAINS=$(printf "%s\n" *.crt *.key 2>/dev/null | sed 's/\.[^.]*$//' | sort -u)

# Apply for certs using HTTP-01:
/opt/utils/script-acme-sh.sh 'your@email.com' "${DOMAINS}"
```

### Method B: DNS-01 Validation (Recommended for Wildcards)
Does not require exposed HTTP ports. Requires [`acme.sh` supported DNS service provider](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) API token (e.g. Cloudflare):


e.g.: the `CF_Token` and `dns_cf` below is for [Cloudflare](https://github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf).
Requires an [`acme.sh`-supported DNS provider](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) API token; no exposed HTTP ports needed. The `CF_Token` and `dns_cf` below are for [Cloudflare](https://github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf).

```bash
export CF_Token='your-cloudflare-api-token'

# define variable to apply cert for multiple domains in a same cert file (the one without wild-card goes first):
# non-wildcard domain goes first:
DOMAINS='example.com *.example.com'

# Apply for certs using DNS-01:
/opt/utils/script-acme-sh.sh 'your@email.com' "${DOMAINS}" "dns_cf"
```

---

## 4. Custom Configurations
## 6. Custom Configurations

- Refer to [source code](https://github.com/NginxProxyManager/nginx-proxy-manager/tree/develop/docker/rootfs/etc/nginx/conf.d) and [docs](https://nginxproxymanager.com/advanced-config/#custom-nginx-configurations) of [Nginx Proxy Manager](https://nginxproxymanager.com/).
See [Nginx Proxy Manager](https://nginxproxymanager.com/) [docs](https://nginxproxymanager.com/advanced-config/#custom-nginx-configurations).

Optional snippets included by `nginx.conf` (each uses the `[.]` glob, so a missing file is ignored):

You can add custom config snippets to extend OpenResty routing:
- `/data/nginx/custom/root_top.conf`: Included at the top of nginx.conf
- `/etc/nginx/custom/root_top.conf`: Included at the top of nginx.conf
- `conf/root.conf`: Included at the very end of nginx.conf
- `conf/http_top.conf`: Included at the top of the main http block
- `conf/http.conf`: Included at the end of the main http block
Expand All @@ -82,9 +100,10 @@ You can add custom config snippets to extend OpenResty routing:
- `conf/server_stream_tcp.conf`: Included at the end of every TCP stream server block
- `conf/server_stream_udp.conf`: Included at the end of every UDP stream server block
- `/data/nginx/custom/server_dead.conf`: Included at the end of every 404 server block
-

## Log fields mappings
---

## Log Field Mappings

| JSON key | standard | proxy | stream |
| -------- | ------------------------- | ------------------------- | -------------------------- |
Expand Down
55 changes: 55 additions & 0 deletions docker_openresty/compose/docker-compose.openresty.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Namespace the project with PROFILE_ENV so multiple instances can coexist,
# consistent with the rest of this repo. Example:
# PROFILE_ENV=X docker compose -f docker-compose.openresty.yml up -d
name: ${PROFILE_ENV:-X}-svc-openresty

networks:
net-ailab-proxy:
external: true


services:
svc-openresty:
container_name: ${PROFILE_ENV:-X}-svc-openresty
hostname: svc-openresty
image: quay.io/labnow/openresty:latest
pull_policy: always
restart: unless-stopped
networks: ["net-ailab-proxy"]
ports: ["80:80", "443:443"]

# Template variables come from env_file. PROFILE_NGINX is optional: when it is unset or empty,
# 20-prepare-template-files.sh skips template preparation and nginx starts without any rendered templates.
# SERVER_DOMAIN_NAME / SERVER_HOME_REDIRECT are only used by the selected profile's templates.
env_file: ["../credentials/${PROFILE_ENV:-@}-openresty.env"]

environment:
TZ: ${TZ:-Asia/Shanghai}
PROFILE_LOCALIZE: aliyun-pub
# Enable 15-local-resolvers.envsh to export NGINX_LOCAL_RESOLVERS for 16-set-resolvers.sh to write the resolver config.
NGINX_ENTRYPOINT_LOCAL_RESOLVERS: "1"

volumes:
# - /var/cache/nginx:/var/cache/nginx:rw
- /data/storage/nginx/ssl:/etc/nginx/ssl:rw
- /data/storage/nginx/web:/var/nginx/web:ro
- /data/storage/log/nginx:/var/log/nginx:rw

# Internal staging directory of the template pipeline.
# Mounted as tmpfs so it is always empty at container start and never leaks stale templates across restarts.
- type: tmpfs
target: /etc/nginx/templates

# Optional custom config (e.g. http_top.conf, http.conf, stream.conf).
# An empty directory is ignored and nginx falls back to its defaults.
- ./nginx-custom.d:/etc/nginx/custom:ro

# Template pipeline (nginx still starts when these directories are empty):
# ./profiles/ -> /etc/nginx/profiles/ profile lists (*.list)
# ./nginx-conf.d-template/ -> /etc/nginx/templates.repo/ template sources (*.conf.template / *.conf.stream-template)
# The in-container defaults already match these mount points, so PROFILE_DIR_NGINX / DIR_TEMPLATE_SOURCE do not need to be set.
# Each non-comment line names a flat template filename from `/etc/nginx/templates.repo/`:
# - `*.conf.template` → HTTP output (`/etc/nginx/conf.d/`)
# - `*.conf.stream-template` → stream output (`/etc/nginx/stream-conf.d/`)
- ./profiles/:/etc/nginx/profiles/:ro
- ./nginx-templates.repo.d:/etc/nginx/templates.repo:ro
10 changes: 5 additions & 5 deletions docker_openresty/openresty.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ COPY work /opt/utils/

RUN set -eux \
&& chmod +x /opt/utils/*.sh \
# ----------------------------- Install acme.sh
&& source /opt/utils/script-setup-acme.sh && setup_acme \
# ----------------------------- Install lua and lua-rocks
## ----------------------------- Install acme.sh
&& source /opt/utils/script-setup-acme.sh && setup_acme \
## ----------------------------- Install lua and lua-rocks
&& source /opt/utils/script-setup-core.sh && setup_lua_base && setup_lua_rocks \
# ----------------------------- Install openresty
## ----------------------------- Install openresty
&& useradd nginx -G www-data \
&& mkdir -pv /var/cache/nginx /var/log/nginx \
&& chown -R nginx:www-data /var/cache/nginx /var/log/nginx \
Expand All @@ -29,7 +29,7 @@ RUN set -eux \
&& nginx -t \
&& install__clean

VOLUME ["/var/log/nginx", "/var/cache/nginx", "/etc/nginx/templates/", "/etc/nginx/ssl", "/root/.acme.sh"]
VOLUME ["/var/log/nginx", "/var/cache/nginx", "/etc/nginx/ssl", "/root/.acme.sh"]

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/sh
# vim:sw=2:ts=2:sts=2:et

set -eu

LC_ALL=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

ME=$(basename "$0")
RESOLVERS_FILE=/etc/nginx/conf.d/include/resolvers.conf

entrypoint_log() {
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
echo "$@"
fi
}

# 15-local-resolvers.envsh export NGINX_LOCAL_RESOLVERS (like "127.0.0.11 8.8.8.8")
# when NGINX_ENTRYPOINT_LOCAL_RESOLVERS is not set or empty, fallback to Docker's embedded DNS.
RESOLVERS="${NGINX_LOCAL_RESOLVERS:-127.0.0.11}"

mkdir -pv "$(dirname "$RESOLVERS_FILE")"

touch "$RESOLVERS_FILE" 2>/dev/null || {
entrypoint_log "$ME: info: cannot write $RESOLVERS_FILE (read-only file system?)"
exit 0
}

{
echo "# Generated by $ME on $(date)"
echo "resolver ${RESOLVERS} valid=10s ipv6=off;"
} > "$RESOLVERS_FILE"

entrypoint_log "$ME: wrote resolver ${RESOLVERS} to $RESOLVERS_FILE"
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/sh
# vim:sw=2:ts=2:sts=2:et

set -eu

LC_ALL=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

ME=$(basename "$0")

DIR_PROFILE="${PROFILE_DIR_NGINX:-/etc/nginx/profiles}"
DIR_SOURCE="${DIR_TEMPLATE_SOURCE:-/etc/nginx/templates.repo}"
DIR_TARGET="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}"
PROFILE="${PROFILE_NGINX:-}"

entrypoint_log() {
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
echo "$@"
fi
}

# when profile is not set, skip template preparation
if [ -z "$PROFILE" ]; then
entrypoint_log "$ME: PROFILE_NGINX not set, skipping template preparation"
exit 0
fi

case "$PROFILE" in
*[!a-zA-Z0-9._-]*)
entrypoint_log "$ME: invalid PROFILE_NGINX '$PROFILE', skipping"
exit 0
;;
esac

FILE_PROFILE="${DIR_PROFILE}/${PROFILE}.list"

if [ ! -f "$FILE_PROFILE" ]; then
entrypoint_log "$ME: profile file not found: $FILE_PROFILE, skipping"
exit 0
fi

if [ ! -d "$DIR_SOURCE" ]; then
entrypoint_log "$ME: template source dir not found: $DIR_SOURCE, skipping"
exit 0
fi

mkdir -p "$DIR_TARGET"
find "$DIR_TARGET" -mindepth 1 -maxdepth 1 -type f -delete

entrypoint_log "$ME: preparing templates for profile '$PROFILE'"

count=0
while IFS= read -r line || [ -n "$line" ]; do
line=$(printf '%s' "$line" | tr -d '\r')
line="${line%%#*}" # remove comments
line=$(printf '%s' "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

if [ -z "$line" ]; then
continue
fi

case "$line" in
*.conf.template|*.conf.stream-template) ;;
*)
entrypoint_log "$ME: skipping invalid template name: $line"
continue
;;
esac

case "$line" in
*/*|*..*)
entrypoint_log "$ME: skipping invalid template path: $line"
continue
;;
esac

src="${DIR_SOURCE}/${line}"
if [ ! -f "$src" ]; then
entrypoint_log "$ME: skipping missing template: $src"
continue
fi

cp "$src" "${DIR_TARGET}/${line}"
count=$((count + 1))
done < "$FILE_PROFILE"

entrypoint_log "$ME: prepared $count template(s)"
exit 0
1 change: 1 addition & 0 deletions docker_openresty/work/nginx/conf.d/include/resolvers.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# resolver configuration is generated by /docker-entrypoint.d/16-set-resolvers.sh at container start
Loading