diff --git a/pom.xml b/pom.xml
index 04da8997d187781229bf68ec264b1754785aadb3..6c108fc7c1b60e7c049fbc6eaf8ef841b7765caa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,6 +79,34 @@
 				<directory>src/main/resources</directory>
 			</resource>
 		</resources>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.apache.maven.plugins</groupId>
+										<artifactId>maven-dependency-plugin</artifactId>
+										<versionRange>[0,)</versionRange>
+										<goals>
+											<goal>unpack-dependencies</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<ignore /> <!-- to avoid warning -->
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
 		<plugins>
 			<plugin>
 				<artifactId>maven-compiler-plugin</artifactId>
@@ -120,9 +148,54 @@
 							<directory>${project.build.directory}/${project.build.finalName}-compress</directory>
 						</resource>
 					</webResources>
-					<warSourceExcludes>WEB-INF/classes/**/*.*,WEB-INF/lib/*.jar</warSourceExcludes>
+					<archive>
+						<manifest>
+							<mainClass>org.docksidestage.HarborBoot</mainClass>
+						</manifest>
+					</archive>
 				</configuration>
 			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-dependency-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>unpack-provided</id>
+						<phase>generate-resources</phase>
+						<goals>
+							<goal>unpack-dependencies</goal>
+						</goals>
+						<configuration>
+							<includeScope>provided</includeScope>
+							<outputDirectory>${project.build.directory}/tomcat-lib</outputDirectory>
+							<includes>**/*</includes>
+							<overWriteReleases>true</overWriteReleases>
+							<overWriteSnapshots>true</overWriteSnapshots>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.5.5</version>
+				<configuration>
+					<finalName>${project.artifactId}-${project.version}</finalName>
+					<appendAssemblyId>false</appendAssemblyId>
+					<outputDirectory>${project.build.directory}/releases/</outputDirectory>
+					<descriptors>
+						<descriptor>${basedir}/src/main/assemblies/package.xml</descriptor>
+					</descriptors>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
 			<plugin>
 				<groupId>com.mycila.maven-license-plugin</groupId>
 				<artifactId>maven-license-plugin</artifactId>
@@ -433,6 +506,7 @@
 			<groupId>args4j</groupId>
 			<artifactId>args4j</artifactId>
 			<version>2.32</version>
