use alpine packages, no longer need to compile ourselves
All checks were successful
Build Multiarch Container Image / call-reusable-workflow (push) Successful in 1m0s

This commit is contained in:
Sebastian Hugentobler 2024-04-26 14:55:30 +02:00
parent 659e14a87d
commit f45cab5235
Signed by: shu
GPG Key ID: BB32CF3CA052C2F0
10 changed files with 130 additions and 155 deletions

View File

@ -1,93 +1,84 @@
FROM docker.io/alpine:3.19 as builder # FROM docker.io/alpine:3.19 as builder
#
RUN apk --no-cache add \ # RUN apk --no-cache add \
rpcgen \ # rpcgen \
g++ \ # g++ \
make \ # make \
openssl \ # openssl \
openssl-dev \ # openssl-dev \
lua5.1-dev \ # lua5.1-dev \
libsodium-dev \ # libsodium-dev \
linux-pam-dev \ # linux-pam-dev \
zlib-dev \ # zlib-dev \
bzip2-dev \ # bzip2-dev \
xz-dev \ # xz-dev \
lz4-dev \ # lz4-dev \
icu-dev \ # icu-dev \
inotify-tools-dev # inotify-tools-dev
#
ENV SHA256_SUM_DOVECOT=05b11093a71c237c2ef309ad587510721cc93bbee6828251549fc1586c36502d # ENV SHA256_SUM_DOVECOT=05b11093a71c237c2ef309ad587510721cc93bbee6828251549fc1586c36502d
ENV DOVECOT_FILENAME=dovecot-2.3.21.tar.gz # ENV DOVECOT_FILENAME=dovecot-2.3.21.tar.gz
RUN wget https://www.dovecot.org/releases/2.3/$DOVECOT_FILENAME # RUN wget https://www.dovecot.org/releases/2.3/$DOVECOT_FILENAME
RUN echo "$SHA256_SUM_DOVECOT $DOVECOT_FILENAME" | sha256sum -c - || exit 1 # RUN echo "$SHA256_SUM_DOVECOT $DOVECOT_FILENAME" | sha256sum -c - || exit 1
RUN mkdir /tmp/dovecot # RUN mkdir /tmp/dovecot
RUN tar xzf $DOVECOT_FILENAME -C /tmp/dovecot --strip 1 # RUN tar xzf $DOVECOT_FILENAME -C /tmp/dovecot --strip 1
#
ENV SHA256_SUM_PIGEONHOLE=1ca71d2659076712058a72030288f150b2b076b0306453471c5261498d3ded27 # ENV SHA256_SUM_PIGEONHOLE=1ca71d2659076712058a72030288f150b2b076b0306453471c5261498d3ded27
ENV PIGEONHOLE_FILENAME=dovecot-2.3-pigeonhole-0.5.21.tar.gz # ENV PIGEONHOLE_FILENAME=dovecot-2.3-pigeonhole-0.5.21.tar.gz
RUN wget https://pigeonhole.dovecot.org/releases/2.3/$PIGEONHOLE_FILENAME # RUN wget https://pigeonhole.dovecot.org/releases/2.3/$PIGEONHOLE_FILENAME
RUN echo "$SHA256_SUM_PIGEONHOLE $PIGEONHOLE_FILENAME" | sha256sum -c - || exit 1 # RUN echo "$SHA256_SUM_PIGEONHOLE $PIGEONHOLE_FILENAME" | sha256sum -c - || exit 1
RUN mkdir /tmp/pigeonhole # RUN mkdir /tmp/pigeonhole
RUN tar xzf $PIGEONHOLE_FILENAME -C /tmp/pigeonhole --strip 1 # RUN tar xzf $PIGEONHOLE_FILENAME -C /tmp/pigeonhole --strip 1
#
RUN cd /tmp/dovecot && \ # RUN cd /tmp/dovecot && \
./configure --prefix '' \ # ./configure --prefix '' \
--with-notify=inotify \ # --with-notify=inotify \
--with-lua \ # --with-lua \
--with-zlib \ # --with-zlib \
--with-bzlib \ # --with-bzlib \
--with-pam \ # --with-pam \
--with-ssl=openssl \ # --with-ssl=openssl \
--with-sodium \ # --with-sodium \
--without-sql \ # --without-sql \
--with-lzma \ # --with-lzma \
--with-lz4 \ # --with-lz4 \
--with-icu \ # --with-icu \
--without-shadow \ # --without-shadow \
--with-ssldir=/etc/ssl/mail \ # --with-ssldir=/etc/ssl/mail \
--with-rundir=/run/dovecot \ # --with-rundir=/run/dovecot \
--disable-static && \ # --disable-static && \
make && \ # make && \
make install # make install
#
RUN cd /tmp/pigeonhole && \ # RUN cd /tmp/pigeonhole && \
./configure --prefix '' \ # ./configure --prefix '' \
--with-dovecot=/lib/dovecot \ # --with-dovecot=/lib/dovecot \
--disable-static && \ # --disable-static && \
make && make install # make && make install
FROM docker.io/thallian/confd-env:3.19-3.1.6.2 FROM docker.io/thallian/confd-env:3.19-3.1.6.2
COPY --from=builder /lib/dovecot/ /lib/dovecot/ # COPY --from=builder /lib/dovecot/ /lib/dovecot/
COPY --from=builder /libexec/dovecot/ /libexec/dovecot/ # COPY --from=builder /libexec/dovecot/ /libexec/dovecot/
COPY --from=builder /bin/doveadm /bin/doveadm # COPY --from=builder /bin/doveadm /bin/doveadm
COPY --from=builder /bin/doveconf /bin/doveconf # COPY --from=builder /bin/doveconf /bin/doveconf
COPY --from=builder /bin/dsync /bin/dsync # COPY --from=builder /bin/dsync /bin/dsync
COPY --from=builder /sbin/dovecot /sbin/dovecot # COPY --from=builder /sbin/dovecot /sbin/dovecot
COPY --from=builder /bin/sieve* /bin/ # COPY --from=builder /bin/sieve* /bin/
RUN apk --no-cache add \ RUN apk --no-cache add \
libsodium \
libbz2 \
zlib \
xz-libs \
lz4-libs \
lz4 \
linux-pam \
openssl \
ssmtp \ ssmtp \
ca-certificates \ dovecot \
lua5.1-libs \ dovecot-pgsql \
lua5.1-rapidjson \ dovecot-lmtpd \
curl \ dovecot-pigeonhole-plugin
inotify-tools \
libssl3
RUN addgroup -g 150 dovecot
RUN adduser -u 140 -h /dev/null -H -s /sbin/nologin -D -G dovecot dovecot
RUN addgroup -g 151 dovenull # RUN addgroup -g 150 dovecot
RUN adduser -u 141 -h /dev/null -H -s /sbin/nologin -D -G dovenull dovenull # RUN adduser -u 140 -h /dev/null -H -s /sbin/nologin -D -G dovecot dovecot
#
# RUN addgroup -g 151 dovenull
# RUN adduser -u 141 -h /dev/null -H -s /sbin/nologin -D -G dovenull dovenull
RUN addgroup -g 2222 access RUN addgroup -g 2222 access
RUN addgroup dovecot access RUN addgroup dovecot access

