diff --git a/radicale/.gitignore b/radicale/.gitignore new file mode 100644 index 0000000..3b53fe0 --- /dev/null +++ b/radicale/.gitignore @@ -0,0 +1,2 @@ +data/ +config/users \ No newline at end of file diff --git a/radicale/README.md b/radicale/README.md new file mode 100644 index 0000000..32c89e7 --- /dev/null +++ b/radicale/README.md @@ -0,0 +1,3 @@ +# Radicale Docker container + +Based on [this](https://github.com/tomsquest/docker-radicale) \ No newline at end of file diff --git a/radicale/build/Dockerfile b/radicale/build/Dockerfile new file mode 100644 index 0000000..45646a1 --- /dev/null +++ b/radicale/build/Dockerfile @@ -0,0 +1,56 @@ +FROM alpine:3.14 + +ARG COMMIT_ID +ENV COMMIT_ID ${COMMIT_ID} + +ARG VERSION +ENV VERSION ${VERSION:-3.1.8} + +ARG BUILD_UID +ENV BUILD_UID ${BUILD_UID:-2999} + +ARG BUILD_GID +ENV BUILD_GID ${BUILD_GID:-2999} + +ARG TAKE_FILE_OWNERSHIP +ENV TAKE_FILE_OWNERSHIP ${TAKE_FILE_OWNERSHIP:-true} + +LABEL maintainer="Mark " \ + org.label-schema.name="Radicale Docker Image" \ + org.label-schema.description="Docker image for Radicale, the CalDAV/CardDAV server" + +RUN apk add --no-cache --virtual=build-dependencies \ + gcc \ + musl-dev \ + libffi-dev \ + python3-dev \ + && apk add --no-cache \ + curl \ + git \ + openssh \ + shadow \ + su-exec \ + tzdata \ + wget \ + python3 \ + py3-tz \ + py3-pip \ + && python3 -m pip install --upgrade pip \ + && python3 -m pip install radicale==$VERSION passlib[bcrypt] \ + && apk del --purge build-dependencies \ + && addgroup -g $BUILD_GID radicale \ + && adduser -D -s /bin/false -H -u $BUILD_UID -G radicale radicale \ + && mkdir -p /config /data \ + && chmod -R 770 /data \ + && chown -R radicale:radicale /data \ + && rm -fr /root/.cache + +COPY config /config/config + +HEALTHCHECK --interval=30s --retries=3 CMD curl --fail http://localhost:5232 || exit 1 +VOLUME /config /data +EXPOSE 5232 + +COPY start.sh /usr/local/bin +ENTRYPOINT ["/usr/local/bin/start.sh"] +CMD ["radicale", "--config", "/config/config"] diff --git a/radicale/build/start.sh b/radicale/build/start.sh new file mode 100755 index 0000000..2115491 --- /dev/null +++ b/radicale/build/start.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +set -e + +# Change uid/gid of radicale if vars specified +if [ -n "$UID" ] || [ -n "$GID" ]; then + if [ ! "$UID" = "$(id radicale -u)" ] || [ ! "$GID" = "$(id radicale -g)" ]; then + # Fail on read-only container + if grep -e "\s/\s.*\sro[\s,]" /proc/mounts > /dev/null; then + echo "You specified custom UID/GID (UID: $UID, GID: $GID)." + echo "UID/GID can only be changed when not running the container with --read-only." + echo "Please see the README.md for how to proceed and for explanations." + exit 1 + fi + + if [ -n "$UID" ]; then + usermod -o -u "$UID" radicale + fi + + if [ -n "$GID" ]; then + groupmod -o -g "$GID" radicale + fi + fi +fi + +# If requested and running as root, mutate the ownership of bind-mounts +if [ "$(id -u)" = "0" ] && [ "$TAKE_FILE_OWNERSHIP" = "true" ]; then + chown -R radicale:radicale /data +fi + +# Run radicale as the "radicale" user or any other command if provided +if [ "$(id -u)" = "0" ] && [ "$1" = "radicale" ]; then + exec su-exec radicale "$@" +else + exec "$@" +fi diff --git a/radicale/config/config b/radicale/config/config new file mode 100644 index 0000000..9c99e95 --- /dev/null +++ b/radicale/config/config @@ -0,0 +1,20 @@ +[auth] +type = htpasswd +htpasswd_filename = /config/users +htpasswd_encryption = bcrypt +delay = 3 + +[rights] +type = owner_only + +[server] +hosts = 0.0.0.0:5232 + +[web] +# type = none: disable web management +# type = internal: enable web management +type = internal + +[storage] +type = multifilesystem +filesystem_folder = /data/collections \ No newline at end of file diff --git a/radicale/docker-compose.yml b/radicale/docker-compose.yml new file mode 100644 index 0000000..fda0c99 --- /dev/null +++ b/radicale/docker-compose.yml @@ -0,0 +1,37 @@ +version: "3.7" + +services: + radicale: + build: + context: ./build + args: + BUILD_UID: 1000 + BUILD_GID: 1000 + TAKE_FILE_OWNERSHIP: "false" + + container_name: radicale + restart: unless-stopped + init: true + healthcheck: + test: curl -f http://127.0.0.1:5232 || exit 1 + interval: 30s + retries: 3 + + # Security + read_only: true + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + cap_add: + - SETUID + - SETGID + - KILL + + ports: + - 5232:5232 + + volumes: + - ./data:/data + - ./config:/config +