diff --git a/.assets/cluster-mysql.dot b/.assets/cluster-mysql.dot
new file mode 100644
index 0000000..048638a
--- /dev/null
+++ b/.assets/cluster-mysql.dot
@@ -0,0 +1,30 @@
+graph {
+ rankdir=LR;
+ subgraph cluster_sshportal {
+ label="sshportal cluster";
+ edge[style=dashed,color=grey,constraint=false];
+ sshportal1; sshportal2; sshportal3; sshportalN;
+ sshportal1 -- MySQL;
+ sshportal2 -- MySQL;
+ sshportal3 -- MySQL;
+ sshportalN -- MySQL;
+ }
+
+ subgraph cluster_hosts {
+ label="hosts";
+ host1; host2; host3; hostN;
+ }
+
+ subgraph cluster_users {
+ label="users";
+ user1; user2; user3; userN;
+ }
+
+ {
+ user1 -- sshportal1 -- host1[color=red,penwidth=3.0];
+ user2 -- sshportal2 -- host2[color=green,penwidth=3.0];
+ user3 -- sshportal3 -- host3[color=blue,penwidth=3.0];
+ user3 -- sshportal2 -- host1[color=purple,penwidth=3.0];
+ userN -- sshportalN -- hostN[style=dotted];
+ }
+}
\ No newline at end of file
diff --git a/.assets/cluster-mysql.svg b/.assets/cluster-mysql.svg
new file mode 100644
index 0000000..9629efb
--- /dev/null
+++ b/.assets/cluster-mysql.svg
@@ -0,0 +1,176 @@
+
+
+
+
+
diff --git a/.assets/overview.dot b/.assets/overview.dot
new file mode 100644
index 0000000..53444c8
--- /dev/null
+++ b/.assets/overview.dot
@@ -0,0 +1,16 @@
+graph {
+ rankdir=LR;
+ node[shape=box,style=rounded,style=rounded,fillcolor=gray];
+
+ db[color=gray];
+
+ user1 -- sshportal -- host1[color=red,penwidth=3.0];
+ user2 -- sshportal -- host2[color=blue,penwidth=3.0];
+ user3 -- sshportal -- host1[color=purple,penwidth=3.0];
+ user2 -- sshportal -- host3[color=green,penwidth=3.0];
+ userN -- sshportal[style=dotted];
+ sshportal -- hostN[style=dotted];
+ sshportal -- db[style=dotted,color=grey];
+
+ { rank=same; sshportal; db; }
+}
\ No newline at end of file
diff --git a/.assets/overview.svg b/.assets/overview.svg
new file mode 100644
index 0000000..ff9c7b1
--- /dev/null
+++ b/.assets/overview.svg
@@ -0,0 +1,128 @@
+
+
+
+
+
diff --git a/Makefile b/Makefile
index c79fb08..df9c077 100644
--- a/Makefile
+++ b/Makefile
@@ -40,3 +40,7 @@ lint:
backup:
mkdir -p data/backups
cp sshportal.db data/backups/$(shell date +%s)-$(VERSION)-sshportal.sqlite
+
+doc:
+ dot -Tsvg ./.assets/overview.dot > ./.assets/overview.svg
+ dot -Tsvg ./.assets/cluster-mysql.dot > ./.assets/cluster-mysql.svg
diff --git a/README.md b/README.md
index e900dc3..9ac1c77 100644
--- a/README.md
+++ b/README.md
@@ -12,30 +12,16 @@ Jump host/Jump server without the jump, a.k.a Transparent SSH bastion
---
-```
- ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
- DMZ │
-┌────────┐ │ ┌────────┐
-│ homer │───▶╔═════════════════╗───▶│ host1 │ │
-└────────┘ ║ ║ └────────┘
-┌────────┐ ║ ║ ┌────────┐ │
-│ bart │───▶║ sshportal ║───▶│ host2 │
-└────────┘ ║ ║ └────────┘ │
-┌────────┐ ║ ║ ┌────────┐
-│ lisa │───▶╚═════════════════╝───▶│ host3 │ │
-└────────┘ │ └────────┘
-┌────────┐ ┌────────┐ │
-│ ... │ │ │ ... │
-└────────┘ └────────┘ │
- └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
-```
+## Overview
+
+![sshportal overview](https://raw.github.com/moul/sshportal/master/.assets/overview.svg?sanitize=true)
## Features
* Single autonomous binary (~10-20Mb) with no runtime dependencies (embeds ssh server and client)
* Portable / Cross-platform
-* Store data in Sqlite3 or MySQL (probably easy to add postgres, mssql thanks to gorm)
-* Stateless -> horizontally scalable when using MySQL as the backend
+* Store data in [Sqlite3](https://www.sqlite.org/) or [MySQL](https://www.mysql.com) (probably easy to add postgres, mssql thanks to gorm)
+* Stateless -> horizontally scalable when using [MySQL](https://www.mysql.com) as the backend
* Connect to remote host using key or password
* Admin commands can be run directly or in an interactive shell
* Host management
@@ -345,6 +331,18 @@ $
the `healtcheck` user can be changed using the `healthcheck-user` option.
+## Scaling
+
+`sshportal` is stateless but relies on a database to store configuration and logs.
+
+By default, `sshportal` uses a local [sqlite](https://www.sqlite.org/) database which isn't scalable by design.
+
+You can run multiple instances of `sshportal` sharing a same [MySQL](https://www.mysql.com) database, using `sshportal --db-conn=user:pass@host/dbname?parseTime=true --db-driver=mysql`.
+
+![sshportal cluster with MySQL backend](https://raw.github.com/moul/sshportal/master/.assets/cluster-mysql.svg?sanitize=true)
+
+See [examples/mysql](http://github.com/moul/sshportal/tree/master/examples/mysql).
+
## Under the hood
* Docker first (used in dev, tests, by the CI and in production)
@@ -362,7 +360,7 @@ the `healtcheck` user can be changed using the `healthcheck-user` option.
* https://github.com/mgutz/ansi: Terminal color helpers
* https://github.com/urfave/cli: CLI flag parsing with subcommands support
-[SQL schema](https://github.com/moul/sshportal/blob/master/.assets/sql-schema.svg)
+![sshportal data model](https://raw.github.com/moul/sshportal/master/.assets/sql-schema.svg?sanitize=true)
## Note