+			<scope>provided</scope>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.tika</groupId>
diff --git a/src/main/assemblies/package.xml b/src/main/assemblies/package.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e50987a993019475409fe95844533992bed6126b
--- /dev/null
+++ b/src/main/assemblies/package.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<assembly
+	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+	<id>package</id>
+	<formats>
+		<format>zip</format>
+	</formats>
+	<includeBaseDirectory>false</includeBaseDirectory>
+	<dependencySets>
+		<dependencySet>
+			<outputDirectory>fess-${project.version}/app</outputDirectory>
+			<useProjectArtifact>true</useProjectArtifact>
+			<unpack>true</unpack>
+			<includes>
+				<include>org.codelibs.fess:fess</include>
+			</includes>
+		</dependencySet>
+	</dependencySets>
+	<fileSets>
+		<!-- lib -->
+		<fileSet>
+			<directory>${project.build.directory}/tomcat-lib</directory>
+			<outputDirectory>fess-${project.version}/lib</outputDirectory>
+		</fileSet>
+		<fileSet>
+			<directory>${project.build.directory}/fess/WEB-INF/classes/org/codelibs/fess/</directory>
+			<includes>
+				<include>FessBoot**</include>
+			</includes>
+			<outputDirectory>fess-${project.version}/lib/org/codelibs/fess</outputDirectory>
+		</fileSet>
+		<!-- app -->
+		<fileSet>
+			<directory>${project.basedir}/src/main/assemblies/scripts</directory>
+			<fileMode>0755</fileMode>
+			<lineEnding>lf</lineEnding>
+			<includes>
+				<include>fess</include>
+				<include>fess.in.sh</include>
+			</includes>
+			<outputDirectory>fess-${project.version}/bin</outputDirectory>
+		</fileSet>
+		<!-- logs -->
+		<fileSet>
+			<directory>src/main/assemblies/scripts</directory>
+			<outputDirectory>fess-${project.version}/logs</outputDirectory>
+			<excludes>
+				<exclude>*</exclude>
+			</excludes>
+			<filtered>false</filtered>
+		</fileSet>
+		<!-- temp -->
+		<fileSet>
+			<directory>src/main/assemblies/scripts</directory>
+			<outputDirectory>fess-${project.version}/temp</outputDirectory>
+			<excludes>
+				<exclude>*</exclude>
+			</excludes>
+			<filtered>false</filtered>
+		</fileSet>
+		<!-- es/plugins -->
+		<fileSet>
+			<directory>${project.basedir}/plugins</directory>
+			<outputDirectory>fess-${project.version}/es/plugins</outputDirectory>
+		</fileSet>
+		<!-- es/data -->
+		<fileSet>
+			<directory>src/main/assemblies/scripts</directory>
+			<outputDirectory>fess-${project.version}/es/data</outputDirectory>
+			<excludes>
+				<exclude>*</exclude>
+			</excludes>
+			<filtered>false</filtered>
+		</fileSet>
+	</fileSets>
+</assembly>
diff --git a/src/main/assemblies/scripts/fess b/src/main/assemblies/scripts/fess
new file mode 100644
index 0000000000000000000000000000000000000000..876a8f902c7b7e8a5f79a64263f24095924410bf
--- /dev/null
+++ b/src/main/assemblies/scripts/fess
@@ -0,0 +1,191 @@
+#!/bin/sh
+
+# OPTIONS:
+#    -d            daemonize (run in background)
+#    -p pidfile    write PID to <pidfile>
+#    -h
+#    --help        print command line options
+#    -v            print fess version, then exit
+#    -D prop       set JAVA system property
+#    -X prop       set non-standard JAVA system property
+#   --prop=val
+#   --prop val     set fess property (i.e.  -Des.<prop>=<val>)
+
+CDPATH=""
+SCRIPT="$0"
+
+# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.
+while [ -h "$SCRIPT" ] ; do
+  ls=`ls -ld "$SCRIPT"`
+  # Drop everything prior to ->
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    SCRIPT="$link"
+  else
+    SCRIPT=`dirname "$SCRIPT"`/"$link"
+  fi
+done
+
+# determine fess home
+FESS_HOME=`dirname "$SCRIPT"`/..
+
+# make ELASTICSEARCH_HOME absolute
+FESS_HOME=`cd "$FESS_HOME"; pwd`
+
+
+# If an include wasn't specified in the environment, then search for one...
+if [ "x$FESS_INCLUDE" = "x" ]; then
+    # Locations (in order) to use when searching for an include file.
+    for include in /usr/share/fess/fess.in.sh \
+                   /usr/local/share/fess/fess.in.sh \
+                   /opt/fess/bin/fess.in.sh \
+                   ~/.fess.in.sh \
+                   $FESS_HOME/bin/fess.in.sh \
+                   "`dirname "$0"`"/fess.in.sh; do
+        if [ -r "$include" ]; then
+            . "$include"
+            break
+        fi
+    done
+# ...otherwise, source the specified include.
+elif [ -r "$FESS_INCLUDE" ]; then
+    . "$FESS_INCLUDE"
+fi
+
+if [ -x "$JAVA_HOME/bin/java" ]; then
+    JAVA="$JAVA_HOME/bin/java"
+else
+    JAVA=`which java`
+fi
+
+if [ ! -x "$JAVA" ]; then
+    echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME"
+    exit 1
+fi
+
+if [ -z "$FESS_CLASSPATH" ]; then
+    echo "You must set the FESS_CLASSPATH var" >&2
+    exit 1
+fi
+
+# Special-case path variables.
+case `uname` in
+    CYGWIN*)
+        FESS_CLASSPATH=`cygpath -p -w "$FESS_CLASSPATH"`
+        FESS_HOME=`cygpath -p -w "$FESS_HOME"`
+    ;;
+esac
+
+launch_service()
+{
+    pidpath=$1
+    daemonized=$2
+    props=$3
+    fess_parms="-Dfess"
+
+    if [ "x$pidpath" != "x" ]; then
+        fess_parms="$fess_parms -Dfess.pidfile=$pidpath"
+    fi
+
+    # Make sure we dont use any predefined locale, as we check some exception message strings and rely on english language
+    # As those strings are created by the OS, they are dependant on the configured locale
+    LANG=en_US.UTF-8
+    LC_ALL=en_US.UTF-8
+
+    export HOSTNAME=`hostname -s`
+
+    if [ "x$daemonized" = "x" ]; then
+        fess_parms="$fess_parms -Dfess.foreground=yes"
+        exec "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \
+                org.codelibs.fess.FessBoot $FESS_OPTS
+    else
+        exec "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \
+                org.codelibs.fess.FessBoot $FESS_OPTS <&- &
+        return $?
+    fi
+}
+
+# Print command line usage / help
+usage() {
+    echo "Usage: $0 [-vdh] [-p pidfile] [-D prop] [-X prop]"
+    echo "Start fess."
+    echo "    -d            daemonize (run in background)"
+    echo "    -p pidfile    write PID to <pidfile>"
+    echo "    -h"
+    echo "    --help        print command line options"
+    echo "    -v            print fess version, then exit"
+    echo "    -D prop       set JAVA system property"
+    echo "    -X prop       set non-standard JAVA system property"
+    echo "   --prop=val"
+    echo "   --prop val     set fess property (i.e. -Des.<prop>=<val>)"
+}
+
+# Parse any long getopt options and put them into properties before calling getopt below
+# Be dash compatible to make sure running under ubuntu works
+ARGV=""
+while [ $# -gt 0 ]
+do
+    case $1 in
+      --help) ARGV="$ARGV -h"; shift;;
+      --*=*) properties="$properties -Dfess.${1#--}"
+           shift 1
+           ;;
+      --*) [ $# -le 1 ] && {
+                echo "Option requires an argument: '$1'."
+                shift
+                continue
+            }
+           properties="$properties -Dfess.${1#--}=$2"
+           shift 2
+           ;;
+      *) ARGV="$ARGV $1" ; shift
+    esac
+done
+
+# Parse any command line options.
+args=`getopt vdhp:D:X: $ARGV`
+eval set -- "$args"
+
+while true; do
+    case $1 in
+        -v)
+            "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -cp "$FESS_CLASSPATH" $props \
+                    org.codelibs.fess.Version
+            exit 0
+        ;;
+        -p)
+            pidfile="$2"
+            shift 2
+        ;;
+        -d)
+            daemonized="yes"
+            shift
+        ;;
+        -h)
+            usage
+            exit 0
+        ;;
+        -D)
+            properties="$properties -D$2"
+            shift 2
+        ;;
+        -X)
+            properties="$properties -X$2"
+            shift 2
+        ;;
+        --)
+            shift
+            break
+        ;;
+        *)
+            echo "Error parsing argument $1!" >&2
+            usage
+            exit 1
+        ;;
+    esac
+done
+
+# Start up the service
+launch_service "$pidfile" "$daemonized" "$properties"
+
+exit $?
diff --git a/src/main/assemblies/scripts/fess.in.sh b/src/main/assemblies/scripts/fess.in.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b0babd4a37e120e70c218c50a8a840fc3a543ab2
--- /dev/null
+++ b/src/main/assemblies/scripts/fess.in.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+FESS_CLASSPATH=$FESS_HOME/lib
+
+if [ "x$FESS_MIN_MEM" = "x" ]; then
+    FESS_MIN_MEM=256m
+fi
+if [ "x$FESS_MAX_MEM" = "x" ]; then
+    FESS_MAX_MEM=2g
+fi
+if [ "x$FESS_HEAP_SIZE" != "x" ]; then
+    FESS_MIN_MEM=$FESS_HEAP_SIZE
+    FESS_MAX_MEM=$FESS_HEAP_SIZE
+fi
+
+# min and max heap sizes should be set to the same value to avoid
+# stop-the-world GC pauses during resize, and so that we can lock the
+# heap in memory on startup to prevent any of it from being swapped
+# out.
+JAVA_OPTS="$JAVA_OPTS -Xms${FESS_MIN_MEM}"
+JAVA_OPTS="$JAVA_OPTS -Xmx${FESS_MAX_MEM}"
+
+# new generation
+if [ "x$FESS_HEAP_NEWSIZE" != "x" ]; then
+    JAVA_OPTS="$JAVA_OPTS -Xmn${FESS_HEAP_NEWSIZE}"
+fi
+
+# max direct memory
+if [ "x$FESS_DIRECT_SIZE" != "x" ]; then
+    JAVA_OPTS="$JAVA_OPTS -XX:MaxDirectMemorySize=${FESS_DIRECT_SIZE}"
+fi
+
+# set to headless, just in case
+JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"
+
+# Force the JVM to use IPv4 stack
+if [ "x$FESS_USE_IPV4" != "x" ]; then
+  JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
+fi
+
+JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC"
+JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC"
+
+JAVA_OPTS="$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=75"
+JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly"
+
+# GC logging options
+if [ "x$FESS_USE_GC_LOGGING" != "x" ]; then
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails"
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCTimeStamps"
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps"
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintClassHistogram"
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintTenuringDistribution"
+  JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCApplicationStoppedTime"
+  JAVA_OPTS="$JAVA_OPTS -Xloggc:/var/log/elasticsearch/gc.log"
+fi
+
+# Causes the JVM to dump its heap on OutOfMemory.
+JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
+# The path to the heap dump location, note directory must exists and have enough
+# space for a full heap dump.
+#JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=$FESS_HOME/logs/heapdump.hprof"
+
+# Disables explicit GC
+JAVA_OPTS="$JAVA_OPTS -XX:+DisableExplicitGC"
+
+# Ensure UTF-8 encoding by default (e.g. filenames)
+JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"
+
+ES_HOME=$FESS_HOME/es
+FESS_OPTS="$FESS_OPTS --context-path /fess"
+FESS_OPTS="$FESS_OPTS --port 8080"
+FESS_OPTS="$FESS_OPTS --webapp-path $FESS_HOME/app"
+FESS_OPTS="$FESS_OPTS --webxml-path $FESS_HOME/app/WEB-INF/web.xml"
+FESS_OPTS="$FESS_OPTS --temp-path $FESS_HOME/temp"
+
diff --git a/src/main/java/org/codelibs/fess/FessBoot.java b/src/main/java/org/codelibs/fess/FessBoot.java
index 3346a0af597cef365fa595412a58b14d560d396e..60a6e2b050108b42c656f596b0e29e1b77444b75 100644
--- a/src/main/java/org/codelibs/fess/FessBoot.java
+++ b/src/main/java/org/codelibs/fess/FessBoot.java
@@ -1,16 +1,86 @@
 package org.codelibs.fess;
 
