Compare commits

...

21 Commits
bkup ... master

Author SHA1 Message Date
8ecdba987b
ubuntu: add rsyslog package for logging 2025-11-11 05:01:09 -05:00
42a40149af
refactor: make it so the entrypoint doesn't overwrite /etc/hostname 2025-11-03 18:41:08 -05:00
708d807cc1
ubuntu: fix incorrect syntax in nfs-common file 2025-11-03 18:40:24 -05:00
4a7463802e
alpine: implement fix/workaround for rpc_pipefs not being mounted in container in some cases 2025-11-03 18:37:36 -05:00
2ac4b483ea
tag alpine image as latest 2025-10-30 00:22:43 -04:00
e12b8dc9a0
add readme.md 2025-10-30 00:17:49 -04:00
6f0b01aeca
alpine: workarounds for use cases with custom exports files 2025-10-30 00:15:51 -04:00
a75674f812
ensure debug tag isn't pushed to docker 2025-10-29 18:13:45 -04:00
bc96ce3655
move repeated bits to common script 2025-10-29 18:12:25 -04:00
9f1be586be
ensure alpine is the default image 2025-10-29 17:19:38 -04:00
62d4856f7a
fix build script using oldest tag instead of newest 2025-10-29 17:17:45 -04:00
a069586179
alpine,ubuntu: add missing semicolons 2025-10-29 17:14:27 -04:00
bdf9e8d9ac
alpine: install alpine-conf in entrypoint instead of embedding it into the image 2025-10-29 17:13:02 -04:00
2c8262a3a8
alpine,ubuntu: trim down preinstalled packages 2025-10-29 17:12:36 -04:00
5db42d05ab
update build helper script to optionally push to a docker registry 2025-10-29 17:11:29 -04:00
2ca3af5635
alpine: log kerberos stuff to syslog 2025-10-29 17:07:43 -04:00
bb47f4ee21
add helper to build images 2025-10-29 15:15:49 -04:00
746d541df7
fix init.sh 2025-10-29 15:09:10 -04:00
666aee5fa4
alpine is fixed !!!! 🎉 2025-10-29 15:06:29 -04:00
93b13af8ab
rename ubuntu files, make entrypoints conditional 2025-10-29 15:06:29 -04:00
0e7565666e
add ubuntu variant 2025-10-29 15:06:20 -04:00
9 changed files with 330 additions and 54 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"nuxt.isNuxtApp": false
}

View File

@ -1,19 +1,29 @@
FROM alpine:latest
ARG DEBUG
ENV DEBUG=${DEBUG}
VOLUME /exports
WORKDIR /root
RUN mkdir -p /run/openrc
RUN touch /run/openrc/softlevel
RUN apk add --no-cache --update openrc
RUN apk add --no-cache --update --verbose bash krb5-server nfs-utils iproute2 krb5-server-openrc procps krb5 syslog-ng
RUN apk add --no-cache --update --verbose tzdata bash krb5-server nfs-utils krb5-server-openrc krb5 syslog-ng chrony nfs-utils-openrc
RUN if [ -n "${DEBUG}" ]; then \
apk add --no-cache --update iproute2 procps; \
fi
RUN rc-update add syslog-ng boot
RUN rc-update add krb5kdc default
RUN rc-update add krb5kadmind default
RUN rc-update add nfs default
RUN rc-update add rpc.pipefs boot
COPY ./common.sh .
COPY ./entrypoint.sh .
COPY ./init.sh .
RUN chmod +x ./entrypoint.sh && chmod +x ./init.sh
RUN chmod +x ./entrypoint.sh && chmod +x ./init.sh && chmod +x ./common.sh
RUN ls

27
Dockerfile.ubuntu Normal file
View File

@ -0,0 +1,27 @@
FROM ubuntu:latest
ARG DEBUG
ENV DEBIAN_FRONTEND=noninteractive
ENV DEBUG=${DEBUG}
WORKDIR /root
RUN apt-get update
RUN apt-get install -y nfs-kernel-server krb5-kdc krb5-admin-server nfs-common bash rsyslog
RUN if [ -n "${DEBUG}" ]; then \
apt-get install iproute2 iputils-ping net-tools; \
fi
RUN cat > /etc/rsyslog.conf <<EOF
*.* /var/log/everything.log
EOF
COPY ./common.sh .
COPY ./entrypoint-ubuntu.sh .
COPY ./init.sh .
RUN chmod +x ./entrypoint-ubuntu.sh && chmod +x ./init.sh && chmod +x ./common.sh
RUN ls
EXPOSE 2049 88 749 750 111 666 892
CMD ["./init.sh", "ubuntu"]

