├── Dockerfile ├── README.md ├── build.sh └── files ├── 60-max-user-watches.conf ├── CrashPlanEngine.patch ├── crashplan.exp ├── crashplan.sh ├── entrypoint.sh └── install.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | # Here we install GNU libc (aka glibc) and set en_US.UTF-8 locale as default. 4 | RUN ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \ 5 | ALPINE_GLIBC_PACKAGE_VERSION="2.23-r3" && \ 6 | ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \ 7 | ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \ 8 | ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \ 9 | apk add --no-cache wget ca-certificates && \ 10 | wget \ 11 | "https://raw.githubusercontent.com/andyshinn/alpine-pkg-glibc/master/sgerrand.rsa.pub" \ 12 | -O "/etc/apk/keys/sgerrand.rsa.pub" && \ 13 | wget \ 14 | "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \ 15 | "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \ 16 | "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \ 17 | apk add --no-cache \ 18 | "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \ 19 | "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \ 20 | "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \ 21 | /usr/glibc-compat/bin/localedef --force --inputfile en_US --charmap UTF-8 en_US.UTF-8 && \ 22 | echo "export LANG=en_US.UTF-8" > /etc/profile.d/locale.sh && \ 23 | rm "/root/.wget-hsts" && \ 24 | rm \ 25 | "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \ 26 | "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \ 27 | "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" 28 | 29 | ######################################### 30 | ## ENVIRONMENTAL CONFIG ## 31 | ######################################### 32 | # Set correct environment variables 33 | ENV CRASHPLAN_VERSION=4.8.0 \ 34 | CRASHPLAN_SERVICE=HOME \ 35 | LC_ALL=en_US.UTF-8 \ 36 | LANG=en_US.UTF-8 \ 37 | LANGUAGE=en_US.UTF-8 38 | 39 | ######################################### 40 | ## RUN INSTALL SCRIPT ## 41 | ######################################### 42 | ADD /files /tmp/installation 43 | 44 | # Increase max file watches 45 | # ADD /files/installation/60-max-user-watches.conf /etc/sysctl.d/60-max-user-watches.conf 46 | 47 | RUN chmod +x /tmp/installation/install.sh && sync && /tmp/installation/install.sh && rm -rf /tmp/installation 48 | 49 | ######################################### 50 | ## VOLUMES ## 51 | ######################################### 52 | VOLUME [ "/var/crashplan", "/storage" ] 53 | 54 | ######################################### 55 | ## EXPOSE PORTS ## 56 | ######################################### 57 | EXPOSE 4243 4242 58 | 59 | WORKDIR /usr/local/crashplan 60 | 61 | ENTRYPOINT ["/entrypoint.sh"] 62 | CMD [ "/crashplan.sh" ] 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://img.shields.io/docker/stars/jrcs/crashplan.svg)](https://hub.docker.com/r/jrcs/crashplan 'DockerHub') [![](https://img.shields.io/docker/pulls/jrcs/crashplan.svg)](https://hub.docker.com/r/jrcs/crashplan 'DockerHub') 2 | [![](https://badge.imagelayers.io/jrcs/crashplan:latest.svg)](https://imagelayers.io/?images=jrcs/crashplan:latest 'Get your own badge on imagelayers.io') 3 | # docker-crashplan 4 | Lightweight (169MB) [Crashplan](http://www.crashplan.com) docker container. 5 | 6 | ## Features: 7 | * Automatic version upgrade 8 | * Access to all configuration files 9 | * Access to log files 10 | 11 | # Quick Start 12 | 13 | - Launch the crashplan container 14 | 15 | ```bash 16 | docker run -d \ 17 | --name crashplan \ 18 | -h $HOSTNAME \ 19 | -e TZ="${TZ:-$(cat /etc/timezone 2>/dev/null)}" \ 20 | --publish 4242:4242 --publish 4243:4243 \ 21 | --volume /srv/crashplan/data:/var/crashplan \ 22 | --volume /srv/crashplan/storage:/storage \ 23 | jrcs/crashplan:latest 24 | ``` 25 | 26 | ## Access the GUI from your desktop crashplan application 27 | - Make a backup of the current `.ui_info` file of your desktop machine locate: 28 | * On Linux: `/var/crashplan/data/id/.ui_info` 29 | * On OSX: `/Library/Application Support/CrashPlan/.ui_info` 30 | * On Windows: `C:\ProgramData\CrashPlan\.ui_info` 31 | - Replace your `.ui_info` file of your desktop machine with the one of the crashplan container: `/srv/crashplan/data/id/.ui_info`. 32 | - In the `.ui_info` file of your desktop machine, replace the IP (should be `0.0.0.0` or `127.0.0.1`) with the IP of your docker host. 33 | - Make sure you can connect to ports 4242 and 4243 on your docker host. 34 | - Start your local CrashPlan GUI. 35 | 36 | # Configuration 37 | 38 | ## Volumes: 39 | * `/var/crashplan`: where the configuration files and logs are store 40 | * `/storage`: where backup files are store 41 | 42 | ## Optional environment variables: 43 | * `PUBLIC_IP`and `PUBLIC_PORT`: force the public ip address and port to use. 44 | * `TZ`: time zone to use in the crashplan logs. Use /etc/timezone string values, e.g. "Europe/Paris" 45 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build -t jrcs/crashplan:dev . && \ 4 | docker push jrcs/crashplan:dev 5 | -------------------------------------------------------------------------------- /files/60-max-user-watches.conf: -------------------------------------------------------------------------------- 1 | ## Increase max file watches 2 | fs.inotify.max_user_watches = 500000 3 | -------------------------------------------------------------------------------- /files/CrashPlanEngine.patch: -------------------------------------------------------------------------------- 1 | --- a/bin/CrashPlanEngine.orig 2 | +++ b/bin/CrashPlanEngine 3 | @@ -128,7 +128,7 @@ 4 | case $1 in 5 | start) 6 | 7 | - FULL_CP="$TARGETDIR/lib/com.backup42.desktop.jar:$TARGETDIR/lang" 8 | + FULL_CP="$TARGETDIR/lib/com.backup42.desktop.jar:$TARGETDIR/lang:$TARGETDIR" 9 | 10 | PID=`_findpid` 11 | if [[ -n "$PID" ]]; then 12 | -------------------------------------------------------------------------------- /files/crashplan.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | set timeout 120 4 | 5 | spawn "./install.sh" 6 | 7 | expect "Press enter to continue with installation." 8 | send "\r" 9 | 10 | expect "What parent directory do you wish to install CrashPlan into?" 11 | send "/usr/local\r" 12 | 13 | expect "/usr/local/crashplan does not exist. Create /usr/local/crashplan?" 14 | send "y\r" 15 | 16 | expect "What directory do you wish to link the CrashPlan executable to?" 17 | send "/usr/local/bin\r" 18 | 19 | expect "What directory do you wish to store incoming backup data?" 20 | send "/storage\r" 21 | 22 | expect "/storage does not exist. Create /storage?" 23 | send "y\r" 24 | 25 | expect "What directory contains your SYSV init scripts?" 26 | send "/etc/init.d\r" 27 | 28 | expect "What directory contains your runlevel init links?" 29 | send "/etc/rc2.d\r" 30 | 31 | expect "Create /etc/rc2.d?" 32 | send "y\r" 33 | 34 | expect "Is this correct?" 35 | send "y\r" 36 | 37 | expect "Press Enter to complete installation." 38 | send "\r" 39 | -------------------------------------------------------------------------------- /files/crashplan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SIGTERM-handler 4 | term_handler() { 5 | 6 | # Stop crashplan 7 | /etc/init.d/crashplan stop 8 | 9 | exit 143; # 128 + 15 -- SIGTERM 10 | } 11 | 12 | trap 'kill "$tail_pid"; term_handler' INT QUIT KILL TERM 13 | 14 | /etc/init.d/crashplan start 15 | 16 | LOGS_FILES="/var/crashplan/log/service.log.0" 17 | for file in $LOGS_FILES; do 18 | [[ ! -f "$file" ]] && touch $file 19 | done 20 | 21 | tail -n0 -F $LOGS_FILES & 22 | tail_pid=$! 23 | 24 | # wait "indefinitely" 25 | while [[ -e /proc/$tail_pid ]]; do 26 | wait $tail_pid # Wait for any signals or end of execution of tail 27 | done 28 | 29 | # Stop container properly 30 | term_handler 31 | -------------------------------------------------------------------------------- /files/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _link() { 4 | if [[ -L ${2} && $(readlink ${2}) == ${1} ]]; then 5 | return 0 6 | fi 7 | if [[ ! -e ${1} ]]; then 8 | if [[ -d ${2} ]]; then 9 | mkdir -p "${1}" 10 | pushd ${2} &>/dev/null 11 | find . -type f -exec cp --parents '{}' "${1}/" \; 12 | popd &>/dev/null 13 | elif [[ -f ${2} ]]; then 14 | if [[ ! -d $(dirname ${1}) ]]; then 15 | mkdir -p $(dirname ${1}) 16 | fi 17 | cp -f "${2}" "${1}" 18 | else 19 | mkdir -p "${1}" 20 | fi 21 | fi 22 | if [[ -d ${2} ]]; then 23 | rm -rf "${2}" 24 | elif [[ -f ${2} || -L ${2} ]]; then 25 | rm -f "${2}" 26 | fi 27 | if [[ ! -d $(dirname ${2}) ]]; then 28 | mkdir -p $(dirname ${2}) 29 | fi 30 | ln -sf ${1} ${2} 31 | } 32 | 33 | # Update the timezone 34 | [[ -n "$TZ" ]] && echo "$TZ" > /etc/timezone 35 | 36 | MOUNTDIR=/var/crashplan 37 | SOURCEDIR=/usr/local/crashplan 38 | TARGETDIR=${MOUNTDIR}/app 39 | 40 | if [[ ! -d ${MOUNTDIR}/app ]]; then 41 | # Migrate the application 42 | rsync -a --ignore-existing ${MOUNTDIR}/ /tmp/app/ 43 | rm -rf ${MOUNTDIR}/* 44 | mv /tmp/app ${TARGETDIR} 45 | rm -f ${TARGETDIR}/install.vars # Will be recreate 46 | fi 47 | 48 | [[ -d ${TARGETDIR}/id && ! -d ${MOUNTDIR}/id ]] && mv ${TARGETDIR}/id ${MOUNTDIR}/id 49 | 50 | # Populate the TARGETDIR 51 | rsync -a --ignore-existing ${SOURCEDIR}/ ${TARGETDIR}/ 52 | 53 | # Update install paths 54 | sed -i -r "s@${SOURCEDIR}@${TARGETDIR}@g" \ 55 | /etc/init.d/crashplan \ 56 | ${TARGETDIR}/install.vars 57 | 58 | # move binaries, jre, libraries and lang files out of container so crashplan can be upgrade automaticaly 59 | _link ${TARGETDIR}/bin ${SOURCEDIR}/bin 60 | _link ${TARGETDIR}/jre ${SOURCEDIR}/jre 61 | _link ${TARGETDIR}/lib ${SOURCEDIR}/lib 62 | _link ${TARGETDIR}/lang ${SOURCEDIR}/lang 63 | 64 | # move identity out of container, this prevent having to adopt account every time you rebuild the Docker 65 | _link ${MOUNTDIR}/id /var/lib/crashplan 66 | 67 | # move cache directory out of container, this prevents re-synchronization every time you rebuild the Docker 68 | _link ${TARGETDIR}/cache ${SOURCEDIR}/cache 69 | 70 | # move log directory out of container 71 | _link ${TARGETDIR}/log ${SOURCEDIR}/log 72 | 73 | # move conf directory out of container 74 | _link ${TARGETDIR}/conf ${SOURCEDIR}/conf 75 | if [[ ! -d ${MOUNTDIR}/conf ]]; then 76 | mv ${TARGETDIR}/conf ${MOUNTDIR}/conf 77 | else 78 | rm -rf ${TARGETDIR}/conf 79 | fi 80 | ln -sf ../conf ${TARGETDIR}/conf 81 | 82 | if [[ -z "$PUBLIC_IP" || -z "$PUBLIC_PORT" ]]; then 83 | # Default values :( 84 | PUBLIC_IP=0.0.0.0 85 | PUBLIC_PORT=4242 86 | fi 87 | 88 | # Update configuration files 89 | if [[ -f "$TARGETDIR"/conf/my.service.xml ]]; then 90 | # Change the public ip/port dynamicaly and 91 | # force to use the cache in /var/crashplan/cache (see https://goo.gl/LZ8eRY) 92 | echo "Configuring CrashPlan to listen on public interface $PUBLIC_IP:$PUBLIC_PORT" 93 | sed -i -r \ 94 | -e "s/[^<]+/$PUBLIC_IP:$PUBLIC_PORT/g" \ 95 | -e "s@[^<]+@${TARGETDIR}/cache@g" \ 96 | "$TARGETDIR"/conf/my.service.xml 97 | fi 98 | 99 | # Create some links (not needed by crashplan) 100 | [[ ! -L ${MOUNTDIR}/log ]] && ln -sf $(basename $TARGETDIR)/log ${MOUNTDIR}/log 101 | 102 | exec $@ 103 | -------------------------------------------------------------------------------- /files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # Determine Crashplan Service Level to install (home or business) 6 | if [ "$CRASHPLAN_SERVICE" = "PRO" ]; then 7 | SVC_LEVEL="CrashPlanPRO" 8 | else 9 | SVC_LEVEL="CrashPlan" 10 | fi 11 | 12 | install_deps='expect sed' 13 | apk add --update bash openssl findutils coreutils procps libstdc++ rsync $install_deps 14 | apk add cpio --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community/ 15 | 16 | mkdir /tmp/crashplan 17 | 18 | echo "Downloading $SVC_LEVEL ${CRASHPLAN_VERSION}..." 19 | wget -O- http://download.code42.com/installs/linux/install/${SVC_LEVEL}/${SVC_LEVEL}_${CRASHPLAN_VERSION}_Linux.tgz \ 20 | | tar -xz --strip-components=1 -C /tmp/crashplan 21 | 22 | 23 | mkdir -p /usr/share/applications 24 | cd /tmp/crashplan && chmod +x /tmp/installation/crashplan.exp && sync && /tmp/installation/crashplan.exp || exit $? 25 | echo 26 | cd / && rm -rf /tmp/crashplan 27 | rm -rf /usr/share/applications 28 | 29 | # Patch CrashPlanEngine 30 | cd /usr/local/crashplan && patch -p1 < /tmp/installation/CrashPlanEngine.patch || exit $? 31 | 32 | # Bind the UI port 4243 to the container ip 33 | sed -i "s||\n\t\n\t\t\ 34 | 0.0.0.0\n\t\t4243\n\t\t\ 35 | 0\n\t\tfalse\n\t\ 36 | |g" /usr/local/crashplan/conf/default.service.xml 37 | 38 | # Install launchers 39 | cp /tmp/installation/entrypoint.sh /tmp/installation/crashplan.sh / 40 | chmod +rx /entrypoint.sh /crashplan.sh 41 | 42 | # Remove unneccessary package 43 | apk del $install_deps 44 | 45 | # Remove unneccessary files and directories 46 | rm -rf /usr/local/crashplan/*.pid \ 47 | /usr/local/crashplan/jre/lib/plugin.jar \ 48 | /usr/local/crashplan/jre/lib/ext/jfxrt.jar \ 49 | /usr/local/crashplan/jre/bin/javaws \ 50 | /usr/local/crashplan/jre/lib/javaws.jar \ 51 | /usr/local/crashplan/jre/lib/desktop \ 52 | /usr/local/crashplan/jre/plugin \ 53 | /usr/local/crashplan/jre/lib/deploy* \ 54 | /usr/local/crashplan/jre/lib/*javafx* \ 55 | /usr/local/crashplan/jre/lib/*jfx* \ 56 | /usr/local/crashplan/jre/lib/amd64/libdecora_sse.so \ 57 | /usr/local/crashplan/jre/lib/amd64/libprism_*.so \ 58 | /usr/local/crashplan/jre/lib/amd64/libfxplugins.so \ 59 | /usr/local/crashplan/jre/lib/amd64/libglass.so \ 60 | /usr/local/crashplan/jre/lib/amd64/libgstreamer-lite.so \ 61 | /usr/local/crashplan/jre/lib/amd64/libjavafx*.so \ 62 | /usr/local/crashplan/jre/lib/amd64/libjfx*.so 63 | 64 | rm -rf /boot /home /lost+found /media /mnt /run /srv 65 | rm -rf /usr/local/crashplan/cache /usr/local/crashplan/log 66 | rm -rf /var/cache/apk/* 67 | rm -f /root/.wget-hsts 68 | --------------------------------------------------------------------------------