View File

@ -1,75 +1,101 @@
[Dovecot](http://www.dovecot.org/) with imap, starttls, oauth2 proxy auth and sieve rules. [Dovecot](http://www.dovecot.org/) with imap, starttls, oauth2 proxy auth and
sieve rules.
Uses [SSMTP](https://packages.debian.org/stable/mail/ssmtp) to send mails (for example if you have a redirect sieve rule). Uses [SSMTP](https://packages.debian.org/stable/mail/ssmtp) to send mails (for
example if you have a redirect sieve rule).
Reuses the same database schema as the {postfix container](/container/postfix).
# Volumes # Volumes
- `/var/lib/vmail/mail` - `/var/lib/vmail/mail`
# Environment Variables # Environment Variables
## HOSTNAME ## HOSTNAME
Fully qualified name of the mail host. Fully qualified name of the mail host.
## GRANT_URL ## GRANT_URL
OAuth2 url for token grants (password grant type). OAuth2 url for token grants (password grant type).
## INTROSPECTION_URL ## INTROSPECTION_URL
OAuth2 url for token information.
## USER_URL OAuth2 url for token information. Must include client id and client secret in
OAuth2 url for getting available users, the username will be appended to the end. basic auth format.
## TOKENINFO_URL ## TOKENINFO_URL
OAuth2 url for requestion information about a token.
## CLIENT_ID OAuth2 url for requestion information about a token. Must include client id and
Id of the OAuth2 application. client secret in basic auth format.
## CLIENT_SECRET ## DB_HOST
Secret of the OAuth2 application.
## OAUTH_ADMIN_USER Postgre database host.
User with which to perform user lookups (does not have to be an admin, but needs enough rights for that).
## OAUTH_ADMIN_PASSWORD ## DB_USER
Password for the `OAUTH_ADMIN_USER`.
User to connect to the database.
## DB_PW
Password to use for the database user.
## DB_NAME
- default: email
Name of the postgre database to connect to.
## SSMTP_MAIL_RELAY ## SSMTP_MAIL_RELAY
Hostname and port for the used smtp relay (for example `mail.example.com:587`). Hostname and port for the used smtp relay (for example `mail.example.com:587`).
## SSMTP_USER ## SSMTP_USER
User to authenticate agains the smtp relay. User to authenticate agains the smtp relay.
## SSMTP_PASSWORD ## SSMTP_PASSWORD
Password to authenticate agains the smtp relay. Password to authenticate agains the smtp relay.
## SSMTP_AUTH_METHOD ## SSMTP_AUTH_METHOD
- default: LOGIN - default: LOGIN
Which authentication mechanism to use for the smtp relay. Which authentication mechanism to use for the smtp relay.
## SSMTP_USE_STARTTLS ## SSMTP_USE_STARTTLS
- default: yes - default: yes
Whether to use starttls for the smtp relay. Whether to use starttls for the smtp relay.
## ALLOWED_USERNAME_CHARS ## ALLOWED_USERNAME_CHARS
- default: äöüabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
- default:
äöüabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
List of characters allowed in a username. List of characters allowed in a username.
## AUTH_MECHANISMS ## AUTH_MECHANISMS
- default: plain - default: plain
Space seperated list of supported [authentication mechanisms](http://wiki2.dovecot.org/Authentication/Mechanisms). Space seperated list of supported
[authentication mechanisms](http://wiki2.dovecot.org/Authentication/Mechanisms).
## SSL_MIN_PROTOCOL ## SSL_MIN_PROTOCOL
- default: TLSv1.2 - default: TLSv1.2
Ssl minimum protocol version. Ssl minimum protocol version.
## SSL_CIPHERLIST ## SSL_CIPHERLIST
- default: ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
- default:
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
Colon seperated list of supported ciphers (`!`disables a cipher). Colon seperated list of supported ciphers (`!`disables a cipher).
@ -77,14 +103,17 @@ Go [here](https://www.openssl.org/docs/manmaster/man1/ciphers.html) for a list
of ciphers. of ciphers.
## IMAP_MAX_USER_CONNECTIONS ## IMAP_MAX_USER_CONNECTIONS
- default: 10 - default: 10
Maximum number of connections from the same user + ip. Maximum number of connections from the same user + ip.
# Ports # Ports
- 143 - 143
# Capabilities # Capabilities
- CHOWN - CHOWN
- DAC_OVERRIDE - DAC_OVERRIDE
- FOWNER - FOWNER

View File

@ -0,0 +1,3 @@
[template]
src = "dovecot-sql.userdb.conf.ext.tmpl"
dest = "/etc/dovecot/dovecot-sql.userdb.conf.ext"

View File

@ -1,3 +0,0 @@
[template]
src = "oauth2-userdb.lua.tmpl"
dest = "/etc/dovecot/oauth2-userdb.lua"

View File

@ -23,4 +23,4 @@ namespace inbox {
} }
} }
mail_plugin_dir = /lib/dovecot mail_plugin_dir = /usr/lib/dovecot

View File

@ -11,6 +11,7 @@ passdb {
} }
userdb { userdb {
driver = lua driver = sql
args = file=/etc/dovecot/oauth2-userdb.lua blocking=yes args = /etc/dovecot/dovecot-sql.userdb.conf.ext
default_fields = uid=vmail gid=vmail home=/var/lib/vmail/mail/%u
} }

