├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── package-lock.json ├── package.json ├── screenshots └── ttyjs.png └── src ├── startup.sh └── tty-me.js /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vim swp files 2 | .vimrc 3 | *.swp 4 | 5 | # OSX os files 6 | .DS_Store 7 | .DS_Store? 8 | 9 | # SASS 10 | .sass-cache 11 | *.css.map 12 | 13 | node_modules 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | MAINTAINER Doro Wu 3 | 4 | EXPOSE 3000 5 | 6 | ENV DEBIAN_FRONTEND=noninteractive \ 7 | USER=ubuntu \ 8 | PASS=ubuntu 9 | 10 | # no Upstart or DBus 11 | # https://github.com/dotcloud/docker/issues/1724#issuecomment-26294856 12 | RUN apt-get update && apt-mark hold initscripts udev plymouth mountall && \ 13 | dpkg-divert --local --rename --add /sbin/initctl && ln -fs /bin/true /sbin/initctl && \ 14 | apt-get install -yqq --no-install-recommends \ 15 | openssh-server \ 16 | pwgen \ 17 | sudo \ 18 | vim-tiny \ 19 | ca-certificates \ 20 | curl 21 | 22 | RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - && \ 23 | apt-get install nodejs 24 | 25 | COPY ./package* /src/ 26 | 27 | WORKDIR /src 28 | 29 | # Install build-time requirements, where compilation is needed 30 | RUN apt-get install -yqq \ 31 | build-essential \ 32 | python \ 33 | && \ 34 | npm i && \ 35 | # Perform extensive cleanup 36 | apt-get remove -y \ 37 | build-essential \ 38 | python \ 39 | && \ 40 | apt-get autoclean -y && \ 41 | apt-get autoremove -y && \ 42 | rm -rf /var/lib/{cache,log}/ && \ 43 | rm -rf /var/lib/apt/lists/*.lz4 && \ 44 | rm -rf /tmp/* /var/tmp/* && \ 45 | rm -rf /usr/share/doc/ && \ 46 | rm -rf /usr/share/man/ 47 | 48 | COPY ./src/* /src/ 49 | 50 | CMD ["/src/startup.sh"] 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | docker-ubuntu-ssh 2 | ========================= 3 | 4 | From Docker Index 5 | 6 | ``` 7 | docker pull dorowu/ubuntu-ssh-ttyjs 8 | ``` 9 | 10 | Build yourself 11 | ``` 12 | git clone https://github.com/fcwu/docker-ubuntu-ssh.git 13 | docker build --rm -t doro/ubuntu-ssh docker-ubuntu-ssh 14 | docker run -i -t --entrypoint=/bin/bash -p 3000:3000 doro/ubuntu-ssh 15 | ``` 16 | 17 | ### Usage 18 | 19 | Use environment variables to overwrite defaults 20 | 21 | Variable | Default | Description 22 | --- | --- | --- 23 | USER | ubuntu | username allowed to login 24 | PASS | ubuntu | password for login 25 | 26 | 27 | Browse http://127.0.0.1:3000/vnc.html 28 | 29 | 30 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docker-ubuntu-ssh", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "active-x-obfuscator": { 8 | "version": "0.0.1", 9 | "resolved": "https://registry.npmjs.org/active-x-obfuscator/-/active-x-obfuscator-0.0.1.tgz", 10 | "integrity": "sha1-CJuJs3FF/x2ex0r2UwvlUmyuHxo=", 11 | "requires": { 12 | "zeparser": "0.0.5" 13 | } 14 | }, 15 | "base64id": { 16 | "version": "0.1.0", 17 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz", 18 | "integrity": "sha1-As4P3u4M709ACA4ec+g08LG/zj8=" 19 | }, 20 | "buffer-crc32": { 21 | "version": "0.2.1", 22 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", 23 | "integrity": "sha1-vj5TgvwCttYySVasGvmKqYsIU0w=" 24 | }, 25 | "bytes": { 26 | "version": "0.2.1", 27 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-0.2.1.tgz", 28 | "integrity": "sha1-VVsIq8sGP4l1kFMCUj5M1P/f3zE=" 29 | }, 30 | "commander": { 31 | "version": "1.3.2", 32 | "resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz", 33 | "integrity": "sha1-io8w7GcKb91kr1LxkUuQfXnq1bU=", 34 | "requires": { 35 | "keypress": "0.1.0" 36 | } 37 | }, 38 | "connect": { 39 | "version": "2.11.0", 40 | "resolved": "https://registry.npmjs.org/connect/-/connect-2.11.0.tgz", 41 | "integrity": "sha1-mZHOCf+bhdnq0n+dQdCyot8vkoQ=", 42 | "requires": { 43 | "buffer-crc32": "0.2.1", 44 | "bytes": "0.2.1", 45 | "cookie": "0.1.0", 46 | "cookie-signature": "1.0.1", 47 | "debug": "3.0.0", 48 | "fresh": "0.2.0", 49 | "methods": "0.0.1", 50 | "multiparty": "2.2.0", 51 | "negotiator": "0.3.0", 52 | "pause": "0.0.1", 53 | "qs": "0.6.5", 54 | "raw-body": "0.0.3", 55 | "send": "0.1.4", 56 | "uid2": "0.0.3" 57 | }, 58 | "dependencies": { 59 | "methods": { 60 | "version": "0.0.1", 61 | "resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz", 62 | "integrity": "sha1-J3yQ+L7zlwlkWoNxxRw7bGSOBow=" 63 | } 64 | } 65 | }, 66 | "cookie": { 67 | "version": "0.1.0", 68 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz", 69 | "integrity": "sha1-kOtGndzpBchm3mh+/EMTHYgB+dA=" 70 | }, 71 | "cookie-signature": { 72 | "version": "1.0.1", 73 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz", 74 | "integrity": "sha1-ROByFIrwHm6OJK+/EmkNaK5pjss=" 75 | }, 76 | "core-util-is": { 77 | "version": "1.0.2", 78 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 79 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 80 | }, 81 | "debug": { 82 | "version": "3.0.0", 83 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.0.0.tgz", 84 | "integrity": "sha512-XQkHxxqbsCb+zFurCHbotmJZl5jXsxvkRt952pT6Hpo7LmjWAJF12d9/kqBg5owjbLADbBDli1olravjSiSg8g==", 85 | "requires": { 86 | "ms": "2.0.0" 87 | } 88 | }, 89 | "express": { 90 | "version": "3.4.4", 91 | "resolved": "https://registry.npmjs.org/express/-/express-3.4.4.tgz", 92 | "integrity": "sha1-C2OuYmyWtxt40T384HnBA1FjWoY=", 93 | "requires": { 94 | "buffer-crc32": "0.2.1", 95 | "commander": "1.3.2", 96 | "connect": "2.11.0", 97 | "cookie": "0.1.0", 98 | "cookie-signature": "1.0.1", 99 | "debug": "3.0.0", 100 | "fresh": "0.2.0", 101 | "methods": "0.1.0", 102 | "mkdirp": "0.3.5", 103 | "range-parser": "0.0.4", 104 | "send": "0.1.4" 105 | } 106 | }, 107 | "extend": { 108 | "version": "1.2.1", 109 | "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", 110 | "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=" 111 | }, 112 | "fresh": { 113 | "version": "0.2.0", 114 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz", 115 | "integrity": "sha1-v9lALPPfEsSkwxDHn5mj3eE9NKc=" 116 | }, 117 | "inherits": { 118 | "version": "2.0.3", 119 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 120 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 121 | }, 122 | "isarray": { 123 | "version": "0.0.1", 124 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 125 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 126 | }, 127 | "keypress": { 128 | "version": "0.1.0", 129 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", 130 | "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=" 131 | }, 132 | "methods": { 133 | "version": "0.1.0", 134 | "resolved": "https://registry.npmjs.org/methods/-/methods-0.1.0.tgz", 135 | "integrity": "sha1-M11Cnu/SG3us8unJIqjSvRSjDk8=" 136 | }, 137 | "mime": { 138 | "version": "1.2.11", 139 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", 140 | "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" 141 | }, 142 | "mkdirp": { 143 | "version": "0.3.5", 144 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", 145 | "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" 146 | }, 147 | "ms": { 148 | "version": "2.0.0", 149 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 150 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 151 | }, 152 | "multiparty": { 153 | "version": "2.2.0", 154 | "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-2.2.0.tgz", 155 | "integrity": "sha1-pWfCrwAK0i3I8qZT2Rl4rh9TFvQ=", 156 | "requires": { 157 | "readable-stream": "1.1.14", 158 | "stream-counter": "0.2.0" 159 | } 160 | }, 161 | "nan": { 162 | "version": "2.3.5", 163 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz", 164 | "integrity": "sha1-gioNwmYpDOTNOhIoLKPn42Rmigg=" 165 | }, 166 | "negotiator": { 167 | "version": "0.3.0", 168 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.3.0.tgz", 169 | "integrity": "sha1-cG1pLv7d9XTVfqn7GriaT6fuj2A=" 170 | }, 171 | "options": { 172 | "version": "0.0.6", 173 | "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", 174 | "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" 175 | }, 176 | "pause": { 177 | "version": "0.0.1", 178 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 179 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 180 | }, 181 | "policyfile": { 182 | "version": "0.0.4", 183 | "resolved": "https://registry.npmjs.org/policyfile/-/policyfile-0.0.4.tgz", 184 | "integrity": "sha1-1rgurZiueeviKOLa9ZAzEeyYLk0=" 185 | }, 186 | "pty.js": { 187 | "version": "0.3.1", 188 | "resolved": "https://registry.npmjs.org/pty.js/-/pty.js-0.3.1.tgz", 189 | "integrity": "sha1-gfW+0zLW5eeraFaI0boDc0ENUbU=", 190 | "requires": { 191 | "extend": "1.2.1", 192 | "nan": "2.3.5" 193 | } 194 | }, 195 | "qs": { 196 | "version": "0.6.5", 197 | "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz", 198 | "integrity": "sha1-KUsmjksNQlD23eGbO4s0k13/FO8=" 199 | }, 200 | "range-parser": { 201 | "version": "0.0.4", 202 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz", 203 | "integrity": "sha1-wEJ//vUcEKy6B4KkbJYC50T/Ygs=" 204 | }, 205 | "raw-body": { 206 | "version": "0.0.3", 207 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-0.0.3.tgz", 208 | "integrity": "sha1-DLPrIs7RymB9Mt2P2Upus4Pz64o=" 209 | }, 210 | "readable-stream": { 211 | "version": "1.1.14", 212 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 213 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 214 | "requires": { 215 | "core-util-is": "1.0.2", 216 | "inherits": "2.0.3", 217 | "isarray": "0.0.1", 218 | "string_decoder": "0.10.31" 219 | } 220 | }, 221 | "redis": { 222 | "version": "0.7.3", 223 | "resolved": "https://registry.npmjs.org/redis/-/redis-0.7.3.tgz", 224 | "integrity": "sha1-7le3pE0l7BWU5ENl2BZfp9HUgRo=", 225 | "optional": true 226 | }, 227 | "send": { 228 | "version": "0.1.4", 229 | "resolved": "https://registry.npmjs.org/send/-/send-0.1.4.tgz", 230 | "integrity": "sha1-vnDY0b4B3mGCGvE3gLUDRaT3Gr0=", 231 | "requires": { 232 | "debug": "3.0.0", 233 | "fresh": "0.2.0", 234 | "mime": "1.2.11", 235 | "range-parser": "0.0.4" 236 | } 237 | }, 238 | "socket.io": { 239 | "version": "0.9.16", 240 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-0.9.16.tgz", 241 | "integrity": "sha1-O6sEROSbVfu8FXQk29Qao3WlGnY=", 242 | "requires": { 243 | "base64id": "0.1.0", 244 | "policyfile": "0.0.4", 245 | "redis": "0.7.3", 246 | "socket.io-client": "0.9.16" 247 | } 248 | }, 249 | "socket.io-client": { 250 | "version": "0.9.16", 251 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-0.9.16.tgz", 252 | "integrity": "sha1-TadRXF53MEHRtCOXBBW8xDDzX8Y=", 253 | "requires": { 254 | "active-x-obfuscator": "0.0.1", 255 | "uglify-js": "1.2.5", 256 | "ws": "0.4.32", 257 | "xmlhttprequest": "1.4.2" 258 | } 259 | }, 260 | "stream-counter": { 261 | "version": "0.2.0", 262 | "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", 263 | "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", 264 | "requires": { 265 | "readable-stream": "1.1.14" 266 | } 267 | }, 268 | "string_decoder": { 269 | "version": "0.10.31", 270 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 271 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 272 | }, 273 | "term.js": { 274 | "version": "0.0.7", 275 | "resolved": "https://registry.npmjs.org/term.js/-/term.js-0.0.7.tgz", 276 | "integrity": "sha1-Um8kz8Dy72+A9RfJ4n2ulHvIcxU=" 277 | }, 278 | "tinycolor": { 279 | "version": "0.0.1", 280 | "resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz", 281 | "integrity": "sha1-MgtaUtg6u1l42Bo+iH1K77FaYWQ=" 282 | }, 283 | "tty.js": { 284 | "version": "0.2.15", 285 | "resolved": "https://registry.npmjs.org/tty.js/-/tty.js-0.2.15.tgz", 286 | "integrity": "sha1-iCM+qnPRhTqLyU6K94e3zcdUj6c=", 287 | "requires": { 288 | "express": "3.4.4", 289 | "pty.js": "0.3.1", 290 | "socket.io": "0.9.16", 291 | "term.js": "0.0.7" 292 | } 293 | }, 294 | "uglify-js": { 295 | "version": "1.2.5", 296 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.2.5.tgz", 297 | "integrity": "sha1-tULCx29477NLIAsgF3Y0Mw/3ArY=" 298 | }, 299 | "uid2": { 300 | "version": "0.0.3", 301 | "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", 302 | "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" 303 | }, 304 | "ws": { 305 | "version": "0.4.32", 306 | "resolved": "https://registry.npmjs.org/ws/-/ws-0.4.32.tgz", 307 | "integrity": "sha1-eHphVEFPPJntg8V3IVOyD+sM7DI=", 308 | "requires": { 309 | "commander": "2.1.0", 310 | "nan": "1.0.0", 311 | "options": "0.0.6", 312 | "tinycolor": "0.0.1" 313 | }, 314 | "dependencies": { 315 | "commander": { 316 | "version": "2.1.0", 317 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", 318 | "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=" 319 | }, 320 | "nan": { 321 | "version": "1.0.0", 322 | "resolved": "https://registry.npmjs.org/nan/-/nan-1.0.0.tgz", 323 | "integrity": "sha1-riT4hQgY1mL8q1rPfzuVv6oszzg=" 324 | } 325 | } 326 | }, 327 | "xmlhttprequest": { 328 | "version": "1.4.2", 329 | "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.4.2.tgz", 330 | "integrity": "sha1-AUU6HZvtHo8XL2SVu/TIxCYyFQA=" 331 | }, 332 | "zeparser": { 333 | "version": "0.0.5", 334 | "resolved": "https://registry.npmjs.org/zeparser/-/zeparser-0.0.5.tgz", 335 | "integrity": "sha1-A3JlYbwmjy5URPVMZlt/1KjAKeI=" 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docker-ubuntu-ssh", 3 | "version": "1.0.0", 4 | "description": "docker-ubuntu-ssh =========================", 5 | "main": "package-lock.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/fcwu/docker-ubuntu-ssh.git" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/fcwu/docker-ubuntu-ssh/issues" 17 | }, 18 | "homepage": "https://github.com/fcwu/docker-ubuntu-ssh#readme", 19 | "dependencies": { 20 | "tty.js": "^0.2.15" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /screenshots/ttyjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcwu/docker-ubuntu-ssh/9d8ae6de7adfd9eb6f631671593403253e05809a/screenshots/ttyjs.png -------------------------------------------------------------------------------- /src/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir /var/run/sshd 4 | 5 | # create an sudo-enabled user 6 | echo "User: $USER Pass: $PASS" 7 | useradd --create-home --shell /bin/bash --user-group --groups adm,sudo $USER 8 | echo "$USER:$PASS" | chpasswd 9 | 10 | /usr/sbin/sshd 11 | node ./tty-me.js 2>/dev/null --daemonize 12 | 13 | _term() { 14 | echo "Exiting!" 15 | exit 0; 16 | } 17 | 18 | trap _term SIGTERM 19 | trap _term SIGINT 20 | 21 | while [ 1 ]; do 22 | /bin/bash 23 | done 24 | -------------------------------------------------------------------------------- /src/tty-me.js: -------------------------------------------------------------------------------- 1 | var tty = require('tty.js'); 2 | 3 | var app = tty.createServer({ 4 | shell: 'login', 5 | port: 3000 6 | }); 7 | 8 | app.get('/health', function(req, res, next) { 9 | res.sendStatus(200); 10 | }); 11 | 12 | app.listen(); 13 | --------------------------------------------------------------------------------