Skip to content

Commit 8a7ed08

Browse files
committed
Merge branch 'dev' into feat/cli
2 parents f9802e6 + f7e3c52 commit 8a7ed08

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1223
-613
lines changed

.air.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tmp_dir = "tmp"
77

88
[build]
99
# Just plain old shell command. You could use `make` as well.
10-
cmd = "CGO_ENABLED=1 go build -tags=jsoniter -ldflags=\"-X 'github.com/0xJacky/Nginx-UI/settings.buildTime=$(date +%s)'\" -v -o ./tmp/main ."
10+
cmd = "CGO_ENABLED=1 go build -tags=jsoniter,unembed -ldflags=\"-X 'github.com/0xJacky/Nginx-UI/settings.buildTime=$(date +%s)'\" -v -o ./tmp/main ."
1111
# Binary file yields from `cmd`.
1212
bin = "tmp/main"
1313
# Customize binary.

.devcontainer/Dockerfile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
FROM mcr.microsoft.com/devcontainers/base:jammy
2+
3+
# Combine installation steps for Nginx and Go to avoid repetitive update/cleanup commands
4+
RUN apt-get update && \
5+
apt-get install -y --no-install-recommends curl gnupg2 ca-certificates lsb-release ubuntu-keyring jq && \
6+
\
7+
# Configure the Nginx repository
8+
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor > /usr/share/keyrings/nginx-archive-keyring.gpg && \
9+
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" \
10+
> /etc/apt/sources.list.d/nginx.list && \
11+
printf "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
12+
> /etc/apt/preferences.d/99nginx && \
13+
\
14+
# Update package information and install Nginx
15+
apt-get update && \
16+
apt-get install -y --no-install-recommends nginx inotify-tools file && \
17+
\
18+
# Automatically retrieve the latest stable Go version and install it,
19+
# download the appropriate binary based on system architecture (amd64 or arm64)
20+
GO_VERSION=$(curl -sSL "https://golang.org/dl/?mode=json" | \
21+
jq -r 'map(select(.stable)) | .[0].version' | sed 's/^go//') && \
22+
ARCH=$(dpkg --print-architecture) && \
23+
if [ "$ARCH" = "arm64" ]; then \
24+
GO_ARCH=linux-arm64; \
25+
else \
26+
GO_ARCH=linux-amd64; \
27+
fi && \
28+
echo "Installing Go version: ${GO_VERSION} for architecture: ${GO_ARCH}" && \
29+
curl -sSL "https://golang.org/dl/go${GO_VERSION}.${GO_ARCH}.tar.gz" -o go.tar.gz && \
30+
rm -rf /usr/local/go && \
31+
tar -C /usr/local -xzf go.tar.gz && \
32+
rm go.tar.gz && \
33+
\
34+
# Remove jq and clean up to reduce image size
35+
apt-get remove -y jq && \
36+
apt-get autoremove -y && \
37+
apt-get clean && \
38+
rm -rf /var/lib/apt/lists/*
39+
40+
RUN cp -rp /etc/nginx /etc/nginx.orig
41+
42+
# Set PATH to include Go installation and default go install binary location
43+
ENV PATH="/usr/local/go/bin:/root/go/bin:${PATH}"
44+
45+
# Install air with go install (requires Go 1.23 or higher)
46+
RUN go install github.com/air-verse/air@latest
47+
48+
# set zsh as default shell
49+
RUN chsh -s $(which zsh)

.devcontainer/devcontainer.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
3+
{
4+
"name": "Ubuntu",
5+
"dockerComposeFile": "docker-compose.yml",
6+
"service": "nginx-ui",
7+
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
8+
"shutdownAction": "stopCompose",
9+
// Features to add to the dev container. More info: https://containers.dev/features.
10+
"features": {
11+
"ghcr.io/devcontainers/features/common-utils:2": {
12+
"installOhMyZsh": true
13+
},
14+
"ghcr.io/devcontainers/features/node:1.6.1": {}
15+
},
16+
17+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
18+
// "forwardPorts": [],
19+
20+
// Use 'postCreateCommand' to run commands after the container is created.
21+
// "postCreateCommand": "",
22+
23+
// Configure tool-specific properties.
24+
"customizations": {
25+
"vscode": {
26+
"extensions": [
27+
"antfu.iconify",
28+
"antfu.unocss",
29+
"github.copilot",
30+
"golang.go",
31+
"vue.volar",
32+
"ms-azuretools.vscode-docker"
33+
]
34+
}
35+
},
36+
37+
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
38+
"remoteUser": "root",
39+
"overrideCommand": false,
40+
"postStartCommand": "./.devcontainer/start.sh",
41+
"mounts": [
42+
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind,consistency=cached"
43+
]
44+
}

.devcontainer/docker-compose.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
services:
2+
nginx-ui:
3+
build: .
4+
image: nginx-ui-dev
5+
container_name: nginx-ui
6+
volumes:
7+
- ../..:/workspaces:cached
8+
- ./go-path:/root/go
9+
- ./data/nginx:/etc/nginx
10+
command: sleep infinity
11+
environment:
12+
- NGINX_UI_CERT_CA_DIR=https://pebble:14000/dir
13+
networks:
14+
nginxui:
15+
nginx-ui-2:
16+
image: nginx-ui-dev
17+
container_name: nginx-ui-2
18+
volumes:
19+
- ../..:/workspaces:cached
20+
- ./data/nginx-ui-2/nginx:/etc/nginx
21+
- ./data/nginx-ui-2/nginx-ui:/etc/nginx-ui
22+
working_dir: /workspaces/nginx-ui
23+
command: ./.devcontainer/node-supervisor.sh
24+
depends_on:
25+
- nginx-ui
26+
networks:
27+
nginxui:
28+
29+
pebble:
30+
image: ghcr.io/letsencrypt/pebble:latest
31+
volumes:
32+
- ./pebble-test:/test
33+
command: -config /test/config/pebble-config.json -strict -dnsserver challtestsrv:8053
34+
ports:
35+
- 14000:14000 # HTTPS ACME API
36+
- 15000:15000 # HTTPS Management API
37+
environment:
38+
- PEBBLE_VA_NOSLEEP=1
39+
- PEBBLE_VA_ALWAYS_VALID=1
40+
networks:
41+
nginxui:
42+
challtestsrv:
43+
image: ghcr.io/letsencrypt/pebble-challtestsrv:latest
44+
command: -defaultIPv6 "" -defaultIPv4 challtestsrv
45+
ports:
46+
- 8055:8055 # HTTP Management API
47+
networks:
48+
nginxui:
49+
casdoor:
50+
image: casbin/casdoor-all-in-one
51+
ports:
52+
- 8001:8000
53+
networks:
54+
- nginxui
55+
56+
networks:
57+
nginxui:

.devcontainer/init-nginx.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# init nginx config dir
2+
if [ "$(ls -A /etc/nginx)" = "" ]; then
3+
echo "Initialing Nginx config dir"
4+
cp -rp /etc/nginx.orig/* /etc/nginx/
5+
echo "Initialed Nginx config dir"
6+
fi

.devcontainer/node-supervisor.sh

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
3+
# Configurable variables
4+
SOURCE_FILE=/workspaces/nginx-ui/tmp/main
5+
TARGET_PATH=/usr/local/bin/nginx-ui
6+
CONFIG_FILE=/etc/nginx-ui/app.ini
7+
8+
# init nginx
9+
./.devcontainer/init-nginx.sh
10+
11+
LOG_PREFIX="[Supervisor]"
12+
13+
# Debug initial state
14+
echo "$LOG_PREFIX Starting supervisor with:"
15+
echo "$LOG_PREFIX SOURCE_FILE: $SOURCE_FILE"
16+
echo "$LOG_PREFIX TARGET_PATH: $TARGET_PATH"
17+
echo "$LOG_PREFIX CONFIG_FILE: $CONFIG_FILE"
18+
19+
# Wait for initial file creation
20+
while [[ ! -f "$SOURCE_FILE" ]]; do
21+
echo "$LOG_PREFIX Waiting for $SOURCE_FILE to be created..."
22+
sleep 1
23+
done
24+
25+
# Initial copy and start
26+
echo "$LOG_PREFIX Initial file detected, starting service..."
27+
cp -fv "$SOURCE_FILE" "$TARGET_PATH"
28+
chmod +x "$TARGET_PATH"
29+
pkill -x nginx-ui || echo "$LOG_PREFIX No existing process to kill"
30+
nohup "$TARGET_PATH" -config "$CONFIG_FILE" > /proc/1/fd/1 2>&1 &
31+
32+
# Use proper field separation for inotify output
33+
inotifywait -m -e close_write,moved_to,create,delete \
34+
--format "%T|%w%f|%e" \
35+
--timefmt "%F-%H:%M:%S" \
36+
"$(dirname "$SOURCE_FILE")" |
37+
while IFS='|' read -r TIME FILE EVENT; do
38+
echo "$LOG_PREFIX [${TIME}] Event: ${EVENT} - ${FILE}"
39+
40+
# Handle atomic save operations
41+
if [[ "$FILE" =~ .*-tmp-umask$ ]] || [[ "$EVENT" == "DELETE" ]]; then
42+
echo "$LOG_PREFIX Detected build intermediate file, checking main..."
43+
sleep 0.3 # Allow atomic replace completion
44+
45+
if [[ -f "$SOURCE_FILE" ]]; then
46+
echo "$LOG_PREFIX Valid main file detected after build"
47+
FILE="$SOURCE_FILE"
48+
else
49+
echo "$LOG_PREFIX Main file missing after build operation"
50+
continue
51+
fi
52+
fi
53+
54+
if [[ "$FILE" == "$SOURCE_FILE" ]]; then
55+
# Stability checks
56+
echo "$LOG_PREFIX File metadata:"
57+
ls -l "$FILE"
58+
file "$FILE"
59+
60+
# Wait for file stability with retries
61+
retries=5
62+
while ((retries-- > 0)); do
63+
if file "$FILE" | grep -q "executable"; then
64+
break
65+
fi
66+
echo "$LOG_PREFIX Waiting for valid executable (${retries} retries left)..."
67+
sleep 1
68+
done
69+
70+
if ((retries <= 0)); then
71+
echo "$LOG_PREFIX ERROR: File validation failed after 5 retries"
72+
continue
73+
fi
74+
75+
# Copy and restart service
76+
echo "$LOG_PREFIX Updating service..."
77+
cp -fv "$FILE" "$TARGET_PATH"
78+
chmod +x "$TARGET_PATH"
79+
80+
echo "$LOG_PREFIX Killing existing process..."
81+
pkill -x nginx-ui || echo "$LOG_PREFIX No process to kill"
82+
83+
echo "$LOG_PREFIX Starting new process..."
84+
nohup "$TARGET_PATH" -config "$CONFIG_FILE" > /proc/1/fd/1 2>&1 &
85+
echo "$LOG_PREFIX Restart complete. New PID: $(pgrep nginx-ui)"
86+
fi
87+
done
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# certs/
2+
3+
This directory contains a CA certificate (`pebble.minica.pem`) and a private key
4+
(`pebble.minica.key.pem`) that are used to issue a end-entity certificate (See
5+
`certs/localhost`) for the Pebble HTTPS server.
6+
7+
To get your **testing code** to use Pebble without HTTPS errors you should
8+
configure your ACME client to trust the `pebble.minica.pem` CA certificate. Your
9+
ACME client should offer a runtime option to specify a list of root CAs that you
10+
can configure to include the `pebble.minica.pem` file.
11+
12+
**Do not** add this CA certificate to the system trust store or in production
13+
code!!! The CA's private key is **public** and anyone can use it to issue
14+
certificates that will be trusted by a system with the Pebble CA in the trust
15+
store.
16+
17+
To re-create all of the Pebble certificates run:
18+
19+
minica -ca-cert pebble.minica.pem \
20+
-ca-key pebble.minica.key.pem \
21+
-domains localhost,pebble \
22+
-ip-addresses 127.0.0.1
23+
24+
From the `test/certs/` directory after [installing
25+
MiniCA](https://github.com/jsha/minica#installation)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# certs/localhost
2+
3+
This directory contains an end-entity (leaf) certificate (`cert.pem`) and
4+
a private key (`key.pem`) for the Pebble HTTPS server. It includes `127.0.0.1`
5+
as an IP address SAN, and `[localhost, pebble]` as DNS SANs.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDGzCCAgOgAwIBAgIIbEfayDFsBtwwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
3+
AxMVbWluaWNhIHJvb3QgY2EgMjRlMmRiMCAXDTE3MTIwNjE5NDIxMFoYDzIxMDcx
4+
MjA2MTk0MjEwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
5+
AQUAA4IBDwAwggEKAoIBAQCbFMW3DXXdErvQf2lCZ0qz0DGEWadDoF0O2neM5mVa
6+
VQ7QGW0xc5Qwvn3Tl62C0JtwLpF0pG2BICIN+DHdVaIUwkf77iBS2doH1I3waE1I
7+
8GkV9JrYmFY+j0dA1SwBmqUZNXhLNwZGq1a91nFSI59DZNy/JciqxoPX2K++ojU2
8+
FPpuXe2t51NmXMsszpa+TDqF/IeskA9A/ws6UIh4Mzhghx7oay2/qqj2IIPjAmJj
9+
i73kdUvtEry3wmlkBvtVH50+FscS9WmPC5h3lDTk5nbzSAXKuFusotuqy3XTgY5B
10+
PiRAwkZbEY43JNfqenQPHo7mNTt29i+NVVrBsnAa5ovrAgMBAAGjYzBhMA4GA1Ud
11+
DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T
12+
AQH/BAIwADAiBgNVHREEGzAZgglsb2NhbGhvc3SCBnBlYmJsZYcEfwAAATANBgkq
13+
hkiG9w0BAQsFAAOCAQEAYIkXff8H28KS0KyLHtbbSOGU4sujHHVwiVXSATACsNAE
14+
D0Qa8hdtTQ6AUqA6/n8/u1tk0O4rPE/cTpsM3IJFX9S3rZMRsguBP7BSr1Lq/XAB
15+
7JP/CNHt+Z9aKCKcg11wIX9/B9F7pyKM3TdKgOpqXGV6TMuLjg5PlYWI/07lVGFW
16+
/mSJDRs8bSCFmbRtEqc4lpwlrpz+kTTnX6G7JDLfLWYw/xXVqwFfdengcDTHCc8K
17+
wtgGq/Gu6vcoBxIO3jaca+OIkMfxxXmGrcNdseuUCa3RMZ8Qy03DqGu6Y6XQyK4B
18+
W8zIG6H9SVKkAznM2yfYhW8v2ktcaZ95/OBHY97ZIw==
19+
-----END CERTIFICATE-----
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEAmxTFtw113RK70H9pQmdKs9AxhFmnQ6BdDtp3jOZlWlUO0Blt
3+
MXOUML5905etgtCbcC6RdKRtgSAiDfgx3VWiFMJH++4gUtnaB9SN8GhNSPBpFfSa
4+
2JhWPo9HQNUsAZqlGTV4SzcGRqtWvdZxUiOfQ2TcvyXIqsaD19ivvqI1NhT6bl3t
5+
redTZlzLLM6Wvkw6hfyHrJAPQP8LOlCIeDM4YIce6Gstv6qo9iCD4wJiY4u95HVL
6+
7RK8t8JpZAb7VR+dPhbHEvVpjwuYd5Q05OZ280gFyrhbrKLbqst104GOQT4kQMJG
7+
WxGONyTX6np0Dx6O5jU7dvYvjVVawbJwGuaL6wIDAQABAoIBAGW9W/S6lO+DIcoo
8+
PHL+9sg+tq2gb5ZzN3nOI45BfI6lrMEjXTqLG9ZasovFP2TJ3J/dPTnrwZdr8Et/
9+
357YViwORVFnKLeSCnMGpFPq6YEHj7mCrq+YSURjlRhYgbVPsi52oMOfhrOIJrEG
10+
ZXPAwPRi0Ftqu1omQEqz8qA7JHOkjB2p0i2Xc/uOSJccCmUDMlksRYz8zFe8wHuD
11+
XvUL2k23n2pBZ6wiez6Xjr0wUQ4ESI02x7PmYgA3aqF2Q6ECDwHhjVeQmAuypMF6
12+
IaTjIJkWdZCW96pPaK1t+5nTNZ+Mg7tpJ/PRE4BkJvqcfHEOOl6wAE8gSk5uVApY
13+
ZRKGmGkCgYEAzF9iRXYo7A/UphL11bR0gqxB6qnQl54iLhqS/E6CVNcmwJ2d9pF8
14+
5HTfSo1/lOXT3hGV8gizN2S5RmWBrc9HBZ+dNrVo7FYeeBiHu+opbX1X/C1HC0m1
15+
wJNsyoXeqD1OFc1WbDpHz5iv4IOXzYdOdKiYEcTv5JkqE7jomqBLQk8CgYEAwkG/
16+
rnwr4ThUo/DG5oH+l0LVnHkrJY+BUSI33g3eQ3eM0MSbfJXGT7snh5puJW0oXP7Z
17+
Gw88nK3Vnz2nTPesiwtO2OkUVgrIgWryIvKHaqrYnapZHuM+io30jbZOVaVTMR9c
18+
X/7/d5/evwXuP7p2DIdZKQKKFgROm1XnhNqVgaUCgYBD/ogHbCR5RVsOVciMbRlG
19+
UGEt3YmUp/vfMuAsKUKbT2mJM+dWHVlb+LZBa4pC06QFgfxNJi/aAhzSGvtmBEww
20+
xsXbaceauZwxgJfIIUPfNZCMSdQVIVTi2Smcx6UofBz6i/Jw14MEwlvhamaa7qVf
21+
kqflYYwelga1wRNCPopLaQKBgQCWsZqZKQqBNMm0Q9yIhN+TR+2d7QFjqeePoRPl
22+
1qxNejhq25ojE607vNv1ff9kWUGuoqSZMUC76r6FQba/JoNbefI4otd7x/GzM9uS
23+
8MHMJazU4okwROkHYwgLxxkNp6rZuJJYheB4VDTfyyH/ng5lubmY7rdgTQcNyZ5I
24+
majRYQKBgAMKJ3RlII0qvAfNFZr4Y2bNIq+60Z+Qu2W5xokIHCFNly3W1XDDKGFe
25+
CCPHSvQljinke3P9gPt2HVdXxcnku9VkTti+JygxuLkVg7E0/SWwrWfGsaMJs+84
26+
fK+mTZay2d3v24r9WKEKwLykngYPyZw5+BdWU0E+xx5lGUd3U4gG
27+
-----END RSA PRIVATE KEY-----

0 commit comments

Comments
 (0)