View File

@ -1,6 +1,4 @@
grant_url = {{ getenv "GRANT_URL" }} grant_url = {{ getenv "GRANT_URL" }}
client_id = {{ getenv "CLIENT_ID" }}
client_secret = {{ getenv "CLIENT_SECRET" }}
introspection_url = {{ getenv "INTROSPECTION_URL" }} introspection_url = {{ getenv "INTROSPECTION_URL" }}
introspection_mode = {{ getenv "INTROSPECTION_MODE" "post" }} introspection_mode = {{ getenv "INTROSPECTION_MODE" "post" }}
username_attribute = username username_attribute = username

View File

@ -1,6 +1,4 @@
grant_url = {{ getenv "GRANT_URL" }} grant_url = {{ getenv "GRANT_URL" }}
client_id = {{ getenv "CLIENT_ID" }}
client_secret = {{ getenv "CLIENT_SECRET" }}
tokeninfo_url = {{ getenv "TOKENINFO_URL" }} tokeninfo_url = {{ getenv "TOKENINFO_URL" }}
introspection_url = {{ getenv "INTROSPECTION_URL" }} introspection_url = {{ getenv "INTROSPECTION_URL" }}
introspection_mode = {{ getenv "INTROSPECTION_MODE" "post" }} introspection_mode = {{ getenv "INTROSPECTION_MODE" "post" }}
@ -8,4 +6,3 @@ username_attribute = username
tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt
use_grant_password = no use_grant_password = no
pass_attrs = pass=%{oauth2:access_token} pass_attrs = pass=%{oauth2:access_token}

