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 --password secret # enable OpenCode's HTTP basic auth
|
||||||
./install-service.sh --username admin --password secret
|
./install-service.sh --username admin --password secret
|
||||||
./install-service.sh --no-password # leave the server unsecured
|
./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 --uninstall # stop and remove the service
|
||||||
./install-service.sh --dry-run # show the unit, change nothing
|
./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.
|
**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).
|
> **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.
|
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=""
|
HOST=""; PORT=""; WORKDIR=""; SVC_USER=""; SVC_GROUP=""
|
||||||
ENABLE="" # 1 | 0 | empty=ask
|
ENABLE="" # 1 | 0 | empty=ask
|
||||||
|
CORS="" # space-separated extra allowed origins
|
||||||
SVC_USERNAME="${OPENCODE_SERVER_USERNAME:-opencode}"
|
SVC_USERNAME="${OPENCODE_SERVER_USERNAME:-opencode}"
|
||||||
PASSWORD="${OPENCODE_SERVER_PASSWORD:-}"
|
PASSWORD="${OPENCODE_SERVER_PASSWORD:-}"
|
||||||
PASSWORD_SET=0
|
PASSWORD_SET=0
|
||||||
|
|
@ -119,6 +120,8 @@ Options:
|
||||||
--user USER run the service as USER (default: you)
|
--user USER run the service as USER (default: you)
|
||||||
--enable start and enable on boot
|
--enable start and enable on boot
|
||||||
--no-enable install only; do not start
|
--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
|
--password PW enable basic auth with this password
|
||||||
--username USER basic-auth username (default: opencode)
|
--username USER basic-auth username (default: opencode)
|
||||||
--no-password do not set a password (server unsecured)
|
--no-password do not set a password (server unsecured)
|
||||||
|
|
@ -153,6 +156,8 @@ while [ $# -gt 0 ]; do
|
||||||
--env-file=*) ENV_FILE="${1#*=}" ;;
|
--env-file=*) ENV_FILE="${1#*=}" ;;
|
||||||
--enable) ENABLE=1 ;;
|
--enable) ENABLE=1 ;;
|
||||||
--no-enable) ENABLE=0 ;;
|
--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 ;;
|
-y|--yes) ASSUME_YES=1 ;;
|
||||||
--uninstall) UNINSTALL=1 ;;
|
--uninstall) UNINSTALL=1 ;;
|
||||||
--dry-run) DRY_RUN=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
|
printf " Start now and enable on boot? [Y/n]: "; v=""; tty_read v
|
||||||
case "$v" in [Nn]*) ENABLE=0 ;; *) ENABLE=1 ;; esac
|
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
|
if [ "$PASSWORD_SET" = 0 ]; then
|
||||||
printf " Protect the server with a password? [y/N]: "; v=""; tty_read v
|
printf " Protect the server with a password? [y/N]: "; v=""; tty_read v
|
||||||
case "$v" in
|
case "$v" in
|
||||||
|
|
@ -253,6 +261,9 @@ if [ "$PASSWORD_SET" = 1 ]; then
|
||||||
case "$SVC_USERNAME" in
|
case "$SVC_USERNAME" in
|
||||||
*$'\n'*) SVC_USERNAME="opencode" ;;
|
*$'\n'*) SVC_USERNAME="opencode" ;;
|
||||||
esac
|
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
|
fi
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -261,6 +272,10 @@ fi
|
||||||
ENV_LINE=""
|
ENV_LINE=""
|
||||||
[ "$PASSWORD_SET" = 1 ] && ENV_LINE="EnvironmentFile=-${ENV_FILE}"
|
[ "$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)"
|
UNIT="$(mktemp 2>/dev/null || mktemp -t oac-unit)"
|
||||||
cat > "$UNIT" <<EOF
|
cat > "$UNIT" <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
|
|
@ -274,7 +289,7 @@ User=${SVC_USER}
|
||||||
Group=${SVC_GROUP}
|
Group=${SVC_GROUP}
|
||||||
${ENV_LINE}
|
${ENV_LINE}
|
||||||
WorkingDirectory=${WORKDIR}
|
WorkingDirectory=${WORKDIR}
|
||||||
ExecStart=${OC_BIN} serve --hostname ${HOST} --port ${PORT}
|
ExecStart=${OC_BIN} serve --hostname ${HOST} --port ${PORT}${CORS_ARGS}
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue