├── Dockerfile ├── Jenkinsfile ├── README.md ├── VERSION ├── docker-compose.yaml └── rootfs ├── etc └── cont-init.d │ └── rclonebrowser.sh └── startapp.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # RcloneBrowser Dockerfile 3 | # 4 | 5 | FROM jlesage/baseimage-gui:alpine-3.12-glibc 6 | 7 | # Define build arguments 8 | ARG RCLONE_VERSION=current 9 | 10 | # Define environment variables 11 | ENV ARCH=amd64 12 | 13 | # Define working directory. 14 | WORKDIR /tmp 15 | 16 | # Install Rclone Browser dependencies 17 | 18 | RUN apk --no-cache add \ 19 | ca-certificates \ 20 | fuse \ 21 | wget \ 22 | qt5-qtbase \ 23 | qt5-qtbase-x11 \ 24 | libstdc++ \ 25 | libgcc \ 26 | dbus \ 27 | xterm \ 28 | && cd /tmp \ 29 | && wget -q http://downloads.rclone.org/rclone-${RCLONE_VERSION}-linux-${ARCH}.zip \ 30 | && unzip /tmp/rclone-${RCLONE_VERSION}-linux-${ARCH}.zip \ 31 | && mv /tmp/rclone-*-linux-${ARCH}/rclone /usr/bin \ 32 | && rm -r /tmp/rclone* && \ 33 | 34 | apk add --no-cache --virtual=build-dependencies \ 35 | build-base \ 36 | cmake \ 37 | make \ 38 | gcc \ 39 | git \ 40 | qt5-qtbase qt5-qtmultimedia-dev qt5-qttools-dev && \ 41 | 42 | # Compile RcloneBrowser 43 | git clone https://github.com/kapitainsky/RcloneBrowser.git /tmp && \ 44 | mkdir /tmp/build && \ 45 | cd /tmp/build && \ 46 | cmake .. && \ 47 | cmake --build . && \ 48 | ls -l /tmp/build && \ 49 | cp /tmp/build/build/rclone-browser /usr/bin && \ 50 | 51 | # cleanup 52 | apk del --purge build-dependencies && \ 53 | rm -rf /tmp/* 54 | 55 | # Maximize only the main/initial window. 56 | RUN \ 57 | sed-patch 's///' \ 58 | /etc/xdg/openbox/rc.xml 59 | 60 | # Generate and install favicons. 61 | RUN \ 62 | APP_ICON_URL=https://github.com/rclone/rclone/raw/master/graphics/logo/logo_symbol/logo_symbol_color_512px.png && \ 63 | install_app_icon.sh "$APP_ICON_URL" 64 | 65 | # Add files. 66 | COPY rootfs/ / 67 | COPY VERSION / 68 | 69 | # Set environment variables. 70 | ENV APP_NAME="RcloneBrowser" \ 71 | S6_KILL_GRACETIME=8000 72 | 73 | # Define mountable directories. 74 | VOLUME ["/config"] 75 | VOLUME ["/media"] 76 | 77 | # Metadata. 78 | LABEL \ 79 | org.label-schema.name="rclonebrowser" \ 80 | org.label-schema.description="Docker container for RcloneBrowser" \ 81 | org.label-schema.version="unknown" \ 82 | org.label-schema.vcs-url="https://github.com/romancin/rclonebrowser-docker" \ 83 | org.label-schema.schema-version="1.0" 84 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | registry="romancin/rclonebrowser" 2 | 3 | podTemplate(label: 'github-docker-builder', cloud: 'kubernetes', 4 | containers: [ 5 | containerTemplate(name: 'buildkit', image: 'moby/buildkit:master', ttyEnabled: true, privileged: true), 6 | containerTemplate(name: 'docker-readme', image: 'sheogorath/readme-to-dockerhub', command: 'sleep', args: '99d'), 7 | ], 8 | volumes: [ 9 | secretVolume(secretName: 'docker-config', mountPath: '/root/.docker') 10 | ]) { 11 | node('github-docker-builder') { 12 | stage('Cloning Git Repository') { 13 | container('buildkit') { 14 | git url: 'https://github.com/romancin/rclonebrowser-docker.git', 15 | branch: '$BRANCH_NAME' 16 | } 17 | } 18 | stage('Building image and pushing it to the registry (develop)') { 19 | if (env.BRANCH_NAME == 'develop') { 20 | def gitbranch = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim() 21 | def version = readFile('VERSION') 22 | def versions = version.split('\\.') 23 | def major = gitbranch + '-' + versions[0] 24 | def minor = gitbranch + '-' + versions[0] + '.' + versions[1] 25 | def patch = gitbranch + '-' + version.trim() 26 | container('buildkit') { 27 | sh """ 28 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${gitbranch},push=true 29 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${major},push=true 30 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${minor},push=true 31 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${patch},push=true 32 | """ 33 | } 34 | } 35 | } 36 | stage('Building image and pushing it to the registry (main)') { 37 | if (env.BRANCH_NAME == 'main') { 38 | def gitbranch = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim() 39 | def version = readFile('VERSION') 40 | def versions = version.split('\\.') 41 | def major = versions[0] 42 | def minor = versions[0] + '.' + versions[1] 43 | def patch = version.trim() 44 | container('buildkit') { 45 | sh """ 46 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:latest,push=true 47 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${major},push=true 48 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${minor},push=true 49 | buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${registry}:${patch},push=true 50 | """ 51 | } 52 | container('docker-readme') { 53 | withEnv(['DOCKERHUB_REPO_NAME=tinymediamanager']) { 54 | withCredentials([usernamePassword(credentialsId: 'dockerhub', passwordVariable: 'DOCKERHUB_PASSWORD', usernameVariable: 'DOCKERHUB_USERNAME')]) { 55 | sh """ 56 | export DOCKERHUB_USERNAME=${DOCKERHUB_USERNAME} 57 | export DOCKERHUB_PASSWORD=${DOCKERHUB_PASSWORD} 58 | rm -rf /data && ln -s `pwd` /data 59 | cd /data && node --unhandled-rejections=strict /app/index.js 60 | """ 61 | } 62 | } 63 | } 64 | } 65 | } 66 | stage('Notify Build Result') { 67 | withCredentials([string(credentialsId: 'discord-webhook-notificaciones', variable: 'DISCORD_WEBHOOK')]) { 68 | discordSend description: "[Jenkins] - Pipeline CI-docker-rclonebrowser", footer: "", link: env.BUILD_URL, result: currentBuild.currentResult, title: JOB_NAME, webhookURL: "${DISCORD_WEBHOOK}" 69 | } 70 | } 71 | } 72 | } 73 | 74 | properties([[ 75 | $class: 'BuildDiscarderProperty', 76 | strategy: [ 77 | $class: 'LogRotator', 78 | artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '10'] 79 | ] 80 | ]); 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rclonebrowser-docker 2 | 3 | A repository for creating a docker container including RClone Browser with GUI interface, based on [kapitainsky fork](https://github.com/kapitainsky/RcloneBrowser) 4 | 5 | Thank you for continue developing this awesome software :) 6 | 7 | [![](https://images.microbadger.com/badges/version/romancin/rclonebrowser.svg)](https://microbadger.com/images/romancin/rclonebrowser "Docker image version") 8 | [![](https://images.microbadger.com/badges/image/romancin/rclonebrowser.svg)](https://microbadger.com/images/romancin/rclonebrowser "Docker image size") 9 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=X2CT2SWQCP74U) 10 | 11 | You can invite me a beer if you want ;) 12 | 13 | This is a completely funcional Docker image with RClone Browser (kapytainsky fork). 14 | 15 | Based on Alpine Linux, which provides a very small size. 16 | 17 | Tested and working on Synology and QNAP, but should work on any x86_64 devices. 18 | 19 | Thanks to @jlesage for a great base image for GUI apps. 20 | 21 | Instructions: 22 | - Map any local port to 5800 for web access 23 | - Map any local port to 5900 for VNC access 24 | - Map a local volume to /config (Stores configuration data) 25 | - Map a local volume to /media (Access media files) 26 | 27 | Sample run command: 28 | 29 | ```bash 30 | docker run -d --name=rclonebrowser \ 31 | -v /share/Container/rclonebrowser/config:/config \ 32 | -v /share/Container/rclonebrowser/media:/media \ 33 | -e GROUP_ID=0 -e USER_ID=0 -e TZ=Europe/Madrid \ 34 | -p 5800:5800 \ 35 | -p 5900:5900 \ 36 | romancin/rclonebrowser:latest 37 | ``` 38 | 39 | Browse to `http://your-host-ip:5800` to access the RClone Browser GUI. 40 | 41 | ### Environment Variables 42 | 43 | To customize some properties of the container, the following environment 44 | variables can be passed via the `-e` parameter (one for each variable). Value 45 | of this parameter has the format `=`. 46 | 47 | | Variable | Description | Default | 48 | |----------------|----------------------------------------------|---------| 49 | |`USER_ID`| ID of the user the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | 50 | |`GROUP_ID`| ID of the group the application runs as. See [User/Group IDs](#usergroup-ids) to better understand when this should be set. | `1000` | 51 | |`SUP_GROUP_IDS`| Comma-separated list of supplementary group IDs of the application. | (unset) | 52 | |`UMASK`| Mask that controls how file permissions are set for newly created files. The value of the mask is in octal notation. By default, this variable is not set and the default umask of `022` is used, meaning that newly created files are readable by everyone, but only writable by the owner. See the following online umask calculator: http://wintelguy.com/umask-calc.pl | (unset) | 53 | |`TZ`| [TimeZone] of the container. Timezone can also be set by mapping `/etc/localtime` between the host and the container. | `Etc/UTC` | 54 | |`KEEP_APP_RUNNING`| When set to `1`, the application will be automatically restarted if it crashes or if user quits it. | `0` | 55 | |`APP_NICENESS`| Priority at which the application should run. A niceness value of -20 is the highest priority and 19 is the lowest priority. By default, niceness is not set, meaning that the default niceness of 0 is used. **NOTE**: A negative niceness (priority increase) requires additional permissions. In this case, the container should be run with the docker option `--cap-add=SYS_NICE`. | (unset) | 56 | |`CLEAN_TMP_DIR`| When set to `1`, all files in the `/tmp` directory are delete during the container startup. | `1` | 57 | |`DISPLAY_WIDTH`| Width (in pixels) of the application's window. | `1280` | 58 | |`DISPLAY_HEIGHT`| Height (in pixels) of the application's window. | `768` | 59 | |`SECURE_CONNECTION`| When set to `1`, an encrypted connection is used to access the application's GUI (either via web browser or VNC client). See the [Security](#security) section for more details. | `0` | 60 | |`VNC_PASSWORD`| Password needed to connect to the application's GUI. See the [VNC Password](#vnc-password) section for more details. | (unset) | 61 | |`X11VNC_EXTRA_OPTS`| Extra options to pass to the x11vnc server running in the Docker container. **WARNING**: For advanced users. Do not use unless you know what you are doing. | (unset) | 62 | |`ENABLE_CJK_FONT`| When set to `1`, open source computer font `WenQuanYi Zen Hei` is installed. This font contains a large range of Chinese/Japanese/Korean characters. | `0` | 63 | 64 | ### Data Volumes 65 | 66 | The following table describes data volumes used by the container. The mappings 67 | are set via the `-v` parameter. Each mapping is specified with the following 68 | format: `:[:PERMISSIONS]`. 69 | 70 | | Container path | Permissions | Description | 71 | |-----------------|-------------|-------------| 72 | |`/config`| rw | This is where the application stores its configuration, log and any files needing persistency. | 73 | |`/media`| rw | This is where downloaded files are stored, or where you put files in your host for uploading. | 74 | 75 | ### Ports 76 | 77 | Here is the list of ports used by the container. They can be mapped to the host 78 | via the `-p` parameter (one per port mapping). Each mapping is defined in the 79 | following format: `:`. The port number inside the 80 | container cannot be changed, but you are free to use any port on the host side. 81 | 82 | | Port | Mapping to host | Description | 83 | |------|-----------------|-------------| 84 | | 5800 | Mandatory | Port used to access the application's GUI via the web interface. | 85 | | 5900 | Optional | Port used to access the application's GUI via the VNC protocol. Optional if no VNC client is used. | 86 | 87 | ## User/Group IDs 88 | 89 | When using data volumes (`-v` flags), permissions issues can occur between the 90 | host and the container. For example, the user within the container may not 91 | exists on the host. This could prevent the host from properly accessing files 92 | and folders on the shared volume. 93 | 94 | To avoid any problem, you can specify the user the application should run as. 95 | 96 | This is done by passing the user ID and group ID to the container via the 97 | `USER_ID` and `GROUP_ID` environment variables. 98 | 99 | To find the right IDs to use, issue the following command on the host, with the 100 | user owning the data volume on the host: 101 | 102 | id 103 | 104 | Which gives an output like this one: 105 | ``` 106 | uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),4(adm),24(cdrom),27(sudo),46(plugdev),113(lpadmin) 107 | ``` 108 | 109 | The value of `uid` (user ID) and `gid` (group ID) are the ones that you should 110 | be given the container. 111 | 112 | ## Security 113 | 114 | By default, access to the application's GUI is done over an unencrypted 115 | connection (HTTP or VNC). 116 | 117 | Secure connection can be enabled via the `SECURE_CONNECTION` environment 118 | variable. See the [Environment Variables](#environment-variables) section for 119 | more details on how to set an environment variable. 120 | 121 | When enabled, application's GUI is performed over an HTTPs connection when 122 | accessed with a browser. All HTTP accesses are automatically redirected to 123 | HTTPs. 124 | 125 | When using a VNC client, the VNC connection is performed over SSL. Note that 126 | few VNC clients support this method. [SSVNC] is one of them. 127 | 128 | [SSVNC]: http://www.karlrunge.com/x11vnc/ssvnc.html 129 | 130 | ### Certificates 131 | 132 | Here are the certificate files needed by the container. By default, when they 133 | are missing, self-signed certificates are generated and used. All files have 134 | PEM encoded, x509 certificates. 135 | 136 | | Container Path | Purpose | Content | 137 | |---------------------------------|----------------------------|---------| 138 | |`/config/certs/vnc-server.pem` |VNC connection encryption. |VNC server's private key and certificate, bundled with any root and intermediate certificates.| 139 | |`/config/certs/web-privkey.pem` |HTTPs connection encryption.|Web server's private key.| 140 | |`/config/certs/web-fullchain.pem`|HTTPs connection encryption.|Web server's certificate, bundled with any root and intermediate certificates.| 141 | 142 | **NOTE**: To prevent any certificate validity warnings/errors from the browser 143 | or VNC client, make sure to supply your own valid certificates. 144 | 145 | **NOTE**: Certificate files are monitored and relevant daemons are automatically 146 | restarted when changes are detected. 147 | 148 | ### VNC Password 149 | 150 | To restrict access to your application, a password can be specified. This can 151 | be done via two methods: 152 | * By using the `VNC_PASSWORD` environment variable. 153 | * By creating a `.vncpass_clear` file at the root of the `/config` volume. 154 | This file should contains the password in clear-text. During the container 155 | startup, content of the file is obfuscated and moved to `.vncpass`. 156 | 157 | The level of security provided by the VNC password depends on two things: 158 | * The type of communication channel (encrypted/unencrypted). 159 | * How secure access to the host is. 160 | 161 | When using a VNC password, it is highly desirable to enable the secure 162 | connection to prevent sending the password in clear over an unencrypted channel. 163 | 164 | **ATTENTION**: Password is limited to 8 characters. This limitation comes from 165 | the Remote Framebuffer Protocol [RFC](https://tools.ietf.org/html/rfc6143) (see 166 | section [7.2.2](https://tools.ietf.org/html/rfc6143#section-7.2.2)). Any 167 | characters beyhond the limit are ignored. 168 | 169 | ## Shell Access 170 | 171 | To get shell access to a the running container, execute the following command: 172 | 173 | ``` 174 | docker exec -ti CONTAINER sh 175 | ``` 176 | 177 | Where `CONTAINER` is the ID or the name of the container used during its 178 | creation (e.g. `crashplan-pro`). 179 | 180 | ## Reverse Proxy 181 | 182 | The following sections contains NGINX configuration that need to be added in 183 | order to reverse proxy to this container. 184 | 185 | A reverse proxy server can route HTTP requests based on the hostname or the URL 186 | path. 187 | 188 | ### Routing Based on Hostname 189 | 190 | In this scenario, each hostname is routed to a different application/container. 191 | 192 | For example, let's say the reverse proxy server is running on the same machine 193 | as this container. The server would proxy all HTTP requests sent to 194 | `rclonebrowser.domain.tld` to the container at `127.0.0.1:5800`. 195 | 196 | Here are the relevant configuration elements that would be added to the NGINX 197 | configuration: 198 | 199 | ``` 200 | map $http_upgrade $connection_upgrade { 201 | default upgrade; 202 | '' close; 203 | } 204 | 205 | upstream rclonebrowser { 206 | # If the reverse proxy server is not running on the same machine as the 207 | # Docker container, use the IP of the Docker host here. 208 | # Make sure to adjust the port according to how port 5800 of the 209 | # container has been mapped on the host. 210 | server 127.0.0.1:5800; 211 | } 212 | 213 | server { 214 | [...] 215 | 216 | server_name rclonebrowser.domain.tld; 217 | 218 | location / { 219 | proxy_pass http://rclonebrowser; 220 | } 221 | 222 | location /websockify { 223 | proxy_pass http://rclonebrowser; 224 | proxy_http_version 1.1; 225 | proxy_set_header Upgrade $http_upgrade; 226 | proxy_set_header Connection $connection_upgrade; 227 | proxy_read_timeout 86400; 228 | } 229 | } 230 | 231 | ``` 232 | 233 | ### Routing Based on URL Path 234 | 235 | In this scenario, the hostname is the same, but different URL paths are used to 236 | route to different applications/containers. 237 | 238 | For example, let's say the reverse proxy server is running on the same machine 239 | as this container. The server would proxy all HTTP requests for 240 | `server.domain.tld/rclonebrowser` to the container at `127.0.0.1:5800`. 241 | 242 | Here are the relevant configuration elements that would be added to the NGINX 243 | configuration: 244 | 245 | ``` 246 | map $http_upgrade $connection_upgrade { 247 | default upgrade; 248 | '' close; 249 | } 250 | 251 | upstream rclonebrowser { 252 | # If the reverse proxy server is not running on the same machine as the 253 | # Docker container, use the IP of the Docker host here. 254 | # Make sure to adjust the port according to how port 5800 of the 255 | # container has been mapped on the host. 256 | server 127.0.0.1:5800; 257 | } 258 | 259 | server { 260 | [...] 261 | 262 | location = /rclonebrowser {return 301 $scheme://$http_host/rclonebrowser/;} 263 | location /rclonebrowser/ { 264 | proxy_pass http://rclonebrowser/; 265 | location /rclonebrowser/websockify { 266 | proxy_pass http://rclonebrowser/websockify/; 267 | proxy_http_version 1.1; 268 | proxy_set_header Upgrade $http_upgrade; 269 | proxy_set_header Connection $connection_upgrade; 270 | proxy_read_timeout 86400; 271 | } 272 | } 273 | } 274 | 275 | ``` 276 | 277 | [TimeZone]: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones 278 | 279 | ## Support or Contact 280 | 281 | Having troubles with the container or have questions? Please 282 | [create a new issue]. 283 | 284 | 285 | ## Changelog 286 | v4.0.1 (28/09/2022): Update Rclone and Rclonebrowser to current version 287 | v4.0.0 (18/05/2022): Update Rclone and Rclonebrowser to current version 288 | v3.0.2 (09/09/2020): Updated to Alpine 3.12 and Rclone current version 289 | v3.0.0 (22/03/2019): Updated to RcloneBrowser 1.8.0 version 290 | v1.0.1 (22/09/2019): Updated to latest image from jlesage and added Jenkinsfile for CI 291 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v4.0.1 2 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | rclonebrowser_service: 2 | image: romancin/rclonebrowser:latest 3 | container_name: rclonebrowser 4 | ports: 5 | - "5804:5800" 6 | environment: 7 | - USER_ID=0 8 | - GROUP_ID=0 9 | - TZ=Europe/Madrid 10 | - VNC_PASSWORD=password 11 | volumes: 12 | - "/share/Container/rclonebrowser:/config:rw" 13 | - "/share/Container/rclonebrowser/shared:/shared:rw" 14 | -------------------------------------------------------------------------------- /rootfs/etc/cont-init.d/rclonebrowser.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv sh 2 | 3 | set -e # Exit immediately if a command exits with a non-zero status. 4 | set -u # Treat unset variables as an error. 5 | 6 | log() { 7 | echo "[cont-init.d] $(basename $0): $*" 8 | } 9 | 10 | # Make sure mandatory directories exist. 11 | mkdir -p /config/logs 12 | 13 | # Take ownership of the config directory content. 14 | chown -R $USER_ID:$GROUP_ID /config/* 15 | 16 | # Take ownership of the output directory. 17 | #if ! chown $USER_ID:$GROUP_ID /output; then 18 | # Failed to take ownership of /output. This could happen when, 19 | # for example, the folder is mapped to a network share. 20 | # Continue if we have write permission, else fail. 21 | # if s6-setuidgid $USER_ID:$GROUP_ID [ ! -w /output ]; then 22 | # log "ERROR: Failed to take ownership and no write permission on /output." 23 | # exit 1 24 | # fi 25 | #fi 26 | 27 | # vim: set ft=sh : 28 | -------------------------------------------------------------------------------- /rootfs/startapp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -u # Treat unset variables as an error. 4 | 5 | trap "exit" TERM QUIT INT 6 | trap "kill_rclonebrowser" EXIT 7 | 8 | log() { 9 | echo "[rclonebrowsersupervisor] $*" 10 | } 11 | 12 | getpid_rclonebrowser() { 13 | PID=UNSET 14 | if [ -f /config/rclonebrowser.pid ]; then 15 | PID="$(cat /config/rclonebrowser.pid)" 16 | # Make sure the saved PID is still running and is associated to 17 | # RcloneBrowser. 18 | if [ ! -f /proc/$PID/cmdline ] || ! cat /proc/$PID/cmdline | grep -qw "rclone"; then 19 | PID=UNSET 20 | fi 21 | fi 22 | if [ "$PID" = "UNSET" ]; then 23 | PID="$(ps -o pid,args | grep -w "rclone" | grep -vw grep | tr -s ' ' | cut -d' ' -f2)" 24 | fi 25 | echo "${PID:-UNSET}" 26 | } 27 | 28 | is_rclonebrowser_running() { 29 | [ "$(getpid_rclonebrowser)" != "UNSET" ] 30 | } 31 | 32 | start_rclonebrowser() { 33 | dbus-uuidgen 34 | export TERMINAL=xterm 35 | /usr/bin/rclone-browser > /config/logs/output.log 2>&1 & 36 | } 37 | 38 | kill_rclonebrowser() { 39 | PID="$(getpid_rclonebrowser)" 40 | if [ "$PID" != "UNSET" ]; then 41 | log "Terminating RcloneBrowser..." 42 | kill $PID 43 | wait $PID 44 | fi 45 | } 46 | 47 | if ! is_rclonebrowser_running; then 48 | log "RcloneBrowser not started yet. Proceeding..." 49 | start_rclonebrowser 50 | fi 51 | 52 | RCLONEBROWSER_NOT_RUNNING=0 53 | while [ "$RCLONEBROWSER_NOT_RUNNING" -lt 5 ] 54 | do 55 | if is_rclonebrowser_running; then 56 | RCLONEBROWSER_NOT_RUNNING=0 57 | else 58 | RCLONEBROWSER_NOT_RUNNING="$(expr $RCLONEBROWSER_NOT_RUNNING + 1)" 59 | fi 60 | sleep 1 61 | done 62 | 63 | log "RcloneBrowser no longer running. Exiting..." 64 | --------------------------------------------------------------------------------