20 Commits

Author SHA1 Message Date
29a1f665e9 1.35.14 release 2026-04-14 01:19:42 -04:00
fba72964fc Make createrepo service names explicit 2026-04-14 01:06:00 -04:00
32afb91dc9 Always run createrepo service as root 2026-04-14 00:58:43 -04:00
1eda1889a8 Don't run createrepo on service creation 2026-04-14 00:43:04 -04:00
dd19c0d794 Run rpmbuild as signing user 2026-04-14 00:37:27 -04:00
1f31922bb4 Always run createrepo service as user 2026-04-14 00:32:10 -04:00
04952eeea9 Surface rpmsign errors 2026-04-14 00:19:00 -04:00
26f09e0ae9 Let DNF handle key import 2026-04-14 00:00:21 -04:00
ed5e08fb20 Fix repo metadata temp file ownership 2026-04-13 23:46:15 -04:00
e8ac6048f3 Fix gpg repo signing command 2026-04-13 23:38:16 -04:00
d933d6bebc Add gpg signing debugging 2026-04-13 23:33:22 -04:00
edb281dad6 Skip running createrepo when generating service 2026-04-13 23:04:05 -04:00
0eebaf8fc0 Sign repomd_xml.asc to a temp file and move to webroot 2026-04-13 22:58:08 -04:00
3c43f546d0 Only install external repos for MC package install 2026-04-13 22:48:24 -04:00
f3a662f058 Pass --debug to createrepo service 2026-04-13 22:32:43 -04:00
6c6c0f6818 Use command array for createrepo service 2026-04-13 22:26:47 -04:00
7c4c36626f Debug webroot user 2026-04-13 22:13:06 -04:00
05c5a5299e Add missing webroot user 2026-04-13 21:56:29 -04:00
6e54c92103 jriver-createrepo: install script to /opt/installJRMC 2026-04-13 21:41:36 -04:00
93026c166b Add optional repo and rpm GPG signing 2026-04-13 21:26:27 -04:00
3 changed files with 338 additions and 105 deletions

View File

@@ -23,19 +23,19 @@ Specifying [tt]--build[/tt], [tt]--createrepo[/tt], [tt]--service[/tt], or [tt]-
[code] [code]
$ installJRMC --help $ installJRMC --help
--install, -i repo|local --install, -i repo|local
repo: Install MC from repository, future updates will be handled by the system package manager. repo: Install MC from repository, updates are handled by the system package manager.
local: Build and install MC package from official source package. local: Build and install MC locally from official source package.
--build[=suse|fedora|centos] --build[=suse|fedora|centos|mandriva]
Build RPM from source DEB but do not install. Build RPM from source DEB but do not install.
Optionally, specify a target distro for cross-building (ex. --build=suse, note the '='). Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=').
--compat --compat
Build/install MC without minimum dependency version requirements. Build/install MC locally without minimum dependency version requirements.
--mcversion VERSION --mcversion VERSION
Specify the MC version, ex. "33", "35.0.51", or "35.0.51-1" (default: latest). Specify the MC version, ex. "35.0.68" or "35" (default: latest release).
--arch ARCH --arch ARCH
Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host architecture). Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host).
--mcrepo REPO --mcrepo REPO
Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: host or official). Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: auto).
--outputdir PATH --outputdir PATH
Generate reusable installJRMC output in this PATH (default: ./output). Generate reusable installJRMC output in this PATH (default: ./output).
--restorefile RESTOREFILE --restorefile RESTOREFILE
@@ -43,30 +43,41 @@ $ installJRMC --help
--betapass PASSWORD --betapass PASSWORD
Enter beta team password for access to beta builds. Enter beta team password for access to beta builds.
--service, -s SERVICE --service, -s SERVICE
See SERVICES section below for the list of services to deploy. See SERVICES below for possible services to install.
--service-type user|system --service-type user|system
Starts services at boot (system) or user login (user) (default: per-service, see SERVICES). Starts services at boot (system) or at user login (user) (default: per service, see SERVICES).
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of containers to deploy.
--createrepo[=suse|fedora|centos]
Build rpm, copy to webroot, and run createrepo.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora, note the '=').
--createrepo-webroot PATH
The webroot directory to install the repo (default: /var/www/jriver/).
--createrepo-user USER
The web server user if different from the current user.
--no-update --no-update
Disable the installJRMC update check. Disable automatic installJRMC self-update.
--uninstall, -u
Uninstall JRiver MC, remove services, containers, and firewall rules (does not remove library files).
--yes, -y, --auto --yes, -y, --auto
Always assumes yes for questions. Assume yes response to questions.
--version, -v --version, -v
Print installJRMC version and exit. Print installJRMC version and exit.
--debug, -d --debug, -d
Print debug output. Print debug output.
--help, -h --help, -h
Print help dialog and exit. Print help dialog and exit.
--uninstall, -u
Uninstall JRiver MC, service files, firewall rules, etc. ADVANCED OPTIONS
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of possible services to install.
--createrepo[=suse|fedora|centos]
Build rpm, copy to webroot, and run createrepo.
Use in conjunction with --build=TARGET for crossbuilding repos.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora).
--createrepo-webroot PATH
Specify the webroot directory to install the repo (default: /var/www/jriver).
--webroot-user USER
Owner/user for createrepo output in the webroot (default: current user).
--createrepo-user USER
Backward-compatible alias for --webroot-user.
--sign
Sign the built RPM and repodata/repomd.xml (if --createrepo).
--sign-user USER
User account used to run rpmsign and gpg signing (default: current user).
--sign-key KEYID
GPG key ID, fingerprint, or UID used for --sign.
[/code] [/code]
[size=18pt]Services[/size] [size=18pt]Services[/size]
@@ -126,12 +137,14 @@ Install the latest version of MC33 from the best available repository with debug
Install a more widely-compatible version of the latest MC version. Install a more widely-compatible version of the latest MC version.
[code]installJRMC --install repo --service jriver-mediacenter --service-type user[/code] [code]installJRMC --install repo --service jriver-mediacenter --service-type user[/code]
Install MC from the repository and start/enable jriver-mediacenter.service as a user service. Install MC from the repository and start/enable jriver-mediacenter.service as a user service.
[code]installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 35.0.51[/code] [code]installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 35.0.68[/code]
Build and install an MC 35.0.51 comptability RPM locally and activate it using the [tt]/path/to/license.mjr[/tt]. Build and install an MC 35.0.68 comptability RPM locally and activate it using the [tt]/path/to/license.mjr[/tt].
[code]installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user[/code] [code]installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --webroot-user www-user[/code]
Build an RPM locally for the current distro, move it to the webroot, and run createrepo as www-user. Build an RPM locally for the current distro, move it to the webroot, and run createrepo as www-user.
[code]installJRMC --service jriver-createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user[/code] [code]installJRMC --service jriver-createrepo --createrepo-webroot /srv/jriver/repo --webroot-user www-user[/code]
Install the jriver-createrepo timer and service to build the RPM, move it to the webroot, and run createrepo as www-user hourly. Install the jriver-createrepo timer and service to build the RPM, move it to the webroot, and run createrepo as www-user hourly.
[code]installJRMC --createrepo --webroot-user nginx --sign --sign-user bryan --sign-key 0xDEADBEEF[/code]
Build/update the RPM repo, sign both RPM and repodata as bryan, and publish files owned by nginx.
[code]installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter --vncpass "letmein"[/code] [code]installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter --vncpass "letmein"[/code]
Install services to share the existing local desktop via VNC and automatically run MC on startup. Install services to share the existing local desktop via VNC and automatically run MC on startup.
[code]installJRMC --install repo --service jriver-xvnc --display ":2"[/code] [code]installJRMC --install repo --service jriver-xvnc --display ":2"[/code]

