feat(service): --cors support + warn when username != opencode
- --cors ORIGIN (repeatable) and an interactive CORS prompt; adds --cors to ExecStart - warn when a password is set with a username other than 'opencode' (the web UI always authenticates as opencode) - README: --cors + the 'don't stack two basic-auth layers' note
This commit is contained in:
parent
b6cbcdc080
commit
8cef2acfa5
2 changed files with 21 additions and 1 deletions
|
|
@ -250,6 +250,7 @@ The service step is a **separate program** — `install-service.sh` — so you c
|
|||
./install-service.sh --password secret # enable OpenCode's HTTP basic auth
|
||||
./install-service.sh --username admin --password secret
|
||||
./install-service.sh --no-password # leave the server unsecured
|
||||
./install-service.sh --cors https://ui.example.com # allow a cross-origin web UI
|
||||
./install-service.sh --uninstall # stop and remove the service
|
||||
./install-service.sh --dry-run # show the unit, change nothing
|
||||
```
|
||||
|
|
@ -257,6 +258,10 @@ The service step is a **separate program** — `install-service.sh` — so you c
|
|||
**Auth (optional).** OpenCode's server has its own HTTP basic auth — enabled purely by setting `OPENCODE_SERVER_PASSWORD` (username defaults to `opencode`, or set `OPENCODE_SERVER_USERNAME`). The installer offers this interactively, or accept it non-interactively with `--password`. The secret is **never written into the unit**: it goes into a root-only env file (`/etc/opencode/opencode.env`, mode `600`) that the unit pulls in via `EnvironmentFile=`. Use this **or** your proxy's basic auth — they don't conflict.
|
||||
|
||||
> **The web app is a client.** On first use it shows an **"Add server"** dialog asking for the **server address** and the **password** — the username is *not* asked because it defaults to `opencode`. Enter your server URL and the password you set here. It's remembered after that. Keep the username as `opencode` (a custom one would not be sent by the browser).
|
||||
>
|
||||
> **Don't stack two basic-auth layers.** A browser can send only one `Authorization` header. If your reverse proxy already does basic auth (Zoraxy, nginx…), **leave OpenCode's password unset** and leave the dialog's password **blank** — otherwise the client's OpenCode credentials overwrite the browser's proxy credentials and the proxy rejects them. Choose one layer, not both.
|
||||
>
|
||||
> If the web UI is served from a **different origin** than the server, start the server with the matching `--cors <origin>`.
|
||||
|
||||
It refuses to run non-interactively unless you pass `--yes`, and backs up any existing unit before replacing it.
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ is_systemd() {
|
|||
# ---------------------------------------------------------------------------
|
||||
HOST=""; PORT=""; WORKDIR=""; SVC_USER=""; SVC_GROUP=""
|
||||
ENABLE="" # 1 | 0 | empty=ask
|
||||
CORS="" # space-separated extra allowed origins
|
||||
SVC_USERNAME="${OPENCODE_SERVER_USERNAME:-opencode}"
|
||||
PASSWORD="${OPENCODE_SERVER_PASSWORD:-}"
|
||||
PASSWORD_SET=0
|
||||
|
|
@ -119,6 +120,8 @@ Options:
|
|||
--user USER run the service as USER (default: you)
|
||||
--enable start and enable on boot
|
||||
--no-enable install only; do not start
|
||||
--cors ORIGIN allow this origin (repeatable); use if the web UI is
|
||||
served from a different origin than the server
|
||||
--password PW enable basic auth with this password
|
||||
--username USER basic-auth username (default: opencode)
|
||||
--no-password do not set a password (server unsecured)
|
||||
|
|
@ -153,6 +156,8 @@ while [ $# -gt 0 ]; do
|
|||
--env-file=*) ENV_FILE="${1#*=}" ;;
|
||||
--enable) ENABLE=1 ;;
|
||||
--no-enable) ENABLE=0 ;;
|
||||
--cors) [ $# -ge 2 ] || die "--cors needs an origin"; CORS="${CORS} $2"; shift ;;
|
||||
--cors=*) CORS="${CORS} ${1#*=}" ;;
|
||||
-y|--yes) ASSUME_YES=1 ;;
|
||||
--uninstall) UNINSTALL=1 ;;
|
||||
--dry-run) DRY_RUN=1 ;;
|
||||
|
|
@ -224,6 +229,9 @@ if [ "$INTERACTIVE" = 1 ] && [ "$DRY_RUN" = 0 ]; then
|
|||
printf " Start now and enable on boot? [Y/n]: "; v=""; tty_read v
|
||||
case "$v" in [Nn]*) ENABLE=0 ;; *) ENABLE=1 ;; esac
|
||||
|
||||
printf " Extra allowed origins (CORS), space-separated [none]: "; v=""; tty_read v
|
||||
[ -n "$v" ] && CORS="${CORS} $v"
|
||||
|
||||
if [ "$PASSWORD_SET" = 0 ]; then
|
||||
printf " Protect the server with a password? [y/N]: "; v=""; tty_read v
|
||||
case "$v" in
|
||||
|
|
@ -253,6 +261,9 @@ if [ "$PASSWORD_SET" = 1 ]; then
|
|||
case "$SVC_USERNAME" in
|
||||
*$'\n'*) SVC_USERNAME="opencode" ;;
|
||||
esac
|
||||
if [ "$SVC_USERNAME" != "opencode" ]; then
|
||||
warn "Username '${SVC_USERNAME}' set — the OpenCode web UI always authenticates as 'opencode', so the browser login will fail unless you keep username 'opencode'."
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -261,6 +272,10 @@ fi
|
|||
ENV_LINE=""
|
||||
[ "$PASSWORD_SET" = 1 ] && ENV_LINE="EnvironmentFile=-${ENV_FILE}"
|
||||
|
||||
# Build the optional --cors flags
|
||||
CORS_ARGS=""
|
||||
for o in $CORS; do CORS_ARGS="${CORS_ARGS} --cors ${o}"; done
|
||||
|
||||
UNIT="$(mktemp 2>/dev/null || mktemp -t oac-unit)"
|
||||
cat > "$UNIT" <<EOF
|
||||
[Unit]
|
||||
|
|
@ -274,7 +289,7 @@ User=${SVC_USER}
|
|||
Group=${SVC_GROUP}
|
||||
${ENV_LINE}
|
||||
WorkingDirectory=${WORKDIR}
|
||||
ExecStart=${OC_BIN} serve --hostname ${HOST} --port ${PORT}
|
||||
ExecStart=${OC_BIN} serve --hostname ${HOST} --port ${PORT}${CORS_ARGS}
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue