Skip to content

Commit

Permalink
adding Kerberos support
Browse files Browse the repository at this point in the history
  • Loading branch information
ehough committed Feb 5, 2018
1 parent c428f6b commit 77458e3
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 92 deletions.
12 changes: 9 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
FROM alpine:latest
# switch back to Alpine when/if https://bugs.alpinelinux.org/issues/8470 is fixed
# FROM alpine:latest
# RUN apk --update upgrade && apk add bash nfs-utils && rm -rf /var/cache/apk/*

# install Bash and nfs-utils
RUN apk --update upgrade && apk add bash nfs-utils && rm -rf /var/cache/apk/*
FROM debian:stable

RUN apt-get update && \
apt-get install -y --no-install-recommends nfs-kernel-server kmod libcap2-bin && \
apt-get clean && \
rm -rf /var/lib/apt/lists

ADD ./entrypoint.sh /usr/local/bin
RUN chmod +x /usr/local/bin/entrypoint.sh
Expand Down
127 changes: 93 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,76 +7,136 @@ A lightweight, robust, flexible, and containerized NFS server.
This is the only containerized NFS server that offers **all** of the following features:

- NFS versions 3, 4, or both simultaneously
- optional Kerberos security
- optional name/ID mapping via [`idmapd`](http://man7.org/linux/man-pages/man8/idmapd.8.html)
- clean teardown of services upon `SIGTERM` or `SIGKILL` (no lingering `nfsd` processes on Docker host)
- flexible construction of `/etc/exports` via a Docker bind mount *or* environment variables
- lightweight image based on [Alpine Linux](https://alpinelinux.org/)
- ability to control server parameters via environment variables
- extensive server configuration via environment variables

## Requirements

1. The Docker **host** kernel will need both the `nfs` and `nfsd` kernel modules. Usually you can enable them both with `modprobe nfs nfsd`.
1. The container will need to run with `CAP_SYS_ADMIN` (or `--privileged`). This is necessary as the server needs to mount several filesystems inside the container to support its operation.
1. You will need to bind mount your exported filesystems into this container. e.g. `-v /some/path/on/host:/some/container/path`
1. The Docker **host** kernel will need the following kernel modules
- `nfs`
- `nfsd`
- `rpcsec_gss_krb5` (*only if Kerberos is used*)

Usually you can enable these modules with: `modprobe {nfs,nfsd,rpcsec_gss_krb5}`
1. The container will need to run with `CAP_SYS_ADMIN` (or `--privileged`). This is necessary as the server needs to mount several filesystems inside the container to support its operation, and performing mounts from inside a container is impossible without these capabilities.
1. The container will need local access to the files you'd like to serve via NFS. You can use Docker volumes, bind mounts, or files baked into a custom image. e.g.

- `-v some_volume:/some/container/path` (Docker volume)
- `-v /some/path/on/host:/some/container/path` (bind mount)
- `ADD /some/path/on/host /some/container/path` (Dockerfile)

## Usage

### Starting the container
### Hello, World!

The container requires you to supply it with your desired [NFS exports](https://linux.die.net/man/5/exports) upon startup. You have **two choices** for doing this:
You will need to provide your desired [NFS exports](https://linux.die.net/man/5/exports) (`/etc/exports`) upon container startup. You have **three choices** for doing this:

1. **Bind mount a full exports file into the container at `/etc/exports`**.
1. **Bind mount `/etc/exports` into the container**

docker run \
-v /host/path/to/exports.txt:/etc/exports:ro \
-v /host/files:/nfs \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs4-server:latest`
docker run \
-v /host/path/to/exports.txt:/etc/exports:ro \
-v /host/files:/nfs \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs-server:latest
1. **Supply each line of `/etc/exports` as an environment variable**.
1. **Provide each line of `/etc/exports` as an environment variable**.

The container will look for environment variables that start with `NFS_EXPORT_` and end with an integer. e.g. `NFS_EXPORT_0`, `NFS_EXPORT_1`, etc.

docker run \
-e NFS_EXPORT_0='/nfs/foo 192.168.1.0/24(ro,no_subtree_check)' \
-e NFS_EXPORT_1='/nfs/bar 123.123.123.123/32(rw,no_subtree_check)' \
-v /host/path/foo:/nfs/foo \
-v /host/path/bar:/nfs/bar \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs4-server:latest`
docker run \
-e NFS_EXPORT_0='/nfs/foo 192.168.1.0/24(ro,no_subtree_check)' \
-e NFS_EXPORT_1='/nfs/bar 123.123.123.123/32(rw,no_subtree_check)' \
-v /host/path/foo:/nfs/foo \
-v /host/path/bar:/nfs/bar \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs-server:latest

1. **Bake `/etc/exports` into a custom image**

e.g. in a `Dockerfile`:

FROM ehough/nfs-server:latest
ADD /host/path/to/exports.txt /etc/exports

### Configuration
### (Optional) User ID Mapping

If you'd like to run [`idmapd`](http://man7.org/linux/man-pages/man8/idmapd.8.html) to map between NFSv4 IDs (e.g. `[email protected]`) and local users, simply provide [`idmapd.conf`](https://linux.die.net/man/5/idmapd.conf) and `/etc/passwd` to the container. This step is required for Kerberos.

docker run \
-v /host/path/to/exports.txt:/etc/exports:ro \
-v /host/files:/nfs \
-v /host/path/to/idmapd.conf:/etc/idmapd.conf:ro \
-v /etc/passwd:/etc/passwd:ro \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs-server:latest
### (Optional) Kerberos

Via optional environment variables, you can adjust the server settings to your needs.
You can enable Kerberos security by performing the following additional actions:

1. set the environment variable `NFS_ENABLE_KERBEROS` to a non-empty value (e.g. `NFS_ENABLE_KERBEROS=1`)
1. set the server's hostname via the `--hostname` flag
1. provide `/etc/krb5.keytab` which contains a principal of the form `nfs/<hostname>`, where `<hostname>` is the hostname you supplied in the previous step.
1. provide [`/etc/krb5.conf`](https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html)
1. provide [`/etc/idmapd.conf`](https://linux.die.net/man/5/idmapd.conf)
1. provide `/etc/passwd` that contains your NFS client users

Here's an example:

docker run \
-v /host/path/to/exports.txt:/etc/exports:ro \
-v /host/files:/nfs \
-e NFS_ENABLE_KERBEROS=1 \
--hostname my-nfs-server.com \
-v /host/path/to/server.keytab:/etc/krb5.keytab:ro \
-v /host/path/to/server.krb5conf:/etc/krb5.conf:ro \
-v /host/path/to/idmapd.conf:/etc/idmapd.conf:ro \
-v /etc/passwd:/etc/passwd:ro \
--cap-add SYS_ADMIN \
-p 2049:2049 \
erichough/nfs-server:latest

### Environment Variables

The following optional environment variables allow you to adjust the server settings to your needs.

- **`NFS_VERSION`** (default is `4.2`)

Set to `3`, `4`, `4.1`, or `4.2` to fine tune the NFS protocol version. Enabling any version will also enable any lesser versions. e.g. `4.2` will enable versions 4.2, 4.1, 4, **and** 3.

- **`NFS_VERSION_DISABLE_V3`** (*not set by default*)
- **`NFS_DISABLE_VERSION_3`** (*not set by default*)

Set to a non-empty value (e.g. `NFS_VERSION_DISABLE_V3=1`) to disable NFS version 3 and run a version-4-only server. This setting is not compatible with `NFS_VERSION=3`.
Set to a non-empty value (e.g. `NFS_DISABLE_VERSION_3=1`) to disable NFS version 3 and run a version-4-only server. This setting is not compatible with `NFS_VERSION=3`.

- **`NFSD_PORT`** (default is `2049`)
- **`NFS_PORT`** (default is `2049`)

Set this to any valid port number (`1` - `65535` inclusive) to change `rpc.nfsd`'s listening port.

- **`NFSD_SERVER_THREADS`** (default is *CPU core count*)
- **`NFS_SERVER_THREAD_COUNT`** (default is *CPU core count*)

Set this to a positive integer to control how many server threads `rpc.nfsd` will use. A good minimum is one thread per CPU core, but 4 or 8 threads per core is probably better.

- **`NFS_MOUNTD_PORT`** (default is `32767`)
- **`NFS_PORT_MOUNTD`** (default is `32767`)

*Only needed for NFS 3*. Set this to any valid port number (`1` - `65535` inclusive) to change `rpc.mountd`'s listening port.

- **`NFS_STATD_IN_PORT`** (default is `32765`)
- **`NFS_PORT_STATD_IN`** (default is `32765`)

*Only needed for NFS 3*. Set this to any valid port number (`1` - `65535` inclusive) to change `rpc.statd`'s listening port.

- **`NFS_STATD_OUT_PORT`** (default is `32766`)
- **`NFS_PORT_STATD_OUT`** (default is `32766`)

*Only needed for NFS 3*. Set this to any valid port number (`1` - `65535` inclusive) to change `rpc.statd`'s outgoing connection port.

- **`NFS_ENABLE_KERBEROS`** (*not set by default*)

Set to a non-empty value (e.g. `NFS_ENABLE_KERBEROS=1`) to enable Kerberos on this server. See "Kerberos" section above for further details.

### Mounting filesystems from a client

Expand All @@ -92,9 +152,8 @@ Via optional environment variables, you can adjust the server settings to your n

## Remaining tasks

- switch back to Alpine Linux once [this bug](https://bugs.alpinelinux.org/issues/8470) in `nfs-utils` is fixed
- figure out why `rpc.nfsd` takes 5 minutes to startup/timeout unless `rpcbind` is running
- add `rpc.idmapd`
- add NFS v4 security (`rpc.svcgssd`, `rpc.gssd`, etc.)

## Acknowledgements

Expand Down
Loading

0 comments on commit 77458e3

Please sign in to comment.