diff --git a/.drone.yml b/.drone.yml index 22779d1..bed6b91 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,7 +6,7 @@ steps: - name: build image only image: plugins/docker settings: - repo: eumau/openvpn + repo: eumau/webdav auto_tag: true dry_run: true when: @@ -16,7 +16,7 @@ steps: - name: build and publish image image: plugins/docker settings: - repo: eumau/openvpn + repo: eumau/webdav auto_tag: true username: from_secret: dockerhub_username diff --git a/Dockerfile b/Dockerfile index 6c01a20..4f80864 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,13 @@ -FROM debian:buster-slim -ARG REMCO_VER=0.11.1 -RUN apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - openvpn unzip wget ca-certificates \ - && wget https://github.com/HeavyHorst/remco/releases/download/v${REMCO_VER}/remco_${REMCO_VER}_linux_amd64.zip \ - && unzip remco_${REMCO_VER}_linux_amd64.zip \ - && rm remco_${REMCO_VER}_linux_amd64.zip \ - && mv remco_linux /bin/remco \ - && apt-get purge -y unzip wget ca-certificates \ - && apt-get autoremove --purge -y \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +FROM golang AS remco +RUN go install github.com/HeavyHorst/remco/cmd/remco@latest + +FROM httpd +COPY --from=remco /go/bin/remco /usr/local/bin/remco COPY config /etc/remco/config -COPY openvpn_setup.tmpl /etc/remco/templates/openvpn_setup.tmpl +COPY *.tmpl /etc/remco/templates/ + +EXPOSE 80 +CMD ["httpd-foreground"] + ENTRYPOINT ["remco"] diff --git a/README.md b/README.md index 5519fab..517fe71 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -# OpenVPN Docker image +# WebDAV Server with LDAP Authentication -This Docker image runs OpenVPN inside Docker. Configuration is done -via environment variables. +This Docker image runs an Apache server with WebDAV capabilities and LDAP authentication. Configuration is done via environment variables. diff --git a/config b/config index 1e83b08..10bfa0d 100644 --- a/config +++ b/config @@ -2,19 +2,24 @@ log_level = "info" log_format = "text" [[resource]] -name = "opendkim" -start_cmd = "/usr/local/sbin/openvpn_setup" +name = "httpd" +start_cmd = "/usr/local/sbin/setup.sh" [resource.exec] -command = "/usr/sbin/openvpn --config /etc/openvpn.conf" +command = "/usr/local/bin/httpd-foreground" [[resource.template]] -src = "/etc/remco/templates/openvpn_setup.tmpl" -dst = "/usr/local/sbin/openvpn_setup" -mode = "0700" +src = "/etc/remco/templates/httpd.conf.tmpl" +dst = "/usr/local/apache2/conf/httpd.conf" +mode = "0644" + +[[resource.template]] +src = "/etc/remco/templates/setup.sh.tmpl" +dst = "/usr/local/sbin/setup.sh" +mode = "0755" [resource.backend] [resource.backend.env] -keys = ["/openvpn"] +keys = ["/webdav","/ldap"] watch = false onetime = true diff --git a/docker-compose.sample.yml b/docker-compose.sample.yml index ef98ce0..f23c44d 100644 --- a/docker-compose.sample.yml +++ b/docker-compose.sample.yml @@ -1,25 +1,18 @@ --- version: "3.5" services: - openvpn: + webdav: build: . - cap_add: - - NET_ADMIN - labels: - - traefik.enable=false environment: - OPENVPN_MODE: client - OPENVPN_DEV: tun - OPENVPN_REMOTE: ${OPENVPN_REMOTE} - OPENVPN_NOBIND: "yes" - OPENVPN_COMP_LZO: "yes" - OPENVPN_NS_CERT_TYPE: server - OPENVPN_TLS_CLIENT: "yes" - # OPENVPN_TA: ${OPENVPN_TA} - # OPENVPN_TA_DIR: "1" - OPENVPN_CA: ${OPENVPN_CA} - OPENVPN_KEY: ${OPENVPN_KEY} - OPENVPN_CERT: ${OPENVPN_CERT} - OPENVPN_VERB: 3 + WEBDAV_LOCK: ${WEBDAV_LOCK_DIR}/DavLock + WEBDAV_PATH: ${WEBDAV_PATH} + WEBDAV_DIR: ${WEBDAV_DIR} + WEBDAV_LDAP_URL: ${WEBDAV_LDAP_URL} volumes: - - /dev/net/tun:/dev/net/tun + - dav:${WEBDAV_DIR} + - lock:${WEBDAV_LOCK_DIR} + labels: + - traefik.http.routers.dav.rule=Host(`dav.example.com`) + - traefik.http.routers.dav.middlewares=dav + - traefik.http.middlewares.dav.redirectregex.regex=^https?://dav.example.com/.well-known/(card|cal)dav.*$$ + - traefik.http.middlewares.dav.redirectregex.replacement=https://dav.example.com/ diff --git a/httpd.conf.tmpl b/httpd.conf.tmpl new file mode 100644 index 0000000..3caf98c --- /dev/null +++ b/httpd.conf.tmpl @@ -0,0 +1,298 @@ +ServerRoot "/usr/local/apache2" +Listen 80 + +LoadModule mpm_event_module modules/mod_mpm_event.so +LoadModule authn_file_module modules/mod_authn_file.so +LoadModule authn_core_module modules/mod_authn_core.so +LoadModule authz_host_module modules/mod_authz_host.so +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so +LoadModule authz_user_module modules/mod_authz_user.so +LoadModule authz_core_module modules/mod_authz_core.so +LoadModule authnz_ldap_module modules/mod_authnz_ldap.so +LoadModule access_compat_module modules/mod_access_compat.so +LoadModule auth_basic_module modules/mod_auth_basic.so +LoadModule reqtimeout_module modules/mod_reqtimeout.so +LoadModule filter_module modules/mod_filter.so +LoadModule mime_module modules/mod_mime.so +LoadModule ldap_module modules/mod_ldap.so +LoadModule log_config_module modules/mod_log_config.so +LoadModule env_module modules/mod_env.so +LoadModule headers_module modules/mod_headers.so +LoadModule setenvif_module modules/mod_setenvif.so +LoadModule version_module modules/mod_version.so +LoadModule unixd_module modules/mod_unixd.so +LoadModule dav_module modules/mod_dav.so +LoadModule status_module modules/mod_status.so +LoadModule autoindex_module modules/mod_autoindex.so + + #LoadModule cgid_module modules/mod_cgid.so + + + #LoadModule cgi_module modules/mod_cgi.so + +LoadModule dav_fs_module modules/mod_dav_fs.so +LoadModule dav_lock_module modules/mod_dav_lock.so +LoadModule dir_module modules/mod_dir.so +LoadModule alias_module modules/mod_alias.so +LoadModule rewrite_module modules/mod_rewrite.so + + +User www-data +Group www-data + + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin {{ getv("/webdav/server/admin", "admin@example.com") }} + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +#ServerName www.example.com:80 + + + AllowOverride none + Require all denied + + +DocumentRoot "/usr/local/apache2/htdocs" + + # + # Possible values for the Options directive are "None", "All", + # or any combination of: + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + # + # Note that "MultiViews" must be named *explicitly* --- "Options All" + # doesn't give it to you. + # + # The Options directive is both complicated and important. Please see + # http://httpd.apache.org/docs/2.4/mod/core.html#options + # for more information. + # + Options Indexes FollowSymLinks + + # + # AllowOverride controls what directives may be placed in .htaccess files. + # It can be "All", "None", or any combination of the keywords: + # AllowOverride FileInfo AuthConfig Limit + # + AllowOverride None + + # + # Controls who can get stuff from this server. + # + Require all granted + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog /proc/self/fd/2 + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + CustomLog /proc/self/fd/1 common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + #CustomLog "logs/access_log" combined + + + + # + # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied + # backend servers which have lingering "httpoxy" defects. + # 'Proxy' request header is undefined by the IETF, not listed by IANA + # + RequestHeader unset Proxy early + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig conf/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + #AddType text/html .shtml + #AddOutputFilter INCLUDES .shtml + + + +# Required modules: mod_alias, mod_auth_digest, mod_authn_core, mod_authn_file, +# mod_authz_core, mod_authz_user, mod_dav, mod_dav_fs, +# mod_setenvif + +# Enable the LDAP connection pool and shared +# memory cache. Enable the LDAP cache status +# handler. Requires that mod_ldap and mod_authnz_ldap +# be loaded. Change the "yourdomain.example.com" to +# match your domain. + +LDAPSharedCacheSize 500000 +LDAPCacheEntries 1024 +LDAPCacheTTL 600 +LDAPOpCacheEntries 1024 +LDAPOpCacheTTL 600 + +# The following example gives DAV write access to a directory called +# "uploads" under the ServerRoot directory. +# +# The User/Group specified in httpd.conf needs to have write permissions +# on the directory where the DavLockDB is placed and on any directory where +# "Dav On" is specified. + +DavLockDB "{{ getv("/webdav/lock", "/usr/local/apache2/var/DavLock") }}" + +Alias {{ getv("/webdav/path", "/") }} "{{ getv("/webdav/dir", "/usr/local/apache2/uploads/") }}" + + + Dav On + + AuthType {{ getv("/webdav/auth/type", "Basic") }} + AuthName {{ getv("/webdav/auth/name", "WebDAV") }} + + AuthBasicProvider ldap + AuthLDAPURL "{{ getv("/webdav/ldap/url", "ldap://ldap/dc=example,dc=com?uid?one") }}" + + # Allow universal read-access, but writes are restricted + # to the admin user. + + {% if eq (getv("/webdav/public/read", "false"), "true") %} + + Require method GET POST OPTIONS + Require valid-user + + {% else %} + Require valid-user + {% endif %} + + + + SetHandler ldap-status + # Require host yourdomain.example.com + + Satisfy any + AuthType Basic + AuthName "LDAP Status" + AuthBasicProvider ldap + AuthLDAPURL "{{ getv("/webdav/ldap/url", "ldap://ldap/dc=example,dc=com?uid?one") }}" + Require valid-user + + +# +# The following directives disable redirects on non-GET requests for +# a directory that does not include the trailing slash. This fixes a +# problem with several clients that do not appropriately handle +# redirects for folders with DAV methods. +# +BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully +BrowserMatch "MS FrontPage" redirect-carefully +BrowserMatch "^WebDrive" redirect-carefully +BrowserMatch "^WebDAVFS/1.[01234]" redirect-carefully +BrowserMatch "^gnome-vfs/1.0" redirect-carefully +BrowserMatch "^XML Spy" redirect-carefully +BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully +BrowserMatch " Konqueror/4" redirect-carefully + +# Configure mod_proxy_html to understand HTML4/XHTML1 + +Include conf/extra/proxy-html.conf + + +# Secure (SSL/TLS) connections + +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin + diff --git a/openvpn_setup.tmpl b/openvpn_setup.tmpl deleted file mode 100644 index 7431894..0000000 --- a/openvpn_setup.tmpl +++ /dev/null @@ -1,156 +0,0 @@ -#!/bin/bash - -# setup openvpn configuration and secrets -mkdir -p /etc/openvpn - -cat - < /etc/openvpn.conf - -# client -{% if exists("/openvpn/mode") %} -{{ getv("/openvpn/mode") }} -{% endif %} - -# dev tun -{% if exists("/openvpn/dev") %} -dev {{ getv("/openvpn/dev") }} -{% endif %} - -# remote -{% if exists("/openvpn/remote") %} -remote {{ getv("/openvpn/remote") }} -{% endif %} - -# proto udp -{% if exists("/openvpn/proto") %} -proto {{ getv("/openvpn/proto") }} -{% endif %} - -# nobind -{% if exists("/openvpn/nobind") %} -nobind -{% endif %} - -# ns-cert-type server -{% if exists("/openvpn/ns/cert/type") %} -ns-cert-type {{ getv("/openvpn/ns/cert/type") }} -{% endif %} - -# up /etc/openvpn/update-resolv-conf -{% if exists("/openvpn/up") %} -up {{ getv("/openvpn/up") }} -{% endif %} - -# down /etc/openvpn/update-resolv-conf -{% if exists("/openvpn/down") %} -down {{ getv("/openvpn/down") }} -{% endif %} - -# tls-client -{% if exists("/openvpn/tls/client") %} -tls-client -{% endif %} - -# tls-auth file 1 -{% if exists("/openvpn/ta") %} -tls-auth /etc/openvpn/ta {{ getv("/openvpn/ta/dir")|default:"1" }} -{% endif %} - -# ca -ca /etc/openvpn/ca - -# cert -cert /etc/openvpn/cert - -# key -key /etc/openvpn/key - -# port 1194 -{% if exists("/openvpn/port") %} -port {{ getv("/openvpn/port") }} -{% endif %} - -{% if exists("/openvpn/user") %} -user {{ getv("/openvpn/user") }} -{% else %} -user nobody -{% endif %} - -{% if exists("/openvpn/group") %} -group {{ getv("/openvpn/group") }} -{% else %} -group nogroup -{% endif %} - -# comp-lzo -{% if exists("/openvpn/comp/lzo") %} -comp-lzo -{% endif %} - -# ping 15 -{% if exists("/openvpn/ping") %} -ping {{ getv("/openvpn/ping") }} -{% endif %} - -# ping-restart 45 -{% if exists("/openvpn/ping/restart") %} -ping-restart {{ getv("/openvpn/ping/restart") }} -{% endif %} - -# ping-timer-rem -{% if exists("/openvpn/ping/timer/rem") %} -ping-timer-rem -{% endif %} - -# persist-tun -{% if exists("/openvpn/persist/tun") %} -persist-tun -{% endif %} - -# persist-remote-ip -{% if exists("/openvpn/persist/remote/ip") %} -persist-remote-ip -{% endif %} - -# persist-key -{% if exists("/openvpn/persist/key") %} -persist-key -{% endif %} - -# verb 4 -{% if exists("/openvpn/verb") %} -verb {{ getv("/openvpn/verb") }} -{% endif %} - -# redirect-gateway def1 -{% if exists("/openvpn/redirect/gateway") %} -redirect-gateway {{ getv("/openvpn/redirect/gateway") }} -{% endif %} -EOF - -{% if exists("/openvpn/ta") %} -cat - < /etc/openvpn/ta -{% for keyline in (replace(getv("/openvpn/ta"),"\\n","!",-1)|split:"!") %} -{{ keyline }} -{% endfor %} -EOKEY -chmod 600 /etc/openvpn/ta -{% endif %} - -cat - < /etc/openvpn/ca -{% for keyline in (replace(getv("/openvpn/ca"),"\\n","!",-1)|split:"!") %} -{{ keyline }} -{% endfor %} -EOKEY - -cat - < /etc/openvpn/cert -{% for keyline in (replace(getv("/openvpn/cert"),"\\n","!",-1)|split:"!") %} -{{ keyline }} -{% endfor %} -EOKEY - -cat - < /etc/openvpn/key -{% for keyline in (replace(getv("/openvpn/key"),"\\n","!",-1)|split:"!") %} -{{ keyline }} -{% endfor %} -EOKEY -chmod 600 /etc/openvpn/key diff --git a/setup.sh.tmpl b/setup.sh.tmpl new file mode 100644 index 0000000..d477c12 --- /dev/null +++ b/setup.sh.tmpl @@ -0,0 +1,5 @@ +#!/bin/bash +mkdir -p "{{ getv("/webdav/root/dir", "/usr/local/apache2/uploads") }}" +chown -R www-data:www-data "{{ getv("/webdav/root/dir", "/usr/local/apache2/uploads") }}" +mkdir -p "$(dirname "{{ getv("/webdav/lock/path", "/usr/local/apache2/var/DavLock") }}")" +chown -R www-data:www-data "$(dirname "{{ getv("/webdav/lock/path", "/usr/local/apache2/var/DavLock") }}")"