diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..cda6982f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,107 @@
+# Contributing
+
+Thank you for your interest in contributing to sshpiper.
+Make sure you have read [README.md](README.md) before starting.
+
+## Getting Started
+
+### Software Requirements
+ * Go
+ * Docker
+ * Docker Compose
+ * Git
+
+### Get the code
+
+rememeber to clone the submodules
+
+```
+git clone https://github.com/tg123/sshpiper
+cd sshpiper
+git submodule update --init --recursive
+```
+
+### Start Develop Environment
+
+```
+# in e2e folder, run:
+SSHPIPERD_DEBUG=1 docker-compose up --force-recreate
+```
+
+you will have two sshd:
+
+ * `host-password`: a password only sshd server (user: `user`, password: `pass`)
+ * `host-publickey`: a public key only sshd server (put your public key in `/sshconfig_publickey/.config/authorized_keys`)
+
+more settings:
+
+### Make some direct changes to source code
+
+after you have done, in e2e folder run:
+
+```
+go test
+```
+
+### Send PR with Github
+
+
+
+## Understanding how sshpiper works
+
+### sshpiper seasoned cryto ssh lib
+
+The `crypto` folder contains the source code of the [sshpiper seasoned cryto ssh lib](./crypto/).
+It based on [crypto/ssh](https://golang.org/pkg/crypto/ssh/) and with a drop-in [sshpiper.go](./crypto/ssh/sshpiper.go) to expose all low level sshpiper required APIs.
+
+### sshpiperd
+
+[sshpiperd](./cmd/sshpiperd/) is the daemon wraps the `crypto/ssh` library to provide ssh connections management.
+It accepts ssh connections from `downstream` and routes them to `upstream`.
+The plugins are responsible to figure out how to authenticate `downstream` and map it to `upstream`
+
+### plugin
+
+The plugin is typically a grpc server that accepts requrests from `sshpiperd`.
+The proto defines in [sshpiper.proto](./proto/sshpiper.proto).
+
+In most of the cases, the plugin connects with `sshpiperd` via `stdin/stdout`. The [ioconnn](./libplugin/ioconn/) wraps stdin/stdout to net.Conn for grpc use.
+`sshpiperd` also supports to create remote grpc connections to a plugin deploy in a different machine.
+
+## Your first plugin
+
+[fixed](./plugin/fixed/) and [simplematch](./plugin/simplematch/) are two good examples of plugins.
+They are very simple and just less than 50 lines of code.
+
+Take `fixed` as an example:
+
+```
+&libplugin.SshPiperPluginConfig{
+ PasswordCallback: func(conn libplugin.ConnMetadata, password []byte) (*libplugin.Upstream, error) {
+ return &libplugin.Upstream{
+ Host: host,
+ Port: int32(port),
+ IgnoreHostKey: true,
+ Auth: libplugin.CreatePasswordAuth(password),
+ }, nil
+ },
+}
+```
+
+Here means the `downstream` is sending password to `sshpiperd`. Then `sshpiperd` will call plugin's `PasswordCallback` to get the `upstream` to connect to.
+The `upstream` object contains host port and auth info about how to connect to the `upstream`. you can aslo return an error to deny the connection.
+
+### build and run the plugin
+
+simple build it with:
+
+```
+go build
+```
+
+you will get the executable in the current directory. say `myplugin`. start it with:
+
+```
+sshpiperd /path/to/myplugin
+```
+
diff --git a/README.md b/README.md
index d648d66c..4c37728b 100644
--- a/README.md
+++ b/README.md
@@ -154,5 +154,10 @@ How this work
For plugins already in `v1`, you need change params to new params. However, not all plugins are migrated to `v1` yet, they are being migrated gradually. you can still use the old plugins in [`v0` branch](https://github.com/tg123/sshpiper/tree/v0)
+
+## Contributing
+
+see [CONTRIBUTING.md](CONTRIBUTING.md)
+
## License
MIT
\ No newline at end of file
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index 0119e4b4..b0474910 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -23,6 +23,7 @@ services:
environment:
- SSHPIPERD_LOG_LEVEL=trace
- SSHPIPERD_E2E_TEST=1
+ - SSHPIPERD_DEBUG=${SSHPIPERD_DEBUG}
build:
context: ../
target: builder
diff --git a/e2e/e2eentry.sh b/e2e/e2eentry.sh
index f1268d9f..f8cbc321 100755
--- a/e2e/e2eentry.sh
+++ b/e2e/e2eentry.sh
@@ -3,7 +3,9 @@
# use entrypoint.sh to generate the ssh_host_rsa_key
PLUGIN="dummy_badname/" bash /sshpiperd/entrypoint.sh 2>/dev/null
-if [ "${SSHPIPERD_DEBUG}" == "1" ]; then
+if [ "${SSHPIPERD_DEBUG}" == "1" ]; then
+ echo "enter debug on hold mode"
+ echo "run [docker exec -ti e2e_testrunner_1 bash] to run to attach"
sleep infinity;
else
go test -v;