+import java.io.File;
+
 import org.dbflute.tomcat.TomcatBoot;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+public class FessBoot extends TomcatBoot {
+
+    private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
+
+    protected Options options;
+
+    public FessBoot(Options options) {
+        super(options.port, options.contextPath);
+        this.options = options;
+    }
+
+    @Override
+    protected String prepareWebappPath() {
+        if (options.webappPath != null) {
+            return options.webappPath;
+        }
+        return super.prepareWebappPath();
+    }
+
+    @Override
+    protected String prepareWebXmlPath() {
+        if (options.webXmlPath != null) {
+            return options.webXmlPath;
+        }
+        return super.prepareWebXmlPath();
+    }
 
-public class FessBoot {
+    protected String getMarkDir() {
+        if (options.tempPath != null) {
+            System.setProperty(JAVA_IO_TMPDIR, options.tempPath);
+            return new File(options.tempPath, "fessboot").getAbsolutePath();
+        }
+        return new File(System.getProperty(JAVA_IO_TMPDIR), "fessboot").getAbsolutePath();
+    }
+
+    // ===================================================================================
+    //                                                                        main
+    //                                                                        ============
 
     public static void main(String[] args) {
-        // TODO args
-        new TomcatBoot(8080, "/fess").useTldDetect().asDevelopment(isNoneEnv()).bootAwait();
+        final Options options = new Options();
+
+        final CmdLineParser parser = new CmdLineParser(options);
+        try {
+            parser.parseArgument(args);
+        } catch (final CmdLineException e) {
+            System.err.println(e.getMessage());
+            System.err.println("java " + FessBoot.class.getCanonicalName() + " [options...] arguments...");
+            parser.printUsage(System.err);
+            return;
+        }
+
+        new FessBoot(options).useTldDetect().asDevelopment(isNoneEnv()).bootAwait();
     }
 
     private static boolean isNoneEnv() {
         return System.getProperty("lasta.env") == null;
     }
 
+    protected static class Options {
+
+        @Option(name = "--port", metaVar = "port", usage = "Listen port")
+        protected int port = 8080;
+
+        @Option(name = "--context-path", metaVar = "contextPath", usage = "Context path")
+        protected String contextPath = "/fess";
+
+        @Option(name = "--webapp-path", metaVar = "webappPath", usage = "Webapp path")
+        protected String webappPath = null;
+
+        @Option(name = "--webxml-path", metaVar = "webXmlPath", usage = "web.xml path")
+        protected String webXmlPath = null;
+
+        @Option(name = "--temp-path", metaVar = "tempPath", usage = "Temporary path")
+        protected String tempPath = null;
+    }
 }
diff --git a/src/main/java/org/codelibs/fess/client/FessEsClient.java b/src/main/java/org/codelibs/fess/client/FessEsClient.java
index 9389a4ef0bea4743ca9d3f0d46daf9fb264c492f..77ca352e0bedbbe749ca69ca5d21ad0569b98eb7 100644
--- a/src/main/java/org/codelibs/fess/client/FessEsClient.java
+++ b/src/main/java/org/codelibs/fess/client/FessEsClient.java
@@ -2,6 +2,7 @@ package org.codelibs.fess.client;
 
 import static org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.newConfigs;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -241,10 +242,15 @@ public class FessEsClient implements Client {
                     config.basePath(esDir);
                 }
                 runner.onBuild((number, settingsBuilder) -> {
+                    File pluginDir = new File(esDir, "plugins");
+                    if (pluginDir.isDirectory()) {
+                        settingsBuilder.put("path.plugins", pluginDir.getAbsolutePath());
+                    } else {
+                        settingsBuilder.put("path.plugins", new File(System.getProperty("user.dir"), "plugins").getAbsolutePath());
+                    }
                     if (settings != null) {
                         settingsBuilder.put(settings);
                     }
-                    settingsBuilder.put("path.plugins", System.getProperty("user.dir") + "/plugins");
                 });
                 runner.build(config);
             }