View File

@ -0,0 +1,3 @@
driver = pgsql
connect = host={{ getenv "DB_HOST" }} dbname={{ getenv "DB_NAME" }} user={{ getenv "DB_USER" }} password={{ getenv "DB_PW" }}
user_query = SELECT COUNT(email) as count FROM virtual_users WHERE email = '%n' HAVING COUNT(email) > 0;

View File

@ -1,44 +0,0 @@
local rapidjson = require('rapidjson')
local clientId = "{{ getenv "CLIENT_ID" }}"
local clientSecret = "{{ getenv "CLIENT_SECRET" }}"
local username = "{{ getenv "OAUTH_ADMIN_USER" }}"
local password = "{{ getenv "OAUTH_ADMIN_PASSWORD" }}"
local tokenUrl = "{{ getenv "GRANT_URL" }}"
local userUrl = "{{ getenv "USER_URL" }}"
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
return s
end
function auth_userdb_lookup(req)
local tokenCmd = "curl -L --silent -X POST -d \"grant_type=password\""
tokenCmd = tokenCmd .. " -d \"client_id=" .. clientId .. "\""
tokenCmd = tokenCmd .. " -d \"client_secret=" .. clientSecret .. "\""
tokenCmd = tokenCmd .. " -d \"username=" .. username .. "\""
tokenCmd = tokenCmd .. " -d \"password=" .. password .. "\""
tokenCmd = tokenCmd .. " \"" .. tokenUrl .. "\""
local tokenRaw = os.capture(tokenCmd)
local tokenJson = rapidjson.decode(tokenRaw)
local accessToken = tokenJson.access_token
local userCmd = "curl -L --silent -H \"Authorization: Bearer " .. accessToken .. "\" \"" .. userUrl .. req.username .. "\""
local userRaw = os.capture(userCmd)
local userJson = rapidjson.decode(userRaw)
if #userJson == 0 then
return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "no such user"
end
if userJson[1].username == req.username then
return dovecot.auth.USERDB_RESULT_OK, "uid=vmail gid=vmail home=/var/lib/vmail/mail/" .. req.username
end
return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "no such user"
end