45
README.md Normal file
View File

@ -0,0 +1,45 @@
# thealmightydrawingtablet/nfs-krb
it's an NFS server with kerberos integrated out of the box !
## why?
because nobody else has made one for some reason ¯\\\_(ツ)\_/¯
# usage
### sharing directory via env var
```bash
# works for both ubuntu and alpine images
docker run -d --privileged -v /path/on/host:/container/srv \
-e SHARED_DIRECTORY=/container/srv -e PERMITTED=10.0.0.0/8 \
-e NFS_KRB_PRINC=nfs/localhost.local -e NFS_KRB_REALM=LOCALHOST.LOCAL -e NFS_KRB_PWD='unguessable!'
```
### bring your own `/etc/exports`
```bash
# ubuntu
docker run -d --privileged -v /path/on/host:/container/srv -v ./exports:/etc/exports \
-e PERMITTED=10.0.0.0/8 \
-e NFS_KRB_PRINC=nfs/localhost.local -e NFS_KRB_REALM=LOCALHOST.LOCAL -e NFS_KRB_PWD='unguessable!'
# alpine
docker run -d --privileged -v /path/on/host:/container/srv/folder-1 -v /another/thing:/container/srv/folder-2 -v ./exports:/etc/exports.mnt \
-e PERMITTED=10.0.0.0/8 \
-e NFS_KRB_PRINC=nfs/localhost.local -e NFS_KRB_REALM=LOCALHOST.LOCAL -e NFS_KRB_PWD='unguessable!'
```
## recognized configuration environment variables
| Variable | Default | Required | Alpine | Ubuntu | Description |
| ------------------ | ------------------ | -------- | ------ | ------ | ------------------------------------------------------------------------------- |
| `NFS_KRB_REALM` | - | yes | ✅ | ✅ | Kerberos realm to authenticate with. |
| `NFS_KRB_PRINC` | - | yes | ✅ | ✅ | the service principal which will be added to the keytab. |
| `NFS_KRB_PWD` | - | yes | ✅ | ✅ | kerberos database master password, as well as the password for `NFS_KRB_PRINC`. |
| `RW_MODE` | `rw` | no | ✅ | ✅ | controls NFS export read/write mode and the per-share option string. |
| `SRV_TZ` | `America/New_York` | no | ✅ | ❌ | overrides the system timezone. |
| `SHARED_DIRECTORY` | - | no | ✅ | ✅ | determines whether to configure a singular export. |
| `PERMITTED` | `*` | no | ✅ | ✅ | provides the allowed client list for a single exported directory. |

11
build.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
IMAGE=${IMAGE:-"thealmightydrawingtablet/nfs-krb"}
VERSION=$(git tag --sort=-committerdate | grep -vi debug | head -n 1)
docker build --progress=plain -t "${IMAGE}:ubuntu" -t "${IMAGE}:${VERSION}-ubuntu" -f ./Dockerfile.ubuntu .
docker build --progress=plain -t "${IMAGE}:alpine" -t "${IMAGE}:${VERSION}-alpine" -t "${IMAGE}:latest" .
if [ "$1" == "push" ]; then
docker push --all-tags "${IMAGE}"
fi

94
common.sh Normal file
View File

@ -0,0 +1,94 @@
#!/bin/bash
cat > /etc/krb5.conf << EOL
[logging]
default = SYSLOG:DEBUG
kdc = SYSLOG:DEBUG
admin_server = SYSLOG:DEBUG
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = ${NFS_KRB_REALM}
[realms]
${NFS_KRB_REALM} = {
kdc = localhost
admin_server = localhost
}
EOL
cat > /etc/idmapd.conf << EOC
[General]
Domain = ${NFS_KRB_REALM}
Verbosity = 5
EOC
cat > /etc/nfs.conf << EOC
[general]
pipefs-directory=/run/rpc_pipefs
[exports]
[exportfs]
debug=1
[gssd]
verbosity=5
rpc-verbosity=5
keytab-file=/etc/krb5.keytab
[exportd]
debug="all"
[mountd]
debug="all"
manage-gids=y
port=892
[nfsdcld]
debug=1
[nfsdcltrack]
debug=1
[nfsd]
debug=1
# threads=8
# host=
# grace-time=90
# lease-time=90
udp=y
tcp=y
vers3=y
vers4=y
vers4.0=y
vers4.1=y
vers4.2=y
EOC
touch /var/lib/krb5kdc/kadm5.acl
kdb5_util -r "${NFS_KRB_REALM}" create -s << EOL
${NFS_KRB_PWD}
${NFS_KRB_PWD}
EOL
# DOMAIN=$(echo "$NFS_KRB_REALM" | tr '[:upper:]' '[:lower:]')
# echo "${DOMAIN}" > /etc/hostname
# setup logging
rpcdebug -m nfsd -s all
rpcdebug -m nfs -s all
rpcdebug -m rpc -s all
kadmin.local << EOS
addprinc ${NFS_KRB_PRINC}@${NFS_KRB_REALM}
${NFS_KRB_PWD}
${NFS_KRB_PWD}
ktadd -norandkey ${NFS_KRB_PRINC}@${NFS_KRB_REALM}
EOS

