{"id":13785594,"url":"https://github.com/42wim/nomadctld","last_synced_at":"2025-08-12T15:14:11.577Z","repository":{"id":44854784,"uuid":"128836565","full_name":"42wim/nomadctld","owner":"42wim","description":"ssh server with ability to exec/attach/logs/tail/stop/restart hashicorp nomad containers ","archived":false,"fork":false,"pushed_at":"2018-09-29T22:13:52.000Z","size":9727,"stargazers_count":68,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-30T09:52:28.217Z","etag":null,"topics":["cli","docker","exec","nomad","nomad-cluster","nomad-job","ssh-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/42wim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-09T21:34:50.000Z","updated_at":"2024-11-19T22:49:37.000Z","dependencies_parsed_at":"2022-09-11T23:51:14.113Z","dependency_job_id":null,"html_url":"https://github.com/42wim/nomadctld","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/42wim/nomadctld","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42wim%2Fnomadctld","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42wim%2Fnomadctld/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42wim%2Fnomadctld/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42wim%2Fnomadctld/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/42wim","download_url":"https://codeload.github.com/42wim/nomadctld/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42wim%2Fnomadctld/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270083001,"owners_count":24523845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","docker","exec","nomad","nomad-cluster","nomad-job","ssh-server"],"created_at":"2024-08-03T19:01:02.256Z","updated_at":"2025-08-12T15:14:11.549Z","avatar_url":"https://github.com/42wim.png","language":"Go","funding_links":[],"categories":["Infrastructure setup"],"sub_categories":["Tools and Utilities"],"readme":"# nomadctld\n\nnomadctld is a ssh server which sits between your users and the nomad cluster.  \nThis way you can give users limited access to your nomad cluster and allow them to attach, see logs, tail logs, stop, restart, exec containers they own on the cluster.\nThe server you're running nomadctld on needs to have access to your nomad server (usually on port 4646) and the docker daemon on all nomad nodes.\n(TLS is not supported yet)\n\n## features\n* Support nomad ACL tokens\n* Authenticate users via ssh-keys\n* Authorize users on nomad job prefixes\n* Supports following commands\n  * ps \u003cfilter\u003e (shows all/filtered nomad jobs) (\u003cfilter\u003e is optional)\n  * batch \u003cfilter\u003e (shows batch nomad jobs) (\u003cfilter\u003e is optional)\n  * exec \u003cexecID\u003e \u003ccommand\u003e (executes \u003ccommand\u003e in container \u003cexecID\u003e (command default is /bin/sh)\n  * logs \u003cexecID\u003e (shows last 100 stdout lines of \u003cexecID\u003e)\n  * tail \u003cexecID\u003e (shows last 100 stdout lines of \u003cexecID\u003e and keeps following them (like tail -f))\n  * stop \u003cjobID\u003e (stops a nomad job with \u003cjobID\u003e (\u003cjobID\u003e is the jobname))\n  * status \u003cjobID\u003e (shows status of a nomad job with \u003cjobID\u003e (\u003cjobID\u003e is the jobname)\n  * inspect \u003cjobID\u003e (inspects a nomad job with \u003cjobID\u003e (\u003cjobID\u003e is the jobname))\n  * di \u003cexecID\u003e (runs equivalent of docker inspect on container \u003cexecID\u003e\n  * raw \u003cproduction/quality\u003e \u003cnomad command\u003e (executes a \"raw\" nomad command (basically talks to the nomad binary))\n  * restart \u003cjobID\u003e (restart a job)\n  * pstree \u003cfilter\u003e (shows all/filtered nomad jobs)\n  * info \u003cjobID\u003e (shows information about all allocations of the job)\n\n## running\nnomadctld looks for a nomadctld.toml in the current directory or in /etc/nomadctld\n\n```\n./nomadctld\n2018/04/12 23:54:53 starting ssh server on  :2222 Using  /etc/ssh/ssh_host_rsa_key\n```\n\nYou can now do a ssh -p2222 localhost ps to see all running jobs\n\nThere's also a `nomadctl` bash script included that wraps ssh, modify the first line `nomadctld=\"/usr/bin/ssh -p2222 yourserver\"` to your own server and optionally specify your sshkey\n\n## example\nFilter for a mattermost job\n\n```\n$ nomadctl ps mattermost\nExec ID    |Job/Task         |Node      |Uptime      |CPU |Mem(max)\n           |q-lnx-mattermost |          |            |    |\nf429aef310 |q-lnx-mattermost |q-node-10 |3 weeks ago |2   |34 MiB(79 MiB)\n           |p-lnx-mattermost |          |            |    |\ne7c3629baf |p-lnx-mattermost |p-node-2  |1 week ago  |4   |56 MiB(201 MiB)\n```\n\nGet a shell on our quality container\n```\n$ nomadctl exec f429aef310\nWelcome Wim (wim, ssh-ed25519 AAAAC3NzaC1lZDI1NT)\nYou have access to [p- q- t- raw]\nwelcome to q-lnx-mattermost on q-node-10\nsh-4.2# ps -ux\nUSER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nroot          1  0.0  0.0  11640  1344 ?        Ss   Mar21   0:00 /bin/bash /docker-entry.sh\nroot          8  0.0  0.2 455808 43488 ?        Sl   Mar21  22:40 ./platform --config /config_docker.json\nroot         31  1.0  0.0  11772  1672 ?        Ss   00:36   0:00 /bin/sh\nroot         38  0.0  0.0  47448  1664 ?        R+   00:36   0:00 ps -ux\nsh-4.2# exit\n$\n```\n\nShow batch jobs\n\n```\n$ nomadctl batch\nJob ID                                           |Next        |                          |Config\np-es-log-curator                                 |5m24s       |2018-07-12T15:52:00+02:00 |52 6,15,18 * * * *\np-iss-frontend-sync                              |9m24s       |2018-07-12T15:56:00+02:00 |11/15 * * * * *\n```\n\n\n## debugging examples\n\nIf you see a OK or a FAIL next to the job, this means the deployment is OK or has FAILed.\nA deployment can fail even when the containers are running, because of allocations that took too much time to become healthy\n\n### Extra column legend\n\n* F = allocation failed\n* P = allocation pending\n* T = allocation has been terminated\n* O = allocation has been terminated by OOM\n* NR = allocation will not restart\n* KV = allocation has been killed because of vault issues\n* U = allocation is unhealthy (based on consul checks)\n\n### With failures\n```\nExec ID    |Job/Task                                     |Node      |Uptime        |CPU |Mem(max)          |Extra\n076f1388af |p-lnx-helloworld2                            |p-node-5  |1 hour ago    |0   |0 B(0 B)          |F,KV,U\n30a1e62b4e |p-es-iss-cluster1-frontend                   |p-node-9  |14 hours ago  |4   |1.9 GiB(2.0 GiB)  |O,O,O\nb4eaf79c05 |q-fii-lamp                                   |q-node-11 |1 day ago     |0   |39 MiB(67 MiB)    |U,T\nf3c6ee4200 |q-fii-monitoring-wmsmonitor                  |q-node-11 |17 hours ago  |0   |22 MiB(43 MiB)    |T\n```\n* p-lnx-helloworld2 allocations have failed because of vault issues and the allocation is unhealthy\n* p-es-iss-cluster1-frontend is 3 times terminated because of a OOM issue (but is still running because no F)\n* q-fii-monitoring-wmsmonitor has been terminated once (but is still running because no F)\n* q-fii-lamp been terminated once and is now unhealthy (but is still running because no F)\n\nFurther debugging of those failures:\n\n```\n$ nomadctl info p-lnx-helloworld2\n\n076f1388af |failed          |1 hour ago |p-lnx-helloworld2-main/p-lnx-helloworld2\n           |p-node-5        |0 Mhz      |0 B(0 B)\n           |1 hour ago      |Received   |Task received by client\n           |1 hour ago      |Task Setup |Building Task Directory\n           |1 hour ago      |Killing    |vault: server error deriving vault token: Error making API request.\n\nURL: POST https://vault.service.consul:8200/v1/auth/token/create/nomad-cluster\nCode: 400. Errors:\n\n* token policies ([default p-lnx-ros]) must be subset of the role's allowed policies ([default p-es-ro p-lnx-ro])\n           |1 hour ago      |Alloc Unhealthy |Unhealthy because of failed task\n```\nWe can see that there is an issue with our vault policy\n\n\n## example configuration\n```\n[general]\nhostkey=\"/etc/ssh/ssh_host_rsa_key\"\n#this is the port your docker daemon is listening on\ndockerport=\"4243\"\n#specify the api, if you're using an older docker (1.24 is needed for centos7)\ndockerapi=\"1.24\"\nnomadbinary=\"/usr/bin/nomad\"\nbind=\":2222\"\n\n#create some aliases\n[alias]\nstatus=\"raw alles status\"\n\n[nomad]\n[nomad.production]\nurl=\"http://nomad.service.consul:4646\"\n#the prefix that production jobs start with, eg p-team1-teamjob\nprefix=[\"p-\"]\n#file containing the nomad acl token with admin privileges\ntoken=\"/etc/nomadctld/token-p\"\n\n[nomad.quality]\nurl=\"http://nomad.service.qconsul:4646\"\n#the prefix that quality jobs start with, eg q-team1-teamjob\n#we're running quality and test on the same cluster, so t- also runs here\nprefix=[\"q-\"]\ntoken=\"/etc/nomadctld/token-q\"\n\n[nomad.test]\nurl=\"http://nomad.service.tconsul:4646\"\n#the prefix that test jobs start with, eg t-team1-teamjob\nprefix=[\"t-\"]\ntoken=\"/etc/nomadctld/token-t\"\n\n\n#prefixes are used for acl\n[prefix]\n#create a lnx prefix that has access to jobs starting with \"p-\",\"q-\",\"t-\"\n#and has access to the \"raw\" command\n[prefix.lnx]\nprefix=[\"p-\",\"q-\",\"t-\",raw\"]\n\n#the team1 prefix has less privileges, it can only see there own jobs\n[prefix.team1]\nprefix=[\"p-team1-\",\"q-team1-\",\"t-team1-\"]\n\n#create some users\n[users]\n[users.wim]\n#key is the public sshkey\nkey=\"ssh-ed25519 ABCEC4NzaC1lZDI2NTE5AADAIB3m1na7Lu74koUa5EYPvEk7xCXiwtToar73gl9w9MND\"\n#which prefix can this user access\nprefix=[\"lnx\"]\nname=\"Wim\"\n\n[users.user2]\nkey=\"ssh-ed25519 ABCEC4NzaC1lZDI2NTE5AADAIB3m1na7Lu74koUa5EYPvEk7xCXiwtToar73gl9abcde\"\nprefix=[\"team2\"]\nname=\"user2\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F42wim%2Fnomadctld","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F42wim%2Fnomadctld","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F42wim%2Fnomadctld/lists"}