diff --git a/bin/ovpn_genconfig b/bin/ovpn_genconfig
index 894133d..974c344 100755
--- a/bin/ovpn_genconfig
+++ b/bin/ovpn_genconfig
@@ -171,8 +171,6 @@ port 1194
dev tun0
status /tmp/openvpn-status.log
-client-config-dir $OPENVPN/ccd
-
user nobody
group nogroup
EOF
diff --git a/bin/ovpn_getclient b/bin/ovpn_getclient
index 0906886..b2055b3 100755
--- a/bin/ovpn_getclient
+++ b/bin/ovpn_getclient
@@ -45,7 +45,7 @@ remote $OVPN_CN $OVPN_PORT $OVPN_PROTO
$(cat $EASYRSA_PKI/private/${cn}.key)
-$(cat $EASYRSA_PKI/issued/${cn}.crt)
+$(openssl x509 -in $EASYRSA_PKI/issued/${cn}.crt)
$(cat $EASYRSA_PKI/ca.crt)
diff --git a/bin/ovpn_run b/bin/ovpn_run
index 5a2c95a..b91da3a 100755
--- a/bin/ovpn_run
+++ b/bin/ovpn_run
@@ -10,6 +10,9 @@ fi
set -e
+# Build runtime arguments array based on environment
+ARGS=("--config" "$OPENVPN/openvpn.conf")
+
source "$OPENVPN/ovpn_env.sh"
mkdir -p /dev/net
@@ -17,8 +20,8 @@ if [ ! -c /dev/net/tun ]; then
mknod /dev/net/tun c 10 200
fi
-if [ ! -d "$OPENVPN/ccd" ]; then
- mkdir -p /etc/openvpn/ccd
+if [ -d "$OPENVPN/ccd" ]; then
+ ARGS+=("--client-config-dir" "$OPENVPN/ccd")
fi
# Setup NAT forwarding if requested
@@ -40,11 +43,21 @@ if [ -r "$EASYRSA_PKI/crl.pem" ]; then
ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
chmod 644 "$OPENVPN/crl.pem"
fi
- ARGS=("--crl-verify" "$OPENVPN/crl.pem")
+ ARGS+=("--crl-verify" "$OPENVPN/crl.pem")
+fi
+
+ip -6 route show default 2>/dev/null
+if [ $? = 0 ]; then
+ echo "Enabling IPv6 Forwarding"
+ # If this fails, ensure the docker container is run with --privileged
+ # Could be side stepped with `ip netns` madness to drop privileged flag
+
+ sysctl net.ipv6.conf.default.forwarding=1
+ sysctl net.ipv6.conf.all.forwarding=1
fi
if [ "$#" -gt 0 ]; then
exec openvpn "$@"
else
- exec openvpn ${ARGS[@]} --config "$OPENVPN/openvpn.conf"
+ exec openvpn ${ARGS[@]}
fi
diff --git a/docs/docker.md b/docs/docker.md
new file mode 100644
index 0000000..2313504
--- /dev/null
+++ b/docs/docker.md
@@ -0,0 +1,52 @@
+# Install Latest Docker Service
+
+Docker included with some distributions lags far behind upstream. This guide aims to provide a quick and reliable way to install or update it.
+
+It is recommended to use platforms that support systemd as future versions of this docker image may require systemd to help with some tasks:
+
+* Fedora
+* Debian 8.1+
+
+## Debian / Ubuntu
+
+### Step 1 — Set Up Docker
+
+Docker is moving fast and Debian / Ubuntu's long term support (LTS) policy doesn't keep up. To work around this we'll install a PPA that will get us the latest version of Docker.
+
+Ensure dependencies are installed:
+
+ sudo apt-get update && sudo apt-get install -y apt-transport-https curl
+
+Add the upstream Docker repository package signing key. The apt-key command uses elevated privileges via sudo, so a password prompt for the user's password may appear:
+
+ curl https://get.docker.io/gpg | sudo apt-key add -
+
+Add the upstream Docker repository to the system list:
+
+ echo deb https://get.docker.io/ubuntu docker main | sudo tee /etc/apt/sources.list.d/docker.list
+
+Update the package list and install the Docker package:
+
+ sudo apt-get update && sudo apt-get install -y lxc-docker
+
+Add your user to the `docker` group to enable communication with the Docker daemon as a normal user, where `$USER` is your username. Exit and log in again for the new group to take effect:
+
+ sudo usermod -aG docker $USER
+
+After **re-logging in** verify the group membership using the id command. The expected response should include docker like the following example:
+
+ uid=1001(test0) gid=1001(test0) groups=1001(test0),27(sudo),999(docker)
+
+### Step 2 — Test Docker
+
+Run a Debian jessie docker container:
+
+ docker run --rm -it debian:jessie bash -l
+
+Once inside the container you'll see the `root@:/#` prompt signifying that the current shell is in a Docker container. To confirm that it's different from the host, check the version of Debian running in the container:
+
+ cat /etc/issue.net
+
+Expected result:
+
+ Debian GNU/Linux 8
diff --git a/docs/faqs.md b/docs/faqs.md
index 4805836..7ed633d 100644
--- a/docs/faqs.md
+++ b/docs/faqs.md
@@ -1,5 +1,12 @@
# Frequently Asked Questions
+## How do I edit `openvpn.conf`?
+
+Use a Docker image with a text editor pre-installed (i.e. Ubuntu) and connect the volume container:
+
+ docker run --volumes-from $OVPN_DATA --rm -it ubuntu vi /etc/openvpn/openvpn.conf
+
+
## Why not keep everything in one image?
The run-time image (`kylemanna/openvpn`) is intended to be an ephemeral image. Nothing should be saved in it so that it can be re-downloaded and re-run when updates are pushed (i.e. newer version of OpenVPN or even Debian). The data container contains all this data and is attached at run time providing a safe home.
diff --git a/docs/ipv6.md b/docs/ipv6.md
new file mode 100644
index 0000000..0916d10
--- /dev/null
+++ b/docs/ipv6.md
@@ -0,0 +1,91 @@
+# IPv6 Support
+
+This is a work in progress, more polish to follow. Use the `dev` git branch and `dev` docker image tag for testing.
+
+## Tunnel IPv6 Address To OpenVPN Clients
+
+This feature is advanced and recommended only for those who already have a functioning IPv4 tunnel and know how IPv6 works.
+
+Systemd is used to setup a static route and Debian 8.1 or later is recommended as the host distribution. Others probably work, but haven't been tested.
+
+
+### Step 1 — Setup IPv6 on the Host Machine
+
+The tutorial uses a free tunnel from [tunnelbroker.net](https://tunnelbroker.net/) to get a /64 and /48 prefix allocated to me. The tunnel endpoint is less then 3 ms away from Digital Ocean's San Francisco datacenter.
+
+Place the following in `/etc/network/interfaces`. Relace `PUBLIC_IP` with your host's public IPv4 address and replace 2001:db8::2 and 2001:db8::1 with the corresponding tunnel endpoints:
+
+ auto he-ipv6
+ iface he-ipv6 inet6 v4tunnel
+ address 2001:db8::2
+ netmask 64
+ endpoint 72.52.104.74
+ local PUBLIC_IP
+ ttl 255
+ gateway 2001:db8::1
+
+Bring the interface up:
+
+ ifup he-ipv6
+
+Test that IPv6 works on the host:
+
+ ping6 google.com
+
+If this doesn't work, figure it out. It may be necessary to add an firewall rule to allow IP protocol 41 through the firewall.
+
+
+### Step 2 — Update Docker's Init To Enable IPv6 Support
+
+Copy the system's existing docker file and append the `--ipv6` argument to the end of the command line:
+
+ sed -e 's:^\(ExecStart.*\):\1 --ipv6:' /lib/systemd/system/docker.service | tee /etc/systemd/system/docker.service
+
+Reload the daemon and restart docker so that it takes affect:
+
+ systemctl daemon-reload && systemctl restart docker.service
+
+
+### Step 3 — Setup the systemd Unit File
+
+Copy the systemd init file from the docker-openvpn /init directory of the repository and install into `/etc/systemd/system/docker-openvpn.service`
+
+ curl -o /etc/systemd/system/docker-openvpn.service https://raw.githubusercontent.com/kylemanna/docker-openvpn/dev/init/docker-openvpn.service
+
+Edit the file, replace `IP6_PREFIX` value with the value of your /64 prefix.
+
+ vi /etc/systemd/system/docker-openvpn.service
+
+Finally, reload systemd so the changes take affect:
+
+ systemctl daemon-reload
+
+### Step 4 — Start OpenVPN
+
+Ensure that OpenVPN has been initialized and configured as described in the top level `README.md`.
+
+Start the systemd service file:
+
+ systemctl start docker-openvpn
+
+Verify logs if needed:
+
+ systemctl status docker-openvpn
+ docker logs openvpn0
+
+### Step 4 — Modify Client Config for IPv6 Default Route
+
+Append the default route for the public Internet:
+
+ echo "route-ipv6 2000::/3" >> clientname.ovpn
+
+### Step 5 — Start up Client
+
+If all went according to plan, then `ping6 2600::` and `ping6 google.com` should work.
+
+Fire up a web browser and attempt to navigate to [https://ipv6.google.com](https://ipv6.google.com).
+
+
+## Connect to the OpenVPN Server Over IPv6
+
+Not implemented, yet.
diff --git a/init/docker-openvpn@.service b/init/docker-openvpn@.service
new file mode 100644
index 0000000..f855e94
--- /dev/null
+++ b/init/docker-openvpn@.service
@@ -0,0 +1,44 @@
+[Unit]
+Description=OpenVPN Docker Container
+Documentation=https://github.com/kylemanna/docker-openvpn
+After=network.target docker.socket
+Requires=docker.socket
+
+[Service]
+RestartSec=10
+Restart=always
+
+# Modify IP6_PREFIX to match network config
+#Environment="IP6_PREFIX=2001:db8::/64"
+#Environment="ARGS=--config openvpn.conf --server-ipv6 2001:db8::/64"
+Environment="NAME=ovpn-%i"
+Environment="DATA_VOL=ovpn-data-%i"
+Environment="IMG=kylemanna/openvpn:dev"
+Environment="PORT=1194:1194/udp"
+
+# To override environment variables, use local configuration directory:
+# /etc/systemd/system/docker-openvpn@foo.d/local.conf
+# http://www.freedesktop.org/software/systemd/man/systemd.unit.html
+
+# Clean-up bad state if still hanging around
+ExecStartPre=-/usr/bin/docker rm -f $NAME
+
+# Attempt to pull new image for security updates
+ExecStartPre=-/usr/bin/docker pull $IMG
+
+# IPv6: Ensure forwarding is enabled on host's networking stack (hacky)
+# Would be nice to use systemd-network on the host, but this doens't work
+# http://lists.freedesktop.org/archives/systemd-devel/2015-June/032762.html
+ExecStartPre=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; sysctl net.ipv6.conf.all.forwarding=1'
+
+# Main process
+ExecStart=/usr/bin/docker run --rm --privileged --volumes-from ${DATA_VOL}:ro --name ${NAME} -p ${PORT} ${IMG} ovpn_run $ARGS
+
+# IPv6: Add static route for IPv6 after it starts up
+ExecStartPost=/bin/sh -c 'test -z "${IP6_PREFIX}" && exit 0; sleep 1; ip route replace ${IP6_PREFIX} via $(docker inspect -f "{{ .NetworkSettings.GlobalIPv6Address }}" $NAME ) dev docker0'
+
+# IPv6: Clean-up
+ExecStopPost=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; ip route del $IP6_PREFIX dev docker0'
+
+[Install]
+WantedBy=multi-user.target
diff --git a/upstart.init b/init/upstart.init
similarity index 100%
rename from upstart.init
rename to init/upstart.init