closer to mvp
This commit is contained in:
+9
-8
@@ -14,15 +14,16 @@ INSTANCE_NAME=My Stoat Instance
|
||||
|
||||
# Admin API listen port and the HTTPS browser origin allowed by CORS.
|
||||
ADMIN_API_PORT=5181
|
||||
ADMIN_WEB_ORIGIN=https://admin.example.com
|
||||
ADMIN_WEB_ORIGIN=https://localhost:9443
|
||||
|
||||
# Admin hostname terminated by the dedicated Caddy proxy. This hostname only
|
||||
# needs to resolve on your WireGuard/private network.
|
||||
ADMIN_HOSTNAME=admin.example.com
|
||||
# Admin hostname terminated by the dedicated Caddy proxy. Use localhost for
|
||||
# local compose usage and replace it with a real name for deployment.
|
||||
ADMIN_HOSTNAME=localhost
|
||||
|
||||
# Compose-level convenience variables for the dedicated admin proxy.
|
||||
# Compose-level convenience variables for the dedicated admin proxy. These
|
||||
# defaults avoid privileged ports locally; set 80/443 in deployment if needed.
|
||||
ADMIN_BIND_IP=127.0.0.1
|
||||
ADMIN_HTTP_PORT=80
|
||||
ADMIN_HTTPS_PORT=443
|
||||
# Leave blank to use same-origin /api requests through admin-proxy.
|
||||
ADMIN_HTTP_PORT=9080
|
||||
ADMIN_HTTPS_PORT=9443
|
||||
# Optional frontend API base URL override for standalone web builds.
|
||||
ADMIN_WEB_API_URL=
|
||||
|
||||
@@ -16,7 +16,8 @@ Stoat Admin is a lightweight self-hosted moderation and invite dashboard for a S
|
||||
```text
|
||||
.
|
||||
├── api/ # Express + TypeScript backend
|
||||
├── web/ # Vite + React + TypeScript frontend
|
||||
├── proxy/ # Caddy + Coraza reverse proxy image
|
||||
├── web/ # Vite + React frontend and static image build
|
||||
├── deploy/s6/ # Example s6 service directories and systemd unit
|
||||
├── compose.yml # Production-oriented compose file
|
||||
├── compose.override.example.yml
|
||||
@@ -93,19 +94,22 @@ pnpm dev:web
|
||||
| `ADMIN_API_PORT` | Listen port for `admin-api` |
|
||||
| `ADMIN_WEB_ORIGIN` | Exact HTTPS browser origin allowed by CORS |
|
||||
| `ADMIN_HOSTNAME` | Hostname served by the dedicated Caddy proxy |
|
||||
| `ADMIN_BIND_IP` | Compose bind IP for the proxy's `80`/`443` ports |
|
||||
| `ADMIN_HTTP_PORT` | Host port for ACME HTTP and redirect handling |
|
||||
| `ADMIN_HTTPS_PORT` | Host port for HTTPS |
|
||||
| `ADMIN_WEB_API_URL` | Optional frontend API base URL override |
|
||||
| `ADMIN_BIND_IP` | Compose bind IP for the proxy's published ports |
|
||||
| `ADMIN_HTTP_PORT` | Published HTTP port for redirect handling |
|
||||
| `ADMIN_HTTPS_PORT` | Published HTTPS port for the admin dashboard |
|
||||
| `ADMIN_WEB_API_URL` | Optional frontend API override outside compose |
|
||||
|
||||
## Deployment
|
||||
|
||||
The repo ships with a standalone `compose.yml` that expects an external `stoat_default` network. Update the network name if your Stoat stack uses a different one.
|
||||
|
||||
For local compose use, the proxy defaults to `https://localhost:9443` and `http://localhost:9080`. For deployed hosts, set `ADMIN_HOSTNAME` to the real admin name and switch `ADMIN_HTTP_PORT`/`ADMIN_HTTPS_PORT` to `80`/`443` or use [compose.override.example.yml](/home/jasonross/workspace/stoat-admin/compose.override.example.yml) as a starting point.
|
||||
|
||||
The deployment topology is:
|
||||
|
||||
- `admin-proxy` publishes ports `80` and `443`, issues a private certificate from Caddy's internal CA, and reverse-proxies `/api/*` to `admin-api` and everything else to `admin-web`.
|
||||
- `admin-proxy` is built from [proxy/Dockerfile](/home/jasonross/workspace/stoat-admin/proxy/Dockerfile), publishes the configured HTTP and HTTPS ports, issues a private certificate from Caddy's internal CA, applies Coraza, and reverse-proxies `/api/*` to `admin-api` and everything else to `admin-web`.
|
||||
- `admin-web` and `admin-api` are no longer published directly on the host.
|
||||
- `admin-web` serves the built Vite bundle privately on the admin network.
|
||||
- `admin-api` stays attached to the shared Stoat network for MongoDB access and also joins a private admin network used by the proxy.
|
||||
|
||||
Before starting the stack, point `ADMIN_HOSTNAME` at the host running `admin-proxy` on your WireGuard/private network and set `ADMIN_WEB_ORIGIN` to `https://<that-hostname>`.
|
||||
@@ -144,7 +148,7 @@ tail -f /var/log/s6/stoat-admin/current | s6-tai64nlocal
|
||||
## Development Notes
|
||||
|
||||
- The backend uses SQLite for admin credentials, audit logs, and invite metadata, and MongoDB for Stoat state.
|
||||
- In the composed deployment, the frontend uses same-origin `/api` requests through `admin-proxy`, while local development can still override `VITE_API_URL`.
|
||||
- In the composed deployment, the frontend always uses same-origin `/api` requests through `admin-proxy`; `VITE_API_URL` is only useful outside compose.
|
||||
- Root task orchestration is handled by Turborepo through [turbo.json](/home/jasonross/workspace/stoat-admin/turbo.json).
|
||||
- The current repo state is a first implementation slice based on the design docs in [docs/stoat-admin-design.md](/home/jasonross/workspace/stoat-admin/docs/stoat-admin-design.md) and [docs/stoat-admin-tasks.md](/home/jasonross/workspace/stoat-admin/docs/stoat-admin-tasks.md).
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
services:
|
||||
admin-proxy:
|
||||
environment:
|
||||
ADMIN_HOSTNAME: admin.example.com
|
||||
ADMIN_HTTP_PORT: 80
|
||||
ADMIN_HTTPS_PORT: 443
|
||||
ports:
|
||||
- "10.0.0.1:80:80"
|
||||
- "10.0.0.1:443:443"
|
||||
environment:
|
||||
ADMIN_HOSTNAME: admin.example.com
|
||||
|
||||
admin-api:
|
||||
environment:
|
||||
@@ -14,5 +16,6 @@ services:
|
||||
# Common customizations:
|
||||
# - Change the external network name in compose.yml if your Stoat stack uses a different name.
|
||||
# - Bind admin-proxy to the interface IP that should answer ports 80/443.
|
||||
# - Use ADMIN_HTTP_PORT/ADMIN_HTTPS_PORT=9080/9443 for local compose HTTPS without privileged ports.
|
||||
# - Ensure ADMIN_HOSTNAME resolves to that IP on your WireGuard/private network.
|
||||
# - Add resource limits or alternate image tags per deployment.
|
||||
|
||||
+10
-8
@@ -15,7 +15,7 @@ services:
|
||||
image: ghcr.io/owner/stoat-admin-api:latest
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "5181"
|
||||
- "${ADMIN_API_PORT:-5181}"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./.env:/app/.env:ro
|
||||
@@ -26,8 +26,6 @@ services:
|
||||
admin-web:
|
||||
build:
|
||||
context: ./web
|
||||
args:
|
||||
VITE_API_URL: ${ADMIN_WEB_API_URL:-}
|
||||
image: ghcr.io/owner/stoat-admin-web:latest
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
@@ -36,18 +34,22 @@ services:
|
||||
- admin
|
||||
|
||||
admin-proxy:
|
||||
image: caddy:latest
|
||||
build:
|
||||
context: ./proxy
|
||||
image: ghcr.io/owner/stoat-admin-proxy:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- admin-api
|
||||
- admin-web
|
||||
environment:
|
||||
ADMIN_HOSTNAME: ${ADMIN_HOSTNAME}
|
||||
ADMIN_API_PORT: ${ADMIN_API_PORT:-5181}
|
||||
ADMIN_HOSTNAME: ${ADMIN_HOSTNAME:-localhost}
|
||||
ADMIN_HTTP_PORT: ${ADMIN_HTTP_PORT:-9080}
|
||||
ADMIN_HTTPS_PORT: ${ADMIN_HTTPS_PORT:-9443}
|
||||
ports:
|
||||
- "${ADMIN_BIND_IP:-127.0.0.1}:${ADMIN_HTTP_PORT:-80}:80"
|
||||
- "${ADMIN_BIND_IP:-127.0.0.1}:${ADMIN_HTTPS_PORT:-443}:443"
|
||||
- "${ADMIN_BIND_IP:-127.0.0.1}:${ADMIN_HTTP_PORT:-9080}:${ADMIN_HTTP_PORT:-9080}"
|
||||
- "${ADMIN_BIND_IP:-127.0.0.1}:${ADMIN_HTTPS_PORT:-9443}:${ADMIN_HTTPS_PORT:-9443}"
|
||||
volumes:
|
||||
- ./proxy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- admin_proxy_data:/data
|
||||
- admin_proxy_config:/config
|
||||
networks:
|
||||
|
||||
+17
-3
@@ -1,14 +1,28 @@
|
||||
{$ADMIN_HOSTNAME} {
|
||||
{
|
||||
http_port {$ADMIN_HTTP_PORT:9080}
|
||||
https_port {$ADMIN_HTTPS_PORT:9443}
|
||||
order coraza_waf first
|
||||
}
|
||||
|
||||
{$ADMIN_HOSTNAME:localhost} {
|
||||
tls internal
|
||||
|
||||
encode zstd gzip
|
||||
|
||||
coraza_waf {
|
||||
load_owasp_crs
|
||||
directives `
|
||||
Include /etc/caddy/coraza.conf
|
||||
SecRuleEngine On
|
||||
`
|
||||
}
|
||||
|
||||
@api path /api/*
|
||||
handle @api {
|
||||
reverse_proxy admin-api:5181
|
||||
reverse_proxy admin-api:{$ADMIN_API_PORT:5181}
|
||||
}
|
||||
|
||||
handle {
|
||||
reverse_proxy admin-web:80
|
||||
reverse_proxy admin-web:80 admin-web:443 admin-web:9080 admin-web:9443
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
FROM caddy:2-builder-alpine AS build-caddy
|
||||
RUN xcaddy build \
|
||||
--with github.com/corazawaf/coraza-caddy/v2
|
||||
|
||||
FROM caddy:2-alpine
|
||||
COPY --from=build-caddy /usr/bin/caddy /usr/bin/caddy
|
||||
COPY Caddyfile /etc/caddy/Caddyfile
|
||||
COPY coraza.conf /etc/caddy/coraza.conf
|
||||
EXPOSE 80 443 9080 9443
|
||||
@@ -1,5 +1,4 @@
|
||||
# Coraza configuration overrides
|
||||
# Tune false positives here as they arise.
|
||||
|
||||
SecAction "id:900000, phase:1, pass, t:none, nolog, setvar:tx.blocking_paranoia_level=1"
|
||||
|
||||
SecAction "id:900000, phase:1, pass, t:none, nolog, setvar:tx.blocking_paranoia_level=1"
|
||||
@@ -1,14 +0,0 @@
|
||||
:80 {
|
||||
coraza_waf {
|
||||
load_owasp_crs
|
||||
directives `
|
||||
Include /etc/caddy/coraza.conf
|
||||
SecRuleEngine On
|
||||
`
|
||||
}
|
||||
|
||||
root * /srv
|
||||
file_server
|
||||
try_files {path} /index.html
|
||||
}
|
||||
|
||||
+1
-12
@@ -5,15 +5,4 @@ RUN corepack enable && pnpm install --frozen-lockfile=false
|
||||
COPY . .
|
||||
ARG VITE_API_URL
|
||||
ENV VITE_API_URL=${VITE_API_URL}
|
||||
RUN pnpm build
|
||||
|
||||
FROM caddy:builder AS build-caddy
|
||||
RUN xcaddy build \
|
||||
--with github.com/corazawaf/coraza-caddy/v2
|
||||
|
||||
FROM caddy:latest
|
||||
COPY --from=build-caddy /usr/bin/caddy /usr/bin/caddy
|
||||
COPY --from=build-app /app/dist /srv
|
||||
COPY Caddyfile /etc/caddy/Caddyfile
|
||||
COPY coraza.conf /etc/caddy/coraza.conf
|
||||
EXPOSE 80
|
||||
EXPOSE 9080 9443
|
||||
Reference in New Issue
Block a user