74
entrypoint-ubuntu.sh Normal file
View File

@ -0,0 +1,74 @@
#!/bin/bash
set -xuo pipefail
trap "stop; exit 0;" SIGTERM SIGINT
SERVICES=(krb5-kdc krb5-admin-server nfs-kernel-server)
stop()
{
echo "signal caught, stopping the world..."
exportfs -uav
for i in "${SERVICES[@]}"; do
service "$i" stop;
done;
echo "bye!"
exit
}
DEFAULT_PERMITTED="*"
RW_MODE="rw"
UID=${NFS_UID:-0}
DOMAIN=$(echo "$NFS_KRB_REALM" | tr '[:upper:]' '[:lower]')
if [ -n "${SHARED_DIRECTORY}" ]; then
options="(${RW_MODE:-rw},\
nohide,sync,no_subtree_check,insecure,no_root_squash,crossmnt,sec=krb5p:krb5i:krb5,fsid=0)"
cat > /etc/exports <<EOE
${SHARED_DIRECTORY} ${PERMITTED:-${DEFAULT_PERMITTED}}$options
# / ${PERMITTED:-${DEFAULT_PERMITTED}}${options%?},fsid=0)
EOE
# nfs v4 root export hack
if [ "$(dirname "${SHARED_DIRECTORY}")" != "/" ]; then
cat >> /etc/exports <<-EOE
# $(dirname "${SHARED_DIRECTORY}") ${PERMITTED:-${DEFAULT_PERMITTED}}${options%?})
EOE
fi
chmod 777 "${SHARED_DIRECTORY}"
fi
cat > /etc/idmapd.conf << EOC
[General]
Domain = $DOMAIN
Verbosity = 5
EOC
cat > /etc/default/nfs-common << EOC
NEED_STATD=yes
# Do you want to start the idmapd daemon? It is only needed for NFSv4.
NEED_IDMAPD=yes
# Do you want to start the gssd daemon? It is required for Kerberos mounts.
NEED_GSSD=yes
EOC
echo NEED_SVCGSSD=y > /etc/default/nfs-kernel-server
./common.sh
exportfs -rvaf
export OPTS_RPC_MOUNTD='--debug all -t 8 -N 3'
echo "OPTS_RPC_MOUNTD=\"${OPTS_RPC_MOUNTD}\"" >> /etc/conf.d/nfs
service nfs restart
kill `pidof rpcbind`
rpcbind -fd &> /var/log/rpcbind.log &
sleep 3
for i in "${SERVICES[@]}"; do
service "$i" start
done
rpc.svcgssd -vf &> /var/log/gssd.log &
cat /etc/krb5.conf
while true; do
sleep 360
done

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -xuo pipefail
set -xo pipefail
trap "stop; exit 0;" SIGTERM SIGINT
stop()
@ -13,73 +13,76 @@ stop()
exit
}
DEFALUT_TIMEZONE="America/New_York"
DEFAULT_PERMITTED="*"
RW_MODE="rw"
UID=${NFS_UID:-0}
apk add --no-cache --update alpine-conf
setup-timezone -z "${SRV_TZ:-${DEFALUT_TIMEZONE}}"
apk del alpine-conf
cat > /etc/chrony/chrony.conf << 'EOF'
pool 0.pool.ntp.org iburst
pool 1.pool.ntp.org iburst
EOF
rc-service chronyd start && rc-update add chronyd default
if [ -n "${SHARED_DIRECTORY}" ]; then
echo "${SHARED_DIRECTORY} ${PERMITTED:-${DEFAULT_PERMITTED}}(${RW_MODE:-rw},root_squash,nohide,fsid=${UID},sync,no_subtree_check,insecure,root_squash,crossmnt,anonuid=${UID},anongid=${UID},sec=krb5p:krb5i:krb5)" \
> /etc/exports
mkdir -p /exports"${SHARED_DIRECTORY}"
options="(${RW_MODE:-rw},no_root_squash,sync,no_subtree_check,insecure,sec=krb5p:krb5i:krb5)"
mount --bind "${SHARED_DIRECTORY}" /exports"${SHARED_DIRECTORY}"
cat > /etc/exports <<- EOE
/exports ${PERMITTED:-${DEFAULT_PERMITTED}}(${RW_MODE:-rw},no_root_squash,insecure,no_subtree_check,hide,fsid=0,sync,sec=krb5p:krb5i:krb5)
/exports${SHARED_DIRECTORY} ${PERMITTED:-${DEFAULT_PERMITTED}}${options%?},fsid=1)
EOE
chmod 777 "${SHARED_DIRECTORY}"
else
cp /etc/exports.mnt /etc/exports
grep -vi "^[[:space:]]*#" /etc/exports | while read -r line; do
if [ -n "${line}" ]; then
trimmed="${line##*([[:space:]])}"
# shellcheck disable=SC2001
rcdir="$(eval "declare -a str=($( echo "$trimmed" | sed 's/[][`~!@#$%^&*():;<>.,?|{}=+-]/\\&/g' )); echo \${str[0]}")"
cdir="${rcdir##*(\")}"
echo "${cdir}"
mkdir -p "/exports${cdir}"
mount --bind -o rw "${cdir}" "/exports${cdir}"
chmod 777 "/exports${cdir}"
fi
done
sed -i -r '/^[[:space:]]*#/!s/^("?)/\1\/exports/' /etc/exports
# root entry
echo -e "\n/exports *(rw,no_root_squash,insecure,no_subtree_check,nohide,fsid=0,sync,sec=krb5p:krb5i:krb5)" >> /etc/exports
fi
cat > /etc/krb5.conf << EOL
[logging]
default = FILE:/var/log/krb5libs.log:DEBUG
kdc = FILE:/var/log/krb5kdc.log:DEBUG
admin_server = FILE:/var/log/kadmind.log:DEBUG
# setup logging
syslogd
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = ${NFS_KRB_REALM}
[realms]
${NFS_KRB_REALM} = {
kdc = localhost
admin_server = localhost
}
EOL
cat > /etc/idmapd.conf << EOC
[General]
Domain = ${NFS_KRB_REALM}
Verbosity = 5
EOC
touch /var/lib/krb5kdc/kadm5.acl
./common.sh
exportfs -rvaf
export OPTS_RPC_MOUNTD='--debug all -t 8 -N 3'
cat >> /etc/conf.d/nfs <<EOC
OPTS_RPC_MOUNTD="${OPTS_RPC_MOUNTD}"
OPTS_RPC_NFSD="--debug --syslog"
EXPORTFS_TIMEOUT=30
EOC
kdb5_util -r "${NFS_KRB_REALM}" create -s << EOL
${NFS_KRB_PWD}
${NFS_KRB_PWD}
ln -s /var/lib/nfs/rpc_pipefs /run/rpc_pipefs
EOL
echo "${NFS_KRB_REALM}" > /etc/hostname
# setup logging
syslogd
rpcdebug -m nfsd -s all
rpcdebug -m nfs -s all
rpcdebug -m rpc -s all
kadmin.local -q "addprinc -pw ${NFS_KRB_PWD} ${NFS_KRB_PRINC}@${NFS_KRB_REALM}"
kadmin.local -q "ktadd ${NFS_KRB_PRINC}@${NFS_KRB_REALM}"
kadmin.local -q "ktadd -k /etc/krb5.keytab ${NFS_KRB_PRINC}@${NFS_KRB_REALM}"
kadmin.local -q "cpw -pw ${NFS_KRB_PWD} ${NFS_KRB_PRINC}"
rc-service rpc.pipefs restart
rc-service krb5kdc start
rc-service krb5kadmind start
rc-service nfs start
export OPTS_RPC_MOUNTD='--debug all -t 8 -N 3'
echo "OPTS_RPC_MOUNTD=\"${OPTS_RPC_MOUNTD}\"" >> /etc/conf.d/nfs
rc-service nfs restart
# shellcheck disable=SC2046
kill -9 $(pidof rpc.svcgssd)
rpc.gssd -vf &> /var/log/rpc-gssd.log &
rpc.svcgssd -vf &> /var/log/gssd.log &
cat /etc/krb5.conf

11
init.sh
View File

@ -1,2 +1,11 @@
#!/bin/bash
exec bash -xc ./entrypoint.sh 2>&1 | tee /root/stuff.log
ENTRY="./entrypoint.sh"
if [ "$1" == "ubuntu" ]; then
ENTRY="./entrypoint-ubuntu.sh"
service --status-all
service rsyslog start
fi
exec bash -xc $ENTRY 2>&1 | tee /root/stuff.log