├── .github └── dependabot.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING ├── CONTRIBUTORS.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── docs ├── api │ ├── apps.md │ ├── cron_jobs.md │ ├── device_groups.md │ ├── general.md │ ├── user_groups.md │ └── users.md ├── architecture.md ├── auto-update-workers.md ├── best-practice.md ├── ci-cd │ ├── drone.md │ └── jenkins.md ├── cli.md ├── compare2orchestrators.md ├── config │ ├── apps.md │ ├── cron_jobs.md │ ├── device_groups.md │ ├── manager.md │ ├── reporter.md │ ├── user_groups.md │ ├── users.md │ └── worker.md ├── contribute.md ├── help.md ├── index.md ├── installing │ ├── digital-ocean-global-example.md │ ├── getting-started.md │ ├── install.md │ └── packet-global-example.md ├── internals.md ├── pictures │ ├── cloudcraft - nebula - IoT.png │ ├── cloudcraft - nebula.png │ ├── logos │ │ ├── nebula-logo.png │ │ └── nebula-logo.svg │ └── nebula v2 - iot - optional reporter.png ├── release-notes.md ├── scaling.md ├── sdk │ └── python.md └── use.md ├── examples ├── haproxy │ └── haproxy.cfg ├── hello-world │ ├── docker-compose.yml │ ├── no_worker │ │ └── docker-compose.yml │ ├── optional_reporting_included │ │ ├── docker-compose.yml │ │ └── start_example_nebula_cluster.sh │ └── start_example_nebula_cluster.sh └── rancheros │ └── cloud-config ├── mkdocs.yml ├── requirements.txt └── scripts └── jenkins └── jenkins-release.py /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | open-pull-requests-limit: 10 9 | labels: 10 | - enhancement 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | .idea/ 103 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at nebula-orchestrator@googlegroups.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Being an open source project means any help offered will be greatly appreciated, below is a quick run through of how you 4 | can help 5 | 6 | ## Getting Started 7 | 8 | * Fork the latest branch of the component you want to contribute to. 9 | * Make sure you have a [GitHub account](https://github.com/signup/free). 10 | * Use virtualenv to install all requirements from the requirements.txt file. 11 | * Fix the issue you \ add a feature. 12 | * Create a pull request. 13 | 14 | ## Design philosophy 15 | Nebula is designed with the following philosophy in mind, any feature\pull requests will be judged against the following: 16 | 17 | * Follow Linux philosophy and have each component do one thing & one thing only. 18 | * Each component needs to be possible to be scaled out to extremely large sizes. 19 | * Reliability is more important then shiny new features. 20 | * No vendor\cloud lock-in, if it's only available in one cloud it will not be used. 21 | * No latency sensitivity, assume workers to have a below average internet access and are in the other side of the world. 22 | * Fully stateless, all data is to be saved in the backend DB. 23 | 24 | ### Documentation 25 | 26 | Nebula docs are hosted at [readthedocs](http://nebula.readthedocs.io/en/latest/) using [MkDocs](http://www.mkdocs.org/) for their creation, reading them is highly recommended 27 | prior to making any pull requests. 28 | 29 | ## What you can help with 30 | 31 | * Documentation - everyone hates them but without them would you be able to figure out how to use Nebula? 32 | * Bug fixes / feature requests - anything off github issues lists. 33 | * Submitting tickets - even if you don't have the time\knowledge to fix a bug just opening a github issue about it will greatly help. 34 | * Suggesting improvements. 35 | * Spreading the word. 36 | 37 | ### Summary 38 | 39 | * Your awesome for helping, thanks. 40 | 41 | P.S. 42 | Don't forget to add yourself to to CONTRIBUTORS.md file. -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | Nebula contributors 2 | =================== 3 | 4 | * **[Naor Livne](https://github.com/naorlivne)** 5 | 6 | * Creator & BDFL 7 | * Original coding 8 | * Design 9 | 10 | * **[All the guys at Vidazoo](https://github.com/Vidazoo)** 11 | 12 | * Design 13 | * Support 14 | * First users\victims 15 | 16 | * **[Freepik from www.flaticon.com](https://www.flaticon.com/authors/freepik)** 17 | 18 | * Logo -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected/Wanted Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 2. 11 | 3. 12 | 13 | ## Specifications 14 | 15 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # 2 | 3 | ## Proposed Changes 4 | 5 | - 6 | - 7 | - 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nebula docs 2 | 3 | ## Main website available [here](https://nebula-orchestrator.github.io/), refer to the [documentation](http://nebula.readthedocs.io/en/latest/) for more details about how to install & use. 4 | 5 | Readthedocs build badge: ![Build Status](https://readthedocs.org/projects/nebula/badge/) 6 | 7 | 8 | Nebula is a open source distributed Docker orchestrator designed for massive scales (tens of thousands of servers/worker devices), unlike Mesos/Swarm/Kubernetes it has the ability to have workers distributed on high latency connections (such as the internet) yet have the pods(containers) be managed centrally with changes taking affect (almost) immediately, this makes Nebula ideal for managing a vast cluster of servers\devices across the globe, some example use cases are: 9 | 10 | * IoT devices 11 | * appliances\virtual appliances located at clients data centers 12 | * edge computing 13 | * POS systems 14 | 15 | Ever wandered how your going to push an update to that smart fridge your company is working on as it's thousands of devices around the globe? 16 | wish you could have the assurance that your service will always use the latest code\envvars\etc in all of it's edge locations? 17 | want the ability to stop\start a globally distributed service with a single command? 18 | 19 | Nebula was designed from the ground up to answer all of this needs and much more, refer to the [documentation](http://nebula.readthedocs.io/en/latest/) if your interested in seeing on how to use it. 20 | 21 | This repo is the documentation of Nebula container orchestrator, it uses MKDocs to build the readthedocs hosted documentation. 22 | -------------------------------------------------------------------------------- /docs/api/apps.md: -------------------------------------------------------------------------------- 1 | # Create app 2 | create a new app inside the Nebula cluster, the docker_image is required with the rest of the parameters getting default values if not declared. 3 | 4 | **request** 5 | 6 | ``` 7 | POST /api/v2/apps/app_name HTTP/1.1 8 | Host: localhost:5000 9 | Authorization: Basic 10 | Content-Type: application/json 11 | Cache-Control: no-cache 12 | 13 | { 14 | "starting_ports": [80], 15 | "containers_per": {"server": 2}, 16 | "env_vars": {"test": "test123"}, 17 | "docker_image" : "nginx", 18 | "running": true, 19 | "volumes": [], 20 | "networks": ["nebula", "bridge"], 21 | "devices": [], 22 | "privileged": false, 23 | "rolling_restart": false 24 | } 25 | ``` 26 | 27 | **response example** 28 | 29 | success 30 | ``` 31 | 200 32 | { 33 | "app_name": "app_name", 34 | "env_vars": { 35 | "test": "test123" 36 | }, 37 | "app_id": 1, 38 | "devices": [], 39 | "privileged": false, 40 | "running": true, 41 | "containers_per": { 42 | "server": 2 43 | }, 44 | "starting_ports": [ 45 | 80 46 | ], 47 | "volumes": [], 48 | "_id": { 49 | "$oid": "5c370a85ebdb54000edb8ef2" 50 | }, 51 | "rolling_restart": false, 52 | "networks": [ 53 | "nebula", 54 | "bridge" 55 | ], 56 | "docker_image": "nginx" 57 | } 58 | ``` 59 | 60 | missing parameters 61 | ``` 62 | 400 63 | { 64 | "missing_parameters": ["running", "volumes"] 65 | } 66 | ``` 67 | 68 | app already exists 69 | ``` 70 | 403 71 | { 72 | "app_exists": true 73 | } 74 | 75 | ``` 76 | 77 | # Delete app 78 | delete an app from the nebula cluster, be careful as the only way to restore a deleted app is manually creating it with the same variables 79 | 80 | **request** 81 | 82 | ``` 83 | DELETE /api/v2/apps/app_name HTTP/1.1 84 | Host: localhost:5000 85 | Authorization: Basic 86 | Content-Type: application/json 87 | Cache-Control: no-cache 88 | ``` 89 | 90 | **response example** 91 | 92 | success: 93 | ``` 94 | 200 95 | {} 96 | ``` 97 | 98 | when trying to delete a non existing app: 99 | ``` 100 | 403 101 | { 102 | "app_exists": false 103 | } 104 | ``` 105 | 106 | # List apps 107 | list all apps managed in the current Nebula cluster 108 | 109 | **request** 110 | 111 | ``` 112 | GET /api/v2/apps HTTP/1.1 113 | Host: localhost:5000 114 | Authorization: Basic 115 | Content-Type: application/json 116 | Cache-Control: no-cache 117 | ``` 118 | 119 | **response example** 120 | 121 | ``` 122 | 200 123 | { 124 | "apps": [ 125 | "app_name" 126 | ] 127 | } 128 | ``` 129 | 130 | # Get app config 131 | get a specific Nebula app config 132 | 133 | **request** 134 | 135 | ``` 136 | GET /api/v2/apps/app_name HTTP/1.1 137 | Host: localhost:5000 138 | Authorization: Basic 139 | Content-Type: application/json 140 | Cache-Control: no-cache 141 | ``` 142 | 143 | **response example** 144 | 145 | ``` 146 | 200 147 | { 148 | "app_name": "app_name", 149 | "env_vars": { 150 | "test": "app_name" 151 | }, 152 | "app_id": 1, 153 | "devices": [], 154 | "privileged": false, 155 | "running": true, 156 | "containers_per": { 157 | "server": 2 158 | }, 159 | "starting_ports": [ 160 | 80 161 | ], 162 | "volumes": [], 163 | "_id": { 164 | "$oid": "5c370a85ebdb54000edb8ef2" 165 | }, 166 | "rolling_restart": false, 167 | "networks": [ 168 | "nebula", 169 | "bridge" 170 | ], 171 | "docker_image": "nginx" 172 | } 173 | ``` 174 | 175 | # Stop app 176 | stop a running Nebula app 177 | 178 | **request** 179 | 180 | ``` 181 | POST /api/v2/apps/app_name/stop HTTP/1.1 182 | Host: localhost:5000 183 | Authorization: Basic 184 | Content-Type: application/json 185 | Cache-Control: no-cache 186 | ``` 187 | 188 | **response example** 189 | 190 | ``` 191 | 202 192 | { 193 | "app_name": "app_name", 194 | "env_vars": { 195 | "test": "app_name" 196 | }, 197 | "app_id": 2, 198 | "devices": [], 199 | "privileged": false, 200 | "running": false, 201 | "containers_per": { 202 | "server": 2 203 | }, 204 | "starting_ports": [ 205 | 80 206 | ], 207 | "volumes": [], 208 | "_id": { 209 | "$oid": "5c370a85ebdb54000edb8ef2" 210 | }, 211 | "rolling_restart": false, 212 | "networks": [ 213 | "nebula", 214 | "bridge" 215 | ], 216 | "docker_image": "nginx" 217 | } 218 | ``` 219 | 220 | # Start app 221 | start a Nebula app 222 | 223 | **request** 224 | 225 | ``` 226 | POST /api/v2/apps/app_name/start HTTP/1.1 227 | Host: localhost:5000 228 | Authorization: Basic 229 | Content-Type: application/json 230 | Cache-Control: no-cache 231 | ``` 232 | 233 | **response example** 234 | 235 | ``` 236 | 202 237 | { 238 | "app_name": "app_name", 239 | "env_vars": { 240 | "test": "app_name" 241 | }, 242 | "app_id": 3, 243 | "devices": [], 244 | "privileged": false, 245 | "running": true, 246 | "containers_per": { 247 | "server": 2 248 | }, 249 | "starting_ports": [ 250 | 80 251 | ], 252 | "volumes": [], 253 | "_id": { 254 | "$oid": "5c370a85ebdb54000edb8ef2" 255 | }, 256 | "rolling_restart": false, 257 | "networks": [ 258 | "nebula", 259 | "bridge" 260 | ], 261 | "docker_image": "nginx" 262 | } 263 | ``` 264 | 265 | # Restart app 266 | note that restarting an app also force pulling the latest version of the docker container so can be used as a form of deployment method assuming that the you overwritten the container tag in your docker registry with a newer version 267 | 268 | **request** 269 | 270 | ``` 271 | POST /api/v2/apps/app_name/restart HTTP/1.1 272 | Host: localhost:5000 273 | Authorization: Basic 274 | Content-Type: application/json 275 | Cache-Control: no-cache 276 | ``` 277 | 278 | **response example** 279 | 280 | ``` 281 | 202 282 | { 283 | "app_name": "app_name", 284 | "env_vars": { 285 | "test": "app_name" 286 | }, 287 | "app_id": 4, 288 | "devices": [], 289 | "privileged": false, 290 | "running": true, 291 | "containers_per": { 292 | "server": 2 293 | }, 294 | "starting_ports": [ 295 | 80 296 | ], 297 | "volumes": [], 298 | "_id": { 299 | "$oid": "5c370a85ebdb54000edb8ef2" 300 | }, 301 | "rolling_restart": false, 302 | "networks": [ 303 | "nebula", 304 | "bridge" 305 | ], 306 | "docker_image": "nginx" 307 | } 308 | ``` 309 | 310 | # Update app 311 | update a Nebula app config 312 | 313 | use POST requests to require updating all of the app fields. 314 | 315 | use PUT requests to update only a subset of the app fields while leaving the rest as is. 316 | 317 | **request** 318 | 319 | ``` 320 | POST /api/v2/apps/app_name/update HTTP/1.1 321 | Host: localhost:5000 322 | Authorization: Basic 323 | Content-Type: application/json 324 | Cache-Control: no-cache 325 | 326 | { 327 | "starting_ports": [80], 328 | "containers_per": {"server": 2}, 329 | "env_vars": {"test": "test123"}, 330 | "docker_image" : "nginx", 331 | "running": true, 332 | "volumes": [], 333 | "networks": ["nebula", "bridge"], 334 | "devices": [], 335 | "privileged": false, 336 | "rolling_restart": false 337 | } 338 | ``` 339 | 340 | **response example** 341 | 342 | success: 343 | ``` 344 | 202 345 | { 346 | "app_name": "app_name", 347 | "env_vars": { 348 | "test": "app_name" 349 | }, 350 | "app_id": 4, 351 | "devices": [], 352 | "privileged": false, 353 | "running": true, 354 | "containers_per": { 355 | "server": 2 356 | }, 357 | "starting_ports": [ 358 | 80 359 | ], 360 | "volumes": [], 361 | "_id": { 362 | "$oid": "5c370a85ebdb54000edb8ef2" 363 | }, 364 | "rolling_restart": false, 365 | "networks": [ 366 | "nebula", 367 | "bridge" 368 | ], 369 | "docker_image": "nginx" 370 | } 371 | ``` 372 | 373 | missing parameters: 374 | ``` 375 | 400 376 | { 377 | "missing_parameters": ["running", "volumes"] 378 | } 379 | ``` 380 | -------------------------------------------------------------------------------- /docs/api/cron_jobs.md: -------------------------------------------------------------------------------- 1 | # list cron jobs 2 | list all cron jobs 3 | 4 | **request** 5 | 6 | ``` 7 | GET /api/v2/cron_jobs HTTP/1.1 8 | Host: localhost:5000 9 | Authorization: Basic 10 | Content-Type: application/json 11 | Cache-Control: no-cache 12 | ``` 13 | 14 | **response example** 15 | 16 | ``` 17 | 200 18 | { 19 | "cron_jobs": [ 20 | "test" 21 | ] 22 | } 23 | ``` 24 | 25 | # delete a cron job 26 | delete a cron job config 27 | 28 | **request** 29 | 30 | ``` 31 | DELETE /api/v2/cron_jobs/cron_job_name HTTP/1.1 32 | Host: localhost:5000 33 | Authorization: Basic 34 | Content-Type: application/json 35 | Cache-Control: no-cache 36 | ``` 37 | 38 | **response example** 39 | 40 | ``` 41 | 200 42 | {} 43 | ``` 44 | 45 | # list a cron job 46 | list a cron job config 47 | 48 | **request** 49 | 50 | ``` 51 | GET /api/v2/cron_jobs/cron_job_name HTTP/1.1 52 | Host: localhost:5000 53 | Authorization: Basic 54 | Content-Type: application/json 55 | Cache-Control: no-cache 56 | ``` 57 | 58 | **response example** 59 | 60 | ``` 61 | { 62 | "cron_job_id": 1, 63 | "cron_job_name": "test", 64 | "schedule": "0 * * * *", 65 | "env_vars": { 66 | "test": "test123" 67 | }, 68 | "docker_image": "nginx", 69 | "running": true, 70 | "networks": [ 71 | "nebula", 72 | "bridge" 73 | ], 74 | "volumes": [], 75 | "devices": [], 76 | "privileged": false 77 | } 78 | ``` 79 | 80 | # create a cron job 81 | create a cron job 82 | 83 | **request** 84 | 85 | ``` 86 | 200 87 | POST /api/v2/cron_jobs/cron_job_name HTTP/1.1 88 | Host: localhost:5000 89 | Authorization: Basic 90 | Content-Type: application/json 91 | Cache-Control: no-cache 92 | 93 | { 94 | "env_vars": {"test": "test123"}, 95 | "docker_image" : "nginx", 96 | "running": true, 97 | "volumes": [], 98 | "networks": ["nebula", "bridge"], 99 | "devices": [], 100 | "privileged": false, 101 | "schedule": "0 * * * *" 102 | } 103 | ``` 104 | 105 | **response example** 106 | 107 | ``` 108 | 200 109 | { 110 | "cron_job_id": 1, 111 | "cron_job_name": "test", 112 | "schedule": "0 * * * *", 113 | "env_vars": { 114 | "test": "test123" 115 | }, 116 | "docker_image": "nginx", 117 | "running": true, 118 | "networks": [ 119 | "nebula", 120 | "bridge" 121 | ], 122 | "volumes": [], 123 | "devices": [], 124 | "privileged": false 125 | } 126 | ``` 127 | 128 | # Update some cron job params (PUT / PATCH) 129 | update a Nebula cron job config, accepts any combination of the cron job configuration params. 130 | 131 | **request** 132 | 133 | ``` 134 | PUT /api/v2/cron_jobs/cron_job_name/update HTTP/1.1 135 | Host: localhost:5000 136 | Authorization: Basic 137 | Content-Type: application/json 138 | Cache-Control: no-cache 139 | 140 | { 141 | "schedule": "0 0 * * *", 142 | "docker_image": "httpd" 143 | } 144 | ``` 145 | 146 | **response example** 147 | 148 | success: 149 | ``` 150 | 202 151 | { 152 | "_id": { 153 | "$oid": "5cb309239d723e5e3d22d0a0" 154 | }, 155 | "cron_job_id": 11, 156 | "cron_job_name": "test", 157 | "schedule": "0 0 * * *", 158 | "env_vars": { 159 | "test": "test123" 160 | }, 161 | "docker_image": "httpd", 162 | "running": true, 163 | "networks": [ 164 | "nebula", 165 | "bridge" 166 | ], 167 | "volumes": [], 168 | "devices": [], 169 | "privileged": false 170 | } 171 | ``` 172 | 173 | missing parameters: 174 | ``` 175 | 400 176 | { 177 | "missing_parameters": "True" 178 | } 179 | ``` 180 | 181 | # Update all cron job params (POST) 182 | update a Nebula cron job config, requires all of the cron job configuration params. 183 | 184 | **request** 185 | 186 | ``` 187 | POST /api/v2/cron_jobs/cron_job_name/update HTTP/1.1 188 | Host: localhost:5000 189 | Authorization: Basic 190 | Content-Type: application/json 191 | Cache-Control: no-cache 192 | 193 | { 194 | "schedule": "0 0 * * *", 195 | "docker_image": "httpd" 196 | } 197 | ``` 198 | 199 | **response example** 200 | 201 | success: 202 | ``` 203 | 202 204 | { 205 | "_id": { 206 | "$oid": "5cb309239d723e5e3d22d0a0" 207 | }, 208 | "cron_job_id": 11, 209 | "cron_job_name": "test", 210 | "schedule": "0 0 * * *", 211 | "env_vars": { 212 | "test": "test123" 213 | }, 214 | "docker_image": "httpd", 215 | "running": true, 216 | "networks": [ 217 | "nebula", 218 | "bridge" 219 | ], 220 | "volumes": [], 221 | "devices": [], 222 | "privileged": false 223 | } 224 | ``` 225 | 226 | missing parameters: 227 | ``` 228 | 400 229 | { 230 | "missing_parameters": "True" 231 | } 232 | ``` 233 | -------------------------------------------------------------------------------- /docs/api/device_groups.md: -------------------------------------------------------------------------------- 1 | # list a device group info 2 | a special endpoint which the devices check every (configurable with the "nebula_manager_check_in_time" param on the workers) X seconds that returns a cached (cache time configurable by the "cache_time" param on the manager) info of all apps of said device_group along with all the the data needed to get the device to match the needed configuration. 3 | 4 | **request** 5 | 6 | ``` 7 | GET /api/v2/device_groups/device_group_name/info HTTP/1.1 8 | Host: localhost:5000 9 | Authorization: Basic 10 | Content-Type: application/json 11 | Cache-Control: no-cache 12 | ``` 13 | 14 | **response example** 15 | 16 | success: 17 | ``` 18 | 200 19 | { 20 | "apps": [ 21 | { 22 | "app_name": "test", 23 | "env_vars": { 24 | "test": "blabla123", 25 | "test3t2t32": "tesg4ehgee" 26 | }, 27 | "app_id": 498, 28 | "running": true, 29 | "containers_per": { 30 | "mem": 1024 31 | }, 32 | "starting_ports": [ 33 | { 34 | "80": "80" 35 | }, 36 | 8888 37 | ], 38 | "networks": [ 39 | "nebula", 40 | "bridge" 41 | ], 42 | "docker_image": "httpd", 43 | "devices": [], 44 | "volumes": [ 45 | "/tmp:/tmp/1", 46 | "/var/tmp/:/var/tmp/1:ro" 47 | ], 48 | "privileged": false, 49 | "rolling_restart": false, 50 | "app_token": "bb627c20-e5e9-402c-9f44-111889da2c39", 51 | "schedule": "0 0 * * *" 52 | }, 53 | { 54 | "app_name": "test123", 55 | "env_vars": { 56 | "test": "blabla123", 57 | "test3t2t32": "tesg4ehgee" 58 | }, 59 | "app_id": 7, 60 | "running": true, 61 | "containers_per": { 62 | "cpu": 1 63 | }, 64 | "starting_ports": [ 65 | { 66 | "888": "888" 67 | } 68 | ], 69 | "networks": [ 70 | "nebula", 71 | "bridge" 72 | ], 73 | "docker_image": "httpd:alpine", 74 | "devices": [], 75 | "volumes": [ 76 | "/tmp:/tmp/1", 77 | "/var/tmp/:/var/tmp/1:ro" 78 | ], 79 | "privileged": false, 80 | "rolling_restart": false, 81 | "app_token": "680b735b-fd64-43a7-b0b8-4b3905e65352" 82 | } 83 | ], 84 | "apps_list": [ 85 | "test", 86 | "test123" 87 | ], 88 | "prune_id": 125, 89 | "cron_jobs": [ 90 | { 91 | "cron_job_id": 1, 92 | "cron_job_name": "test", 93 | "schedule": "0 * * * *", 94 | "env_vars": { 95 | "test": "test123" 96 | }, 97 | "docker_image": "nginx", 98 | "running": true, 99 | "networks": [ 100 | "nebula", 101 | "bridge" 102 | ], 103 | "volumes": [], 104 | "devices": [], 105 | "privileged": false 106 | } 107 | ], 108 | "cron_jobs_list": [ 109 | "test" 110 | ], 111 | "device_group_id": 31 112 | } 113 | ``` 114 | 115 | # list a device group 116 | list a device group config 117 | 118 | **request** 119 | 120 | ``` 121 | GET /api/v2/device_groups/device_group_name HTTP/1.1 122 | Host: localhost:5000 123 | Authorization: Basic 124 | Content-Type: application/json 125 | Cache-Control: no-cache 126 | ``` 127 | 128 | **response example** 129 | 130 | ``` 131 | { 132 | "prune_id": 544, 133 | "_id": { 134 | "$oid": "5c2cc6849d723e6c88ba466e" 135 | }, 136 | "apps": [ 137 | "test", 138 | "test123" 139 | ], 140 | "cron_jobs": [ 141 | "test" 142 | ], 143 | "device_group_id": 116, 144 | "device_group": "device_group_name" 145 | } 146 | ``` 147 | 148 | # list device groups 149 | list all device groups 150 | 151 | **request** 152 | 153 | ``` 154 | GET /api/v2/device_groups HTTP/1.1 155 | Host: localhost:5000 156 | Authorization: Basic 157 | Content-Type: application/json 158 | Cache-Control: no-cache 159 | ``` 160 | 161 | **response example** 162 | 163 | ``` 164 | { 165 | "device_groups": [ 166 | "test", 167 | "test123" 168 | ] 169 | } 170 | ``` 171 | 172 | # create a device group 173 | create a device group 174 | 175 | **request** 176 | 177 | ``` 178 | POST /api/v2/device_groups/device_group_name HTTP/1.1 179 | Host: localhost:5000 180 | Authorization: Basic 181 | Content-Type: application/json 182 | Cache-Control: no-cache 183 | 184 | { 185 | "apps": [ 186 | "test", 187 | "test123" 188 | ], 189 | "cron_jobs": [ 190 | "test" 191 | ] 192 | } 193 | ``` 194 | 195 | **response example** 196 | 197 | ``` 198 | 200 199 | { 200 | "prune_id": 544, 201 | "_id": { 202 | "$oid": "5c2cc6849d723e6c88ba466e" 203 | }, 204 | "apps": [ 205 | "test", 206 | "test123" 207 | ], 208 | "device_group_id": 116, 209 | "device_group": "device_group_name", 210 | "cron_jobs": [ 211 | "test" 212 | ] 213 | } 214 | ``` 215 | 216 | # delete a device group 217 | delete a device group config 218 | 219 | **request** 220 | 221 | ``` 222 | DELETE /api/v2/device_groups/device_group_name HTTP/1.1 223 | Host: localhost:5000 224 | Authorization: Basic 225 | Content-Type: application/json 226 | Cache-Control: no-cache 227 | ``` 228 | 229 | **response example** 230 | 231 | ``` 232 | 200 233 | {} 234 | ``` 235 | 236 | # update a device group 237 | update a device group 238 | 239 | use POST requests to require updating all of the device_group fields. 240 | 241 | use PUT requests to update only a subset of the device_group fields while leaving the rest as is. 242 | 243 | **request** 244 | 245 | ``` 246 | POST /api/v2/device_groups/device_group_name/update HTTP/1.1 247 | Host: localhost:5000 248 | Authorization: Basic 249 | Content-Type: application/json 250 | Cache-Control: no-cache 251 | 252 | { 253 | "apps": [ 254 | "test", 255 | "test123" 256 | ], 257 | "cron_jobs": [ 258 | "test" 259 | ] 260 | } 261 | ``` 262 | 263 | **response example** 264 | 265 | ``` 266 | 202 267 | { 268 | "prune_id": 544, 269 | "_id": { 270 | "$oid": "5c2cc6849d723e6c88ba466e" 271 | }, 272 | "apps": [ 273 | "test", 274 | "test123" 275 | ], 276 | "device_group_id": 116, 277 | "device_group": "device_group_name", 278 | "cron_jobs": [ 279 | "test" 280 | ] 281 | } 282 | ``` 283 | 284 | # prune images on a device group 285 | Prune unused images on devices that are part of a given device group 286 | 287 | **request** 288 | 289 | ``` 290 | POST /api/v2/device_groups/device_group_name/prune HTTP/1.1 291 | Host: localhost:5000 292 | Authorization: Basic 293 | Content-Type: application/json 294 | Cache-Control: no-cache 295 | ``` 296 | 297 | **response example** 298 | 299 | ``` 300 | 202 301 | { 302 | "prune_id": 545, 303 | "_id": { 304 | "$oid": "5c2cc6849d723e6c88ba466e" 305 | }, 306 | "apps": [ 307 | "test", 308 | "test123" 309 | ], 310 | "device_group_id": 117, 311 | "device_group": "test" 312 | } 313 | ``` -------------------------------------------------------------------------------- /docs/api/general.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | There are currently 2 possible authentication methods: 4 | 5 | * Basic auth - pass the `Authorization: Basic ` header to the API call 6 | * Bearer tokens - pass the `Authorization: Bearer ` header to the API call 7 | 8 | you can use either\both however you please, should you wish to disable both auth you must set the `auth_enabled` parameter on the manager to `false`. 9 | 10 | The `basic_auth_user`, `basic_auth_password` & `auth_token` parameters of the manager configure the local admin user which is automatically granted permissions for everything, aside from the local admin user there is also internal users which is managed by being attached to user_groups and granting permissions to said user_groups, this allows you to set read only or read\write permissions on both the app level and the device_group level, allow\disallow pruning permissions & create more admin users. 11 | 12 | # Get api status 13 | a simple endpoint that can be used to monitor the API is working 14 | 15 | **request** 16 | 17 | ``` 18 | GET /api/v2/status HTTP/1.1 19 | Host: localhost:5000 20 | Authorization: Basic 21 | Content-Type: application/json 22 | Cache-Control: no-cache 23 | ``` 24 | 25 | **response example** 26 | 27 | success 28 | ``` 29 | 200 30 | { 31 | "api_available": true 32 | } 33 | ``` 34 | 35 | # Prune unused images on all device 36 | Prune unused images on all devices 37 | 38 | **request** 39 | 40 | ``` 41 | POST /api/v2/prune HTTP/1.1 42 | Host: localhost:5000 43 | Authorization: Basic 44 | Content-Type: application/json 45 | Cache-Control: no-cache 46 | ``` 47 | 48 | **response example** 49 | 50 | ``` 51 | 202 52 | { 53 | "prune_ids": { 54 | "test": 544, 55 | "test123": 222 56 | } 57 | } 58 | ``` 59 | 60 | # List a filtered paginated view of the optional reports system 61 | The optional reporting system reports can be queried from this endpoint in the manager. 62 | 63 | Can be filtered via the request parameters (none are required): 64 | 65 | * page_size = the number of reports per page to show 66 | * hostname = an exact match to a hostname to filter by 67 | * device_group = an exact match to a device_group to filter by 68 | * report_creation_time = the value (in seconds since unix epoch) of time to filter by 69 | * report_creation_time_filter = the math expression to filter the report_creation_time by, defaults to eq (equal), one of: 70 | * eq 71 | * gt 72 | * lt 73 | * gte 74 | * lte 75 | * ne 76 | * last_id = the last_id that is returned by the a current paginated query, passing it will make the load the next paginated page, upon reaching the last page 'null' will be returned. 77 | * updated = setting to "True" will return only reports where there was a change in the device configuration, setting to "False" will return only the reports where there was no changes in the device configuration, if unset all reports will be returned. 78 | 79 | 80 | **request** 81 | 82 | ``` 83 | GET /api/v2/reports?page_size=3& hostname=5c5b7ceae29a& device_group=test& report_creation_time_filter=gt& report_creation_time=1551252013& last_id=5c75489a209bde00015570e5 HTTP/1.1 84 | Host: 127.0.0.1:5000 85 | Authorization: Basic 86 | Content-Type: application/json 87 | cache-control: no-cache 88 | ``` 89 | 90 | **response example** 91 | 92 | ``` 93 | 200 94 | { 95 | "data": [ 96 | { 97 | ...very_long_paginated_view_of_3_reports... 98 | } 99 | ], 100 | "last_id": { 101 | "$oid": "5c75489a209bde00015570e8" 102 | } 103 | } 104 | ``` 105 | -------------------------------------------------------------------------------- /docs/api/user_groups.md: -------------------------------------------------------------------------------- 1 | All of the user groups endpoints require an "admin" to edit\view. 2 | 3 | # Update user_group 4 | Updates a user_group 5 | 6 | **request** 7 | 8 | ``` 9 | PUT /api/v2/user_groups//update HTTP/1.1 10 | Host: 127.0.0.1:5000 11 | Content-Type: application/json 12 | cache-control: no-cache 13 | Authorization: Basic 14 | 15 | { 16 | "group_members": ["test123"], 17 | "pruning_allowed": true, 18 | "apps": {"test": "rw", "test123": "ro"}, 19 | "cron_jobs": {"test": "rw", "test123": "ro"}, 20 | "device_groups": {"test": "rw", "test123": "ro"}, 21 | "admin": true 22 | } 23 | ``` 24 | 25 | **response example** 26 | 27 | ``` 28 | 200 29 | { 30 | "_id": { 31 | "$oid": "5c921a639d723e083d2a2fd5" 32 | }, 33 | "user_group": "test_user_group", 34 | "group_members": [ 35 | "test123" 36 | ], 37 | "pruning_allowed": true, 38 | "apps": { 39 | "test": "rw", 40 | "test123": "ro" 41 | }, 42 | "cron_jobs": { 43 | "test": "rw", 44 | "test123": "ro" 45 | }, 46 | "device_groups": { 47 | "test": "rw", 48 | "test123": "ro" 49 | }, 50 | "admin": true 51 | } 52 | ``` 53 | 54 | # Create a user_group 55 | Create a new user_group 56 | 57 | **request** 58 | 59 | ``` 60 | POST /api/v2/user_groups/ HTTP/1.1 61 | Host: 127.0.0.1:5000 62 | Content-Type: application/json 63 | cache-control: no-cache 64 | Authorization: Basic 65 | 66 | { 67 | "group_members": ["test123"], 68 | "pruning_allowed": false, 69 | "apps": {"test": "rw", "test123": "ro"}, 70 | "cron_jobs": {"test": "rw", "test123": "ro"}, 71 | "device_groups": {"test": "rw", "test123": "ro"}, 72 | "admin": false 73 | } 74 | ``` 75 | 76 | **response example** 77 | 78 | ``` 79 | 200 80 | { 81 | "_id": { 82 | "$oid": "5c921a639d723e083d2a2fd5" 83 | }, 84 | "user_group": "test_user_group", 85 | "group_members": [ 86 | "test123" 87 | ], 88 | "pruning_allowed": true, 89 | "apps": { 90 | "test": "rw", 91 | "test123": "ro" 92 | }, 93 | "device_groups": { 94 | "test": "rw", 95 | "test123": "ro" 96 | }, 97 | "cron_jobs": { 98 | "test": "rw", 99 | "test123": "ro" 100 | }, 101 | "admin": true 102 | } 103 | ``` 104 | 105 | When trying to add a existing user_group: 106 | 107 | ``` 108 | 403 109 | { 110 | "user_group_exists": true 111 | } 112 | ``` 113 | 114 | # Delete a user_group 115 | Removes a user_group 116 | 117 | **request** 118 | 119 | ``` 120 | DELETE /api/v2/user_groups/ HTTP/1.1 121 | Host: 127.0.0.1:5000 122 | Content-Type: application/json 123 | cache-control: no-cache 124 | Authorization: Basic 125 | ``` 126 | 127 | **response example** 128 | 129 | ``` 130 | 200 131 | {} 132 | ``` 133 | 134 | When trying to delete a non existing user_group: 135 | 136 | ``` 137 | 403 138 | { 139 | "user_group_exists": false 140 | } 141 | ``` 142 | 143 | # List all user_groups 144 | list all user_groups 145 | 146 | **request** 147 | 148 | ``` 149 | GET /api/v2/users HTTP/1.1 150 | Host: 127.0.0.1:5000 151 | Content-Type: application/json 152 | cache-control: no-cache 153 | Authorization: Basic 154 | ``` 155 | 156 | **response example** 157 | 158 | ``` 159 | 200 160 | { 161 | "user_groups": [ 162 | "test_user_group" 163 | ] 164 | } 165 | ``` 166 | 167 | # List user_group info 168 | list a user_group info 169 | 170 | **request** 171 | 172 | ``` 173 | GET /api/v2/user_groups/ HTTP/1.1 174 | Host: 127.0.0.1:5000 175 | Content-Type: application/json 176 | cache-control: no-cache 177 | Authorization: Basic 178 | ``` 179 | 180 | **response example** 181 | 182 | ``` 183 | 200 184 | { 185 | "user_group": "test_user_group", 186 | "group_members": [ 187 | "test123" 188 | ], 189 | "pruning_allowed": true, 190 | "apps": { 191 | "test": "rw", 192 | "test123": "ro" 193 | }, 194 | "device_groups": { 195 | "test": "rw", 196 | "test123": "ro" 197 | }, 198 | "cron_jobs": { 199 | "test": "rw", 200 | "test123": "ro" 201 | }, 202 | "admin": true 203 | } 204 | ``` 205 | -------------------------------------------------------------------------------- /docs/api/users.md: -------------------------------------------------------------------------------- 1 | All of the users endpoints require an "admin" to edit\view. 2 | 3 | # Update user 4 | Updates a user password and\or token, note that the response of said fields is hashed. 5 | 6 | **request** 7 | 8 | ``` 9 | PUT /api/v2/users//update HTTP/1.1 10 | Host: 127.0.0.1:5000 11 | Content-Type: application/json 12 | cache-control: no-cache 13 | Authorization: Basic 14 | 15 | { 16 | "password": "", 17 | "token": "" 18 | } 19 | ``` 20 | 21 | **response example** 22 | 23 | ``` 24 | 200 25 | { 26 | "_id": { 27 | "$oid": "5c85134a9d723e4c9a7dd03c" 28 | }, 29 | "user_name": "", 30 | "password": "$2b$12$bKJRenSWB/XQrFYLNqKan.oWrPvGrgkd1Oy75nsWrn.tEj5RDdCq.", 31 | "token": "$2b$12$LOqP59o2z48.H4qPLldHxOfXHJtw3JqeY7R.DG4xEECd6kwdnJ8bm" 32 | } 33 | ``` 34 | 35 | # Create a user 36 | Create a new user, note that the response of said fields is hashed. 37 | 38 | **request** 39 | 40 | ``` 41 | POST /api/v2/users/ HTTP/1.1 42 | Host: 127.0.0.1:5000 43 | Content-Type: application/json 44 | cache-control: no-cache 45 | Authorization: Basic 46 | 47 | { 48 | "password": "", 49 | "token": "" 50 | } 51 | ``` 52 | 53 | **response example** 54 | 55 | ``` 56 | 200 57 | { 58 | "user_name": "", 59 | "password": "$2b$12$XjZjbZivcPfJQbJMIPbv3Oh5OMhk.0IftkoaysxJvVJzo8k//.Ipi", 60 | "token": "$2b$12$BImGUFUk2fcXACipwEwGqumyZdmvfLLQfaKVvsjDn0iWCAQBBG106" 61 | } 62 | ``` 63 | 64 | When trying to add a existing user: 65 | 66 | ``` 67 | 403 68 | { 69 | "user_exists": true 70 | } 71 | ``` 72 | 73 | # Refresh a user token 74 | Generate a new secure random token for a user and returns it. 75 | 76 | 77 | !!! note 78 | This is the only time the token will be returned unhashed, make sure to keep it safe. 79 | 80 | 81 | **request** 82 | 83 | ``` 84 | POST /api/v2/users//refresh HTTP/1.1 85 | Host: 127.0.0.1:5000 86 | Content-Type: application/json 87 | cache-control: no-cache 88 | Authorization: Basic 89 | 90 | {} 91 | ``` 92 | 93 | **response example** 94 | 95 | ``` 96 | 200 97 | { 98 | "token": "v7s3agw1NXfkkUXz9WHMO_U1QS9xXs9ZEHoKETiNWQY" 99 | } 100 | ``` 101 | 102 | # Delete a user 103 | Removes a user 104 | 105 | **request** 106 | 107 | ``` 108 | DELETE /api/v2/users/ HTTP/1.1 109 | Host: 127.0.0.1:5000 110 | Content-Type: application/json 111 | cache-control: no-cache 112 | Authorization: Basic 113 | ``` 114 | 115 | **response example** 116 | 117 | ``` 118 | 200 119 | {} 120 | ``` 121 | 122 | When trying to delete a non existing user: 123 | 124 | ``` 125 | 403 126 | { 127 | "user_exists": false 128 | } 129 | ``` 130 | 131 | # List all users 132 | list all users 133 | 134 | **request** 135 | 136 | ``` 137 | GET /api/v2/users HTTP/1.1 138 | Host: 127.0.0.1:5000 139 | Content-Type: application/json 140 | cache-control: no-cache 141 | Authorization: Basic 142 | ``` 143 | 144 | **response example** 145 | 146 | ``` 147 | 200 148 | { 149 | "users": [ 150 | "test123" 151 | ] 152 | } 153 | ``` 154 | 155 | # List user info 156 | list a user info, not much info in it as everything is hashed but can show you if a user exists already 157 | 158 | **request** 159 | 160 | ``` 161 | GET /api/v2/users/ HTTP/1.1 162 | Host: 127.0.0.1:5000 163 | Content-Type: application/json 164 | cache-control: no-cache 165 | Authorization: Basic 166 | ``` 167 | 168 | **response example** 169 | 170 | ``` 171 | 200 172 | { 173 | "user_name": "test123", 174 | "password": "$2b$12$bi7hX3cR43rLmqaT3o360eeU2F3VSm2i5dCG5WmvMz3jRgyHFo0Wu", 175 | "token": "$2b$12$BTq.s2QTO9TzV4MLoMRa1uX0dNbkjuiY05UeE5qyue.lgRYj.GSuW" 176 | } 177 | ``` 178 | -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # Common Nebula architecture designs 2 | 3 | While there are too many possible ways to design Nebula architecture to list them all the following 2 designs will help cover common use cases as well as serve as a stepping stone to help explain the different components of Nebula: 4 | 5 | ## IoT deployment 6 | 7 | ![example nebula architecture](../pictures/cloudcraft%20-%20nebula%20-%20IoT.png "example nebula architecture") 8 | 9 | In the above deployment example Nebula manages a distributed set of identical IoT devices, each devices configured with to be part of the same "device_group", every time a new devices is turned on it follows this steps: 10 | 11 | 1. The IoT device connects to the manager. 12 | 2. The IoT device pulls the latest device_group config. 13 | 3. From this point on the IoT device periodically (configured with the "nebula_manager_check_in_time") checks with the worker for any changes, due to memoization techniques in use the managers have a built in short term cache (configured with the "cache_time") and due to Kafka inspired monotonic ID's for field it's safe to use memoization without worrying about having stale configurations. 14 | 15 | Now if an admin wishes to deploy a new version or change any setting (envvar, mount, etc...) on all devices he simply has to follow this steps: 16 | 17 | 1. Push a new container version with a new tag to the configured Docker registry. 18 | 2. Update the control api (manager) by using the CLI\SDK\API with the latest app config that uses the new version tag as it's docker_image value, from here on Nebula will take care of the rest by doing the following: 19 | 1. Nebula manager will update the MongoDB backend with the new config. 20 | 2. after the configurable "cache_time" expires (10 seconds by default) all the managers will contact MongoDB and receive the updated config. 21 | 3. All the relevant IoT devices will receive the updated config and match their device status to the needed config. 22 | 23 | It's worth mentioning the follow: 24 | 25 | * MongoDB needs to be accessible only from the managers, not the workers - it will work perfectly even when using the Internet rather then LAN and will tolerate disconnects with no issues, due to monotonic ID's in use the workers will simply sync up to the latest needed configuration upon the network reconnects. 26 | * Nebula is fail hard, Nebula worker container issues will result with it killing itself in order for it to be restarted via Docker engine `--restart=always` flag, Nebula will then proceed to treat the IoT device as a new device and will follow the steps described above to get it in sync with the rest of the cluster. 27 | * Each part of the system can scale out - MongoDB can be sharded and replicated, the managers are stateless so can be increased as needed and there is no limit for the amount of workers as long as you make sure to scale out the other components to handle it. 28 | * Nebula ensures consistency among all workers as long as the backend MongoDB is consistent, if for some reason you get a split brain in either or any other form or consistency issues Nebula cannot guarantee consistency so make sure to follow best practice in both to avoid those risks from happening. 29 | * Nebula is eventually consistent, all workers will sync to the latest config but it might take up to "nebula_manager_check_in_time" + "device_group" seconds (40 seconds by default) for that to happen 30 | 31 | ### IoT deployment with the optional reporting system 32 | 33 | ![example nebula architecture](../pictures/nebula%20v2%20-%20iot%20-%20optional%20reporter.png "example nebula architecture") 34 | 35 | The optional reporting is an additive system (meaning all of the above is also true for it), what changes about it is as following: 36 | 37 | 1. The workers send their current state to a Kafka cluster after every sync with the manager. 38 | 2. The "reporter" component (it's own microservice) pulls from Kafka and populate the the state data into the backend DB 39 | 3. the manager can query the new state data from the backend DB to let the admin know the state of managed devices. 40 | 41 | ## Large scale webapp deployment 42 | 43 | ![example nebula architecture](../pictures/cloudcraft%20-%20nebula.png "example nebula architecture") 44 | 45 | The following design uses nebula to manage thousands of webservers for a very large scale webapp, while the entire flow described in the IoT deployment above is also correct for this design it expends on it in the following ways: 46 | 47 | * Rather then being distributed all apps are in the same VPC\DC 48 | * In front of all of those thousands of workers there is an LB layer which distributes requests among all of the servers, depending on your preference it can be an ELB\HAProxy\Nginx, DNS level LB, floating IP or any other LB method. 49 | * Each server consists of an internal LB (which is in itself an Nebula app) which routes the requests arriving to that server between the webapp containers running on it 50 | * Each server has multiple webapp containers to better utilize all of it resources which are all the same Nebula app (for example the `containers_per` config has the value of `{"cpu": 2}` which will then ensure each server will have 2 webapp containers per CPU core) 51 | -------------------------------------------------------------------------------- /docs/auto-update-workers.md: -------------------------------------------------------------------------------- 1 | # Automatically update workers 2 | 3 | !!! warning 4 | Automatically updating workers is not recommended for production use. 5 | 6 | If you want to have the worker containers Automatically update you can set them to use the "latest" tag of the worker and run the following nebula cron_job which uses [ouroboros](https://github.com/pyouroboros/ouroboros) to ensure the worker containers are updated whenever a newer version is released. 7 | 8 | ```bash 9 | curl -X POST \ 10 | http://your_nebula_manager_fqdn/api/v2/cron_jobs/auto_upgrade_workers \ 11 | -H 'Content-Type: application/json' \ 12 | -H 'Authorization: Bearer your_bearer_token' \ 13 | -H 'cache-control: no-cache' \ 14 | -d '{ 15 | "env_vars": {"RUN_ONCE": "true", "MONITOR":"worker", "CLEANUP":"true"}, 16 | "docker_image" : "pyouroboros/ouroboros", 17 | "running": true, 18 | "volumes": ["/var/run/docker.sock:/var/run/docker.sock"], 19 | "networks": ["nebula", "bridge"], 20 | "devices": [], 21 | "privileged": false, 22 | "schedule": "0 * * * *" 23 | }' 24 | ``` 25 | 26 | Make sure to change the following to suit your need: 27 | 28 | * your_nebula_manager_fqdn - the FQDN where you connect to your nebula manager. 29 | * MONITOR envvar - will need to be the same as the container name you give your worker ("worker" in this example). 30 | * "schedule" - will need to be a valid cron of when you want the auto update check to take place at. 31 | * "your_bearer_token" - the token to auth to your nebula manager, basic auth can also be used by switching from Bearer to Basic. 32 | 33 | You will then need to add the new cron_job to every device_group you want the workers of to be auto_updated, for example: 34 | 35 | ```bash 36 | curl -X PUT \ 37 | http://your_nebula_manager_fqdn/api/v2/device_groups/device_group_you_want_to_auto_update_worker/update \ 38 | -H 'Authorization: Bearer your_bearer_token' \ 39 | -H 'Content-Type: application/json' \ 40 | -H 'cache-control: no-cache' \ 41 | -d '{ 42 | "cron_jobs": ["auto_upgrade_workers"] 43 | }' 44 | ``` 45 | 46 | Make sure to change the following to suit your need: 47 | 48 | * your_nebula_manager_fqdn - the FQDN where you connect to your nebula manager. 49 | * device_group_you_want_to_auto_update_worker - the name of the device_group you want to have auto updated. 50 | * "your_bearer_token" - the token to auth to your nebula manager, basic auth can also be used by switching from Bearer to Basic. 51 | -------------------------------------------------------------------------------- /docs/best-practice.md: -------------------------------------------------------------------------------- 1 | ### What to monitor? 2 | 3 | It's best to monitor the following components: 4 | 5 | * MongoDB - following MongoDB best practices. 6 | * Docker service - on all hosts. 7 | * Docker manager container - check that the manager container is running. 8 | * Docker manager - a API endpoint for monitoring the status is available at `/api/status`, consult the [api](https://nebula.readthedocs.io/en/latest/api/general/#get-api-status) docs for more info. 9 | * Docker worker container - check that the worker container is running on all worker nodes. 10 | * (Optional) routing layers - changes depending on your design. 11 | * (Optional) reporting system - follow Kafka best practice to monitor it & ensure that the reporting containers\services are running. 12 | * App containers - check that the app containers are running on your worker nodes - adding a HEALTHCHECK configuration to the Dockerfile will make Nebula automatically restart containers marked as "unhealthy" and is therefor highly recommended. 13 | * End2End network connections - if your app accepts HTTP\TCP\UDP requests best to check e2e connectivity as well. 14 | 15 | ### Securing Nebula 16 | 17 | In production environments it's important to keep the following in mind in order to provide the best security practices 18 | 19 | * Strong passwords (8+ chars made of combination of upper case, lower case, numbers & special characters) should be used in the API layer & MongoDB. 20 | * The manager support HTTPS stripping on the LB layer in front of it, it's recommended to use that configuration. 21 | * MongoDB also supports SSL, which is stored on a remote location should be considered to be used. 22 | * Only the manager (API layer) should be accessible to worker devices, the MongoDB backend should be accessible only from the manager. 23 | * Using the latest version of Nebula is always recommended, vulnerabilities in packages are always discovered & patched on a routine manner. 24 | * The API logs by default write each request to the API including the IP which originated the request. 25 | * (Optional) reporting system - use certificate based connections to Kafka. -------------------------------------------------------------------------------- /docs/ci-cd/drone.md: -------------------------------------------------------------------------------- 1 | There's a [Drone](https://drone.io/) plugin for deploying to [Nebula](http://nebula-orchestrator.github.io/) in a fully automated CI/CD fashion. 2 | 3 | Note that this plugin is only in charge of the deploying to Nebula part of the CI/CD, other steps in the drone.io pipeline will likely be needed to build the container from the source code of your repo & deploy it to a Docker registry (as well as testing it) with this plugin likely being the final step of the deployment. 4 | 5 | ## Usage 6 | 7 | This plugin can be used to deploy applications to a nebula server, it will create\update the given nebula tasks as needed. 8 | 9 | The below pipeline configuration demonstrates simple usage: 10 | 11 | !!! note 12 | In addition to the `.drone.yml` file you will need to create a `nebula.json` file that contains the nebula configuration as well as the "app_name" (for app) or "cron_job_name" (for cron_job) field. Please see [here](https://github.com/nebula-orchestrator/drone-nebula/blob/master/test/test_files/nebula.json) for an example. 13 | 14 | ```yaml 15 | kind: pipeline 16 | type: docker 17 | name: default 18 | 19 | steps: 20 | - name: nebula_deploy 21 | image: nebulaorchestrator/drone-nebula 22 | settings: 23 | nebula_host: my-nebula-host.com 24 | nebula_job_file: nebula.json 25 | ``` 26 | 27 | ### Value substitution 28 | 29 | Example configuration with values substitution: 30 | 31 | ```yaml 32 | kind: pipeline 33 | type: docker 34 | name: default 35 | 36 | steps: 37 | - name: nebula_deploy 38 | image: nebulaorchestrator/drone-nebula 39 | settings: 40 | nebula_host: my-nebula-host.com 41 | nebula_job_file: nebula.json 42 | my_image_tag: my_dynamic_image 43 | ``` 44 | 45 | In the nebula.json file (please note the $ before the PLUGIN_MY_IMAGE_TAG key): 46 | 47 | ```json 48 | { 49 | ... 50 | "image": "myrepo/myimage:$PLUGIN_MY_IMAGE_TAG", 51 | ... 52 | } 53 | ``` 54 | 55 | will result in: 56 | 57 | ```json 58 | { 59 | ... 60 | "image": "myrepo/myimage:my_dynamic_image", 61 | ... 62 | } 63 | ``` 64 | 65 | ## Parameter Reference 66 | 67 | | envvar | description | default value | required | 68 | |-----------------|--------------------------------------------------------------------------------|---------------|-----------| 69 | | nebula_host | The nebula server FQDN\IP | | yes | 70 | | nebula_job_file | The nebula configuration file location relative to the root folder of the repo | "nebula.json" | no | 71 | | nebula_username | The nebula basic_auth username to use | None | no | 72 | | nebula_password | The nebula basic_auth password to use | None | no | 73 | | nebula_token | The nebula token_auth token to use | None | no | 74 | | nebula_port | The nebula server port | 80 | no | 75 | | nebula_protocol | The nebula server protocol | "http" | no | 76 | | nebula_job_type | The type of nebula job, "app" or "cron_job" | "app" | no | 77 | -------------------------------------------------------------------------------- /docs/ci-cd/jenkins.md: -------------------------------------------------------------------------------- 1 | The best way to deploy to [Nebula](http://nebula-orchestrator.github.io/) from Jenkins in a fully automated CI/CD fashion is to use the [Drone](https://drone.io/) plugin in it's container form (Drone plugins are basically containers). 2 | 3 | Note that this plugin is only in charge of the deploying to Nebula part of the CI/CD, other steps in Jenkins will likely be needed to build the container from the source code of your repo & deploy it to a Docker registry (as well as testing it) with this plugin likely being the final step of the deployment. 4 | 5 | ## Usage 6 | 7 | This plugin can be used to deploy applications to a nebula server, it will create\update the given nebula tasks as needed. 8 | 9 | The below pipeline configuration demonstrates simple usage: 10 | 11 | !!! note 12 | In addition to the run command given below you will need to create a `nebula.json` file that contains the nebula configuration as well as the "app_name" (for app) or "cron_job_name" (for cron_job) field in your repo root. Please see [here](https://github.com/nebula-orchestrator/drone-nebula/blob/master/test/test_files/nebula.json) for an example. 13 | 14 | ```bash 15 | docker run -e PLUGIN_NEBULA_HOST=my-nebula-host.com -e PLUGIN_NEBULA_JOB_FILE=nebula.json -v $(pwd):/my_repo --workdir /my_repo nebulaorchestrator/drone-nebula 16 | 17 | ``` 18 | 19 | ### Value substitution 20 | 21 | Example configuration with values substitution: 22 | 23 | ```bash 24 | docker run -e my_image_tag=my_dynamic_image -e PLUGIN_NEBULA_HOST=my-nebula-host.com -e PLUGIN_NEBULA_JOB_FILE=nebula.json -v $(pwd):/my_repo --workdir /my_repo nebulaorchestrator/drone-nebula 25 | 26 | ``` 27 | 28 | In the nebula.json file (please note the $ before the PLUGIN_MY_IMAGE_TAG key): 29 | 30 | ```json 31 | { 32 | ... 33 | "image": "myrepo/myimage:$PLUGIN_MY_IMAGE_TAG", 34 | ... 35 | } 36 | ``` 37 | 38 | will result in: 39 | 40 | ```json 41 | { 42 | ... 43 | "image": "myrepo/myimage:my_dynamic_image", 44 | ... 45 | } 46 | ``` 47 | 48 | ## Parameter Reference 49 | 50 | | envvar | description | default value | required | 51 | |------------------------|--------------------------------------------------------------------------------|---------------|-----------| 52 | | PLUGIN_NEBULA_HOST | The nebula server FQDN\IP | | yes | 53 | | PLUGIN_NEBULA_JOB_FILE | The nebula configuration file location relative to the root folder of the repo | "nebula.json" | no | 54 | | PLUGIN_nebula_USERNAME | The nebula basic_auth username to use | None | no | 55 | | PLUGIN_NEBULA_PASSWORD | The nebula basic_auth password to use | None | no | 56 | | PLUGIN_NEBULA_TOEKN | The nebula token_auth token to use | None | no | 57 | | PLUGIN_NEBULA_PORT | The nebula server port | 80 | no | 58 | | PLUGIN_NEBULA_PROTOCOL | The nebula server protocol | "http" | no | 59 | | PLUGIN_NEBULA_JOB_TYPE | The type of nebula job, "app" or "cron_job" | "app" | no | 60 | -------------------------------------------------------------------------------- /docs/cli.md: -------------------------------------------------------------------------------- 1 | # Install 2 | the first step in using the nebulactl CLI tool is to install it, you do that by running the following command on a 64bit Linux OS: 3 | 4 | ```bash 5 | sudo wget https://github.com/nebula-orchestrator/nebula-cmd/raw/master/dist/nebulactl -O /usr/local/bin/nebulactl && sudo chmod +x /usr/local/bin/nebulactl 6 | ``` 7 | 8 | this install a single bin file in the /usr/local/bin path which makes it accessible from any path in the shell. 9 | 10 | # Login 11 | after installing "nebulactl" you have to configure it by pointing it to your cluster, you do it by running the following command 12 | 13 | ```bash 14 | nebulactl login --username --password --host --port <80> --protocol 15 | ``` 16 | 17 | or if you prefer a guided questions login just run: 18 | 19 | ```bash 20 | nebulactl login 21 | ``` 22 | 23 | either of this 2 methods creates a file in ~/.nebula.json with the login details, nebulactl checks this file every time it runs a command against the nebula API, also note that the file is per user so if you have multiple users you will have to either copy this file or run the `nebulactl login` command for each of them 24 | 25 | # Use 26 | the --help argument will give you the needed parameters for each command, most commands will also prompt interactively if a required parameter is missing to ease first time users. 27 | 28 | ```bash 29 | nebulactl --help 30 | 31 | Usage: nebulactl.py [OPTIONS] COMMAND [ARGS]... 32 | 33 | Connect to a Nebula orcherstrator management endpoint, Create Nebula apps 34 | and Manage them all from a simple CLI. 35 | 36 | Options: 37 | --version Show the version and exit. 38 | --help Show this message and exit. 39 | 40 | Commands: 41 | apps Manage nebula apps. 42 | cron-jobs Manage nebula cron_jobs. 43 | device-groups Manage nebula device_groups. 44 | login login to nebula 45 | logout logout of nebula, useful when you want to make sure to... 46 | ping check nebula api responds 47 | prune Prune images. 48 | reports List nebula device reports. 49 | user-groups Manage nebula user groups. 50 | users Manage nebula users. 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/compare2orchestrators.md: -------------------------------------------------------------------------------- 1 | # Nebula comparision to other orchestration platforms 2 | 3 | A common question is why need another orchestrator when there are many other popular options? 4 | 5 | The answer for that is that while the popular container orchestrators are great they have a few limitations which Nebula avoids: 6 | 7 | 1. Scale - even though this issue keep improving with all orchestrators Nebula approach allows for far greater scalability (alongside Mesos) 8 | 2. Multi region clusters - orchestrators tend to be latency sensitive, Nebula unique architecture makes it ideal to managing distributed apps (like CDN or IOT), while still maintaining agility 9 | 3. Managing clients appliances\IoT devices - this option is not covered by any of the current orchestrators as it's outside their use case scope 10 | 4. Config management - while Puppet\Chef\Ansible are great for config management and orchestrators are great for scaling containers Nebula can also be thought of as a docker config management system 11 | 12 | Attached below is a table comparision between Nebula and the popular options, info in it is correct to the time of writing. 13 | 14 | !!! tip 15 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 16 | 17 | | | Nebula | Mesos+Marathon\DC/OS | Kubernetes | Swarm | balena.io | 18 | |-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| 19 | | Optimal use case | Distributed systems orchestration and\or IoT deployments orchestration | DataCenter orchestration | DataCenter orchestration | DataCenter orchestration | IoT deployments orchestration | 20 | | Stateless masters | yes | yes | yes | no - data stored in local master raft consensus | unknown | 21 | | Worker nodes Scale limit | tens of thousands | tens of thousands | 1000-5000 depending on version | unknown | unknown | 22 | | Containers Scale limit | millions | millions | 120000 | unknown | unknown | 23 | | Health-check limits | unlimited - uses docker builtin health checks | depending on check type - https://mesosphere.com/blog/2017/01/05/introducing-mesos-native-health-checks-apache-mesos-part-1/ | unknown | unlimited - uses docker builtin health checks | unknown | 24 | | Multi region\DC workers | yes | possible but not recommended according to latest DC/OS docs | possible via multiple clusters controlled via an ubernetes cluster | yes | unknown | 25 | | Multi region\DC masters | yes - each master is only contacted when an API call is made | possible but extremely not recommended according to latest DC/OS docs | not possible - even with ubernetes each region masters only manage it's own regions | possible but not recommended do to raft consensus | unknown | 26 | | Designed for huge scales | yes | yes | if you consider 1000-5000 instances huge | unknown | unknown | 27 | | Full REST API | yes | yes | yes | partial - by default no outside endpoint is available | yes | 28 | | Self healing | yes | yes | yes | yes | yes | 29 | | Simple worker scaling up & down | yes | yes | yes | partial - scaling down cleanly requires an api call rather then just shutting down the server like the rest | semi - requires flushing a custom OS onto the device | 30 | | cron job management support | yes | yes | yes | no | no | 31 | | CLI | yes | yes | yes | yes | yes | 32 | | GUI | WIP | yes | yes | no | on managed service version | 33 | | Load Balancing | yes- supports bringing your own HAProxy\Nginx\etc in a 2 step process (the first between instances & the 2nd between containers on that instance) | yes - HTTP only for outside connections - marathon-lb, supports bringing your own otherwise | yes | yes - auto routes inside the cluster but you still need to LB between cluster nodes from the outside | no - IoT devices only | 34 | | Simple masters scaling up & down | yes - master is fully stateless | no | no | partial - simple as long as quorum remains in the process | unknown | 35 | | Simple containers scaling up & down | yes - single api call and\or adding\removing worker nodes | yes - single api call | yes - single api call | yes - single api call | unknown | 36 | | Modular design (or plugin support) | yes - every part does 1 thing only | yes - 2 step orchestrator | yes | yes | unknown | 37 | | Backend DB's | MongoDB | Zookeeper | EtcD | internal in masters | Postgres & Redis & S3| 38 | | Multiple apps share worker node | yes | yes | yes | yes | yes | 39 | | Distributed apps support | yes | no | no | no | yes | 40 | | Dynamic allocation of work containers | no | yes | yes | yes | no | 41 | | Changes processing time scalability | extremely short, each worker is unaffected from the rest | longish - must wait for an offer matching it requirements first which at complex clusters can take a bit | short - listens to EtcD for changes which is fast but the masters don't scale when the load does | longish - gossip protocol will get there in the end but might take the scenic route | unknown | 42 | | Type of containers supported | docker with possible future extension | docker, mesos universal container | docker with possible future extension | docker only | docker only - requires a custom OS on devices | 43 | | Key trade-offs | allows scales of Mesos with full health checks with very rapid deployments\changes while being unlimited to a single region\DC while being stable at the cost of changing apps per node require an envvar change & having lots of moving parts | battle proven orchestrator that's damn near impossible to break at the cost of speed of changes & sticking to a single zone (for clusters with requests counts smaller then a million in a single region this is an amazing solution) | the buzzword choice, very popular (so support & updates are great) but kinda forces you to do things the Google way & not nearly as scalable as some other choices | comes prebuilt with the docker engine so easy to set up but is kinda of a black box, also using GOSSIP only ensures eventual consistency so who knows when a requested change takes affect | designed for IoT so it shares a similar set of trade-offs to Nebula | 44 | | Recommended deployment method | run a docker container of it | complex and varies depending on your design | complex and varies depending on your design | prebuilt in docker engine so just a couple of commands | run the managed service of it | 45 | | Usual pricing strategy | FOSS - pay for infra only | FOSS - pay for infra only | managed - pay for infra + masters overhead management | FOSS - pay for infra only | managed - pay per device | -------------------------------------------------------------------------------- /docs/config/apps.md: -------------------------------------------------------------------------------- 1 | ## Configuring apps 2 | 3 | The following table shows the config variables used to set individual apps inside nebula (via the API): 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | field | type | default value | example value | description | 9 | |--------------------|--------------------------|--------------------------|--------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 10 | | starting_ports | list of int and\or dicts | [] | [{"85": "80"}, 443, 5555] | a list of starting ports to bind the work containers, if ints the host port & the container port will be the same value, if dict it will follow the {"host_port":"container_port"} format, note that due to JSON format if using a dict values must be passed as strings (with ""), if using ints values must not be passed as strings, mixing and matching is allowed, for example a worker server with 8 CPU's & containers_per={"cpu": 3} and starting_ports=[{"81": "80"}] will have 24 containers binding to port 81 to port 104, so your worker-node LB can bind to port 80 and redirect traffic among the container on ports 81...104 which are bounded on the host & redirect to port 80 inside the container, an HAProxy config example can be found at [example-config](https://github.com/nebula-orchestrator/nebula/blob/master/docs/haproxy.cfg), use [] for non | 11 | | containers_per | dict | {server: 1} | {"server": 3} or {"cpu": 0.5} or {"memory": 512} | the number of containers to run on each worker node, possible keys are {"server": int}, {instance": int} & {cpu": int/float}, "server" and "instance" are both the same and will load x number of containers on each node, cpu will load x containers per cpu on each node, "memory" or "mem" will both figure out an run an amount of containers on the workers so that on average each will have the X you set memory in mb for it to use so setting them to {"memory": 512} on a worker with 1024mb will result in 2 containers running of that app | 12 | | env_vars | dict | {} | {"test1": "test123", "example": "example123"} | a dict of envvars that will be passed to each work containers, use {} for non | 13 | | docker_image | string | none - must be declared | "registry.myprivatergistry.com:5000/nginx" | what docker image to run, note that it's currently not possible to set a different starting command then the one set in the container Dockerfile | 14 | | running | bool | true | true | true - app will run, false - stops said app | 15 | | networks | list | ["nebula", "bridge"] | ["nebula", "bridge"] | the networks containers will be part of, if you wish to use "host" or "none" networks make sure that they are alone in the list (["host"] or ["none"]), a default bridge user network named "nebula" is also added in any case which is not "host" or "none", the "nebula" network can either be added explicitly (["nebula", "example-net"]) or implicitly (["example-net"]) and will also be added if an empty list is set ([]), note that aside from the default "nebula" network (& Docker default networks of "bridge", "none", "host") you will have to create what networks you wish to use manually on the worker prior to using them, the main advantage of the default "nebula" user network over the "bridge" network is that it allows container name based discovery so if you have a server with 2 containers named "con1" and "con2" you can ping from "con1" to "con2" just by using "ping con2" from inside "con1" | 16 | | volumes | list | [] | ["/tmp:/tmp/1", "/var/tmp/:/var/tmp/1:ro"] | what volumes to mount inside the containers ,follows docker run -v syntax of host_path:container_path:ro/rw, use [] for non | 17 | | privileged | bool | false | false | true - app gets privileged permissions, false - no privileged permissions | 18 | | devices | list | [] | ["/dev/usb/hiddev0:/dev/usb/hiddev0:rwm"] | what devices to grant the containers access ,follows docker run --device of host_path:container_path:ro/rwm, use [] for non | 19 | | rolling_restart | bool | false | false | if the apps should be updated using a rolling restart or not, unless you configure the "containers_per" param to be higher then 1 container of the app on each device will have no affect | 20 | -------------------------------------------------------------------------------- /docs/config/cron_jobs.md: -------------------------------------------------------------------------------- 1 | ## Configuring cron_jobs 2 | 3 | The following table shows the config variables used to set individual cron_jobs inside nebula (via the API): 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | field | type | example value | default value | description | 9 | |--------------------|--------------------------|-----------------------------------------------|--------------------------|------------------------------------------------------------------------------------------------------------------------------| 10 | | env_vars | dict | {"test": "test123"} | {} | a dict of envvars that will be passed to each work containers, use {} for non | 11 | | docker_image | string | nginx | none - must be declared | what docker image to run | 12 | | running | bool | true | true | true - cron will be enabled, false - stops said cron | 13 | | volumes | list | [] | [] | what volumes to mount inside the containers ,follows docker run -v syntax of host_path:container_path:ro/rw, use [] for non | 14 | | devices | list | [] | [] | what devices to grant the containers access ,follows docker run --device of host_path:container_path:ro/rwm, use [] for non | 15 | | privileged | bool | false | false | true - cron gets privileged permissions, false - no privileged permissions | 16 | | schedule | string | 0 * * * * | none - must be declared | the schedule of the cron to run, follows standard linux cron schedule syntax | 17 | | networks | list | ["my_network"] | ["nebula", "bridge"] | the networks containers will be part of, if you wish to use "host" or "none" networks make sure that they are alone in the list (["host"] or ["none"]), a default bridge user network named "nebula" is also added in any case which is not "host" or "none", the "nebula" network can either be added explicitly (["nebula", "example-net"]) or implicitly (["example-net"]) and will also be added if an empty list is set ([]), note that aside from the default "nebula" network (& Docker default networks of "bridge", "none", "host") you will have to create what networks you wish to use manually on the worker prior to using them, the main advantage of the default "nebula" user network over the "bridge" network is that it allows container name based discovery so if you have a server with 2 containers named "con1" and "con2" you can ping from "con1" to "con2" just by using "ping con2" from inside "con1" | 18 | -------------------------------------------------------------------------------- /docs/config/device_groups.md: -------------------------------------------------------------------------------- 1 | ## Configuring device_groups 2 | 3 | The following table shows the config variables used to set individual device_groups inside nebula (via the API): 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | field | type | example value | description | 9 | |--------------------|--------------------------|-----------------------------------------------|----------------------------------------------------------------------------------------| 10 | | apps | list | ["app1", "app2"] | a list of apps that will run on each device that is part of the device_group | 11 | -------------------------------------------------------------------------------- /docs/config/manager.md: -------------------------------------------------------------------------------- 1 | ## Configuring Nebula manager 2 | 3 | The following table shows the config variables used to set nebula manager at start time, due to using [parse_it](https://github.com/naorlivne/parse_it) for config parsing you can use env_vars as well as JSON, YAML or TOML (and more) to configure the app provided they are in the config folder and have a correct file extension: 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | config file variable name | envvar variable name | default value | example value | type | description | required | 9 | |------------------------------------|----------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| 10 | | basic_auth_user | BASIC_AUTH_USER | | admin | string | the basic auth user used to secure the manager - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 11 | | basic_auth_password | BASIC_AUTH_PASSWORD | | P@ssw0rd | string | the basic auth password used to secure the api-manger - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 12 | | auth_token | AUTH_TOKEN | | ZDMwN2JmYjBmODliMDRmOTViZDlkYmJl | string | the bearer token to use to secure the api-manager - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 13 | | auth_enabled | AUTH_ENABLED | true | false | bool | defaults to true, if set to false will disable basic auth on nebula-api, setting to false is only recommended to be used if you are using an upstream LB\web server that handles the basic-auth for you instead | yes | 14 | | | ENV | prod | dev | string | envvar only, defaults to "prod", if set to "dev" will use flask built-in web server on port 5000 to make devs life a tad easier, unless your developing new features to nebula or hunting down a bug in it best to not include it at all | no | 15 | | mongo_url | MONGO_URL | | mongodb://mongo_user:mongo_pass@mongo_host:27017/?ssl=true&replicaSet=mongo_replica_set&authSource=mongo_auth_schema | string | mongo URI string | yes | 16 | | schema_name | SCHEMA_NAME | nebula | mongo_schema | string | mongo schema name | yes | 17 | | cache_time | CACHE_TIME | 10 | 30 | int | the amount of time (in seconds) the cache will be kept before the manager will check in with the backend DB to grab any changes, the higher this number the less frequent changes will take affect on the workers & the less load there will be on the DB | yes | 18 | | cache_max_size | CACHE_MAX_SIZE | 1024 | 2048 | int | the maximum number of device_groups that will be kept in cache, if you have more device_groups then this number the LRU device_group will be evicted from the cache so for best performance best to make sure this number is higher then the maximum amount of device_group | yes | 19 | | mongo_max_pool_size | MONGO_MAX_POOL_SIZE | 25 | 100 | int | the size of the connection pool between the manager and the backend MongoDB - a good rule of thumb is to have 3 for each device_group in the cluster but no more then 100 at most | yes | 20 | 21 | 22 | envvars take priority over variables set in the config/ files in case both are set (the registry user & pass values can also be set by using the standard "~/.docker/config.json" file and not setting them as envvars and the Nebula config file ), it's suggested to always wrap envvars values in quotation marks but it's only required if the envvar uses special characters (for example "mongodb://mongo_user:mongo_pass@mongo_host:27017/?ssl=true&replicaSet=mongo_replica_set&authSource=mongo_auth_schema"), some variables have defaults that will be used if they are not set as envvars and in the conf.json file. 23 | 24 | An example config file is located at "example_conf.json.example" at the /config/ folder of the manager github repo (and inside the containers of them by extension). 25 | 26 | The following table shows the path of each config file inside the docker containers: 27 | 28 | | container | config path inside container | example Dockerfile COPY command overwrite | 29 | |----------------|------------------------------|-------------------------------------------------| 30 | | manager | /www/config/conf.json | COPY config/conf.json /www/config/conf.json | 31 | 32 | As the manager uses gunicorn as the main application web-server inside the container there is a config.py at the container root folder which is pulled from the repo /config/config.py file, consult [gunicron guide](http://docs.gunicorn.org/en/stable/index.html) if you wish to change it's parameters. 33 | -------------------------------------------------------------------------------- /docs/config/reporter.md: -------------------------------------------------------------------------------- 1 | ## Configuring Nebula optional reporter 2 | 3 | The following table shows the config variables used to set nebula optional reporter at start time, due to using [parse_it](https://github.com/naorlivne/parse_it) for config parsing you can use env_vars as well as JSON, YAML or TOML (and more) to configure the app provided they are in the config folder and have a correct file extension: 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | config file variable name | envvar variable name | default value | example value | type | description | required | 9 | |------------------------------------|----------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| 10 | | kafka_bootstrap_servers | KAFKA_BOOTSTRAP_SERVERS | | mykafka.mydomain.com:9092 or empty | string | the FQDN\ip address of the bootstrap kafka nodes, if not set everything regarding the optional reporting system will be unused, setting it to any value is the trigger to turn on the reporting component of the workers | yes | 11 | | kafka_security_protocol | KAFKA_SECURITY_PROTOCOL | PLAINTEXT | PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL | string | Protocol used to communicate with the kafka brokers, valid values are PLAINTEXT, SSL, SASL_PLAINTEXT or SASL_SSL | no | 12 | | kafka_sasl_mechanism | KAFKA_SASL_MECHANISM | | PLAIN or empty | string | string picking sasl mechanism when security_protocol is SASL_PLAINTEXT or SASL_SSL. valid values are PLAIN or EMPTY, leaving empty\undefeind will mean sasl is not used | no | 13 | | kafka_sasl_plain_username | KAFKA_SASL_PLAIN_USERNAME | | mysaslusername or empty | string | the username to use to connect to the kafka brokers if kafka_sasl_mechanism is set to PLAIN & kafka_security_protocol is set to SASL_PLAINTEXT | no | 14 | | kafka_sasl_plain_password | KAFKA_SASL_PLAIN_PASSWORD | | mysaslpassword or empty | string | the password to use to connect to the kafka brokers if kafka_sasl_mechanism is set to PLAIN & kafka_security_protocol is set to SASL_PLAINTEXT | no | 15 | | kafka_ssl_keyfile | KAFKA_SSL_KEYFILE | | /mykeyfile or empty | string | path of SSL keyfile to connecto to the kafka brokers with if SSL is set to be used | no | 16 | | kafka_ssl_password | KAFKA_SSL_PASSWORD | | mysslpassword or empty | string | path of SSL keyfile password to connecto to the kafka brokers with if SSL is set to be used | no | 17 | | kafka_ssl_certfile | KAFKA_SSL_CERTFILE | | /mycertfile or empty | string | path of SSL certfile to connecto to the kafka brokers with if SSL is set to be used | no | 18 | | kafka_ssl_cafile | KAFKA_SSL_CAFILE | | /mycafile or empty | string | path of SSL cafile to connecto to the kafka brokers with if SSL is set to be used | no | 19 | | kafka_ssl_crlfile | KAFKA_SSL_CRLFILE | | /mycrlfile or empty | string | path of SSL crlfile to connecto to the kafka brokers with if SSL is set to be used | no | 20 | | kafka_sasl_kerberos_service_name | KAFKA_SASL_KERBEROS_SERVICE_NAME | kafka | kafka | string | the kerberos service name used to connect to the kafka brokers if kerberos is configured to be used | no | 21 | | kafka_sasl_kerberos_domain_name | KAFKA_SASL_KERBEROS_DOMAIN_NAME | kafka | kafka | string | the kerberos domain name used to connect to the kafka brokers if kerberos is configured to be used | no | 22 | | kafka_topic | KAFKA_TOPIC | nebula-reports | my-nebula-kafka-topic | string | the kafka topic name reports will be written to, it's up to the admin to ensure proper topic sizing\partitioning on the kafka side | no | 23 | | mongo_url | MONGO_URL | | mongodb://mongo_user:mongo_pass@mongo_host:27017/?ssl=true&replicaSet=mongo_replica_set&authSource=mongo_auth_schema | string | mongo URI string | yes | 24 | | schema_name | SCHEMA_NAME | nebula | mongo_schema | string | mongo schema name | yes | 25 | | mongo_max_pool_size | MONGO_MAX_POOL_SIZE | 25 | 100 | int | the size of the connection pool between the manager and the backend MongoDB - a good rule of thumb is to have 3 for each device_group in the cluster but no more then 100 at most | yes | 26 | | kafka_auto_offset_reset | KAFKA_AUTO_OFFSET_RESET | earliest | latest | string | the point to start pulling data from Kafka should the current data point is not avilable, must be either "earliest" or "latest" | no | 27 | | kafka_group_id | KAFKA_GROUP_ID | nebula-reporter-group | my-kafka-consumer-group | string | the group ID of the kafka consumers. | no | 28 | | mongo_report_ttl | MONGO_REPORT_TTL | 3600 | 1800 | int | the amount of time in seconds which the reports will be saved in the backend DB after being pulled from Kafka | no | 29 | 30 | 31 | envvars take priority over variables set in the config/* files in case both are set (the registry user & pass values can also be set by using the standard "~/.docker/config.json" file and not setting them as envvars and the Nebula config file ), it's suggested to always wrap envvars values in quotation marks but it's only required if the envvar uses special characters (for example "mongodb://mongo_user:mongo_pass@mongo_host:27017/?ssl=true&replicaSet=mongo_replica_set&authSource=mongo_auth_schema"), some variables have defaults that will be used if they are not set as envvars and in the conf.json file. 32 | 33 | An example config file is located at "example_conf.json.example" at the /config/ folder of the worker github repo (and inside the containers of them by extension). 34 | 35 | The following table shows the path of each config file inside the docker containers: 36 | 37 | | container | config path inside container | example Dockerfile COPY command overwrite | 38 | |----------------|------------------------------|--------------------------------------------------| 39 | | reporter | /reporter/config/conf.json | COPY config/conf.json /reporter/config/conf.json | 40 | -------------------------------------------------------------------------------- /docs/config/user_groups.md: -------------------------------------------------------------------------------- 1 | ## Configuring user_groups 2 | 3 | The following table shows the config variables used to set individual user_groups inside nebula (via the API): 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | field | type | example value | default value | description | 9 | |--------------------|--------------------------|-----------------------------------------------|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| 10 | | group_members | list | ["test123"] | [] | a list of users that are a part of the group | 11 | | pruning_allowed | bool | false | false | false - group members are not allowed to run prune commands, true - group members can run prune commands | 12 | | apps | dict | {"test": "rw", "test123": "ro"} | {} | a key\value dict of the name of the app and the permission level granted access to group members, ro - read only, rw - read\write | 13 | | cron_jobs | dict | {"test": "rw", "test123": "ro"} | {} | a key\value dict of the name of the cron_job and the permission level granted access to group members, ro - read only, rw - read\write | 14 | | device_groups | dict | {"test": "rw", "test123": "ro"} | {} | a key\value dict of the name of the device_group and the permission level granted access to group members, ro - read only, rw - read\write | 15 | | admin | bool | true | false | false - group members are normal users, true - group members are admins that can run any command | 16 | -------------------------------------------------------------------------------- /docs/config/users.md: -------------------------------------------------------------------------------- 1 | ## Configuring users 2 | 3 | The following table shows the config variables used to set individual users inside nebula (via the API): 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | field | type | example value | default value |description | 9 | |--------------------|--------------------------|-----------------------------------------------|---------------------------|-------------------------------------------------------------| 10 | | password | string | h340h49j3443h34 | none - must be declared | the password used to authenticate the user with basic auth | 11 | | token | string | v7s3agw1NXfkkUXz9WHMO_U1QS9xXs9ZEHoKETiNWQY | randomly generated | the token used to authenticate the user with bearer auth | 12 | -------------------------------------------------------------------------------- /docs/config/worker.md: -------------------------------------------------------------------------------- 1 | ## Configuring Nebula workers 2 | 3 | The following table shows the config variables used to set nebula worker at start time, due to using [parse_it](https://github.com/naorlivne/parse_it) for config parsing you can use env_vars as well as JSON, YAML or TOML (and more) to configure the app provided they are in the config folder and have a correct file extension: 4 | 5 | !!! tip 6 | The tables slides to to side for viewing it's full information (not clear do to the rtfd theme) 7 | 8 | | config file variable name | envvar variable name | default value | example value | type | description | required | 9 | |------------------------------------|----------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| 10 | | registry_auth_user | REGISTRY_AUTH_USER | None | user | string | the docker registry basic auth user, if not set or set to None (the default value) Nebula will attempt to use the standard registry config file that's located inside the container "~/.docker/config.json" file path (if you need multiple registries auth auth use this option) & if that's not configured will carry using no registry auth | no | 11 | | registry_auth_password | REGISTRY_AUTH_PASSWORD | None | P@ssw0rd | string | the docker registry basic auth password, if not set or set to None (the default value) Nebula will attempt to use the standard registry config file that's located inside the container "~/.docker/config.json" file path (if you need multiple registries auth auth use this option) & if that's not configured will carry using no registry auth | no | 12 | | registry_host | REGISTRY_HOST | https://index.docker.io/v1/ | https://my_registry.example.com:5000 | string | the docker registry FQDN or IP | yes | 13 | | max_restart_wait_in_seconds | MAX_RESTART_WAIT_IN_SECONDS | 0 | 5 | int | maximum time (in seconds) each worker server will wait before reloading the containers in case of restart\update (minimum time hard coded to 0 and each worker server will randomly choose between the that range to spread load on on the managers to avoid a roaring hoard) | yes | 14 | | nebula_manager_auth_user | NEBULA_MANAGER_AUTH_USER | | admin | string | the basic auth user used to secure the manager - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 15 | | nebula_manager_auth_password | NEBULA_MANAGER_AUTH_PASSWORD | | P@ssw0rd | string | the basic auth password used to secure manager - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 16 | | nebula_manager_auth_token | NEBULA_MANAGER_AUTH_TOKEN | | ZDMwN2JmYjBmODliMDRmOTViZDlkYmJl | string | the bearer token used to secure manager - unless you set auth_enabled=false you must configure either basic_auth (user & pass) or token auth | no | 17 | | nebula_manager_host | NEBULA_MANAGER_HOST | | mynebulaapi.exampledomain.com | string | the FQDN\IP of the Nebula manager - **Note**: you must configure either the nebula_manager_uri or the nebula_manager_host | no | 18 | | nebula_manager_port | NEBULA_MANAGER_PORT | 80 | 80 | int | the port of the Nebula manager | no | 19 | | nebula_manager_protocol | NEBULA_MANAGER_PROTOCOL | http | http | string | protocol used to contact the Nebula manager - http or https | no | 20 | | nebula_manager_uri | NEBULA_MANAGER_URI | | https://mynebulaapi.exampledomain.com:8080/nebulaManager | string | Complete URI of the nebula manager including the protocol, host FQDN/IP, port and path -**Note** you must configure either the nebula_manager_uri or the nebula_manager_host | no | 21 | | nebula_manager_request_timeout | NEBULA_MANAGER_REQUEST_TIMEOUT | 60 | 60 | int | the time (in seconds) to wait for a response from the Nebula manager before timing out | yes | 22 | | nebula_manager_check_in_time | NEBULA_MANAGER_CHECK_IN_TIME | 30 | 30 | int | the time (in seconds) the device will check in with the Nebula manager to see if any changes to the application happens, the lower this is the faster changes to any app or device_group will propagate to the device but the higher the load to the manager will be so more mangers will be needed | yes | 23 | | device_group | DEVICE_GROUP | | smart_fridge_device_group | string | the device group to attach a device to - each device can only exist in a single device_group but each device_group can have unlimited apps in it | yes | 24 | | reporting_fail_hard | REPORTING_FAIL_HARD | true | false | bool | part of the optional reporting system, if true any failures in the reporting system will fail hard and restart the worker and if false will attempt to continue, setting to false will mean that a lot of errors will need to be manually fixed by the admin | no | 25 | | report_on_update_only | REPORT_ON_UPDATE_ONLY | false | true | bool | part of the optional reporting system, if false(the default) will send all reports to kafka and if true will only send reports which have had a change in the device configuration in them. | no | 26 | | kafka_bootstrap_servers | KAFKA_BOOTSTRAP_SERVERS | | mykafka.mydomain.com:9092 or empty | string | part of the optional reporting system, the FQDN\ip address of the bootstrap kafka nodes, if not set everything regarding the optional reporting system will be unused, setting it to any value is the trigger to turn on the reporting component of the workers | no | 27 | | kafka_security_protocol | KAFKA_SECURITY_PROTOCOL | PLAINTEXT | PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL | string | part of the optional reporting system, Protocol used to communicate with the kafka brokers, valid values are PLAINTEXT, SSL, SASL_PLAINTEXT or SASL_SSL | no | 28 | | kafka_sasl_mechanism | KAFKA_SASL_MECHANISM | | PLAIN or empty | string | part of the optional reporting system, string picking sasl mechanism when security_protocol is SASL_PLAINTEXT or SASL_SSL. valid values are PLAIN or EMPTY, leaving empty\undefeind will mean sasl is not used | no | 29 | | kafka_sasl_plain_username | KAFKA_SASL_PLAIN_USERNAME | | mysaslusername or empty | string | part of the optional reporting system, the username to use to connect to the kafka brokers if kafka_sasl_mechanism is set to PLAIN & kafka_security_protocol is set to SASL_PLAINTEXT | no | 30 | | kafka_sasl_plain_password | KAFKA_SASL_PLAIN_PASSWORD | | mysaslpassword or empty | string | part of the optional reporting system, the password to use to connect to the kafka brokers if kafka_sasl_mechanism is set to PLAIN & kafka_security_protocol is set to SASL_PLAINTEXT | no | 31 | | kafka_ssl_keyfile | KAFKA_SSL_KEYFILE | | /mykeyfile or empty | string | part of the optional reporting system, path of SSL keyfile to connecto to the kafka brokers with if SSL is set to be used | no | 32 | | kafka_ssl_password | KAFKA_SSL_PASSWORD | | mysslpassword or empty | string | part of the optional reporting system, path of SSL keyfile password to connecto to the kafka brokers with if SSL is set to be used | no | 33 | | kafka_ssl_certfile | KAFKA_SSL_CERTFILE | | /mycertfile or empty | string | part of the optional reporting system, path of SSL certfile to connecto to the kafka brokers with if SSL is set to be used | no | 34 | | kafka_ssl_cafile | KAFKA_SSL_CAFILE | | /mycafile or empty | string | part of the optional reporting system, path of SSL cafile to connecto to the kafka brokers with if SSL is set to be used | no | 35 | | kafka_ssl_crlfile | KAFKA_SSL_CRLFILE | | /mycrlfile or empty | string | part of the optional reporting system, path of SSL crlfile to connecto to the kafka brokers with if SSL is set to be used | no | 36 | | kafka_sasl_kerberos_service_name | KAFKA_SASL_KERBEROS_SERVICE_NAME | kafka | kafka | string | part of the optional reporting system, the kerberos service name used to connect to the kafka brokers if kerberos is configured to be used | no | 37 | | kafka_sasl_kerberos_domain_name | KAFKA_SASL_KERBEROS_DOMAIN_NAME | kafka | kafka | string | part of the optional reporting system, the kerberos domain name used to connect to the kafka brokers if kerberos is configured to be used | no | 38 | | kafka_topic | KAFKA_TOPIC | nebula-reports | my-nebula-kafka-topic | string | part of the optional reporting system, the kafka topic name reports will be written to, it's up to the admin to ensure proper topic sizing\partitioning on the kafka side | no | 39 | 40 | 41 | envvars take priority over variables set in the config/* files in case both are set (the registry user & pass values can also be set by using the standard "~/.docker/config.json" file and not setting them as envvars and the Nebula config file ), it's suggested to always wrap envvars values in quotation marks but it's only required if the envvar uses special characters (for example "mongodb://mongo_user:mongo_pass@mongo_host:27017/?ssl=true&replicaSet=mongo_replica_set&authSource=mongo_auth_schema"), some variables have defaults that will be used if they are not set as envvars and in the conf.json file. 42 | 43 | An example config file is located at "example_conf.json.example" at the /config/ folder of the worker github repo (and inside the containers of them by extension). 44 | 45 | The following table shows the path of each config file inside the docker containers: 46 | 47 | | container | config path inside container | example Dockerfile COPY command overwrite | 48 | |----------------|------------------------------|--------------------------------------------------| 49 | | worker | /worker/config/conf.json | COPY config/conf.json /worker/config/conf.json | 50 | -------------------------------------------------------------------------------- /docs/contribute.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Being an open source project means any help offered will be greatly appreciated, below is a quick run through of how you 4 | can help 5 | 6 | ## Getting Started 7 | 8 | * Fork the latest branch of the component you want to contribute to: 9 | 10 | * [manager](https://github.com/nebula-orchestrator/worker) - the api endpoint through which Nebula is controlled, includes manager Dockerfile & entire code structure 11 | * [docs](https://github.com/nebula-orchestrator/docs) - docs (schematics, wishlist\todo's, and API doc) 12 | * [worker](https://github.com/nebula-orchestrator/manager) - the worker manager that manages individual Nebula workers, includes worker Dockerfile & entire code structure 13 | * [nebula-python-sdk](https://github.com/nebula-orchestrator/nebula-python-sdk) - a pythonic SDK for using Nebula 14 | * [nebula-cmd](https://github.com/nebula-orchestrator/nebula-cmd) - a CLI for using Nebula 15 | * [reporter](https://github.com/nebula-orchestrator/reporter) - an optional component used to populate status reports to the backend DB to allow the admin to know the status of the managed devices 16 | * [nebula-orchestrator.github.io](https://github.com/nebula-orchestrator/nebula-orchestrator.github.io) - the Jekyll based main website 17 | 18 | 19 | * Make sure you have a [GitHub account](https://github.com/signup/free) 20 | * Use virtualenv to install all requirements from the requirements.txt file 21 | * Fix an issue \ add a feature 22 | * Create a pull request 23 | 24 | ## Design philosophy 25 | Nebula is designed with the following philosophy in mind, any feature\pull requests will be judged against the following: 26 | 27 | * Follow Linux philosophy and have each component do one thing & one thing only. 28 | * Each component needs to be possible to be scaled out to extremely large sizes. 29 | * Reliability is more important then shiny new features. 30 | * No vendor\cloud lock-in, if it's only available in one cloud it will not be used. 31 | * No latency sensitivity, assume workers to have a below average internet access and are in the other side of the world. 32 | 33 | ### Documentation 34 | 35 | Nebula docs are hosted at [readthedocs](http://nebula.readthedocs.io/en/latest/) using [MkDocs](http://www.mkdocs.org/) for their creation, reading them is highly recommended 36 | prior to making any pull requests 37 | 38 | ## What you can help with 39 | 40 | * Documentation - everyone hates them but without them would you be able to figure out how to use Nebula? 41 | * Bug fixes / feature requests - anything off github issues lists 42 | * Submitting tickets - even if you don't have the time\knowledge to fix a bug just opening a github issue about it will greatly help 43 | * Suggesting improvements 44 | * Spreading the word 45 | 46 | ### Summary 47 | 48 | * Your awesome for helping, thanks. 49 | 50 | P.S. 51 | Don't forget to add yourself to to CONTRIBUTORS.md file. -------------------------------------------------------------------------------- /docs/help.md: -------------------------------------------------------------------------------- 1 | # Where to find help? 2 | 3 | So you read the entire Nebula documentation, maybe even tried it out but you still have questions unanswered and your wandering where\how is the best way to look for help? 4 | Attached below are some of possible answers. 5 | 6 | 7 | ## GitHub Issues 8 | 9 | GitHub issue ticket system is a great tool for FOSS projects, if your problem can be pin pointed to one of Nebula components consider going over the open\closed ticket lists of that component or open a new one to describe your issue: 10 | 11 | * [manager](https://github.com/nebula-orchestrator/worker/issues) - the api endpoint through which Nebula is controlled, includes manager Dockerfile & entire code structure 12 | * [docs](https://github.com/nebula-orchestrator/docs/issues) - docs (schematics, wishlist\todo's, and API doc) 13 | * [worker](https://github.com/nebula-orchestrator/manager/issues) - the worker manager that manages individual Nebula workers, includes worker Dockerfile & entire code structure 14 | * [nebula-python-sdk](https://github.com/nebula-orchestrator/nebula-python-sdk/issues) - a pythonic SDK for using Nebula 15 | * [nebula-cmd](https://github.com/nebula-orchestrator/nebula-cmd/issues) - a CLI for using Nebula 16 | * [nebula-orchestrator.github.io](https://github.com/nebula-orchestrator/nebula-orchestrator.github.io/issues) - the Jekyll based main website 17 | * [reporter](https://github.com/nebula-orchestrator/reporter/issues) - an optional component used to populate status reports to the backend DB to allow the admin to know the status of the managed devices 18 | 19 | 20 | ## Google MailGroup 21 | 22 | There is a Google MailGroup you can email at [nebula-orchestrator@googlegroups.com](mailto:nebula-orchestrator@googlegroups.com) if you have questions that are more generic & not about a specific component, the mailgroup forums\history is available [here](https://groups.google.com/d/forum/nebula-orchestrator). 23 | 24 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ***Welcome to Nebula Documentation*** 2 | 3 | ![Nebula-logo](pictures/logos/nebula-logo.png "Nebula-logo") 4 | 5 | # Description 6 | 7 | [Nebula](https://nebula-orchestrator.github.io) is a open source project created for Docker orchestration and designed to manage massive clusters at scale, it achieves this by scaling each project component out as far as required. 8 | The project’s aim is to act as Docker orchestrator for IoT devices as well as for distributed services such as CDN or edge computing. 9 | Nebula is capable of simultaneously updating tens of thousands of IoT devices worldwide with a single API call in an effort to help devs and ops treat IoT devices just like distributed Dockerized apps. 10 | 11 | Among other things Nebula allows to: 12 | 13 | 1. Change ports. 14 | 2. Change envvars. 15 | 3. Stop\start\restart\rolling restart containers. 16 | 4. Force pull updated containers. 17 | 5. Change # of containers running per core/memory/instance. 18 | 6. Change image used. 19 | 7. Manage multiple apps over different worker servers, each server "device_group" can have an unlimited amount of apps added\removed from it which will then be picked up by all devices that are part of that "device_group". 20 | 8. Mount volumes. 21 | 9. Set containers with privileged permissions. 22 | 10. Mount devices . 23 | 11. Control containers network affiliation. 24 | 12. Auto integrate with Dockerfile healthchecks to restart unhealthy containers. 25 | 26 | There are 2 custom created services that are mandatory: 27 | 28 | 1. manager - a REST API endpoint to control nebula, fully stateless (all data stored in DB only). 29 | 2. worker - a container which periodically checks in with the manager and manages the worker server it runs on, one has to run on each worker, fully stateless. 30 | 31 | There is also an optional third component (the reporter) which can be added to allow managed devices be quried about their state (this also requires adding a Kafka cluster to the design). 32 | 33 | Due to clever use of TTL based [memoization](https://en.wikipedia.org/wiki/Memoization) it's possible to manage millions of devices with a single Nebula cluster without overloading the backend DB (or having it ridiculously large) & due to Kafka inspired monotonic ID you can rest easy knowing that the managed devices will always match the most recent configuration. 34 | 35 | # Example use cases 36 | 37 | 1. Apps with resource and\or traffic requirements so massive other orchestrators can't handle (thousands of servers and\or tens or even hundreds of millions of requests per minute) 38 | 2. Managing apps that spans multiple regions and\or clouds from a single source with a single API call 39 | 3. IOT\POS\client deployments - a rather inventive use case which can allow you to deploy a new version to all of your clients (even if they range in the thousands) appliances with a single API call in minutes 40 | 4. SAAS providers - if you have a cluster per client (as you provide them with managed "private" instances) or such Nebula allows you to push new versions all your clients managed instances at once 41 | 5. A form of docker configuration management, think of it as a cross between Docker-Compose to Puppet\Chef only it also pushes changes in configurations to all managed servers. 42 | 43 | # Repo folder structure 44 | 45 | * [manager](https://github.com/nebula-orchestrator/manager) - the api endpoint through which Nebula is controlled, includes manager Dockerfile & entire code structure 46 | * [docs](https://github.com/nebula-orchestrator/docs) - docs (schematics, wishlist\todo's, and API doc) 47 | * [worker](https://github.com/nebula-orchestrator/worker) - the worker manager that manages individual Nebula workers, includes worker Dockerfile & entire code structure 48 | * [nebula-python-sdk](https://github.com/nebula-orchestrator/nebula-python-sdk) - a pythonic SDK for using Nebula 49 | * [nebula-cmd](https://github.com/nebula-orchestrator/nebula-cmd) - a CLI for using Nebula 50 | * [nebula-orchestrator.github.io](https://github.com/nebula-orchestrator/nebula-orchestrator.github.io/issues) - the Jekyll based main website 51 | * [reporter](https://github.com/nebula-orchestrator/reporter) - an optional component used to populate status reports to the backend DB to allow the admin to know the status of the managed devices 52 | 53 | # docker hub repos 54 | 55 | * [manager](https://hub.docker.com/r/nebulaorchestrator/manager/) - prebuilt docker image of the manager 56 | * [worker](https://hub.docker.com/r/nebulaorchestrator/worker/) - prebuilt docker image of the worker 57 | * [reporter](https://hub.docker.com/r/nebulaorchestrator/reporter/) - prebuilt docker image of the optional reporter 58 | 59 | # Notices 60 | 61 | 1. This is an open source project, see attached license for more details. 62 | 2. While still being a young project Nebula is already seeing production use at multiple companies across a variety of industries. 63 | 3. Help is very much welcomed. 64 | 4. Tested OS: CoreOS, RancherOS, Ubuntu server 14.04 & 16.04, CentOS 6 & 7, Amazon linux, expected to work with any Docker compatible Linux distro. 65 | 5. Tested Docker versions: each Nebula version is tested on the latest Docker version at the time of it's release but any Docker version that has support for user networks should work with Nebula. 66 | 67 | # Example architecture 68 | 69 | Attached are 2 example for you to draw inspiration from when designing yours, a more detailed explanation of it can be found at the [architecture](architecture.md) page: 70 | 71 | ![example nebula architecture](pictures/cloudcraft%20-%20nebula%20-%20IoT.png "example nebula architecture") 72 | 73 | 74 | ![example nebula architecture](pictures/cloudcraft%20-%20nebula.png "example nebula architecture") 75 | 76 | 77 | ![example nebula architecture](pictures/nebula%20v2%20-%20iot%20-%20optional%20reporter.png "example nebula architecture") 78 | -------------------------------------------------------------------------------- /docs/installing/digital-ocean-global-example.md: -------------------------------------------------------------------------------- 1 | # Nebula on Digital Ocean global deployment example 2 | 3 | The [docker-compose tutorial](getting-started.md) is great for getting a feeling and doing local development on the Nebula API but as a repeated request has been to have a simple way to confirm Nebula global scalability a terrform module has been created which will do the following: 4 | 5 | - Install a MongoDB & Nebula manager on a single digital ocean droplet 6 | - Create multiple droplets (by default 9) over multiple digital ocean regions (a list of 9 different regions by default) 7 | - Create and configure an `example` app & device_group on Nebula 8 | 9 | ## Requirements: 10 | 11 | - terraform 0.12.0 or higher 12 | - [DIGITALOCEAN_TOKEN](https://www.terraform.io/docs/providers/do/index.html#token) envvar set to your digital ocean token 13 | - an ssh pub key pre uploaded to digital ocean 14 | - curl installed on the machine running terraform 15 | 16 | 17 | ## Configuration variables : 18 | 19 | - server_size - the size of the Nebula manager server - defaults to `2gb` 20 | - server_region_droplet - the region where the nebula manager server will reside - defaults to `nyc3` 21 | - ssh_key_name - the public ssh key as given in digital ocean that will be attached to the droplets, requires a single name - required 22 | - worker_count - the number of Nebula workers to create - defaults to `9` 23 | - worker_region_droplet - the regions where the workers will be deployed on - defaults to `["nyc1", "nyc3", "sfo2", "ams3", "sgp1", "lon1", "fra1", "tor1", "blr1"]` 24 | - worker_size - the size of the servers used in Nebula - note that at least 1GB is needed as it uses a RancherOS for simplicity sake - defaults to `2gb` 25 | - DIGITALOCEAN_TOKEN - the token used to connect to your digital ocean account - needs to be declared as an envvar - required 26 | 27 | Should you want to ssh to the droplets for any reason (not needed for the system to work) you can do so with the private key & the `centos` user for the manager and `rancher` user for the workers. 28 | 29 | ## Running instructions 30 | 31 | 1. [clone the github repo](https://github.com/nebula-orchestrator/nebula-digitalocean-global-deployment-example) 32 | 2. cd into the repo folder 33 | 3. Change the run.tf (in repo root folder) to your variables 34 | 4. run `terraform apply`. 35 | 36 | ## this can take 10-15 minutes for the manager to start as it has to install docker & docker-compose then download and run all containers, the initial boot of the workers is considerably faster but it might still be a couple of minutes after the terraform run completes. 37 | -------------------------------------------------------------------------------- /docs/installing/getting-started.md: -------------------------------------------------------------------------------- 1 | # Hello World tutorial 2 | 3 | The easiest way to get started is usually with a hands on approach, the following tutorial will use [docker-compose](https://docs.docker.com/compose/) to set a local Nebula cluster on your machine that includes MongoDB, the manager & the worker (which normally you will want be different devices but for testing this is sufficient), it of course requires docker & docker-compose installed so if you don't have them install them first. 4 | 5 | !!! tip 6 | You can run the following and skip to step 4 if you don't want to change the docker-compose to add a private Docker registry access: 7 | 8 | ```bash 9 | curl -L "https://raw.githubusercontent.com/nebula-orchestrator/docs/master/examples/hello-world/docker-compose.yml" -o docker-compose.yml && sudo docker-compose up -d 10 | ``` 11 | 12 | 13 | 1. First get the [docker-compose.yml](https://github.com/nebula-orchestrator/docs/blob/master/examples/hello-world/docker-compose.yml) of this tutorial and save it locally on your machine 14 | 2. Nebula is geared towards using a private registry but will also work with docker hub, to use your own user\pass (by default no auth is used) edit the docker-compose.yml by entering your docker hub user & password into "REGISTRY_AUTH_USER" & "REGISTRY_AUTH_PASSWORD" under the "worker" container, if your using a private registry change the "REGISTRY_HOST" variable as well to point to your private registry, if you are planning on only using public images you can keep the settings as is and use no Docker registry auth. 15 | 3. from the directory where you saved docker-compose.yml at (same name is important) run `docker-compose up -d` (you might need to `sudo su` first if you didn't set your user to be part of the docker group), don't worry if you see the worker & manager restarting, it's because the mongo container take a couple of seconds to initialize. 16 | 4. You now have a running Nebula cluster, lets use Curl to create an nginx app to fill the "example" app that we will run as part of our device_group: 17 | 18 | curl -X POST \ 19 | http://127.0.0.1/api/v2/apps/example \ 20 | -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 21 | -H 'cache-control: no-cache' \ 22 | -H 'content-type: application/json' \ 23 | -d '{ 24 | "starting_ports": [{"81":"80"}], 25 | "containers_per": {"server": 1}, 26 | "env_vars": {}, 27 | "docker_image" : "nginx", 28 | "running": true, 29 | "volumes": ["/tmp:/tmp/1", "/var/tmp/:/var/tmp/1:ro"], 30 | "networks": ["nebula"], 31 | "privileged": false, 32 | "devices": [], 33 | "rolling_restart": false 34 | }' 35 | 36 | 5. Now that we have an app let's create an the "example" device_group with the "example" app part of it by using another curl command: 37 | 38 | curl -X POST \ 39 | http://127.0.0.1/api/v2/device_groups/example \ 40 | -H 'Authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 41 | -H 'Content-Type: application/json' \ 42 | -H 'cache-control: no-cache' \ 43 | -d '{ 44 | "apps": [ 45 | "example" 46 | ] 47 | }' 48 | 49 | 6. Either wait for the changes to catch (usually few seconds at most) or restart the worker container, you now have your first nebula worker (try logging into 127.0.0.1:81 in your browser to see), because the network is internal in this tutorial you can only run more on the same machine (which kinda defeats the purpose) but after you deploy Nebula by following the [install](install.md) guide you can run as many workers as you need by having multiple servers running the same worker container with the same envvars\config file. 50 | 51 | ## One command run 52 | 53 | Running the following command will run the "Hello World" tutorial described above in an automated fashion, this makes it easier to play around with the API, it's still recommended to learn the tutorial above at least once to better understand the system install process and architecture: 54 | 55 | ```bash 56 | curl -L "https://raw.githubusercontent.com/nebula-orchestrator/docs/master/examples/hello-world/start_example_nebula_cluster.sh" -o start_example_nebula_cluster.sh && sudo sh start_example_nebula_cluster.sh 57 | ``` 58 | 59 | If you want to also have the optional reporting system run the following command instead, it's exectly the same like the one above only it also includes Zookeeper, Kafka & the optional reporter microservice configured, this will allow you to query the workers reports via the manager /reports API endpoint. 60 | 61 | ```bash 62 | curl -L "https://raw.githubusercontent.com/nebula-orchestrator/docs/master/examples/hello-world/optional_reporting_included/start_example_nebula_cluster.sh" -o start_example_nebula_cluster.sh && sudo sh start_example_nebula_cluster.sh 63 | ``` -------------------------------------------------------------------------------- /docs/installing/install.md: -------------------------------------------------------------------------------- 1 | # Nebula components 2 | 3 | Nebula is composed of the following components: 4 | 5 | * MongoDB - the database layer, the manager stays is the only component that needs to access the backend DB. 6 | * manager - this is the endpoint that manages Nebula, it updates the DB with any changes and is the endpoint where the workers query for any device_group\app changes. 7 | * worker - this is the container that manages worker nodes, it makes sures to keep all app in sync with the required configuration by checking in every (configruable) X seconds with the manager and updating it's status accordingly. 8 | 9 | Optionally you will also want to add the following if your use case is a massive scale web facing cluster in the same VPC\DC, not usually needed for a distributed system deployment: 10 | 11 | * A server layer load balancer - ELB works well for this, it job is to direct traffic between all worker nodes 12 | * A container layer load balancer - the recommended method is to create a nebula app with HAProxy\Nginx that will bind to the host network (not bridge) and will load balance requests to all containers on 127.0.0.1:containers_port 13 | 14 | # How to install 15 | 16 | The basic steps to getting Nebula to work is: 17 | 18 | 1. Create MongoDB, preferably a cluster & even a sharded cluster for large enough cluster 19 | 2. Create a database for Nebula on MongoDB & a user with read&write permissions for the api-manger, for example: 20 | 21 | use nebula 22 | db.createUser( 23 | { 24 | user: "nebula", 25 | pwd: "password", 26 | roles: [ "readWrite" ] 27 | } 28 | ) 29 | 30 | 3. Create your copy of the manager docker image, a base image is available at [docker-hub](https://hub.docker.com/r/nebulaorchestrator/manager/) with the "manager" tag (example: `docker pull nebulaorchestrator/manager`), either use it as a baseline FROM to create your own image or mount your own config file to replace the default one or use envvars to config it, consulate the [config](config/manager.md) for reference on the configuration values needed (and optional). 31 | 4. Create manager servers and have them run the manager container, make sure to open the manager ports on everything along the way & it's recommended having the restart=always flag set, preferably 2 at least load balanced between them for example: 32 | `/usr/bin/docker run -d -p 80:80 --restart=always --name nebula-manager ` 33 | 5. Create your copy of the worker docker image, a base image is available at docker hub at [docker-hub](https://hub.docker.com/r/nebulaorchestrator/worker/) with the "worker" tag (example: `docker pull nebulaorchestrator/worker`), either use it as a baseline FROM to create your own image or mount your own config file to replace the default one or use envvars to config it, consulate the [config](config/worker.md) for reference on the configuration values needed (and optional). 34 | 6. Create the worker servers and have them run the worker container, make sure to bind the docker socket & having the restart=always flag set is mandatory as nebula worker relies on containers restarts to reconnect to the manager, the container needs to run with an DEVICE_GROUP envvvar: 35 | `/usr/bin/docker run -d --restart=always -e DEVICE_GROUP="example-device-group" --name nebula-worker -v /var/run/docker.sock:/var/run/docker.sock ` 36 | * note that to make things easier a sample RancherOS [cloud-config](https://github.com/nebula-orchestrator/docs/blob/master/examples/rancheros/cloud-config) is provided, just change every variable marked inside <> and start a new server with it. 37 | 7. If used for a web based service & not an IoT deployment create the haproxy\lb on each worker server, the recommended method is to have it containerized and managed from inside nebula as another nebula app (possibly not needed for services not accepting outside requests or for small scale where just the outside LB will do), attached is an [example-config](https://github.com/nebula-orchestrator/nebula/blob/master/docs/haproxy.cfg). 38 | 8. If used for a web based service & not an IoT deployment create either an external LB\ELB to route traffic between the worker servers or route53\DNS LB between the servers. 39 | 9. Create the apps using the nebula API. 40 | 10. create the device_group with the same name as the one you gave the workers "DEVICE_GROUP" envvar and have it include the apps you created. 41 | 42 | 43 | # ARM version 44 | 45 | Both the API & the workers have an ARM64v8 version auto deployed to Docker Hub tagged as follows: 46 | 47 | * latest ARM version is tagged arm64v8 48 | * each numbered version ARM build larger then 1.4.0 has a tag with the version number that is suffixed with "-arm64v8" 49 | 50 | Other ARM versions are not currently auto built. 51 | 52 | # Optional reporting system 53 | 54 | The optional reporting systems requires a working Kafka cluster (and by extension a Zookeeper cluster), once you have that you will also need to add the following: 55 | 56 | * Have the workers configured with the "kafka_bootstrap_servers" configuration option, other kafka options are optional but this is the option which when configured tells the workers to start sending their reports 57 | * Add the optional [reporter micro-service](https://nebula.readthedocs.io/en/latest/config/reporter/) 58 | 59 | It's to the admin to ensure proper configurations of the Kafka topic & the number of partitions in it. -------------------------------------------------------------------------------- /docs/installing/packet-global-example.md: -------------------------------------------------------------------------------- 1 | # Nebula on Packet global deployment example 2 | 3 | The [docker-compose tutorial](getting-started.md) is great for getting a feeling and doing local development on the Nebula API but as a repeated request has been to have a simple way to confirm Nebula global scalability a terrform module has been created which will do the following: 4 | 5 | - Install a MongoDB & Nebula manager on a single packet devices 6 | - Create multiple devices (by default 5) over multiple packet facilities (a list of 5 different facilities by default) 7 | - Create and configure an `example` app & device_group on Nebula 8 | 9 | ## Running instructions 10 | 11 | 1. clone the repo 12 | 2. cd into the repo folder 13 | 3. Change the run.tf (in repo root folder) to your variables 14 | 4. run `terraform apply`. 15 | 16 | You now have a nebula cluster that includes a single manager and as many workers you gave it (default 9) spread out across packet regions (default 9 regions). 17 | 18 | ## Requires: 19 | 20 | - terraform 0.12.0 or higher 21 | - [PACKET_AUTH_TOKEN](https://www.terraform.io/docs/providers/packet/index.html) envvar set to your packet token 22 | - a packet organization 23 | - curl installed on the machine running terraform 24 | 25 | ## Configuration variables : 26 | 27 | - server_size - the size of the Nebula manager server - defaults to `c1.small.x86` 28 | - server_region_device - the region where the nebula manager server will reside - defaults to `ams1` 29 | - worker_count - the number of Nebula workers to create - defaults to `5` 30 | - worker_region_device - the regions where the workers will be deployed on - defaults to `["ams1","dfw2","ewr1","nrt1","sjc1"]` 31 | - worker_size - the size of the servers used in Nebula - note that at least 1GB is needed as it uses a RancherOS for simplicity sake - defaults to `c1.small.x86` 32 | - PACKET_AUTH_TOKEN - the token used to connect to your packet account - needs to be declared as an envvar - required 33 | 34 | Should you want to ssh to the devices for any reason (not needed for the system to work) you can do so with the private key & the `root` user for the manager and `rancher` user for the workers. 35 | 36 | ## this can take 10-15 minutes for the manager to start as it has to install docker & docker-compose then download and run all containers, the initial boot of the workers is considerably faster but it might still be a couple of minutes after the terraform run completes. 37 | -------------------------------------------------------------------------------- /docs/internals.md: -------------------------------------------------------------------------------- 1 | # Internal design of Nebula 2 | 3 | This is an advanced explanation on the logic behind using Nebula and how it ensures consistent application deployments at scale, You can safely skip this part of the guide if all you care about is deploying & using Nebula without knowing how it works, this part of the guide also assumes some knowledge of MongoDB. 4 | 5 | ## Motivation 6 | 7 | Nebula is Designed to allow orchestration & deployments of Containers to distributed systems (IoT deployments being a good example of a distributed system but also CDN, POS, etc...), this comes with several limitations which prevents the use of standard orchestration solutions: 8 | 9 | * Each app\service has to be bound to the specific hardware. 10 | * Network can't be counted on (latency, disconnects). 11 | * Scaling should be (virtually) unlimited. 12 | 13 | ## Persistence 14 | 15 | Nebula gracefully handle service crashes without losing any data do to it's reliance on production tested system to handle all data storage (MongoDB) & having all custom services (API & worker) being stateless by design. 16 | 17 | * MongoDB - MongoDB sharding should be enabled to ensure Persistence as long as the majority of the cluster is up. 18 | * workers - designed to fail hard & upon restart the workers follow a flow of pulling the latest config of their device_group & then starting to periodaclly check in with the managers for any changes, a Kafka inspired monotonic ID is attached to each change (app_id, device_group_id & prune_id) which ensures consistency in the changes & provides an addional protection against rolls back due to network delays returning a stale response. 19 | * managers - the managers syncs in periodically with the MongoDB backend regarding the device_group /info endpoint (the only one the deivces check in with) and stores them in a short term (default 10 seconds) memoize cache, this avoids overloading the backend MongoDB even with millions of devices, all other endpoints (that are typically only accessed for admin tasks) always immediately sync in with the backend DB, the monotonic ID's in use also provide assurance that only the latest change will be the one cached and synced to the devices despite the fact that each manager has it's own decentralized memoized cache. 20 | 21 | ## Backend DB selection 22 | 23 | Currently the only implemented Backend DB is MongoDB, the reason for it being the first implemented DB being the ease at which JSON can be changed while still providing the ability to scale out as needed. 24 | Future improvements will likely include the ability to use MariaDB & ETCD as other types of Backend DB. 25 | 26 | ## Scaling up vs Scaling out 27 | 28 | There are usually 2 way of scaling services, scaling up (getting bigger\faster machines) & scaling out (getting more machines), Nebula is firmly in the "scaling out" camp, the reason for that is simply do to having possible limitations of scaling up (there's a limit to how many CPU cores you can stick in a single server) there is no limit to how much you can scale out (you can always buy more machines), by design nebula ensures that each component of it can be scaled out independently from each other (making each component a micro-service in it's own rights). 29 | 30 | ## Push vs Pull 31 | 32 | Nebula is a pull based system, each worker periodically checks in with the master and pull the latest configuration which it then compares to it's existing local config & should any monotonic ID differ it will sync it's status to match the one received from the manager , this eliminates the need of keeping a list of worker addresses up to date in a centralized location & allows a much simpler way of adding\removing workers. 33 | 34 | ## Load Balancing 35 | 36 | In larger deployments there will likely be multiple of each component, each component can be load balanced: 37 | 38 | * MongoDB mongos acts as a load balancer for the MongoDB backend, load balancing between multiple mongos is possible using standard HTTP LB. 39 | * API managers - being a standard HTTP service the can be load balanced using standard HTTP LB, HTTPS stripping on the LB level is both possible and recommended. 40 | 41 | ## Fail hard vs Fail soft 42 | Nebula is fail hard, this means that on any error which isn't trivial (trivial being an error which can't affect consistency or future requests in any way) it will drop the entire service (both in the API managers & in the workers, depending on where the problem is), it is therefore necessary to ensure that both will always be restarted upon failure, in Docker engine this is achieved by having the `--restart` flag set to `unless-stopped`, the fail hard deign is a lot safer then fail soft as it removes risk of improper error handling. 43 | 44 | ## The API managers 45 | 46 | The managers provide 2 essential services, the first is being the RESTful API endpoint through which Nebula is managed, they do so by serving an HTTP rest interface, HTTP REST was chosen do to it being used by virtually any programming language in the world, SDK (for instance the Python SDK) simply provide a bridge to Nebula API & CLI tools are in turn built using those SDK. 47 | on top of this first essential service the manager also provide a special RESTful endpoint which is memoized and return the entire config a device needs to sync in with the latest state of a device_group, this endpoint is cached short and is contacted by the devices to sync with the latest version often. 48 | 49 | ## The workers 50 | 51 | Each worker follows the same basic steps: 52 | 53 | 1. At start contact the manager and get the needed config of a device that's part of it's configurable "device_group" 54 | 2. start all apps that are set to run on devices that are part of the "device_group" it's on 55 | 3. start another thread which checks the healthcheck configured in any app Dockerfile and restarts that container as needed 56 | 4. periodically (defined by the "nebula_manager_check_in_time" in param and by default every 30 seconds) check in with the manager and get the latest config 57 | 1. if any monotonic ID of the response received from the manager is larger then the one stored in the local configuration change the local configuration to match it 58 | 1. if an app_id is larger update the app as needed (stop\start\restart\update\etc) 59 | 2. if a device_group_id is larger update the apps by either starting the added app or removing a removed app from the device_group 60 | 3. if the prune_id is larger then run pruning of docker images 61 | 2. if any changes happened in the previous step save the newer configuration to the local config 62 | 63 | ## Cron jobs 64 | 65 | Each worker run also controls running cron_jobs containers, this allows for simple periodic jobs (such as disk cleaning) to take place without the needs for a container running non stop and hugging resources, the cron_jobs are scheduled with each worker check_in so there might be a delay of "nebula_manager_check_in_time" at most after the scheduled job time to it's actual time run. 66 | 67 | ## The optional reporting system 68 | 69 | The optional reporter system is Kafka based, this is really a classic use-case for Kafka, where a lot of devices each send a single report every X seconds with it's current state configuration, the flow for the reporting system goes from the workers to the Kafka, from there a "reporter" component populates the backend DB with the data which the manager instances can in turn query to retrieve to the admin the state of managed devices. -------------------------------------------------------------------------------- /docs/pictures/cloudcraft - nebula - IoT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nebula-orchestrator/docs/73b0f39266b04e97e510721f371804586a03b6b4/docs/pictures/cloudcraft - nebula - IoT.png -------------------------------------------------------------------------------- /docs/pictures/cloudcraft - nebula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nebula-orchestrator/docs/73b0f39266b04e97e510721f371804586a03b6b4/docs/pictures/cloudcraft - nebula.png -------------------------------------------------------------------------------- /docs/pictures/logos/nebula-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nebula-orchestrator/docs/73b0f39266b04e97e510721f371804586a03b6b4/docs/pictures/logos/nebula-logo.png -------------------------------------------------------------------------------- /docs/pictures/logos/nebula-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/pictures/nebula v2 - iot - optional reporter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nebula-orchestrator/docs/73b0f39266b04e97e510721f371804586a03b6b4/docs/pictures/nebula v2 - iot - optional reporter.png -------------------------------------------------------------------------------- /docs/release-notes.md: -------------------------------------------------------------------------------- 1 | ### Release notes 2 | 3 | Each component has it's own release notes page in the GitHub Release page 4 | 5 | * API - [GitHub Release page](https://github.com/nebula-orchestrator/manager/releases) 6 | * Worker - [GitHub Release page](https://github.com/nebula-orchestrator/worker/releases) 7 | * Python-SDK - [GitHub Release page](https://github.com/nebula-orchestrator/nebula-python-sdk/releases) 8 | * nebulactl (CMD) - [GitHub Release page](https://github.com/nebula-orchestrator/nebula-cmd/releases) 9 | * Documentation - [GitHub Release page](https://github.com/nebula-orchestrator/docs/releases) 10 | * Nebula website - [GitHub Release page](https://github.com/nebula-orchestrator/nebula-orchestrator.github.io/releases) 11 | * Reporter - [GitHub Release page](https://github.com/nebula-orchestrator/reporter/releases) 12 | -------------------------------------------------------------------------------- /docs/scaling.md: -------------------------------------------------------------------------------- 1 | # Scaling considerations 2 | 3 | Nebula was designed so that each component can scale out, below are some things to consider when designing your architecture. 4 | 5 | * There are no special configuration needed to scale out\up the manager or the worker, you simply add more as needed. 6 | * The manager is fully stateless, the recommended way to running it is inside a docker container on more then 1 server (for redundancy) with either a floating IP between them or behind a load balancer, requests to the API are made when a change is pushed (by admin\user or CI\CD tool) & it's also used for the workers sync, as such the required size & number of managers is depended on your frequency nebula managed devices check in with the master, keep in mind that a single manager can handle hundreds of devices due to effective memoization cache. 7 | * There is only a need for 1 worker per worker node as each worker can handle an unlimited amount of apps as part of the device_group, there is no hard limit on the amount of worker nodes you can manage with nebula provided you make sure to scale the other Nebula components to handle the required load. 8 | * Unless using for small scale it's recommended to increase the # of open files allowed on your managers to avoid the risk of running out of open connections. 9 | * MongoDB should be clustered with the data being replicated multiple times for large scales, preferring to read from secondaries(slaves) will greatly increase performance ,sharding is possible but it's a lot less of an issue as each app config is rather small on it's own. 10 | * Don't forget to consider how your going to scale out your routing layer, a load-balancer can get saturated just like a web app can. 11 | * the scale needed is determined by both the amount of workers you have and the frequency where they check in with the managers, if you have a device_group where you don't mind updates taking a bit longer it might be easier (not to mention cheaper) to increase the check in frequency rather then adding more managers. 12 | * if using the optional reporting system the Kafka cluster should be supported by multiple zookeeper nodes and have it's partitions replicated across multiple servers, it's up to the admin to ensure the Kafka topic is created with enough partitions to support the needed scale (keep in mind that the number of the "reporter" containers will be considerably less affective if they outnumber the number of Kafka partitions). 13 | 14 | # Stress test results 15 | 16 | Using [Siege](https://github.com/JoeDog/siege) a single manager has been stress tested against the device_group /info endpoint, due to it being the only endpoint a device checks in with this provide a good estimate to the performance of a single manager under heavy load, here are the results of 500 concurrent connections each repeating the request 100 times with no delay between them: 17 | 18 | ```bash 19 | Transactions: 50000 hits 20 | Availability: 100.00 % 21 | Elapsed time: 64.24 secs 22 | Data transferred: 20.12 MB 23 | Response time: 0.36 secs 24 | Transaction rate: 778.33 trans/sec 25 | Throughput: 0.31 MB/sec 26 | Concurrency: 281.08 27 | Successful transactions: 50000 28 | Failed transactions: 0 29 | Longest transaction: 12.54 30 | Shortest transaction: 0.00 31 | ``` 32 | 33 | This test results shows that a single manager can handle any of the following: 34 | 35 | * 466800 device checking in every 600 seconds with a 10 seconds cache 36 | * 46680 device checking in every 60 seconds with a 10 seconds cache 37 | * 23340 device checking in every 30 seconds with a 10 seconds cache 38 | * 7780 device checking in every 10 seconds with a 10 seconds cache 39 | 40 | Keep in mind that this is for a single manager, a Nebula cluster can scale the amount of managers out with near liner scalability so if you have a million devices you would still only need 22 manager containers to have them all kept in sync every minute (or you can use just 3 if you don't mind waiting 10 minutes for changes to catch on all devices). 41 | 42 | 43 | !!! note 44 | It should also be mentioned that Siege CPU usage was the limiting factor for this test which likely means that each manager can potentially handle a much larger number of requests\second but this provide a good rule of thumb for any number crunching needs. 45 | -------------------------------------------------------------------------------- /docs/sdk/python.md: -------------------------------------------------------------------------------- 1 | # Nebula-Python-SDK 2 | An SDK for managing [nebula](https://nebula-orchestrator.github.io/) via python. 3 | 4 | translates all of Nebula [API](https://nebula.readthedocs.io/en/latest/api/general/) calls to something more pythonic. 5 | 6 | Source code is available at [github](https://github.com/nebula-orchestrator/nebula-python-sdk) 7 | 8 | # How To Use 9 | first get NebulaPythonSDK onto your machine 10 | ```bash 11 | # Install from PyPi 12 | pip install NebulaPythonSDK 13 | ``` 14 | 15 | now use it in your code 16 | ```python 17 | # Load API wrapper from library 18 | from NebulaPythonSDK import Nebula 19 | 20 | # Create API object. 21 | # port defaults to 80, protocol defaults to "http" & request_timeout defaults to 60 if any of them is not set. 22 | connection = Nebula(username="your_nebula_user", password="your_nebula_pass", host="nebula.example.com", port=80, protocol="http", request_timeout=60) 23 | 24 | # List apps 25 | app_list = connection.list_apps() 26 | 27 | # List app info 28 | app_config = connection.list_app_info("app_name") 29 | 30 | # Create app 31 | app_conf = { 32 | "containers_per_cpu": 8, 33 | "env_vars": { 34 | "test": "blabla", 35 | "test3t2t32": "tesg4ehgee" 36 | }, 37 | "docker_ulimits": [], 38 | "networks": ["nebula"], 39 | "running": True, 40 | "rolling_restart": False, 41 | "volumes": ["/tmp:/tmp/1", "/var/tmp/:/var/tmp/1:ro"], 42 | "containers_per": { 43 | "cpu": 6 44 | }, 45 | "starting_ports": [ 46 | { 47 | "81": 80 48 | } 49 | ], 50 | "docker_image": "httpd", 51 | "privileged": False, 52 | "devices": [] 53 | } 54 | connection.create_app("app_name", app_conf) 55 | 56 | # create device group 57 | device_group_config = {"apps": ["app_name"]} 58 | connection.create_device_group("device_group_name", device_group_config) 59 | 60 | # list device group 61 | connection.list_device_group("device_group_name") 62 | 63 | # list device group info 64 | connection.list_device_group_info("device_group_name") 65 | 66 | # ping api 67 | connection.check_api() 68 | 69 | # delete app 70 | connection.delete_app("app_name") 71 | 72 | # stop app 73 | connection.stop_app("app_name") 74 | 75 | # start app 76 | connection.start_app("app_name") 77 | 78 | # restart app 79 | connection.restart_app("app_name") 80 | 81 | # update app 82 | connection.update_app("app_name", app_conf) 83 | 84 | # update app force all params - will reset all params to default values if not declared and raise an error for params 85 | # that are required but not given, similar to the POST update of the API 86 | connection.update_app("app_name", app_conf, force_all=True) 87 | 88 | # prune images on all device groups 89 | connection.prune_images() 90 | 91 | # delete device_group 92 | connection.delete_device_group("device_group_name") 93 | 94 | # prune images on a selected device groups 95 | connection.prune__device_group_images("device_group_name") 96 | 97 | # update device group 98 | connection.update_device_group("device_group_name", device_group_config) 99 | 100 | # list paginated reports 101 | connection.list_reports() 102 | 103 | # create a user 104 | user_config = {"password": "user_password", "token": "user_token"} 105 | connection.create_user("user_name", user_config) 106 | 107 | # list user info 108 | connection.list_user("user_name") 109 | 110 | # list all users 111 | connection.list_users() 112 | 113 | # update a user 114 | user_config = {"password": "new_password", "token": "new_token"} 115 | connection.update_user("user_name", user_config) 116 | 117 | # refresh a user token 118 | connection.refresh_user_token("user_name") 119 | 120 | # delete a user 121 | connection.delete_user("user_name") 122 | 123 | # create a user group 124 | user_group_config = { 125 | "group_members": [ 126 | "user_name" 127 | ], 128 | "pruning_allowed": True, 129 | "apps": { 130 | "app_name": "rw" 131 | }, 132 | "device_groups": { 133 | "device_group_name": "ro" 134 | }, 135 | "admin": False 136 | } 137 | connection.create_user_group("user_group_name", user_group_config) 138 | 139 | # list user group info 140 | connection.list_user_group("user_group_name") 141 | 142 | # list all users group 143 | connection.list_user_groups() 144 | 145 | # update a user group 146 | user_group_config = {"admin": False} 147 | connection.update_user_group("user_group_name", user_group_config) 148 | 149 | # delete a user group 150 | connection.delete_user_group("user_group_name") 151 | 152 | # list all cron jobs 153 | connection.list_cron_jobs() 154 | 155 | # delete a cron job 156 | connection.delete_cron_job("cron_job_name") 157 | 158 | # list a cron job 159 | connection.list_cron_job_info("cron_job_name") 160 | 161 | # create a cron job 162 | cron_job_config = { 163 | "env_vars": {"test": "test123"}, 164 | "docker_image" : "nginx", 165 | "running": True, 166 | "volumes": [], 167 | "networks": ["nebula", "bridge"], 168 | "devices": [], 169 | "privileged": False, 170 | "schedule": "0 * * * *" 171 | } 172 | connection.create_cron_job("cron_job_name", cron_job_config) 173 | 174 | # update a cron job 175 | cron_job_config = { 176 | "schedule": "5 * * * *" 177 | } 178 | connection.update_cron_job("cron_job_name", cron_job_config) 179 | 180 | # update a cron job force all params - will reset all params to default values if not declared and raise an error for 181 | # params that are required but not given, similar to the POST update of the API 182 | cron_job_config = { 183 | "schedule": "5 * * * *", 184 | "docker_image" : "nginx" 185 | } 186 | connection.update_cron_job("cron_job_name", cron_job_config, force_all=True) 187 | 188 | ``` 189 | -------------------------------------------------------------------------------- /docs/use.md: -------------------------------------------------------------------------------- 1 | After you have Nebula installed using it is rather straightforward, you make an API request to the manager every time you want to change one of the apps (deploying new version, update envvar, etc...), aside from that nebula will keep everything running with the latest version & if you want to scale out you simply add more servers of the component you want to add more. 2 | 3 | # Configuring Nebula 4 | 5 | Configuring can be done either via envvars or via replacing the attached config/conf.json to one with your own variables, more info about possible config variables & the config file location can be found at the [config page](http://nebula.readthedocs.io/en/latest/config/) 6 | 7 | # Creating & configuring apps 8 | 9 | Let's say your devices are a bunch of smart speakers (like echo dot or google home) and you want to manage them using Nebula: 10 | 11 | 1. first thing you will want to do is create an nebula app that will run the container of your smart speaker and all the needed parameters for it (frontpage for initial user configuration, envvars, etc), let's create an app named "smart_speaker" to do that: 12 | 13 | ``` 14 | POST /api/v2/apps/smart_speaker HTTP/1.1 15 | Host: 16 | Authorization: Basic 17 | Content-Type: application/json 18 | Cache-Control: no-cache 19 | 20 | { 21 | "starting_ports": [{"80": "80"}], 22 | "containers_per": {"server": 1}, 23 | "env_vars": {"SPEAKER_ENV": "prod"}, 24 | "docker_image" : "registry.awsomespeakersinc.com:5000/speaker:v25", 25 | "running": true, 26 | "volumes": ["/etc/speaker/conf:/etc/speaker/conf:rw"], 27 | "networks": ["nebula", "bridge"], 28 | "devices": [], 29 | "privileged": false, 30 | "rolling_restart": false 31 | } 32 | ``` 33 | 34 | 2. now that we have an app created we will need to attach said app to a device_group, each device_group consists of a list of apps that are designed to run on each device that is part of that device_group, let's create a device_group named "speakers" and attach it the "smart_speaker" app to it: 35 | 36 | ``` 37 | POST /api/v2/device_groups/speakers HTTP/1.1 38 | Host: 39 | Authorization: Basic 40 | Content-Type: application/json 41 | cache-control: no-cache 42 | { 43 | "apps": [ 44 | "smart_speaker" 45 | ] 46 | } 47 | ``` 48 | 49 | 3. now that we have the nebula app & device_group configured in nebula all that's left is to start the nebula worker container on each of the smart speaker devices and to have the "DEVICE_GROUP" envvar configured to "speakers" (can also be done via the configuration file) - this will tell the device it's part of the "speakers" device_group and will sync in with the managers to match it's running apps configuration to the one needed every (configurable) X seconds. 50 | 51 | Your done, each change you now make in nebula will be synced to all of your devices. 52 | 53 | # Scheduled cron jobs 54 | 55 | Similar to how apps are created cron jobs can also be scheduled to run on all workers: 56 | 57 | 1. we create a cron_job that manages the cron schedule, container image, envvar, etc - it's important to have that container exit when done, the following example will run every hour (0 * * * *): 58 | 59 | ``` 60 | POST /api/v2/cron_jobs/smart_speaker_cron HTTP/1.1 61 | Host: 62 | Authorization: Basic 63 | Content-Type: application/json 64 | Cache-Control: no-cache 65 | 66 | { 67 | "env_vars": {"RUN_ONCE": "true", "CLEANUP":"true"}, 68 | "docker_image" : "registry.awsomespeakersinc.com:5000/speaker_clean_up_cron:v7", 69 | "running": true, 70 | "volumes": ["/var/run/docker.sock:/var/run/docker.sock"], 71 | "networks": ["nebula", "bridge"], 72 | "devices": [], 73 | "privileged": false, 74 | "schedule": "0 * * * *" 75 | } 76 | ``` 77 | 78 | 2. we then add said cron to our device_group, as we already have a device_group for the smart speakers created in the previous step where we configured the main app we will update said device_group config: 79 | 80 | ``` 81 | PU /api/v2/device_groups/speakers/update HTTP/1.1 82 | Host: 83 | Authorization: Basic 84 | Content-Type: application/json 85 | cache-control: no-cache 86 | { 87 | "cron_jobs": [ 88 | "smart_speaker_cron" 89 | ] 90 | } 91 | ``` 92 | 93 | Now as the workers on all the smart speakers are already configured from the app step to be part of the "speakers" device_group they will all receive the configuration to run the new cron automatically without any additional steps needed. 94 | 95 | # Backup & restore 96 | 97 | As the only stateful part of the entire design is the MongoDB backing it up using any of the best practice methods available to it is sufficient, that being said it might be a good idea to also have your version of the manager & worker containers available in more then one registry in case of issues with your chosen registry supplier (or self hosted one). 98 | Restoring in case of a complete disaster is simply a matter of recreating all the components using the installing method described above and populating your MongoDB with the most recent backup of the MongoDB database. 99 | 100 | # Health checks 101 | 102 | Nebula utilizes Dockerfile builtin [healthcheck](https://docs.docker.com/engine/reference/builder/#healthcheck) capabilities, you configure them inside your Dockerfile and Nebula has an out of band process which looks every few seconds for any containers marked as unhealthy as a result of the healthcheck, any container found to be unhealthy is then restarted. 103 | 104 | !!! note 105 | The restart of a container at an unhealthy status is equivalent to running a "docker restart" with the docker CLI on it. 106 | -------------------------------------------------------------------------------- /examples/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # the following is an example for a nebula worker node HAPRoxy to route port 80 3 | # and ssl strip port 443 traffic (both configured as HTTP) & redirect said 4 | # traffic to 32 work containers that runs as a service on each worker node 5 | # as a service (not inside container), this is just an example so your config 6 | # will likely be different depending on your environment. 7 | ############################################################################### 8 | 9 | #--------------------------------------------------------------------- 10 | # Global settings 11 | #--------------------------------------------------------------------- 12 | global 13 | # to have these messages end up in /var/log/haproxy.log you will 14 | # need to: 15 | # 16 | # 1) configure syslog to accept network log events. This is done 17 | # by adding the '-r' option to the SYSLOGD_OPTIONS in 18 | # /etc/sysconfig/syslog 19 | # 20 | # 2) configure local2 events to go to the /var/log/haproxy.log 21 | # file. A line like the following can be added to 22 | # /etc/sysconfig/syslog 23 | # 24 | # local2.* /var/log/haproxy.log 25 | # 26 | log 127.0.0.1 local2 27 | 28 | nbproc 4 29 | cpu-map 1 0 30 | cpu-map 2 1 31 | cpu-map 3 2 32 | cpu-map 4 3 33 | 34 | chroot /var/lib/haproxy 35 | pidfile /var/run/haproxy.pid 36 | maxconn 300000 37 | user haproxy 38 | group haproxy 39 | daemon 40 | 41 | # turn on stats unix socket 42 | stats socket /var/lib/haproxy/stats 43 | 44 | #--------------------------------------------------------------------- 45 | # common defaults that all the 'listen' and 'backend' sections will 46 | # use if not designated in their block 47 | #--------------------------------------------------------------------- 48 | defaults 49 | mode http 50 | log global 51 | #option httplog 52 | option dontlognull 53 | option http-server-close 54 | option forwardfor #except 127.0.0.0/8 55 | option redispatch 56 | retries 3 57 | timeout http-request 30s 58 | timeout queue 1m 59 | timeout connect 10s 60 | timeout client 30s 61 | timeout server 30s 62 | timeout http-keep-alive 31s 63 | timeout check 10s 64 | maxconn 300000 65 | 66 | #--------------------------------------------------------------------- 67 | # HTTP frontend which proxys to the backends clusters 68 | #--------------------------------------------------------------------- 69 | frontend main 70 | bind *:80 71 | 72 | mode http 73 | #option httplog 74 | #option httpclose 75 | option http-server-close 76 | 77 | acl is_nebula dst_port 80 78 | 79 | 80 | use_backend nebula if is_nebula 81 | default_backend nebula 82 | 83 | #--------------------------------------------------------------------- 84 | # nebula backend for serving up our microservices 85 | #--------------------------------------------------------------------- 86 | backend nebula 87 | option httplog 88 | option httpclose 89 | option httpchk HEAD / 90 | http-check expect status 200 91 | option forwardfor 92 | 93 | balance static-rr 94 | maxconn 300000 95 | default-server inter 5s fall 1 rise 1 96 | server nebula-01 127.0.0.1:81 weight 30 maxconn 100 check 97 | server nebula-02 127.0.0.1:82 weight 30 maxconn 100 check 98 | server nebula-03 127.0.0.1:83 weight 30 maxconn 100 check 99 | server nebula-04 127.0.0.1:84 weight 30 maxconn 100 check 100 | server nebula-05 127.0.0.1:85 weight 30 maxconn 100 check 101 | server nebula-06 127.0.0.1:86 weight 30 maxconn 100 check 102 | server nebula-07 127.0.0.1:87 weight 30 maxconn 100 check 103 | server nebula-08 127.0.0.1:88 weight 30 maxconn 100 check 104 | server nebula-09 127.0.0.1:89 weight 30 maxconn 100 check 105 | server nebula-10 127.0.0.1:90 weight 30 maxconn 100 check 106 | server nebula-11 127.0.0.1:91 weight 30 maxconn 100 check 107 | server nebula-12 127.0.0.1:92 weight 30 maxconn 100 check 108 | server nebula-13 127.0.0.1:93 weight 30 maxconn 100 check 109 | server nebula-14 127.0.0.1:94 weight 30 maxconn 100 check 110 | server nebula-15 127.0.0.1:95 weight 30 maxconn 100 check 111 | server nebula-16 127.0.0.1:96 weight 30 maxconn 100 check 112 | server nebula-17 127.0.0.1:97 weight 30 maxconn 100 check 113 | server nebula-18 127.0.0.1:98 weight 30 maxconn 100 check 114 | server nebula-19 127.0.0.1:99 weight 30 maxconn 100 check 115 | server nebula-20 127.0.0.1:100 weight 30 maxconn 100 check 116 | server nebula-21 127.0.0.1:101 weight 30 maxconn 100 check 117 | server nebula-22 127.0.0.1:102 weight 30 maxconn 100 check 118 | server nebula-23 127.0.0.1:103 weight 30 maxconn 100 check 119 | server nebula-24 127.0.0.1:104 weight 30 maxconn 100 check 120 | server nebula-25 127.0.0.1:105 weight 30 maxconn 100 check 121 | server nebula-26 127.0.0.1:106 weight 30 maxconn 100 check 122 | server nebula-27 127.0.0.1:107 weight 30 maxconn 100 check 123 | server nebula-28 127.0.0.1:108 weight 30 maxconn 100 check 124 | server nebula-29 127.0.0.1:109 weight 30 maxconn 100 check 125 | server nebula-30 127.0.0.1:110 weight 30 maxconn 100 check 126 | server nebula-31 127.0.0.1:111 weight 30 maxconn 100 check 127 | server nebula-32 127.0.0.1:112 weight 30 maxconn 100 check 128 | 129 | #--------------------------------------------------------------------- 130 | # Statistics and Monitoring 131 | #--------------------------------------------------------------------- 132 | 133 | # you might want to change the IP below to a private IP address to be able to reach the status page from outside the server 134 | listen stats 127.0.0.1:8080 135 | mode http 136 | balance 137 | timeout client 5000 138 | timeout connect 4000 139 | timeout server 5000 140 | 141 | #This is the virtual URL to access the stats page 142 | stats uri /haproxy_stats 143 | 144 | #Authentication realm. This can be set to anything. Escape space characters with a backslash. 145 | stats realm HAProxy\ Statistics 146 | 147 | #The user/pass you want to use. Change this password! 148 | stats auth admin:password 149 | 150 | #This allows you to take down and bring up back end servers. 151 | #This will produce an error on older versions of HAProxy. 152 | stats admin if TRUE -------------------------------------------------------------------------------- /examples/hello-world/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mongo: 5 | container_name: mongo 6 | hostname: mongo 7 | image: mongo:4.0.1 8 | ports: 9 | - "27017:27017" 10 | restart: unless-stopped 11 | environment: 12 | MONGO_INITDB_ROOT_USERNAME: nebula 13 | MONGO_INITDB_ROOT_PASSWORD: nebula 14 | 15 | manager: 16 | container_name: manager 17 | hostname: manager 18 | depends_on: 19 | - mongo 20 | image: nebulaorchestrator/manager 21 | ports: 22 | - "80:80" 23 | restart: unless-stopped 24 | environment: 25 | MONGO_URL: mongodb://nebula:nebula@mongo:27017/nebula?authSource=admin 26 | SCHEMA_NAME: nebula 27 | BASIC_AUTH_PASSWORD: nebula 28 | BASIC_AUTH_USER: nebula 29 | AUTH_TOKEN: nebula 30 | 31 | worker: 32 | container_name: worker 33 | depends_on: 34 | - manager 35 | - mongo 36 | image: nebulaorchestrator/worker 37 | volumes: 38 | - /var/run/docker.sock:/var/run/docker.sock 39 | restart: unless-stopped 40 | hostname: worker 41 | environment: 42 | REGISTRY_HOST: https://index.docker.io/v1/ 43 | MAX_RESTART_WAIT_IN_SECONDS: 0 44 | NEBULA_MANAGER_AUTH_USER: nebula 45 | NEBULA_MANAGER_AUTH_PASSWORD: nebula 46 | NEBULA_MANAGER_HOST: manager 47 | NEBULA_MANAGER_PORT: 80 48 | NEBULA_MANAGER_PROTOCOL: http 49 | NEBULA_MANAGER_CHECK_IN_TIME: 5 50 | DEVICE_GROUP: example 51 | -------------------------------------------------------------------------------- /examples/hello-world/no_worker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mongo: 5 | container_name: mongo 6 | hostname: mongo 7 | image: mongo:4.0.1 8 | ports: 9 | - "27017:27017" 10 | restart: unless-stopped 11 | environment: 12 | MONGO_INITDB_ROOT_USERNAME: nebula 13 | MONGO_INITDB_ROOT_PASSWORD: nebula 14 | 15 | manager: 16 | container_name: manager 17 | hostname: manager 18 | depends_on: 19 | - mongo 20 | image: nebulaorchestrator/manager 21 | ports: 22 | - "80:80" 23 | restart: unless-stopped 24 | environment: 25 | MONGO_URL: mongodb://nebula:nebula@mongo:27017/nebula?authSource=admin 26 | SCHEMA_NAME: nebula 27 | BASIC_AUTH_PASSWORD: nebula 28 | BASIC_AUTH_USER: nebula 29 | AUTH_TOKEN: nebula 30 | -------------------------------------------------------------------------------- /examples/hello-world/optional_reporting_included/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mongo: 5 | container_name: mongo 6 | hostname: mongo 7 | image: mongo:4.0.1 8 | ports: 9 | - "27017:27017" 10 | restart: unless-stopped 11 | environment: 12 | MONGO_INITDB_ROOT_USERNAME: nebula 13 | MONGO_INITDB_ROOT_PASSWORD: nebula 14 | 15 | manager: 16 | container_name: manager 17 | hostname: manager 18 | depends_on: 19 | - mongo 20 | image: nebulaorchestrator/manager 21 | ports: 22 | - "80:80" 23 | restart: unless-stopped 24 | environment: 25 | MONGO_URL: mongodb://nebula:nebula@mongo:27017/nebula?authSource=admin 26 | SCHEMA_NAME: nebula 27 | BASIC_AUTH_PASSWORD: nebula 28 | BASIC_AUTH_USER: nebula 29 | AUTH_TOKEN: nebula 30 | 31 | worker: 32 | container_name: worker 33 | depends_on: 34 | - manager 35 | - kafka 36 | image: nebulaorchestrator/worker 37 | volumes: 38 | - /var/run/docker.sock:/var/run/docker.sock 39 | restart: unless-stopped 40 | hostname: worker 41 | environment: 42 | REGISTRY_HOST: https://index.docker.io/v1/ 43 | MAX_RESTART_WAIT_IN_SECONDS: 0 44 | NEBULA_MANAGER_AUTH_USER: nebula 45 | NEBULA_MANAGER_AUTH_PASSWORD: nebula 46 | NEBULA_MANAGER_HOST: manager 47 | NEBULA_MANAGER_PORT: 80 48 | NEBULA_MANAGER_PROTOCOL: http 49 | NEBULA_MANAGER_CHECK_IN_TIME: 5 50 | DEVICE_GROUP: example 51 | KAFKA_BOOTSTRAP_SERVERS: kafka:9092 52 | KAFKA_TOPIC: nebula-reports 53 | 54 | zookeeper: 55 | container_name: zookeeper 56 | hostname: zookeeper 57 | image: zookeeper:3.4.13 58 | ports: 59 | - 2181:2181 60 | restart: unless-stopped 61 | environment: 62 | ZOO_MY_ID: 1 63 | 64 | kafka: 65 | container_name: kafka 66 | hostname: kafka 67 | image: confluentinc/cp-kafka:5.1.2 68 | ports: 69 | - 9092:9092 70 | restart: unless-stopped 71 | depends_on: 72 | - zookeeper 73 | environment: 74 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 75 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 76 | KAFKA_BROKER_ID: 1 77 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 78 | 79 | reporter: 80 | container_name: reporter 81 | hostname: reporter 82 | depends_on: 83 | - mongo 84 | - kafka 85 | image: nebulaorchestrator/reporter 86 | restart: unless-stopped 87 | environment: 88 | MONGO_URL: mongodb://nebula:nebula@mongo:27017/nebula?authSource=admin 89 | SCHEMA_NAME: nebula 90 | BASIC_AUTH_PASSWORD: nebula 91 | BASIC_AUTH_USER: nebula 92 | KAFKA_BOOTSTRAP_SERVERS: kafka:9092 93 | KAFKA_TOPIC: nebula-reports 94 | -------------------------------------------------------------------------------- /examples/hello-world/optional_reporting_included/start_example_nebula_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # run the following to start the API, MongoDB & an example worker preconfigured to connect to an app named "example" all on one server 4 | sudo curl -L "https://raw.githubusercontent.com/nebula-orchestrator/docs/master/examples/hello-world/optional_reporting_included/docker-compose.yml" -o docker-compose.yml 5 | sudo docker-compose pull 6 | sudo docker-compose up -d 7 | 8 | # wait until the manager is online 9 | until $(curl --output /dev/null --silent --head --fail -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' -H 'cache-control: no-cache' http://127.0.0.1/api/v2/status); do 10 | echo "Waiting on the manager API to become available..." 11 | sleep 3 12 | done 13 | 14 | # run the curl below to create the example app 15 | echo "Creating an example app (creatively) named example" 16 | echo "" 17 | curl -X POST \ 18 | http://127.0.0.1/api/v2/apps/example \ 19 | -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 20 | -H 'cache-control: no-cache' \ 21 | -H 'content-type: application/json' \ 22 | -d '{ 23 | "starting_ports": [{"81":"80"}], 24 | "containers_per": {"server": 1}, 25 | "env_vars": {}, 26 | "docker_image" : "nginx", 27 | "running": true, 28 | "volumes": ["/tmp:/tmp/1", "/var/tmp/:/var/tmp/1:ro"], 29 | "networks": ["nebula"], 30 | "privileged": false, 31 | "devices": [], 32 | "rolling_restart": false 33 | }' 34 | 35 | echo "" 36 | 37 | # run the curl below to create the example device_group 38 | echo "Creating an example device_group (creatively) named example" 39 | curl -X POST \ 40 | http://127.0.0.1/api/v2/device_groups/example \ 41 | -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 42 | -H 'cache-control: no-cache' \ 43 | -H 'content-type: application/json' \ 44 | -d '{ 45 | "apps": ["example"] 46 | }' 47 | 48 | echo "" 49 | 50 | # wait until the example nginx is online 51 | until $(curl --output /dev/null --silent --head --fail -H 'cache-control: no-cache' http://127.0.0.1:81/); do 52 | echo "Waiting on the example work container to become available..." 53 | sleep 3 54 | done 55 | 56 | # give instructions on how to other other devices & a link to the documentation 57 | echo "" 58 | echo "Example nebula cluster is now ready for use" 59 | echo "" 60 | echo "Want more remote devices to join? just run the following on them:" 61 | echo "sudo docker run -d --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock --env DEVICE_GROUP=example --env REGISTRY_HOST=https://index.docker.io/v1/ --env MAX_RESTART_WAIT_IN_SECONDS=0 --env NEBULA_MANAGER_AUTH_USER=nebula --env NEBULA_MANAGER_AUTH_PASSWORD=nebula --env NEBULA_MANAGER_HOST= --env NEBULA_MANAGER_PORT=80 --env nebula_manager_protocol=http --env NEBULA_MANAGER_CHECK_IN_TIME=5 --name nebula-worker nebulaorchestrator/worker" 62 | echo "" 63 | echo "You can now connect to each device on port 81 via your browser to see and example nginx running" 64 | echo "" 65 | echo "Feel free to play around with Nebula API https://nebula.readthedocs.io/en/latest/api/ on port 80 with the basic auth user & pass being 'nebula' or to read more about it at https://nebula.readthedocs.io/en/latest/" 66 | -------------------------------------------------------------------------------- /examples/hello-world/start_example_nebula_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # run the following to start the API, MongoDB & an example worker preconfigured to connect to an app named "example" all on one server 4 | sudo curl -L "https://raw.githubusercontent.com/nebula-orchestrator/docs/master/examples/hello-world/docker-compose.yml" -o docker-compose.yml 5 | sudo docker-compose pull 6 | sudo docker-compose up -d 7 | 8 | # wait until the manager is online 9 | until $(curl --output /dev/null --silent --head --fail -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' -H 'cache-control: no-cache' http://127.0.0.1/api/v2/status); do 10 | echo "Waiting on the manager API to become available..." 11 | sleep 3 12 | done 13 | 14 | # run the curl below to create the example app 15 | echo "Creating an example app (creatively) named example" 16 | echo "" 17 | curl -X POST \ 18 | http://127.0.0.1/api/v2/apps/example \ 19 | -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 20 | -H 'cache-control: no-cache' \ 21 | -H 'content-type: application/json' \ 22 | -d '{ 23 | "starting_ports": [{"81":"80"}], 24 | "containers_per": {"server": 1}, 25 | "env_vars": {}, 26 | "docker_image" : "nginx", 27 | "running": true, 28 | "volumes": ["/tmp:/tmp/1", "/var/tmp/:/var/tmp/1:ro"], 29 | "networks": ["nebula"], 30 | "privileged": false, 31 | "devices": [], 32 | "rolling_restart": false 33 | }' 34 | 35 | echo "" 36 | 37 | # run the curl below to create the example device_group 38 | echo "Creating an example device_group (creatively) named example" 39 | curl -X POST \ 40 | http://127.0.0.1/api/v2/device_groups/example \ 41 | -H 'authorization: Basic bmVidWxhOm5lYnVsYQ==' \ 42 | -H 'cache-control: no-cache' \ 43 | -H 'content-type: application/json' \ 44 | -d '{ 45 | "apps": ["example"] 46 | }' 47 | 48 | echo "" 49 | 50 | # wait until the example nginx is online 51 | until $(curl --output /dev/null --silent --head --fail -H 'cache-control: no-cache' http://127.0.0.1:81/); do 52 | echo "Waiting on the example work container to become available..." 53 | sleep 3 54 | done 55 | 56 | # give instructions on how to other other devices & a link to the documentation 57 | echo "" 58 | echo "Example nebula cluster is now ready for use" 59 | echo "" 60 | echo "Want more remote devices to join? just run the following on them:" 61 | echo "sudo docker run -d --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock --env DEVICE_GROUP=example --env REGISTRY_HOST=https://index.docker.io/v1/ --env MAX_RESTART_WAIT_IN_SECONDS=0 --env NEBULA_MANAGER_AUTH_USER=nebula --env NEBULA_MANAGER_AUTH_PASSWORD=nebula --env NEBULA_MANAGER_HOST= --env NEBULA_MANAGER_PORT=80 --env nebula_manager_protocol=http --env NEBULA_MANAGER_CHECK_IN_TIME=5 --name nebula-worker nebulaorchestrator/worker" 62 | echo "" 63 | echo "You can now connect to each device on port 81 via your browser to see and example nginx running" 64 | echo "" 65 | echo "Feel free to play around with Nebula https://nebula.readthedocs.io on port 80 with the both the bearer token & basic auth user/pass being 'nebula' or to read more about it" 66 | -------------------------------------------------------------------------------- /examples/rancheros/cloud-config: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | ssh_authorized_keys: 3 | - ssh-rsa @rancher 4 | runcmd: 5 | - sudo hostname nebula--`openssl rand -hex 4`.nebula..com 6 | rancher: 7 | sysctl: 8 | net.ipv4.conf.default.rp_filter: 1 9 | net.ipv4.ip_forward: 0 10 | net.ipv4.conf.default.accept_source_route: 0 11 | kernel.sysrq: 0 12 | kernel.core_uses_pid: 1 13 | net.ipv4.tcp_syncookies: 1 14 | kernel.msgmnb: 65536 15 | kernel.msgmax: 65536 16 | kernel.shmmax: 68719476736 17 | kernel.shmall: 4294967296 18 | fs.file-max: 10000000 19 | fs.nr_open: 10000000 20 | net.ipv4.ip_local_port_range: 10000 65535 21 | net.ipv4.tcp_max_syn_backlog: 300000 22 | net.core.somaxconn: 10000 23 | net.core.rmem_max: 16777216 24 | net.ipv4.tcp_tw_reuse: 1 25 | net.core.wmem_max: 16777216 26 | net.ipv4.tcp_fin_timeout: 60 27 | registry_auths: 28 | https://index.docker.io/v1/: 29 | username: 30 | password: 31 | :: 32 | username: 33 | password: 34 | write_files: 35 | - path: /home/rancher/.docker/config.json 36 | permissions: "0755" 37 | owner: rancher 38 | content: | 39 | { 40 | "auths": { 41 | "https://index.docker.io/v1/": { 42 | "auth": "", 43 | "email": "" 44 | }, 45 | " :": { 46 | "auth": "" 47 | } 48 | } 49 | } 50 | 51 | - path: /root/.docker/config.json 52 | permissions: "0755" 53 | owner: rancher 54 | content: | 55 | { 56 | "auths": { 57 | "https://index.docker.io/v1/": { 58 | "auth": "", 59 | "email": "" 60 | }, 61 | " :": { 62 | "auth": "" 63 | } 64 | } 65 | } 66 | 67 | - path: /etc/rc.local 68 | permissions: "0755" 69 | owner: root 70 | content: | 71 | #!/bin/bash 72 | wait-for-docker 73 | docker run -d --restart=always -e DEVICE_GROUP= --name nebula-worker -v /var/run/docker.sock:/var/run/docker.sock 74 | sudo dd if=/dev/zero of=/swapfile bs=1k count=2000000 75 | sudo chmod 600 /swapfile 76 | sudo mkswap /swapfile 77 | sudo swapon /swapfile -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Nebula Container Orchestrator 2 | theme: readthedocs 3 | nav: 4 | - Home: index.md 5 | - Design: 6 | - Architecture: architecture.md 7 | - Internals: internals.md 8 | - Setting up: 9 | - Installing: 'installing/install.md' 10 | - Docker-compose localhost tutorial: 'installing/getting-started.md' 11 | - Globale cloud terraformed examples: 12 | - Digital Ocean: 'installing/digital-ocean-global-example.md' 13 | - Packet: 'installing/packet-global-example.md' 14 | - Configuring: 15 | - Using: use.md 16 | - Configuration settings: 17 | - 'config/apps.md' 18 | - 'config/device_groups.md' 19 | - 'config/manager.md' 20 | - 'config/worker.md' 21 | - 'config/reporter.md' 22 | - 'config/cron_jobs.md' 23 | - 'config/users.md' 24 | - 'config/user_groups.md' 25 | - Scaling: scaling.md 26 | - Controling: 27 | - CLI: cli.md 28 | - API: 29 | - General: 'api/general.md' 30 | - Apps: 'api/apps.md' 31 | - device_groups: 'api/device_groups.md' 32 | - users: 'api/users.md' 33 | - user_groups: 'api/user_groups.md' 34 | - cron_jobs: 'api/cron_jobs.md' 35 | - SDK: 36 | - Python: 'sdk/python.md' 37 | - Misc: 38 | - Automatically update workers: auto-update-workers.md 39 | - CI/CD: 40 | - Drone.io: 'ci-cd/drone.md' 41 | - Jenkins: 'ci-cd/jenkins.md' 42 | - Monitoring & Securing: best-practice.md 43 | - Nebula vs. Others: compare2orchestrators.md 44 | - Contributing: contribute.md 45 | - Where to get help: help.md 46 | - Release notes: release-notes.md 47 | repo_url: https://github.com/nebula-orchestrator/docs 48 | markdown_extensions: 49 | - admonition 50 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | backports-abc==0.5 2 | certifi==2025.1.31 3 | chardet==5.2.0 4 | Click==8.1.8 5 | idna==3.10 6 | Jinja2==3.1.5 7 | livereload==2.7.1 8 | Markdown==3.7 9 | MarkupSafe==3.0.2 10 | mkdocs==1.6.1 11 | PyYAML==6.0.2 12 | requests==2.32.3 13 | singledispatch==4.1.1 14 | six==1.17.0 15 | tornado==6.4.2 16 | urllib3==2.3.0 17 | -------------------------------------------------------------------------------- /scripts/jenkins/jenkins-release.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2.7 2 | # 3 | # requires requests module installed on your jenkins server 4 | # 5 | # the following script allows jenkins to restart a nebula app thus loading a new version of it for deployment to use 6 | # just have the script on the jenkins server\worker as well as ensuring it has requests python module installed after 7 | # changing the 'BASIC_AUTH_TOKEN' & 'NEBULA_API_HOST' to you basic auth key & Nebula api FQDN then have your build have 8 | # an "execute shall" run the following command: 9 | # ./jenkins-release.py 10 | import requests, sys 11 | 12 | # change this to your Nebula user:pass auth64 basic auth token 13 | BASIC_AUTH_TOKEN = "" 14 | # change this to your nebula api FQDN 15 | NEBULA_API_HOST = "" 16 | 17 | app = sys.argv[1] 18 | 19 | url = "http://" + NEBULA_API_HOST + "/api/v2/apps/" + app + "/restart" 20 | 21 | payload = "" 22 | headers = { 23 | 'authorization': "Basic " + BASIC_AUTH_TOKEN, 24 | 'content-type': "application/json", 25 | 'cache-control': "no-cache" 26 | } 27 | 28 | response = requests.request("POST", url, data=payload, headers=headers) 29 | print(response.text) 30 | 31 | if response.status_code in range(200, 300): 32 | exit(0) 33 | else: 34 | exit(2) 35 | --------------------------------------------------------------------------------