Files
3m-ui/Dockerfile
T
風雪 39608cd0fb fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
fix(infra): fail-closed checksums, sandbox hardening, non-root Docker
Critical (supply chain):
- C-3: Mihomo binary download had no checksum. Add verify_mihomo_sha256()
downloading MetaCubeX SHA256SUMS and verifying the .gz BEFORE
decompression. Mismatch is fatal.
- C-4: verify_release_sha256 soft-failed (return 0) when SHA256SUMS
was missing or asset unlisted. Now fail-closed: err exit unless the
operator sets THREE_M_UI_INSECURE=1 (prints a loud WARNING). sha256
tooling is now a hard dependency.
- C-5: Downloaded binaries were executed as root (--version / -v) for
smoke-testing. Remove every invocation; rely on checksum + 'file'
ELF check instead.
- H-1: Drop raw.githubusercontent.com fallback for helper scripts.
Missing release asset now hard-fails (supply-chain posture).
Sandbox:
- H-2: systemd unit gains UMask=0077, ProtectSystem=strict,
ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables/
Modules/Logs, ProtectControlGroups, ReadWritePaths,
RestrictAddressFamilies, RestrictNamespaces, RestrictRealtime,
RestrictSUIDSGID, LockPersonality, SystemCallArchitectures=native,
SystemCallFilter=@system-service ~@privileged @resources.
CapabilityBoundingSet now includes CAP_NET_ADMIN for Mihomo TUN.
- C-4(Docker): Dockerfile creates non-root user 3m-ui (UID 10001),
pre-creates & chowns volumes, sets USER 10001:10001.
- M-3: docker-compose ports 8080:8080 -> 127.0.0.1:8080:8080
(loopback-only by default; operator uses reverse proxy).
- M-9: docker-compose gains security notes (reverse-proxy guidance,
admin/admin + forced first-login change, THREE_M_UI_ADMIN_PASSWORD
example, UID 10001 volume ownership).
- M-10: release.yml gains a TODO comment for cosign keyless signing.
- LOW: AGENTS.md Go 1.24+ -> Go 1.25+; install.sh final message now
'Initial administrator: admin / admin. You MUST change the password
on first login.'
2026-08-29 09:39:25 +00:00

46 lines
2.1 KiB
Docker

# Multi-stage build: pure-Go static 3m-ui binary with embedded Ant Design frontend.
# Compatible with glibc and musl hosts (scratch/alpine/distroless).
# TODO(supply-chain, H-3): pin base images to immutable digests for reproducible
# builds. Floating tags (node:22-alpine, golang:1.25-alpine, alpine:3.21) are
# mutable — only @sha256:<digest> guarantees byte-identical rebuilds. Compute
# digests with `docker pull <image> && docker inspect --format='{{.RepoDigests}}' <image>`
# and replace each `FROM` line below with `<image>@sha256:<digest>`.
FROM node:22-alpine AS frontend
WORKDIR /src/frontend
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm install --no-audit --no-fund
COPY frontend/ ./
RUN npm run build
FROM golang:1.25-alpine AS backend
WORKDIR /src
RUN apk add --no-cache git ca-certificates
COPY backend/go.mod backend/go.sum ./backend/
WORKDIR /src/backend
RUN go mod download
COPY backend/ ./
COPY --from=frontend /src/frontend/dist ./cmd/server/web/dist
ENV CGO_ENABLED=0
RUN go build -tags sqlite_modernc -trimpath -ldflags='-s -w' -o /out/3m-ui ./cmd/server
FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata
# Run as a non-root user (H-2 / C-4). The panel binary does not need root in
# container mode. Mihomo TUN mode requires CAP_NET_ADMIN and is expected to run
# on the host (or in a privileged sidecar) — not inside this panel container.
RUN addgroup -S -g 10001 3m-ui && adduser -S -D -H -u 10001 -G 3m-ui 3m-ui
WORKDIR /app
COPY --from=backend /out/3m-ui /usr/local/bin/3m-ui
# Pre-create the volume mount points with correct ownership so named volumes
# (docker-compose) inherit UID 10001 on first creation. Bind-mounted host dirs
# must also be `chown 10001:10001` on the host by the operator.
RUN mkdir -p /etc/3m-ui /var/lib/3m-ui /var/log/3m-ui && \
chown -R 3m-ui:3m-ui /app /usr/local/bin/3m-ui /etc/3m-ui /var/lib/3m-ui /var/log/3m-ui
# Default paths match the installer layout.
ENV THREE_M_UI_CONFIG=/etc/3m-ui/config.yaml
VOLUME ["/etc/3m-ui", "/var/lib/3m-ui", "/var/log/3m-ui"]
EXPOSE 8080
USER 10001:10001
ENTRYPOINT ["/usr/local/bin/3m-ui"]