View File

@@ -20,50 +20,61 @@ Specifying `--build`, `--createrepo`, `--service`, or `--uninstall` disables the
```text ```text
$ installJRMC --help $ installJRMC --help
--install, -i repo|local --install, -i repo|local
repo: Install MC from repository, future updates will be handled by the system package manager. repo: Install MC from repository, updates are handled by the system package manager.
local: Build and install MC package locally from official source package. local: Build and install MC locally from official source package.
--build[=suse|fedora|centos|mandriva] --build[=suse|fedora|centos|mandriva]
Build RPM from source DEB but do not install. Build RPM from source DEB but do not install.
Optionally, specify a target distro for cross-building (ex. --build=suse, note the '='). Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=').
--compat --compat
Build/install MC without minimum dependency version requirements. Build/install MC locally without minimum dependency version requirements.
--mcversion VERSION --mcversion VERSION
Build or install a specific MC version, ex. "35.0.51" or "33" (default: latest). Specify the MC version, ex. "35.0.68" or "35" (default: latest release).
--mcrepo REPO --mcrepo REPO
Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: latest official). Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: auto).
--arch ARCH --arch ARCH
Specify the MC architecture, ex. "amd64", "arm64", etc (default: host architecture). Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host).
--outputdir PATH --outputdir PATH
Generate rpmbuild output in this PATH (default: ./output). Generate reusable installJRMC output in this PATH (default: ./output).
--restorefile RESTOREFILE --restorefile MJR_FILE
Restore file location for automatic license registration. Restore file location for automatic license registration.
--betapass PASSWORD --betapass PASSWORD
Enter beta team password for access to beta builds. Enter beta team password for access to beta builds.
--service, -s SERVICE --service, -s SERVICE
See SERVICES section below for the list of services to deploy. See SERVICES below for possible services to install.
--service-type user|system --service-type user|system
Starts services at boot (system) or user login (user) (default: per-service, see SERVICES). Starts services at boot (system) or at user login (user) (default: per service, see SERVICES).
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of containers to deploy.
--createrepo[=suse|fedora|centos|mandriva]
Build rpm, copy to webroot, and run createrepo.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora, note the '=').
--createrepo-webroot PATH
The webroot directory to install the repo (default: /var/www/jriver/).
--createrepo-user USER
The web server user if different from the current user.
--no-update --no-update
Disable the installJRMC update check. Disable automatic installJRMC self-update.
--uninstall, -u
Uninstall JRiver MC, remove services, containers, and firewall rules (does not remove library files).
--yes, -y, --auto --yes, -y, --auto
Always assume yes for questions. Assume yes response to questions.
--version, -v --version, -v
Print installJRMC version and exit. Print installJRMC version and exit.
--debug, -d --debug, -d
Print debug output. Print debug output.
--help, -h --help, -h
Print help dialog and exit. Print help dialog and exit.
--uninstall, -u
Uninstall JRiver MC, service files, and firewall rules (does not remove library or media files). ADVANCED OPTIONS
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of possible services to install.
--createrepo[=suse|fedora|centos|mandriva]
Build rpm, copy to webroot, and run createrepo.
Use in conjunction with --build=TARGET for crossbuilding repos.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora).
--createrepo-webroot PATH
Specify the webroot directory to install the repo (default: /var/www/jriver).
--webroot-user USER
Owner/user for createrepo output in the webroot (default: current user).
--createrepo-user USER
Backward-compatible alias for --webroot-user.
--sign
Sign the built RPM and repodata/repomd.xml (if --createrepo).
--sign-user USER
User account used to run rpmsign and gpg signing (default: current user).
--sign-key KEYID
GPG key ID, fingerprint, or UID used for --sign.
``` ```
### `--service=` ### `--service=`
@@ -130,18 +141,22 @@ Multiple services (but not `--service-types`) can be installed at one time using
Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service. Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service.
* `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 35.0.51` * `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 35.0.68`
Build and install an MC 35.0.51 compatibility RPM locally and activate it using the `/path/to/license.mjr`. Build and install an MC 35.0.68 compatibility RPM locally and activate it using the `/path/to/license.mjr`.
* `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user` * `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --webroot-user www-user`
Build an RPM locally for the current distro, move it to the webroot, and run createrepo as `www-user`. Build an RPM locally for the current distro, move it to the webroot, and run createrepo as `www-user`.
* `installJRMC --service jriver-createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user` * `installJRMC --service jriver-createrepo --createrepo-webroot /srv/jriver/repo --webroot-user www-user`
Install the jriver-createrepo timer and service to build the RPM, move it to the webroot, and run createrepo as `www-user` hourly. Install the jriver-createrepo timer and service to build the RPM, move it to the webroot, and run createrepo as `www-user` hourly.
* `installJRMC --createrepo --webroot-user nginx --sign --sign-user bryan --sign-key 0xDEADBEEF`
Build/update the RPM repo, sign both RPM and repodata as `bryan`, and publish files owned by `nginx`.
* `installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter --vncpass "letmein"` * `installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter --vncpass "letmein"`
Install services to share the existing local desktop via VNC and automatically run MC on startup. Install services to share the existing local desktop via VNC and automatically run MC on startup.

View File

@@ -16,13 +16,14 @@
# NOTES # NOTES
# * Be careful with tabs in heredocs # * Be careful with tabs in heredocs
# * Avoid execute() for stdout # * Avoid execute() for stdout
# * RPM repo creation requires rpmbuild and rpmsign
# #
# Allow indirection to match service names to their functions # Allow indirection to match service names to their functions
# shellcheck disable=SC2329 # shellcheck disable=SC2329
shopt -s extglob shopt -s extglob
declare -g SCRIPT_VERSION="1.35.13" declare -g SCRIPT_VERSION="1.35.14"
declare -g MC_VERSION_HARDCODE="35.0.51" # do find all replace declare -g MC_VERSION_HARDCODE="35.0.68" # do find all replace
declare -g MC_REPO_HARDCODE="bookworm" # should match the MC_VERSION_HARDCODE declare -g MC_REPO_HARDCODE="bookworm" # should match the MC_VERSION_HARDCODE
declare -g BOARD_ID="92.0" # MC35 board ID for fallback latest version detection declare -g BOARD_ID="92.0" # MC35 board ID for fallback latest version detection
declare -gi SELF_UPDATE_SWITCH=1 # 0 to disable installJRMC self-update declare -gi SELF_UPDATE_SWITCH=1 # 0 to disable installJRMC self-update
@@ -41,7 +42,7 @@ print_help() {
USAGE: USAGE:
installJRMC [[OPTION] [VALUE]]... installJRMC [[OPTION] [VALUE]]...
installJRMC defaults to --install=repo on platforms with a JRiver repository and --install=local on all others. installJRMC defaults to --install=repo on platforms with a JRiver repository and --install=local on others.
Specifying --build, --createrepo, --service, or --uninstall disables the default install method. Specifying --build, --createrepo, --service, or --uninstall disables the default install method.
OPTIONS OPTIONS
@@ -66,19 +67,9 @@ print_help() {
--betapass PASSWORD --betapass PASSWORD
Enter beta team password for access to beta builds. Enter beta team password for access to beta builds.
--service, -s SERVICE --service, -s SERVICE
See SERVICES section below for a list of possible services to install. See SERVICES below for possible services to install.
--service-type user|system --service-type user|system
Starts services at boot (system) or at user login (user) (default: per service, see SERVICES). Starts services at boot (system) or at user login (user) (default: per service, see SERVICES).
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of possible services to install.
--createrepo[=suse|fedora|centos|mandriva]
Build rpm, copy to webroot, and run createrepo.
Use in conjunction with --build=TARGET for crossbuilding repos.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora, note the '=').
--createrepo-webroot PATH
Specify the webroot directory to install the repo (default: /var/www/jriver).
--createrepo-user USER
Specify the web server user if it differs from \$USER.
--no-update --no-update
Disable automatic installJRMC self-update. Disable automatic installJRMC self-update.
--uninstall, -u --uninstall, -u
@@ -111,6 +102,26 @@ print_help() {
current display incremented by 1 (Xvnc)). current display incremented by 1 (Xvnc)).
jriver-createrepo (system) jriver-createrepo (system)
Install hourly service to build latest MC RPM and run createrepo. Install hourly service to build latest MC RPM and run createrepo.
ADVANCED OPTIONS
--container, -c CONTAINER (TODO: Under construction)
See CONTAINERS section below for a list of possible services to install.
--createrepo[=suse|fedora|centos|mandriva]
Build rpm, copy to webroot, and run createrepo.
Use in conjunction with --build=TARGET for crossbuilding repos.
Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora).
--createrepo-webroot PATH
Specify the webroot directory to install the repo (default: /var/www/jriver).
--webroot-user USER
Owner/user for createrepo output in the webroot (default: current user).
--createrepo-user USER
Backward-compatible alias for --webroot-user.
--sign
Sign the built RPM and repodata/repomd.xml (if --createrepo).
--sign-user USER
User account used to run rpmsign and gpg signing (default: current user).
--sign-key KEYID
GPG key ID, fingerprint, or UID used for --sign.
EOF EOF
} }
@@ -120,15 +131,18 @@ parse_input() {
debug "${FUNCNAME[0]}()" "$@" debug "${FUNCNAME[0]}()" "$@"
declare -gi BUILD_SWITCH REPO_INSTALL_SWITCH LOCAL_INSTALL_SWITCH \ declare -gi BUILD_SWITCH REPO_INSTALL_SWITCH LOCAL_INSTALL_SWITCH \
CONTAINER_INSTALL_SWITCH CREATEREPO_SWITCH SNAP_INSTALL_SWITCH \ CONTAINER_INSTALL_SWITCH CREATEREPO_SWITCH SNAP_INSTALL_SWITCH \
APPIMAGE_INSTALL_SWITCH COMPAT_SWITCH UNINSTALL_SWITCH YES_SWITCH DEBUG=0 APPIMAGE_INSTALL_SWITCH COMPAT_SWITCH UNINSTALL_SWITCH YES_SWITCH \
SIGN_SWITCH DEBUG=0
declare -g MC_VERSION_USER MC_MVERSION_USER MC_RELEASE_USER MC_REPO_USER USER_ARCH MJR_FILE \ declare -g MC_VERSION_USER MC_MVERSION_USER MC_RELEASE_USER MC_REPO_USER USER_ARCH MJR_FILE \
BETAPASS SERVICE_TYPE VNCPASS USER_DISPLAY BUILD_TARGET CREATEREPO_TARGET BETAPASS SERVICE_TYPE VNCPASS USER_DISPLAY BUILD_TARGET CREATEREPO_TARGET \
WEBROOT_USER SIGN_USER SIGN_KEY
local long_opts short_opts input local long_opts short_opts input
long_opts="install:,build::,outputdir:,mcversion:,arch:,mcrepo:,compat," long_opts="install:,build::,outputdir:,mcversion:,arch:,mcrepo:,compat,"
long_opts+="restorefile:,betapass:," long_opts+="restorefile:,betapass:,"
long_opts+="service-type:,service:,services:," long_opts+="service-type:,service:,services:,"
long_opts+="version,debug,verbose,help,uninstall,yes,auto,no-update," long_opts+="version,debug,verbose,help,uninstall,yes,auto,no-update,"
long_opts+="createrepo::,createrepo-webroot:,createrepo-user:," long_opts+="createrepo::,createrepo-webroot:,webroot-user:,createrepo-user:,"
long_opts+="sign,sign-user:,sign-key:,"
long_opts+="vncpass:,display:,container:" long_opts+="vncpass:,display:,container:"
short_opts="+i:b::s:c:uyvdh" short_opts="+i:b::s:c:uyvdh"
@@ -196,7 +210,10 @@ parse_input() {
--createrepo) shift; CREATEREPO_TARGET="$1"; BUILD_TARGET="$1" --createrepo) shift; CREATEREPO_TARGET="$1"; BUILD_TARGET="$1"
BUILD_SWITCH=1; CREATEREPO_SWITCH=1 ;; BUILD_SWITCH=1; CREATEREPO_SWITCH=1 ;;
--createrepo-webroot) shift; CREATEREPO_WEBROOT="$1" ;; --createrepo-webroot) shift; CREATEREPO_WEBROOT="$1" ;;
--createrepo-user) shift; CREATEREPO_USER="$1" ;; --webroot-user|--createrepo-user) shift; WEBROOT_USER="$1" ;;
--sign) SIGN_SWITCH=1 ;;
--sign-user) shift; SIGN_USER="$1" ;;
--sign-key) shift; SIGN_KEY="$1" ;;
--vncpass) shift; VNCPASS="$1" ;; --vncpass) shift; VNCPASS="$1" ;;
--display) shift; USER_DISPLAY="$1" ;; --display) shift; USER_DISPLAY="$1" ;;
--compat) COMPAT_SWITCH=1; BUILD_SWITCH=1 ;; --compat) COMPAT_SWITCH=1; BUILD_SWITCH=1 ;;
@@ -227,6 +244,14 @@ parse_input() {
echo "Warning: not all repositories have beta channels" echo "Warning: not all repositories have beta channels"
echo "If the MC package is unavailable, try using --mcrepo to select another repository" echo "If the MC package is unavailable, try using --mcrepo to select another repository"
fi fi
# If jriver-createrepo is being installed as a service, treat --createrepo
# as service configuration only and defer build/repo execution to the timer.
if [[ " ${SERVICES[*]} " =~ [[:space:]]jriver-createrepo[[:space:]] ]] && ((CREATEREPO_SWITCH)); then
debug "Deferring --createrepo execution while configuring jriver-createrepo service"
BUILD_SWITCH=0
CREATEREPO_SWITCH=0
fi
} }
# @description Perform OS detection and generate OS-specific functions # @description Perform OS detection and generate OS-specific functions
@@ -243,7 +268,8 @@ init() {
declare -g OUTPUT_DIR="$SCRIPT_DIR/output" declare -g OUTPUT_DIR="$SCRIPT_DIR/output"
declare -g CREATEREPO_WEBROOT="/var/www/jriver" declare -g CREATEREPO_WEBROOT="/var/www/jriver"
declare -g CREATEREPO_USER="$USER" # can be root declare -g WEBROOT_USER # can be root
declare -g SIGN_USER
declare -g ID VERSION_ID UBUNTU_CODENAME VERSION_CODENAME ARCH MC_ARCH NAME declare -g ID VERSION_ID UBUNTU_CODENAME VERSION_CODENAME ARCH MC_ARCH NAME
declare -g MC_MVERSION MC_RELEASE MC_PKG MC_RPM MC_ROOT declare -g MC_MVERSION MC_RELEASE MC_PKG MC_RPM MC_ROOT
declare -ga PKG_INSTALL PKG_REMOVE PKG_UPDATE PKG_QUERY declare -ga PKG_INSTALL PKG_REMOVE PKG_UPDATE PKG_QUERY
@@ -253,7 +279,7 @@ init() {
# Try to save users from themselves # Try to save users from themselves
if [[ $EUID -eq 0 ]]; then if [[ $EUID -eq 0 ]]; then
err "Running as root but attempting to continue" echo "Warning: running as root"
ask_ok "Continue as root user (not recommended)?" || exit 1 ask_ok "Continue as root user (not recommended)?" || exit 1
elif [[ -n $SUDO_USER ]]; then elif [[ -n $SUDO_USER ]]; then
err "Sudo detected, installJRMC should not be run with sudo but attempting to continue" err "Sudo detected, installJRMC should not be run with sudo but attempting to continue"
@@ -261,6 +287,10 @@ init() {
USER="${SUDO_USER:-$USER}" USER="${SUDO_USER:-$USER}"
fi fi
# Default webroot/signing contexts to the account currently running installJRMC.
WEBROOT_USER="${WEBROOT_USER:-$USER}"
SIGN_USER="${SIGN_USER:-$(id -un)}"
# Run the self-updater if enabled # Run the self-updater if enabled
((SELF_UPDATE_SWITCH)) && ((! SCRIPT_IS_PIPED)) && update "$@" ((SELF_UPDATE_SWITCH)) && ((! SCRIPT_IS_PIPED)) && update "$@"
@@ -872,7 +902,8 @@ build_rpm() {
# shellcheck disable=SC2178 # shellcheck disable=SC2178
declare -n requires_arr="$1" recommends_arr="$2" declare -n requires_arr="$1" recommends_arr="$2"
local requires_str recommends_str local requires_str recommends_str
local i rpmbuild_cmd stub local i rpmbuild_cmd sign_cmd stub sign_output
local -a build_prefix sign_prefix
local spec_file="$OUTPUT_DIR/SPECS/mediacenter$MC_MVERSION-$MC_VERSION-$MC_RELEASE-$BUILD_TARGET-$ARCH.spec" local spec_file="$OUTPUT_DIR/SPECS/mediacenter$MC_MVERSION-$MC_VERSION-$MC_RELEASE-$BUILD_TARGET-$ARCH.spec"
# skip rebuilding the rpm if it already exists # skip rebuilding the rpm if it already exists
@@ -966,8 +997,64 @@ build_rpm() {
"$spec_file" "$spec_file"
) )
# Build as signing user when running as root with a non-root SIGN_USER.
# This keeps RPM ownership aligned with rpmsign and avoids permission mismatches.
if [[ $(id -un) == "$SIGN_USER" ]]; then
build_prefix=()
else
build_prefix=(sudo -H -u "$SIGN_USER")
execute chown -R "$SIGN_USER:$SIGN_USER" "$OUTPUT_DIR"
fi
# Run rpmbuild and verify output RPM exists # Run rpmbuild and verify output RPM exists
execute "${rpmbuild_cmd[@]}" && [[ -f $MC_RPM ]] execute "${build_prefix[@]}" "${rpmbuild_cmd[@]}" && [[ -f $MC_RPM ]] || return 1
# Optionally sign the built RPM with the configured key
if ((SIGN_SWITCH)); then
command -v rpmsign &>/dev/null || { err "rpmsign command missing (install rpm-sign/rpm-build)"; return 1; }
command -v gpg &>/dev/null || { err "gpg command missing"; return 1; }
if ! id "$SIGN_USER" &>/dev/null; then
err "Signing user does not exist: $SIGN_USER"
return 1
fi
if [[ $(id -un) == "$SIGN_USER" ]]; then
sign_prefix=()
else
# Use target HOME so rpmsign reads the expected user keyring.
sign_prefix=(sudo -H -u "$SIGN_USER")
fi
if [[ -n $SIGN_KEY ]] && ! "${sign_prefix[@]}" gpg --batch --list-secret-keys --with-colons "$SIGN_KEY" 2>/dev/null | grep -q '^sec'; then
err "Signing key not found in $SIGN_USER keyring: $SIGN_KEY"
err "Import the private key for $SIGN_USER or adjust --sign-user/--sign-key"
return 1
fi
sign_cmd=(rpmsign --addsign)
if [[ -n $SIGN_KEY ]]; then
if rpmsign --help 2>&1 | grep -q -- '--key-id'; then
sign_cmd+=(--key-id "$SIGN_KEY")
else
sign_cmd+=(--define "_gpg_name $SIGN_KEY")
fi
fi
sign_cmd+=("$MC_RPM")
echo "Signing RPM: $MC_RPM"
debug "${sign_prefix[*]} ${sign_cmd[*]}"
if ! sign_output=$("${sign_prefix[@]}" "${sign_cmd[@]}" 2>&1); then
err "RPM signing failed"
[[ -n $sign_output ]] && echo "$sign_output" >&2
err "Hint: for non-interactive service runs, ensure $SIGN_USER can access an unlocked GPG key"
return 1
fi
((DEBUG)) && [[ -n $sign_output ]] && echo "$sign_output"
fi
return 0
} }
# @description Creates the Arch PKGBUILD file for Media Center # @description Creates the Arch PKGBUILD file for Media Center
@@ -1111,20 +1198,36 @@ install_mc_arch() {
popd &>/dev/null || return popd &>/dev/null || return
} }
# @description Copy the RPM to createrepo-webroot and run createrepo as the createrepo-user # @description Copy the RPM to createrepo-webroot and run createrepo as the webroot-user
run_createrepo() { run_createrepo() {
debug "${FUNCNAME[0]}()" debug "${FUNCNAME[0]}()"
local -a cr_opts gpg_cmd sign_prefix
local repomd_xml repomd_asc pubkey_file
install_package createrepo_c install_package createrepo_c
# Ensure WEBROOT_USER exists or offer to create it
if ! id "$WEBROOT_USER" &>/dev/null; then
err "Specified --webroot-user '$WEBROOT_USER' does not exist"
if ask_ok "Create local user '$WEBROOT_USER'?"; then
if ! execute sudo useradd "$WEBROOT_USER"; then
err "Failed to create user '$WEBROOT_USER'"
return 1
fi
else
err "Cannot continue without a valid --webroot-user"
return 1
fi
fi
# Ensure the webroot exists # Ensure the webroot exists
if [[ ! -d $CREATEREPO_WEBROOT ]]; then if [[ ! -d $CREATEREPO_WEBROOT ]]; then
if ! execute sudo -u "$CREATEREPO_USER" mkdir -p "$CREATEREPO_WEBROOT"; then if ! execute sudo -u "$WEBROOT_USER" mkdir -p "$CREATEREPO_WEBROOT"; then
if ! (execute sudo mkdir -p "$CREATEREPO_WEBROOT" || if ! (execute sudo mkdir -p "$CREATEREPO_WEBROOT" ||
execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then execute sudo chown -R "$WEBROOT_USER:$WEBROOT_USER" "$CREATEREPO_WEBROOT"); then
err "Could not create the createrepo-webroot path!" err "Could not create the createrepo-webroot path!"
err "Make sure that the webroot $CREATEREPO_WEBROOT is writable by user $CREATEREPO_USER" err "Make sure that the webroot $CREATEREPO_WEBROOT is writable by user $WEBROOT_USER"
err "Or change the repo ownership with --createrepo-user" err "Or change the repo ownership with --webroot-user"
return 1 return 1
fi fi
fi fi
@@ -1132,20 +1235,72 @@ run_createrepo() {
# Copy built RPMs to webroot # Copy built RPMs to webroot
if ! execute sudo cp -nf "$MC_RPM" "$CREATEREPO_WEBROOT" || if ! execute sudo cp -nf "$MC_RPM" "$CREATEREPO_WEBROOT" ||
! execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"; then ! execute sudo chown -R "$WEBROOT_USER:$WEBROOT_USER" "$CREATEREPO_WEBROOT"; then
err "Could not copy $MC_RPM to $CREATEREPO_WEBROOT" err "Could not copy $MC_RPM to $CREATEREPO_WEBROOT"
return 1 return 1
fi fi
# Run createrepo # Run createrepo
local -a cr_opts=(--update) cr_opts=(--update)
# [[ -d "$CREATEREPO_WEBROOT/repodata" ]] && cr_opts+=(--update) # TODO temporarily disabled for legacy createrepo # [[ -d "$CREATEREPO_WEBROOT/repodata" ]] && cr_opts+=(--update) # TODO temporarily disabled for legacy createrepo
if ! execute sudo -u "$CREATEREPO_USER" createrepo "${cr_opts[@]}" "$CREATEREPO_WEBROOT"; then if ! execute sudo -u "$WEBROOT_USER" createrepo "${cr_opts[@]}" "$CREATEREPO_WEBROOT"; then
if ! (execute sudo createrepo "${cr_opts[@]}" "$CREATEREPO_WEBROOT" && execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then if ! (execute sudo createrepo "${cr_opts[@]}" "$CREATEREPO_WEBROOT" && execute sudo chown -R "$WEBROOT_USER:$WEBROOT_USER" "$CREATEREPO_WEBROOT"); then
err "createrepo failed" err "createrepo failed"
return 1 return 1
fi fi
fi fi
# Optionally sign repodata so clients can use repo_gpgcheck=1
if ((SIGN_SWITCH)); then
command -v gpg &>/dev/null || { err "gpg command missing"; return 1; }
repomd_xml="$CREATEREPO_WEBROOT/repodata/repomd.xml"
repomd_asc="$repomd_xml.asc"
[[ -f $repomd_xml ]] || { err "repomd.xml missing after createrepo"; return 1; }
[[ -n $SIGN_KEY ]] || { err "--sign requires --sign-key for repodata signing"; return 1; }
if [[ $(id -un) == "$SIGN_USER" ]]; then
sign_prefix=()
else
sign_prefix=(sudo -H -u "$SIGN_USER")
fi
# Sign repo.md to a temp file first and then move to webroot
local repomd_asc_tmp
if ! repomd_asc_tmp=$("${sign_prefix[@]}" mktemp); then
err "Failed to create temp file for signature"
return 1
fi
gpg_cmd=(gpg --batch --yes --pinentry-mode loopback --default-key "$SIGN_KEY" --armor --detach-sign --output "$repomd_asc_tmp")
((DEBUG)) && gpg_cmd+=(--verbose)
gpg_cmd+=("$repomd_xml")
echo "Signing repodata: $repomd_xml"
if ! execute "${sign_prefix[@]}" "${gpg_cmd[@]}"; then
rm -f "$repomd_asc_tmp"
err "Repodata signing failed"
return 1
fi
execute sudo install -m 0644 "$repomd_asc_tmp" "$repomd_asc"
execute sudo chown "$WEBROOT_USER:$WEBROOT_USER" "$repomd_asc"
rm -f "$repomd_asc_tmp"
# Export public key so clients can import it via repo gpgkey URL
pubkey_file="$CREATEREPO_WEBROOT/RPM-GPG-KEY-jriver.asc"
local pubkey_tmp
if ! pubkey_tmp=$("${sign_prefix[@]}" mktemp); then
err "Failed to create temp file for public key"
return 1
fi
if ! execute "${sign_prefix[@]}" gpg --batch --yes --armor --output "$pubkey_tmp" --export "$SIGN_KEY"; then
rm -f "$pubkey_tmp"
err "Public key export failed for SIGN_KEY=$SIGN_KEY"
return 1
fi
execute sudo install -m 0644 "$pubkey_tmp" "$pubkey_file"
execute sudo chown "$WEBROOT_USER:$WEBROOT_USER" "$pubkey_file"
rm -f "$pubkey_tmp"
fi
} }
# @description Symlink certificates if they do not exist in default location # @description Symlink certificates if they do not exist in default location
@@ -1522,21 +1677,61 @@ service_jriver-x11vnc() {
# JRiver Media Center RPM from the source DEB and create/update an RPM repository # JRiver Media Center RPM from the source DEB and create/update an RPM repository
service_jriver-createrepo() { service_jriver-createrepo() {
debug "${FUNCNAME[0]}()" debug "${FUNCNAME[0]}()"
local -a sign_args start_cmd
local service_script start_cmd
if [[ $CREATEREPO_USER != "$USER" ]]; then CREATEREPO_SWITCH=0 # skip running createrepo when generating service
USER="root" set_service_vars "${FUNCNAME[0]##*_}" "system"
set_service_vars "${FUNCNAME[0]##*_}" "system"
# jriver-createrepo must run as root, not templated per-user
SERVICE_NAME="jriver-createrepo.service"
TIMER_NAME="jriver-createrepo.timer"
SERVICE_FNAME="/usr/lib/systemd/system/jriver-createrepo.service"
TIMER_FNAME="/usr/lib/systemd/system/jriver-createrepo.timer"
USER_STRING=""
# System services cannot exec files from home directories (SELinux).
# If the script lives under /home/, copy it to a system path first.
if [[ $SCRIPT_PATH == /home/* ]]; then
service_script="/opt/installJRMC/installJRMC"
echo "Script is in a home directory; installing to $service_script for system service"
if ! { execute sudo mkdir -p "/opt/installJRMC" && execute sudo install -m 0755 "$SCRIPT_PATH" "$service_script"; }; then
err "Could not install script to $service_script; the service may fail to start"
service_script="$SCRIPT_PATH"
fi
else else
set_service_vars "${FUNCNAME[0]##*_}" "system" service_script="$SCRIPT_PATH"
fi fi
sign_args=()
((SIGN_SWITCH)) && sign_args+=(--sign)
[[ -n $SIGN_USER ]] && sign_args+=(--sign-user="$SIGN_USER")
[[ -n $SIGN_KEY ]] && sign_args+=(--sign-key="$SIGN_KEY")
start_cmd=(
"$service_script"
--outputdir="$OUTPUT_DIR"
--createrepo="$CREATEREPO_TARGET"
--createrepo-webroot="$CREATEREPO_WEBROOT"
--webroot-user="$WEBROOT_USER"
--mcrepo="$MC_REPO"
"${sign_args[@]}"
--yes
--no-update
)
# Pass --debug to service file if it was set for the main script
((DEBUG)) && start_cmd+=("--debug")
debug "ExecStart=${start_cmd[*]}"
sudo bash -c "cat <<-EOF > $SERVICE_FNAME sudo bash -c "cat <<-EOF > $SERVICE_FNAME
[Unit] [Unit]
Description=Builds JRiver Media Center RPM, moves it to the repo dir, and runs createrepo Description=Builds JRiver Media Center RPM, moves it to the repo dir, and runs createrepo
[Service] [Service]
$USER_STRING ExecStart=${start_cmd[*]}
ExecStart=$SCRIPT_DIR/installJRMC --outputdir=$OUTPUT_DIR --createrepo=$CREATEREPO_TARGET \
--createrepo-webroot=$CREATEREPO_WEBROOT --createrepo-user=$CREATEREPO_USER --mcrepo=$MC_REPO --yes --no-update
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@@ -1779,21 +1974,26 @@ main() {
exit 0 exit 0
fi fi
install_external_repos
if ((REPO_INSTALL_SWITCH)); then if ((REPO_INSTALL_SWITCH)); then
echo "Installing JRiver Media Center from remote repository" echo "Installing JRiver Media Center from remote repository"
local repo_file local repo_file
install_external_repos
case $ID in case $ID in
fedora|centos) fedora|centos)
repo_file="/etc/yum.repos.d/jriver.repo" local keyurl="https://repos.bryanroessler.com/jriver/RPM-GPG-KEY-jriver.asc"
local keyfile="/etc/pki/rpm-gpg/RPM-GPG-KEY-jriver"
echo "Installing repository file: $repo_file" echo "Installing repository file: $repo_file"
repo_file="/etc/yum.repos.d/jriver.repo"
sudo tee "$repo_file" &>/dev/null <<-EOF sudo tee "$repo_file" &>/dev/null <<-EOF
[jriver] [jriver]
baseurl = https://repos.bryanroessler.com/jriver baseurl = https://repos.bryanroessler.com/jriver
enabled = 1 enabled = 1
gpgcheck = 0 gpgcheck = 1
repo_gpgcheck = 1
gpgkey = $keyurl
name = JRiver Media Center hosted by BryanC name = JRiver Media Center hosted by BryanC
EOF EOF
;; ;;
@@ -1844,7 +2044,7 @@ main() {
fi fi
echo "Installing $MC_PKG package" echo "Installing $MC_PKG package"
if install_package --no-install-check --no-gpg-check --allow-downgrades "$MC_PKG"; then if install_package --no-install-check --allow-downgrades "$MC_PKG"; then
echo "Successfully installed JRiver Media Center from repository" echo "Successfully installed JRiver Media Center from repository"
else else
err "MC failed to install" err "MC failed to install"
@@ -1893,9 +2093,14 @@ main() {
if ((LOCAL_INSTALL_SWITCH)); then if ((LOCAL_INSTALL_SWITCH)); then
echo "Installing JRiver Media Center from local package" echo "Installing JRiver Media Center from local package"
install_external_repos
# Install MC package # Install MC package
case $ID in case $ID in
fedora|centos|mandriva|suse) install_package --no-install-check --no-gpg-check --allow-downgrades "$MC_RPM" ;; fedora|centos|mandriva|suse)
local -a gpg_flag; ((SIGN_SWITCH)) || gpg_flag=(--no-gpg-check)
install_package --no-install-check "${gpg_flag[@]}" --allow-downgrades "$MC_RPM"
;;
debian|ubuntu) install_mc_deb "$@" ;; debian|ubuntu) install_mc_deb "$@" ;;
arch) install_mc_arch ;; arch) install_mc_arch ;;
unknown) install_mc_generic ;; unknown) install_mc_generic ;;
@@ -1913,14 +2118,6 @@ main() {
open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp" open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
fi fi
if ((CREATEREPO_SWITCH)); then
if run_createrepo; then
echo "Successfully updated repo"
else
err "Repo creation failed"
fi
fi
if [[ ${#SERVICES[@]} -gt 0 ]]; then if [[ ${#SERVICES[@]} -gt 0 ]]; then
declare service declare service
for service in "${SERVICES[@]}"; do for service in "${SERVICES[@]}"; do
@@ -1936,6 +2133,14 @@ main() {
done done
unset service unset service
fi fi
if ((CREATEREPO_SWITCH)); then
if run_createrepo; then
echo "Successfully updated repo"
else
err "Repo creation failed"
fi
fi
} }
# @section Helper functions # @section Helper functions